Other Parts Discussed in Thread: MSP430F5172
您好!
我使用 ADC 通过 MSP430f5172微控制器感应电压和电流。 我正在使用 MODOSC 时钟、因此数据表显示它以5MHz 的频率运行。 然而、当我使用一个简单的 LED 打开和关闭代码来查看它的执行时间时、它的频率为10s 或更低。 这是测量 ADC 采样频率的正确方法吗? 我本来期望~300kHz、因为我正在使用采样并保存16个样本。
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Other Parts Discussed in Thread: MSP430F5172
您好!
我使用 ADC 通过 MSP430f5172微控制器感应电压和电流。 我正在使用 MODOSC 时钟、因此数据表显示它以5MHz 的频率运行。 然而、当我使用一个简单的 LED 打开和关闭代码来查看它的执行时间时、它的频率为10s 或更低。 这是测量 ADC 采样频率的正确方法吗? 我本来期望~300kHz、因为我正在使用采样并保存16个样本。
Bruce、您好!
感谢你的答复。 以下是我的代码。 我正在使用 DMA 并同时读取通道序列。
#include
#include
#include
//定义函数
void SetVcoreUp (unsigned int level);
void SetADC ();
void SetDMA();
#define T_BUCK 200 //降压级周期- 200MHz/500kHz (所需频率)=400
#define T_BOOST 200 ////升压级周期
unsigned int adc_result[9];// 10位 ADC 转换结果数组
int iin_temp;// 10位 ADC 转换结果数组
int Vin_temp;// 10位 ADC 转换结果数组
int vbat_temp;// 10位 ADC 转换结果数组
int ibat_temp;// 10位 ADC 转换结果数组
int Vout_temp;// 10位 ADC 转换结果数组
int Iout_temp;// 10位 ADC 转换结果数组
int Vbuckout_temp;
void main (void){
WDTCTL = WDTPW + WDTHOLD;//停止看门狗计时器
//配置 PWM 通道
P1SEL |= BIT7;//将 P1.7设置为输出方向-高降压
P1DIR |= BIT7;
P3SEL |= BIT0;//将 P3.0设置为输出方向- BAT_GD_EN
P3DIR |= BIT0;
P2SEL |= BIT0;//将 P2.0设置为输出方向-低降压
P2DIR |= BIT0;
P2SEL |= BIT2;//将 P2.2设置为输出方向-高升压
P2DIR |= BIT2;
P2SEL |= BIT3;//将 P2.3设置为输出方向-低升压
P2DIR |= BIT3;
P2SEL |= BIT6;//将 P2.6设定为输出方向- Vgate BAT
P2DIR |= BIT6;
//配置 ADC 引脚
PMAPPWD = 0x02D52;//启用写入访问以修改端口映射寄存器
PMAPCTL = PMAPRECFG;//允许在运行时重新配置
//P1MAP0|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A0
P1MAP1|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A1
P1MAP2|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A2
P1MAP3|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A3
P1OMAP4|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A4
P1MAP5|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A5
P3MAP5|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A8
P3MAP6|= PM_ANALOG;//修改所有 PxMAPy 寄存器- A7
PMAPPWD = 0;//通过写入不正确的密钥来禁用写入访问以修改端口映射寄存器
P1SEL |=BIT5+BIT4+BIT3+BIT2+BIT1+BIT0;//在应用模拟信号时将端口映射寄存器 PxMAPy 与 PxSEL.y=1一起设置为 PM_ANALOG
P3SEL |=BIT6+BIT4;
//将 Vcore 设置增加到3级以支持 fsystem=25MHz
//注意:一次改变一个电平内核电压。
SetVcoreUp (0x01);
SetVcoreUp (0x02);
SetVcoreUp (0x03);
//将 DCO 初始化为25MHz
_bis_SR_register (SCG0);//禁用 FLL 控制循环-设置 SCG0
UCSCTL0 = 0x0000;//设置可能的最低 DCOx、MODx
UCSCTL1 = DCORSEL_6;//选择 DCO 范围4.6MHz-88MHz 运行
UCSCTL2 = FLLD_1_763;//将 DCO 乘法器设置为25MHz
//(N + 1)* FLLRef = Fdco
//(762 + 1)* 32768 = 25MHz
//设置 FLL Div = fDCOCLK/2
_BIC_SR_register (SCG0);//启用 FLL 控制循环-清除 SCG0
// DCO 范围位已经存在时、DCO 的最坏情况稳定时间
//已更改 n x 32 x 32 x f_MCLK / f_FLL_reference。 请参阅5xx 中的 UCS 一章
// UG 进行优化。
// 32 x 32 x 25 MHz/32、768Hz = 781250 = DCO 稳定的 MCLK 周期
//__delay_cycles (781250);
_DELAY_CYCLES (782000);
SetADC();
SetDMA();
SetPWM (T_BUCK、T_BOOST);
__DELAY_CYCLES (100);//序列转换之间的延迟
P1DIR |= BIT0;//将 P1.0设置为输出方向
for (;;){
// ADC 采样频率
P1OUT ^= BIT0;//使用异或切换 P1.0
while (ADC10CTL1 & BUSY);//如果 ADC10内核处于活动状态则等待
ADC10CTL0 |= ADC10ENC + ADC10SC;//采样和转换准备就绪
_bis_SR_register (CPUOFF + GIE);// LPM0、ADC10_ISR 将强制退出
}
_bis_SR_register (LPM0_bits);//输入 LPM0
}
// DMA ISR
#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector=dma_vector
_interrupt void DMA0_ISR (void)
#Elif defined (_GNU_)
void __attribute__((中断(DMA_vector)) DMA0_ISR (void)
其他
错误编译器不受支持!
#endif
{
switch (__evo_in_range (DMAIV、16))
{
情况0:中断;//无中断
案例2:
//转换序列完成
ADC10CTL0 &=~ADC10ENC;//禁用 ADC 转换
_BIC_SR_REGISTER_ON_EXIT (CPUOFF);//退出 LPM
中断;// DMA0IFG
案例4:中断;// DMA1IFG
案例6:中断;// DMA2IFG
案例8:中断;//保留
案例10:中断;//保留
案例12:中断;//保留
案例14:中断;//保留
案例16:中断;//保留
默认值:break;
}
}
//函数
void SetVcoreUp (无符号 int 级别)
{
//子例程来更改内核电压
//打开 PMM 寄存器进行写入
PMMCTL0_H = PMMPW_H;
//将 SVS/SVM 高电平设置为新的电平
SVSMHCTL = SVSHE + SVSHRVL0 *电平+ SVMHE + SVSMHRRL0 *电平;
//将 SVM 低电平设置为新的电平
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 *电平;
//等待 SVM 稳定
while ((PMMIFG & SVSMLDLYIFG)=0);
//清除已设置的标志
PMMIFG &=~(SVMLVLRIFG + SVMLIFG);
//将 VCORE 设置为新的电平
PMMCTL0_L = PMMCOREV0 *电平;
//等待达到新级别
IF (((PMMIFG 和 SVMLIFG))
while ((PMMIFG & SVMLVLRIFG)=0);
//将 SVS/SVM 低电平侧设定为新的电平
SVSMLCTL = SVSLE + SVSLRVL0 *电平+ SVMLE + SVSMLRRL0 *电平;
//锁定 PMM 寄存器以进行写访问
PMMCTL0_H = 0x00;
}
//配置 ADC 通道
void SetADC (){
ADC10CTL0 = ADC10SHT_2 + ADC10MSC + ADC10ON;// 16xADC 时钟周期、多采样转换、ADC10ON
ADC10CTL1 = ADC10SSEL_0+ADC10SHP+ ADC10CONSEQ_1;// ADCCLK = MODOSC;采样信号来源于采样定时器、单次序列
ADC10CTL2 = ADC10RES;// 10位转换结果
ADC10MCTL0= ADC10INCH_8 + ADC10SREF_1;//选择 ADC 通道;使用 VR+= VREF 和 VR-= AVSS
//默认情况下、REFMSTR=1 => REFCTL 被用来配置内部基准
while (REFCTL0 & REFGENBUSY);//如果基准发生器忙,请等待
REFCTL0 |= REFVSEL_2 + REFON;//选择内部基准= 2.5V
_DELAY_CYCLS (75);//参考建立延迟(~75us)-ADC10采样和转换=(32+13)*2/SMCLK = 90/SMCLK = 75us
}
void SetDMA(){
//配置 DMA0 (ADC10IFG 触发器)
DMACTL0 = DMA0TSEL_24;// ADC10IFG 触发器
__data20_write_long ((uintptr_t)&DMA0SA、(uintptr_t)&ADC10MEM0);//源单地址
__data20_write_long ((uintptr_t)&DMA0DA、(uintptr_t)&ADC_Result [0]);//更新目标数组地址
DMA0SZ = 0x09;// 8次转换-字节或字传输的数量
DMA0CTL = DMADT_4 + DMADSTINCR_3 + DMAEN +DMAIE;// Rpt、inc dest、启用转换序列后的 int
}
是的,这接近于我得到的值。 不过、我有两个问题。 我们为什么要除以(16+11)。 我明白为什么有16个、但不确定是否有11个。 我的第二个问题 与在每个 通道中使用 DMA 与顺序代码进行感应有关。 我的硬件原型上有大约7个传感器、我认为使用 DMA 和自动扫描模式来获取所有通道将有助于我提高性能。 我是否应该使用某种方法来提高性能? 我在降压和升压转换器级中使用该器件、由于与开关频率(500kHz)相比、我的采样频率非常小、因此我的闭环无法稳定
1) 1) 11表示10个转换时钟和1个移动结果时钟。 [参考 UG 图27-7]。 查看 UG 表27-5、"10"指的是8位结果。 您的情况(10位)需要(12+1)才能实现正确的转换。
2) 2)带有 DMA 的 CONSEQ=1非常接近您可以做的最好的事情。 您可以选择 CONSEQ=3、但不能选择采样率。 只有一个采样电容器(SET)、因此您无法并行进行转换。
一个选项是减少采样/保持时间(SHT0)。 有一个较低的限制、它实际上是电气限制(源阻抗)、但如果您不处于该限制、则可以获取几个时钟[参考 UG 章节27.2.5.3]。 您还可以执行8位采样、这样可以减少2个转换时钟。 即使所有这些都不会使您获得超过40%的增益。
数据表仅声明200ksps (渐近)、并将其分布在9个通道上、每个通道的工作速率约为22ksps。 即使是单个500kHz 信号、也不会成功进行奈奎斯特采样。 我对开关稳压器的工作方式不了解多少详细信息。 您是否有机会在数字域中执行某些操作?
感谢您的详细回答。 我尝试在 PLECs 仿真中降低采样频率、它可以工作、但在硬件中不能工作。 我将研究其他选项。
此外、计算中可能缺少系数2、因为我刚刚检查了采样频率、它实际上是计算结果的~一半。 对于9个样本、采样频率为9kHz;对于1个样本、采样频率约为62.5KHz。 此外、当我使用子模块/主时钟时、采样频率高于 MODOSC。 我本来希望 MODCLCK 的值更高、但 DMA 也能与 MODCLK 配合使用、所以在使用这些替代时钟时、我没有获得正确的传感器读数。 我是否可以在设置中执行错误操作?
如果您使用的是 SMCLK (25MHz)、请记住 ADC10_A 被限制为5.5MHz 时钟[参考数据表(SLAS619R)第5.39节]、因此您需要对 SMCLK 进行分频、此时您也可以使用 MODCLK。
我怀疑您也受到源阻抗的限制;这通常表现为串扰。 这是一项物理定律(您将电子输入采样电容器的速度有多快?) 因此、这里没有太多技巧。 如果将 SHT0降低得太低、则会得到相同的效果。
UG 章节 27.2.5.3中有一个公式、可为您提供最短采样时间(然后转换为时钟)。 我的经验是,这个公式有点乐观,我通常不得不四舍五入。