MSP430G2553测信号频率在LCD1602显示代码,自制,精度较好。
单片机源程序如下:
- #include <msp430.h>
- #include "stdint.h"
- #include "LCD1602.h"
- #include <math.h>
- volatile double voltage = 0;
- volatile double frequence = 0;
- volatile uint8_t flag = 0;
- volatile double virtual_fact_plus = 0.0;
- volatile double virtual_fact = 0.0;
- volatile uint16_t TAcnt = 0;
- volatile uint16_t cnt = 0;
- volatile uint16_t adcvalue = 0;
- volatile uint16_t adcvalueMax = 0;
- volatile uint16_t adcvalueMin = 0;
- volatile uint32_t cap = 0;
- volatile double virtual_ideal_sine = 0.0;
- volatile double virtual_ideal_tri = 0.0;
- volatile uint16_t num = 0;
- volatile uint32_t timestamp = 0;
- volatile uint32_t time = 0;
- void PrintVoltage(double voltage);
- /*函数声明*/
- void InitSystemClock(void);
- void InitADC(void);
- void InitTimer_A1(void);
- void GetVpp(void);
- void GetFreq(void);
- void GetVirtual(void);
- void tell_Rec(void);
- uint32_t GetCurrentTime(void);
- void Enable_P1_3(void);
- void InitUART(void);
- void UARTSendString(uint8_t *pbuff,uint8_t num);
- void PrintVoltage(double voltage);
- void PrintFreq(double freq);
- /*
- * @fn: void InitSystemClock(void)
- * @brief: 初始化系统时钟
- * @para: none
- * @return: none
- * @comment:初始化系统时钟
- */
- void InitSystemClock(void)
- {
- /*配置DCO为1MHz*/
- DCOCTL = CALDCO_16MHZ;
- BCSCTL1 = CALBC1_16MHZ;
- /*配置SMCLK的时钟源为DCO*/
- BCSCTL2 &= ~SELS;
- /*SMCLK的分频系数置为1*/
- BCSCTL2 &= ~(DIVS0 | DIVS1);
- }
- /*
- * @fn: void InitADC(void)
- * @brief: 初始化ADC
- * @para: none
- * @return: none
- * @comment:初始化ADC
- */
- void InitADC(void)
- {
- /*设置ADC时钟MCLK*/
- ADC10CTL1 |= ADC10SSEL_2;
- /*ADC 2分频*/
- ADC10CTL1 |= ADC10DIV_0;
- /*设置ADC基准源*/
- ADC10CTL0 |= SREF_1;
- /*设置ADC采样保持时间64CLK*/
- ADC10CTL0 |= ADC10SHT_2;
- /*设置ADC采样率200k*/
- ADC10CTL0 &= ~ADC10SR;
- /*ADC基准选择2.5V*/
- ADC10CTL0 |= REF2_5V;
- /*开启基准*/
- ADC10CTL0 |= REFON;
- /*选择ADC输入通道A0*/
- ADC10CTL1 |= INCH_0;
- /*允许A0模拟输入*/
- ADC10AE0 |= BIT0;
- /*开启ADC*/
- ADC10CTL0 |= ADC10ON;
- }
- /*
- * @fn: void InitTimer_A1(void)
- * @brief 初始化Timer_A1进行计数
- * @para: none
- * @return: none
- * @comment:初始化Timer_A1
- */
- void InitTimer_A1(void)
- {
- /*设置时钟源为SMCLK*/
- TA1CTL |= TASSEL_2;
- /*设置工作模式为Up Mode*/
- TA1CTL |= MC_1;
- /*设置定时间隔*/
- TA1CCR0 = 49999;// 50ms 1MHz 1/1MHz 1ns 50ms / 1ns = 50000 50000 - 1 = 49999
- /*开启TAIFG中断*/
- TA1CTL |= TAIE;
- }
- /*计算峰峰值*/
- void GetVpp(void)
- {
- for(cnt = 0; cnt < 10000; cnt ++)
- {
- /*开始转换*/
- ADC10CTL0 |= ADC10SC|ENC;
- /*等待转换完成*/
- while(ADC10CTL1&ADC10BUSY);
- if(adcvalueMax < ADC10MEM)
- adcvalueMax = ADC10MEM;
- if(adcvalueMin > ADC10MEM)
- adcvalueMin = ADC10MEM;
- }
- voltage = (adcvalueMax - adcvalueMin) * 2.5 / 1023;
- }
- /*计算波形频率*/
- void GetFreq(void)
- {
- /*开始转换*/
- ADC10CTL0 |= ADC10SC|ENC;
- /*等待转换完成*/
- while(ADC10CTL1&ADC10BUSY);
- while(fabs((double)(adcvalueMax - ADC10MEM)) > 20)
- {
- /*开始转换*/
- ADC10CTL0 |= ADC10SC|ENC;
- /*等待转换完成*/
- while(ADC10CTL1&ADC10BUSY);
- }
- timestamp = GetCurrentTime();
- while(num < 1000)
- {
- while(fabs((double)(ADC10MEM - adcvalueMin)) > 100)
- {
- /*开始转换*/
- ADC10CTL0 |= ADC10SC|ENC;
- /*等待转换完成*/
- while(ADC10CTL1&ADC10BUSY);
- }
- while(fabs((double)(adcvalueMax - ADC10MEM)) > 100)
- {
- /*开始转换*/
- ADC10CTL0 |= ADC10SC|ENC;
- /*等待转换完成*/
- while(ADC10CTL1&ADC10BUSY);
- }
- num ++;
- }
- num = 0;
- time = GetCurrentTime() - timestamp;
- /*计算信号频率*/
- frequence = 16000000000.0 / (float)(GetCurrentTime() - timestamp);
- }
- /*计算有效值*/
- void GetVirtual(void)
- {
- virtual_fact_plus = 0.0;
- for(cnt = 0; cnt < 10000; cnt ++)
- {
- /*开始转换*/
- ADC10CTL0 |= ADC10SC|ENC;
- /*等待转换完成*/
- while(ADC10CTL1&ADC10BUSY);
- virtual_fact_plus += pow((ADC10MEM * 2.5 / 1023), 2);
- }
- virtual_fact = sqrt(virtual_fact_plus / 10000);
- }
- /*判断方波*/
- void tell_Rec(void)
- {
- for(cnt = 0; cnt < 10000; cnt ++)
- {
- /*开始转换*/
- ADC10CTL0 |= ADC10SC|ENC;
- /*等待转换完成*/
- while(ADC10CTL1&ADC10BUSY);
- if(fabs((double)(ADC10MEM - adcvalueMin)) < 100 || fabs((double)(adcvalueMax - ADC10MEM)) < 100)
- num ++;
- __delay_cycles(100);
- }
- if(num > 9800)
- flag = 2; //方波
- else if(2 == flag) flag = 0;
- num = 0;
- }
- /*
- * @fn: uint32_t GetCurrentTime(void)
- * @brief: 得到当前计时器计数大小
- * @para: none
- * @return: currenttime = cnt * 50000 + TA1CCR2
- * @comment:得到当前计时器计数大小
- */
- uint32_t GetCurrentTime(void)
- {
- return((uint32_t)(TAcnt * 50000 + TA1R));
- }
- /*
- * @fn: void Enable_P1_3(void)
- * @brief: 使能P1.3口中断
- * @para: none
- * @return: none
- * @comment:使能P1.3口中断
- */
- void Enable_P1_3(void)
- {
- P1DIR &= ~BIT3;
- /*使能P1.3口的上拉电阻*/
- P1REN |= BIT3;
- P1OUT |= BIT3;
- /*打开P1.3口中断*/
- P1IE |= BIT3;
- /*设定为下降沿触发*/
- P1IES |= BIT3;
- /*清除中断标志位*/
- P1IFG &= ~BIT3;
- }
- void InitUART(void)
- {
- /*复位USCI_Ax*/
- UCA0CTL1 |= UCSWRST;
- /*选择USCI_Ax为UART模式*/
- UCA0CTL0 &= ~UCSYNC;
- /*配置UART时钟源为SMCLK*/
- UCA0CTL1 |= UCSSEL1;
- /*配置波特率为9600@1MHz*/
- UCA0BR0 = 0x68;
- UCA0BR1 = 0x00;
- UCA0MCTL = 0x31;
- /*使能端口复用*/
- P1SEL |= BIT1 + BIT2;
- P1SEL2 |= BIT1 + BIT2;
- /*清除复位位,使能UART*/
- UCA0CTL1 &= ~UCSWRST;
- }
- /*
- * @fn: void UARTSendString(uint8_t *pbuff,uint8_t num)
- * @brief: 通过串口发送字符串
- * @para: pbuff:指向要发送字符串的指针
- * num:要发送的字符个数
- * @return: none
- * @comment:通过串口发送字符串
- */
- void UARTSendString(uint8_t *pbuff,uint8_t num)
- {
- uint8_t cnt = 0;
- for(cnt = 0;cnt < num;cnt ++)
- {
- while(UCA0STAT & UCBUSY);
- UCA0TXBUF = *(pbuff + cnt);
- }
- }
- /*
- * @fn: void PrintFloat(float num)
- * @brief: 通过串口发送电压,单位为V,保留两位小数
- * @para: voltage:电压
- * @return: none
- * @comment:通过串口发送浮点数,可发送1位整数位+3位小数位
- */
- void PrintVoltage(double voltage)
- {
- uint8_t charbuff[] = {0, '.', 0, 0, 0};
- uint16_t temp = (uint16_t)(voltage * 1000);
- charbuff[0] = (uint8_t)(temp / 1000) + '0';
- charbuff[2] = (uint8_t)((temp % 1000) / 100) + '0';
- charbuff[3] = (uint8_t)((temp % 100) / 10)+ '0';
- charbuff[4] = (uint8_t)(temp % 10) + '0';
- UARTSendString(charbuff, 5);
- UARTSendString("V\n", 2);
- }
- /*
- * @fn: void PrintFreq(float freq)
- * @brief: 通过串口发送频率,单位为Hz,保留两位小数
- * @para: freq:频率
- * @return: none
- * @comment:通过串口发送频率
- */
- void PrintFreq(double freq)
- {
- uint32_t temp = (uint32_t)(freq);
- uint8_t charbuff[] = {0, 0, 0, 0, 0};//最大999999.99Hz
- int8_t cnt = 0;
- for(cnt = 4; cnt >= 0; cnt --)
- {
- charbuff[cnt] = (uint8_t)(temp % 10) + '0';
- temp /= 10;
- }
- UARTSendString("frequence = ", 12);
- UARTSendString(charbuff, 2);
- UARTSendString(".", 1);
- UARTSendString(charbuff + 2, 3);
- UARTSendString("kHz\n", 4);
- }
- /**
- * main.c
- */
- int main(void)
- {
- WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
- InitSystemClock();
- InitADC();
- InitTimer_A1(); //计数
- InitUART();
- delay_nms(10);
- Print_Name();
- Enable_P1_3();
- __bis_SR_register(GIE);/*打开全局中断*/
- while(1)
- {
- num = 0;
- GetVpp();
- if(fabs((double)(adcvalueMax - adcvalueMin)) < 50)
- {
- flag = 1; //直流
- frequence = 0.0;
- }
- else if(1 == flag) flag = 0;
- if(1 != flag)
- {
- GetFreq();
- if(frequence < 0.1)
- frequence = 150.0;
- else frequence -= frequence * 135.0 / 10000.0;
- TAcnt = 0;
- }
- GetVirtual();
- tell_Rec();
- if(2 != flag && 1 != flag)
- {
- virtual_ideal_sine = sqrt(pow((adcvalueMax + adcvalueMin) * 2.5 / 2046, 2) + (pow(voltage / 2, 2) / 2));
- virtual_ideal_tri = sqrt((pow(adcvalueMax * 2.5 / 1023, 2) + pow(adcvalueMin * 2.5 / 1023, 2) + adcvalueMax * adcvalueMin * 6.25 / pow(1023, 2)) / 3);
- if(fabs(virtual_fact - virtual_ideal_sine) < 0.02)
- flag = 3; //正弦波
- else if(fabs(virtual_fact - virtual_ideal_tri) < 0.02)
- flag = 4;
- else flag = 0;
- }
- /*switch(flag)
- {
- case 0:UARTSendString("unknown type\n", 13); break;
- case 1:UARTSendString("Direct\n", 7); break;
- case 2:UARTSendString("Rectangle\n", 10); break;
- case 3:UARTSendString("Sine\n", 5); break;
- case 4:UARTSendString("Triangle\n", 9); break;
- default: break;
- }
- UARTSendString("Vpp = ", 6);
- PrintVoltage(voltage);
- PrintFreq(frequence);
- PrintVoltage(virtual_fact);
- delay_nms(1000);
- */
- }
- return 0;
- }
- #pragma vector = TIMER1_A1_VECTOR
- __interrupt void Time_Tick(void)
- {
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
Wave-Detect.rar
(92.52 KB, 下载次数: 71)
|