测量频率、占空比、脉冲宽度等信号数字量应该算是430中比较简单的一个实验,而且幸运的是TI官方的示例程序中有相关的内容。
传送门:
https://dev.ti.com/tirex/explore/node?devices=MSP430G2553&node=AFB5DJx-bgFTI4ERhplnuw__IOGqZri__LATEST
https://dev.ti.com/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 TA0.CCI0A 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 /** * main.c 2022/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 timer P1SEL|=BIT1; //set input as TA0.CCI0A 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++; }
上一篇:FPGA与MSP430通信 UART串口操作
下一篇:MSP430 & 4x4 矩阵键盘测试
推荐阅读最新更新时间:2024-11-05 19:31
设计资源 培训 开发板 精华推荐
- SSM2315 无滤波器、高效、单声道 3W D 类音频放大器的典型单端输入配置、用户可调增益电路
- 基于ESP32 C3的4.2寸墨水屏天气预报时钟
- 智能手办盒【miniBox】
- 具有最大功率点跟踪功能的 LTC4162EUFD-SAD 太阳能供电 12V 3.2A 充电器的典型应用
- OP295GSZ-REEL 4.5V、低压降运算放大器基准的典型应用
- 低成本带双路电子电位器的电压电流表
- EVAL-AD73360LEB,用于工业计量的 AD73360、16 位、6CH ADC 的评估板
- LF80CDT-TR 8V低压灯泡典型应用
- AM2G-2409SZ 9V 2 瓦 DC-DC 转换器的典型应用
- 【核心板】GD32F130G6U6TR核心板