还是简简单单的记录一下学习过程。
测量频率、占空比、脉冲宽度等信号数字量应该算是430中比较简单的一个实验,而且幸运的是TI官方的示例程序中有相关的内容。
传送门:
/tirex/explore/node?devices=MSP430G2553&node=AFB5DJx-bgFTI4ERhplnuw__IOGqZri__LATEST/tirex/explore/node?devices=MSP430G2553&node=AFB5DJx-bgFTI4ERhplnuw__IOGqZri__LATEST
进行测量的重点是对信号上升沿和下降沿的捕获,这一点利用定时器的捕获功能就可以实现。
之后进行相关计算,计算也相对简单。
N1:捕获到第一个上升沿的数据;
N2:捕获到下降沿的数据;
N3:捕获到第二个上升沿的数据;
f0和t0根据自己的设置来决定。
本工程中设置P1.1引脚作为信号输入引脚,相关配置见MSP430的手册
参考代码:(仅供参考)
unsigned int Forward_Posedge_Flag = 1, Counting_Flag=0, Negedge_Flag=0;
unsigned long int Posedge1_data=0, Posedge2_data =0, Negedge_data=0;
double fre, duty_cycle, pulse_width;
int num=0; //测试用
int num1=0,num2=0;
void Calculate_Data();
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
P1SEL|=BIT1; //set input as I0A at P1.1
DCOCTL = CALDCO_16MHZ; BCSCTL1 = CALBC1_16MHZ;
TA0CTL = TASSEL_2 + TACLR + MC_2 + TAIE;
TA0CCTL0 = CM_3 + CCIS_0 + SCS + CAP + CCIE ;
while(1)
{
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0
__no_operation(); // For debugger
}
}
void Calculate_Data()
{
Posedge2_data = Posedge2_data + 65536 * (num1+num2);
Negedge_data = Negedge_data + 65536 * num1;
fre = 16000000.0 / (Posedge2_data - Posedge1_data) ;
duty_cycle = ((double)(Negedge_data - Posedge1_data)) / ((double)(Posedge2_data - Posedge1_data)) ;
pulse_width = ( Negedge_data - Posedge1_data) / 16.0 ; //unit:us
}
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A(void)
{
if(TA0CCTL0 & CCI)
{
if(Forward_Posedge_Flag) //First rising edge captured
{
Posedge1_data = TA0CCR0;
Forward_Posedge_Flag = 0;
Counting_Flag = 1;
}
else if(Counting_Flag = 1 && Negedge_Flag==1) //Second rising edge captured
{
TA0CTL &=TAIE;
TA0CCTL0 &= ~(COV+CCIE);
Posedge2_data = TA0CCR0;
Calculate_Data();
Counting_Flag = 0;
Posedge1_data = 0;
Posedge2_data = 0;
Negedge_data = 0;
Forward_Posedge_Flag = 1;
Negedge_Flag=0;
num=0;
num1=0;
num2=0;
TA0CTL= TASSEL_2 + TACLR + MC_2 + TAIE;
TA0CCTL0 = CM_3 + CCIS_0 + SCS + CAP + CCIE ;
__bic_SR_register_on_exit(LPM0_bits + GIE); // Exit LPM0 on return to main
}
}
else
{
// Falling Edge was captured
if(Counting_Flag==1 && Negedge_Flag==0)
{
Negedge_data = TA0CCR0;
Negedge_Flag = 1;
}
}
}
#pragma vector = TIMER0_A1_VECTOR //TAIFG中断
__interrupt void Timer_A_IV(void)
{
if(TA0IV==0X0A)
{
num= num+1;
if(Counting_Flag == 1 && Negedge_Flag==0)
{
num1++;
}
else if(Counting_Flag == 1 && Negedge_Flag==1)
{
num2++;
}
}
}
下面重点提一些内容:
1. 相对于给出的参考例程,代码中新增了TAIFG中断代码以正确地获得N1,N2,N3的值。在输入信号频率较低时存在TA0R计数溢出。(参考下图)
2. 比较坑的一点:原本在新增中断中进行实时更新,也就是测量过程中对N2,N3直接加65536,但是最后在测试的时候数据乱飞,偶尔几次得到正确的结果,搞得头痛。。一开始实在没想到这样有什么问题。。最后决定在中断中仅仅进行比较简单的num++等操作累计溢出次数,最后算的时候再加和。
3. 捕获到第二个上升沿后进行计算,本人习惯性的disable掉了中断使能,算完之后再重新使能中断。曾经因为这一点也是让程序运行结果百思不得其解,有点无语之感。这里不这样写也许能用。
4.SMCLK设置为16MHz,如果设置的频率低了一点,能测量的高频信号的范围就更窄了。现在硬木口袋能提供的方波最高频率是50kHz,测试结果应该还可以。再高的频率以后找时间测试。。该死的疫情,我真的谢。。
5.紫色那一句表示判断捕捉到的是上升沿还是下降沿,这一点我也是从例程中才知道的。
6.一些符号说明:Counting_Flag表示捕捉到了第一个上升沿,Negedge_Flag表示捕捉到了下降沿。
附上一些测试结果:
1Hz 占空比50%
2Hz 占空比20%
50Hz 占空比80%
1000Hz 占空比50%
5000Hz 占空比40%
10kHz 占空比60%
50kHz 占空比50%
总结:测量很不精确,有点赔钱之感。。。
此外附上之前做的等精度测频法的结果,稍作对比。。
下面分别是1Hz,2Hz,10Hz,50Hz,1kHz,5kHz,10kHz,50kHz的结果
感觉效果也没有好到哪里去,用之前FPGA做的等精度测频效果更好。
FPGA等精度测频传送门:
Verilog设计练习 基于FPGA的等精度频率计_Krism0912的博客-CSDN博客
复制代码请复制代码段:
#include <msp430.h> /*** main.c /3/16 -- 3/17 Krism*/unsigned int Forward_Posedge_Flag = 1, Counting_Flag=0, Negedge_Flag=0;unsigned long int Posedge1_data=0, Posedge2_data =0, Negedge_data=0;double fre, duty_cycle, pulse_width;int num=0; //测试用int num1=0,num2=0;void Calculate_Data();void main(void){WDTCTL = WDTPW | WDTHOLD; // stop watchdog timerP1SEL|=BIT1; //set input as I0A at P1.1DCOCTL = CALDCO_16MHZ; BCSCTL1 = CALBC1_16MHZ;TA0CTL = TASSEL_2 + TACLR + MC_2 + TAIE;TA0CCTL0 = CM_3 + CCIS_0 + SCS + CAP + CCIE ;while(1){__bis_SR_register(LPM0_bits + GIE); // Enter LPM0__no_operation(); // For debugger}}void Calculate_Data(){Posedge2_data = Posedge2_data + 65536 * (num1+num2);Negedge_data = Negedge_data + 65536 * num1;fre = 16000000.0 / (Posedge2_data - Posedge1_data) ;duty_cycle = ((double)(Negedge_data - Posedge1_data)) / ((double)(Posedge2_data - Posedge1_data)) ;pulse_width = ( Negedge_data - Posedge1_data) / 16.0 ; //unit:us}#pragma vector = TIMER0_A0_VECTOR__interrupt void Timer_A(void){if(TA0CCTL0 & CCI){if(Forward_Posedge_Flag) //First rising edge captured{Posedge1_data = TA0CCR0;Forward_Posedge_Flag = 0;Counting_Flag = 1;}else if(Counting_Flag = 1 && Negedge_Flag==1) //Second rising edge captured{TA0CTL &=TAIE;TA0CCTL0 &= ~(COV+CCIE);Posedge2_data = TA0CCR0;Calculate_Data();Counting_Flag = 0;Posedge1_data = 0;Posedge2_data = 0;Negedge_data = 0;Forward_Posedge_Flag = 1;Negedge_Flag=0;num=0;num1=0;num2=0;TA0CTL= TASSEL_2 + TACLR + MC_2 + TAIE;TA0CCTL0 = CM_3 + CCIS_0 + SCS + CAP + CCIE ;__bic_SR_register_on_exit(LPM0_bits + GIE); // Exit LPM0 on return to main}}else{// Falling Edge was capturedif(Counting_Flag==1 && Negedge_Flag==0){Negedge_data = TA0CCR0;Negedge_Flag = 1;}}}#pragma vector = TIMER0_A1_VECTOR//TAIFG中断__interrupt void Timer_A_IV(void){if(TA0IV==0X0A){num= num+1;if(Counting_Flag == 1 && Negedge_Flag==0){num1++;}else if(Counting_Flag == 1 && Negedge_Flag==1){num2++;}}}
-------------------------------------------------------------------------------------
更新:上述测试结果差距加大完全是因为使用的波形发生器太辣鸡!