基于msp430G2553的低频方波频率占空比峰峰值测量函数
Posted 芯青年0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于msp430G2553的低频方波频率占空比峰峰值测量函数相关的知识,希望对你有一定的参考价值。
使用的平台是TI公司的launch pad,频率和占空比已经实现,峰峰值还有有待改进
1、主函数部分:
/*********************************************\\ * _ooOoo_ * * o8888888o * * 88" . "88 * * (| -_- |) * * O\\ = /O * * ____/`---'\\____ * * .' \\\\| |// `. * * / \\\\||| : |||// \\ * * / _||||| -:- |||||- \\ * * | | \\\\\\ - /// | | * * | \\_| ''\\---/'' | | * * \\ .-\\__ `-` ___/-. / * * ___`. .' /--.--\\ `. . __ * * ."" '< `.___\\_<|>_/___.' >'"". * * | | : `- \\`.;`\\ _ /`;.`/ - ` : | | * * \\ \\ `-. \\_ __\\ /__ _/ .-` / / * *======`-.____`-.___\\_____/___.-`____.-'======* * `=---=' * *^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^* * No bug forever * \\*********************************************/ /* * Author: 余裕鑫 * function:测量信号的频率和占空比,信号输入管脚为P2.1.串口打印输出信息。 * 串口:9600,无校验位,8位数据位,1位停止位 * Created on: 2018年5月2日 *注意:测频率和占空比采用分别是测量一个周期和高电平期间的时钟个数,故适合于低频部分的频率和占空比的测量 * 当频率高于100Hz时,误差逐渐增大, * 100Hz时,误差约为1%,1Hz * 1000Hz时,误差约为1.5%,15Hz * 10000Hz时,误差约为0.37%,37Hz * 20000Hz时,误差约为2%,199Hz * 30000Hz时,误差约为6.5%,650Hz */ #include <msp430g2553.h> #include "stdio.h" #include "pwminput.h" #include "uart.h" #include "datatype.h" extern volatile u16 Frequency; extern volatile u8 Duty; extern volatile u16 PeakValue; float PeakValueF; /** * main.c */ void main(void) unsigned char str[20]; WDTCTL = WDTPW + WDTHOLD; // stop watchdog timer // 将MCLK 和 SMCLK 设置为16MHZ,ACLK默认为32.768KHz DCOCTL = CALDCO_16MHZ; BCSCTL1 = CALBC1_16MHZ; //使用高频时钟而减小误差 _EINT(); UART_Init(); sprintf(str,"frequency and duty:\\n"); UARTSendString(str); while(1) Measure_Frequency_Duty(); sprintf(str,"Frequency : %d \\n",Frequency); UARTSendString(str); sprintf(str,"Duty : %d \\n",Duty); UARTSendString(str); // Measure_Peak_Value(); // PeakValueF = PeakValue*3.6/1024; // sprintf(str,"Peak Value : %0.2f \\n",PeakValueF); // UARTSendString(str); __delay_cycles(50000000);2、C文件部分:
/* * pwminput.c * * Created on: 2018年4月23日 * Author: yyx */ #include "pwminput.h" #include "adc.h" #define T0C1A P1DIR&=~BIT2;P1SEL|=BIT2;P1SEL2&=~BIT2 #define T1C0A P2DIR&=~BIT0;P2SEL|=BIT0;P2SEL2&=~BIT0 #define T1C1A P2DIR&=~BIT1;P2SEL|=BIT1;P2SEL2&=~BIT1 #define SAMPLETIMES 10 //测峰峰值中一个周期采样的次数 #define SAMPLEPERIODS 5 //测一次峰峰值中采样的周期个数 u8 FreqFlag = 0; u16 PwmStart;//初始时间 u16 PwmHighEnd,PwmLowEnd;//高电平和低电平的结束时间 u16 HighOverFlow,AllOverFlow; //高电平和一个周期的翻转个数 u32 HighClockSteps,AllClockSteps; u16 PeakIntervalSteps; volatile u16 Frequency; volatile u8 Duty; volatile u16 PeakValue; extern volatile u16 ADC10_Result; u8 SampleStatus; //频率占空比测量函数 void Measure_Frequency_Duty(void) T1C1A; //管脚配置p2.1 FreqFlag=1; //频率测量中断标志 TA1CCTL1 = CAP+CM_1+CCIS_0+SCS+CCIE; // 输入捕捉,上升沿触发(upCM_1,downCM_2,updownCM_3),同步捕捉,CCI0A 中断使能 TA1CTL = TASSEL_2 + MC_2 + TAIE + TACLR; // 选择SMCLK为时钟,连续计数模式 ,溢出中断使能 while(FreqFlag); if(PwmHighEnd>PwmStart) HighClockSteps=(HighOverFlow-1)*65536+PwmHighEnd-PwmStart; else HighClockSteps=(HighOverFlow-1)*65536+PwmHighEnd+65536-PwmStart; if(PwmLowEnd>PwmStart) AllClockSteps=(AllOverFlow-1)*65536+PwmLowEnd-PwmStart; else AllClockSteps=(AllOverFlow-1)*65536+PwmLowEnd+65536-PwmStart; if(AllClockSteps) PeakIntervalSteps = (u16)AllClockSteps/SAMPLETIMES; //测峰峰值中以10倍频率进行采样 Frequency = 16000000/AllClockSteps; Duty = HighClockSteps*100.0/AllClockSteps; /* * 功能:测P1.3管脚信号的峰峰值 * */ void Measure_Peak_Value(void) if(PeakIntervalSteps) //如果采样间隔不为0 //使用TimerA1的计数模式, TA1CTL |= TACLR; //定时器清零 TA1CTL |= TASSEL_2+ MC_1+ID_0; //SMCLK(16MHz),1分频,上数模式 //定时器开始计数从0到CCR0 TA1CCR0 = PeakIntervalSteps; //十分之一个周期中断一次 TA1CCTL0=CCIE; //使能中断 ADC10_Init(3); // 初始化ADC SampleStatus = SAMPLEPERIODS; while(SampleStatus); #pragma vector = TIMER1_A0_VECTOR __interrupt void TimerA1_ISR(void) _DINT(); static u16 PeriodValue[2*SAMPLETIMES],MaxValue[SAMPLEPERIODS+1],MinValue[SAMPLEPERIODS+1]; u32 MaxSum,MinSum; static u8 i; u8 j; if(SampleStatus) if(i<2*SAMPLETIMES) ADC10_Start_Convey(); PeriodValue[i++] = ADC10_Result; if(i==2*SAMPLETIMES) i=0; MaxValue[SampleStatus]=MinValue[SampleStatus]=PeriodValue[0];//初始化最值 for(j=0;j<2*SAMPLETIMES;j++) if(PeriodValue[j]>MaxValue[SampleStatus])MaxValue[SampleStatus]=PeriodValue[j]; if(PeriodValue[j]<MinValue[SampleStatus])MinValue[SampleStatus]=PeriodValue[j]; SampleStatus--; //测量的周期次数减1 if(SampleStatus==0)//如果采样完成 for(j=1;j<=SAMPLEPERIODS;j++) MaxSum+=MaxValue[j]; MinSum+=MinValue[j]; PeakValue=(u16)(MaxSum-MinSum)/SAMPLEPERIODS; MaxSum=MinSum=0; _EINT(); #pragma vector = TIMER1_A1_VECTOR __interrupt void TimerA1_Capture_ISR(void) _DINT(); //关闭中断, switch(TA1IV)//向量查询 case 2: //捕获中断,CCR1 if(FreqFlag) static u8 index; if((TA1CCTL1&CM0)&&(index==0)) //第一次上升沿 TA1CCTL1|=CM_2;//更变为下降沿触发 PwmStart=TA1R;//记录初始时间 HighOverFlow = AllOverFlow = 0; //溢出计数变量复位 PwmHighEnd=PwmLowEnd=0; index=(index+1)%3; else if((TA1CCTL1&CM1)&&(index==1))//下降沿 TA1CCTL1|=CM_1;//更改设置为上升沿触发 HighOverFlow = AllOverFlow; PwmHighEnd = TA1R; //记录高电平结束时间 index=(index+1)%3; else if((TA1CCTL1&CM0)&&(index==2)) //第二次上升沿 //测完一个周期,等待下一个上升沿 PwmLowEnd = TA1R; FreqFlag = 0; index=(index+1)%3; break; case 4:break;//CCR2 case 10: if(FreqFlag) AllOverFlow++; TA1CTL &= ~TAIFG; break; default: break; _EINT(); //打开中断3、头文件部分:
/* * pwminput.h * * Created on: 2018年4月23日 * Author: yyx */ #ifndef PWMINPUT_H_ #define PWMINPUT_H_ #include <msp430g2553.h> #include "datatype.h" void Measure_Frequency_Duty(void); void Measure_Peak_Value(void); #endif /* SRC_PWMINPUT_H_ */
4、其中涉及的相关辅助型文件
①、ADC
/* * adc.c * * Created on: 2018年5月2日 * Author: yyx */ #include "adc.h" volatile u16 ADC10_Result; /** * 功能:ADC10初始化函数 * 参数: * pin:选择模拟输入的管脚,取值为0-7,对应P1.0到P1.7 * */ void ADC10_Init(u8 pin) ADC10CTL0 |= ADC10SHT_2 + ADC10ON; //打开ADC10,并设置为16个ADC时钟 ADC10CTL0 |= ADC10IE; ADC10CTL1 |= ADC10SSEL_3; switch(pin) case 3: ADC10CTL1 |= INCH_3; ADC10AE0 |= BIT3; P1DIR &= ~BIT3; break; default:break; /* * adc.h * * Created on: 2018年5月2日 * Author: yyx */ #ifndef SRC_ADC_H_ #define SRC_ADC_H_ #include "msp430g2553.h" #include "datatype.h" void ADC10_Init(u8 pin); void ADC10_Start_Convey(void); #endif /* ADC_H_ */ void ADC10_Start_Convey(void) ADC10CTL0 |=ENC + ADC10SC; //开始转换 #pragma vector = ADC10_VECTOR __interrupt void ADC10_ISR(void) _DINT(); //关总中断 ADC10_Result = ADC10MEM; ADC10CTL0 &= ~ADC10SC; //结束转换 _EINT(); //开总中断
②、uart
/* * uart.c * * Created on: 2018年4月22日 * Author: yyx */ #include "uart.h" void UART_Init() P1SEL |= BIT1 + BIT2; P1SEL2 |= BIT1 + BIT2; //将p1.1和p1.2选为UART模式 P1DIR &= ~BIT1; P1DIR |= BIT2; UCA0CTL1 |= UCSSEL_2; //SMCLK UCA0BR1 = 1666/256; //高8位 UCA0BR0 = 1666%256; UCA0MCTL |= UCBRS_6 + UCBRF_0; //设置波特率为9600 UCA0CTL1 &= ~UCSWRST; //开始运行 // IE2 |= UCA0RXIE+UCA0TXIE; //使能中断 /******************************************************************** * *******************************************************************/ void UARTSendChar(char ch) if(ch == '\\n') while(UCA0STAT & UCBUSY); UCA0TXBUF = '\\r'; while(UCA0STAT & UCBUSY); UCA0TXBUF = ch; /******************************************************************** * *******************************************************************/ void UARTSendString(char *pt) UART_Init(); while(UCA0STAT & UCBUSY); while(*pt) UARTSendChar(*pt++); /* * uart.h * * Created on: 2018年4月22日 * Author: yyx */ #ifndef SRC_UART_H_ #define SRC_UART_H_ #include <msp430g2553.h> void UART_Init(void); void UARTSendChar(char ch); void UARTSendString(char *pt); #endif /* SRC_UART_H_ */
③、数据类型的重定义
/* * datatype.h * * Created on: 2018年5月1日 * Author: yyx */ #ifndef SRC_DATATYPE_H_ #define SRC_DATATYPE_H_ typedef unsigned char u8; typedef unsigned int u16; typedef unsigned long u32; #endif /* DATATYPE_H_ */
以上是关于基于msp430G2553的低频方波频率占空比峰峰值测量函数的主要内容,如果未能解决你的问题,请参考以下文章