找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8655|回复: 3
收起左侧

MSP430G2553测信号频率在LCD1602显示源代码

[复制链接]
ID:294185 发表于 2018-4-7 20:54 | 显示全部楼层 |阅读模式
MSP430G2553测信号频率在LCD1602显示代码,自制,精度较好。

单片机源程序如下:
  1. #include <msp430.h>
  2. #include "stdint.h"
  3. #include "LCD1602.h"
  4. #include <math.h>
  5. volatile  double voltage = 0;
  6. volatile double frequence = 0;
  7. volatile uint8_t flag = 0;
  8. volatile double virtual_fact_plus = 0.0;
  9. volatile double virtual_fact = 0.0;
  10. volatile uint16_t TAcnt = 0;
  11. volatile uint16_t cnt = 0;
  12. volatile uint16_t adcvalue = 0;
  13. volatile uint16_t adcvalueMax = 0;
  14. volatile uint16_t adcvalueMin = 0;
  15. volatile uint32_t cap = 0;
  16. volatile double virtual_ideal_sine = 0.0;
  17. volatile double virtual_ideal_tri = 0.0;
  18. volatile uint16_t num = 0;
  19. volatile uint32_t timestamp = 0;
  20. volatile uint32_t time = 0;
  21. void PrintVoltage(double voltage);
  22. /*函数声明*/
  23. void InitSystemClock(void);
  24. void InitADC(void);
  25. void InitTimer_A1(void);
  26. void GetVpp(void);
  27. void GetFreq(void);
  28. void GetVirtual(void);
  29. void tell_Rec(void);
  30. uint32_t GetCurrentTime(void);
  31. void Enable_P1_3(void);
  32. void InitUART(void);
  33. void UARTSendString(uint8_t *pbuff,uint8_t num);
  34. void PrintVoltage(double voltage);
  35. void PrintFreq(double freq);
  36. /*
  37. * @fn:     void InitSystemClock(void)
  38. * @brief:  初始化系统时钟
  39. * @para:   none
  40. * @return: none
  41. * @comment:初始化系统时钟
  42. */
  43. void InitSystemClock(void)
  44. {
  45.     /*配置DCO为1MHz*/
  46.     DCOCTL = CALDCO_16MHZ;
  47.     BCSCTL1 = CALBC1_16MHZ;
  48.     /*配置SMCLK的时钟源为DCO*/
  49.     BCSCTL2 &= ~SELS;
  50.     /*SMCLK的分频系数置为1*/
  51.     BCSCTL2 &= ~(DIVS0 | DIVS1);
  52. }
  53. /*
  54. * @fn:     void InitADC(void)
  55. * @brief:  初始化ADC
  56. * @para:   none
  57. * @return: none
  58. * @comment:初始化ADC
  59. */
  60. void InitADC(void)
  61. {
  62.       /*设置ADC时钟MCLK*/
  63.       ADC10CTL1 |= ADC10SSEL_2;
  64.       /*ADC 2分频*/
  65.       ADC10CTL1 |= ADC10DIV_0;
  66.       /*设置ADC基准源*/
  67.       ADC10CTL0 |= SREF_1;
  68.       /*设置ADC采样保持时间64CLK*/
  69.       ADC10CTL0 |= ADC10SHT_2;
  70.       /*设置ADC采样率200k*/
  71.       ADC10CTL0 &= ~ADC10SR;
  72.       /*ADC基准选择2.5V*/
  73.       ADC10CTL0 |= REF2_5V;
  74.       /*开启基准*/
  75.       ADC10CTL0 |= REFON;
  76.       /*选择ADC输入通道A0*/
  77.       ADC10CTL1 |= INCH_0;
  78.       /*允许A0模拟输入*/
  79.       ADC10AE0 |= BIT0;
  80.       /*开启ADC*/
  81.       ADC10CTL0 |= ADC10ON;
  82. }
  83. /*
  84. * @fn:     void InitTimer_A1(void)
  85. * @brief   初始化Timer_A1进行计数
  86. * @para:   none
  87. * @return: none
  88. * @comment:初始化Timer_A1
  89. */
  90. void InitTimer_A1(void)
  91. {
  92.     /*设置时钟源为SMCLK*/
  93.     TA1CTL |= TASSEL_2;
  94.     /*设置工作模式为Up Mode*/
  95.     TA1CTL |= MC_1;
  96.     /*设置定时间隔*/
  97.     TA1CCR0 = 49999;// 50ms 1MHz 1/1MHz 1ns 50ms / 1ns = 50000 50000 - 1 = 49999
  98.     /*开启TAIFG中断*/
  99.     TA1CTL |= TAIE;
  100. }
  101. /*计算峰峰值*/
  102. void GetVpp(void)
  103. {
  104.     for(cnt = 0; cnt < 10000; cnt ++)
  105.     {
  106.         /*开始转换*/
  107.         ADC10CTL0 |= ADC10SC|ENC;
  108.         /*等待转换完成*/
  109.         while(ADC10CTL1&ADC10BUSY);
  110.         if(adcvalueMax < ADC10MEM)
  111.         adcvalueMax = ADC10MEM;
  112.         if(adcvalueMin > ADC10MEM)
  113.         adcvalueMin = ADC10MEM;
  114.     }
  115.     voltage = (adcvalueMax - adcvalueMin) * 2.5 / 1023;
  116. }
  117. /*计算波形频率*/
  118. void GetFreq(void)
  119. {
  120.     /*开始转换*/
  121.     ADC10CTL0 |= ADC10SC|ENC;
  122.     /*等待转换完成*/
  123.     while(ADC10CTL1&ADC10BUSY);
  124.     while(fabs((double)(adcvalueMax - ADC10MEM)) > 20)
  125.     {
  126.         /*开始转换*/
  127.         ADC10CTL0 |= ADC10SC|ENC;
  128.         /*等待转换完成*/
  129.         while(ADC10CTL1&ADC10BUSY);
  130.     }
  131.     timestamp = GetCurrentTime();
  132.     while(num < 1000)
  133.     {
  134.         while(fabs((double)(ADC10MEM - adcvalueMin)) > 100)
  135.         {
  136.             /*开始转换*/
  137.             ADC10CTL0 |= ADC10SC|ENC;
  138.             /*等待转换完成*/
  139.             while(ADC10CTL1&ADC10BUSY);
  140.         }
  141.         while(fabs((double)(adcvalueMax - ADC10MEM)) > 100)
  142.         {
  143.             /*开始转换*/
  144.             ADC10CTL0 |= ADC10SC|ENC;
  145.             /*等待转换完成*/
  146.             while(ADC10CTL1&ADC10BUSY);
  147.         }
  148.         num ++;
  149.     }
  150.     num = 0;
  151.     time = GetCurrentTime() - timestamp;
  152.     /*计算信号频率*/
  153.     frequence = 16000000000.0 / (float)(GetCurrentTime() - timestamp);
  154. }
  155. /*计算有效值*/
  156. void GetVirtual(void)
  157. {
  158.     virtual_fact_plus = 0.0;
  159.     for(cnt = 0; cnt < 10000; cnt ++)
  160.     {
  161.         /*开始转换*/
  162.         ADC10CTL0 |= ADC10SC|ENC;
  163.         /*等待转换完成*/
  164.         while(ADC10CTL1&ADC10BUSY);
  165.         virtual_fact_plus += pow((ADC10MEM * 2.5 / 1023), 2);
  166.     }
  167.     virtual_fact = sqrt(virtual_fact_plus / 10000);
  168. }
  169. /*判断方波*/
  170. void tell_Rec(void)
  171. {
  172.     for(cnt = 0; cnt < 10000; cnt ++)
  173.     {
  174.         /*开始转换*/
  175.         ADC10CTL0 |= ADC10SC|ENC;
  176.         /*等待转换完成*/
  177.         while(ADC10CTL1&ADC10BUSY);
  178.         if(fabs((double)(ADC10MEM - adcvalueMin)) < 100 || fabs((double)(adcvalueMax - ADC10MEM)) < 100)
  179.         num ++;
  180.         __delay_cycles(100);
  181.     }
  182.     if(num > 9800)
  183.         flag = 2;       //方波
  184.     else if(2 == flag)  flag = 0;
  185.     num = 0;
  186. }
  187. /*
  188. * @fn:     uint32_t GetCurrentTime(void)
  189. * @brief:  得到当前计时器计数大小
  190. * @para:   none
  191. * @return: currenttime = cnt * 50000 + TA1CCR2
  192. * @comment:得到当前计时器计数大小
  193. */
  194. uint32_t GetCurrentTime(void)
  195. {
  196.     return((uint32_t)(TAcnt * 50000 + TA1R));
  197. }
  198. /*
  199. * @fn:     void Enable_P1_3(void)
  200. * @brief:  使能P1.3口中断
  201. * @para:   none
  202. * @return: none
  203. * @comment:使能P1.3口中断
  204. */
  205. void Enable_P1_3(void)
  206. {
  207.     P1DIR &= ~BIT3;
  208.     /*使能P1.3口的上拉电阻*/
  209.     P1REN |= BIT3;
  210.     P1OUT |= BIT3;
  211.     /*打开P1.3口中断*/
  212.     P1IE |= BIT3;
  213.     /*设定为下降沿触发*/
  214.     P1IES |= BIT3;
  215.     /*清除中断标志位*/
  216.     P1IFG &= ~BIT3;
  217. }
  218. void InitUART(void)
  219. {
  220.     /*复位USCI_Ax*/
  221.     UCA0CTL1 |= UCSWRST;

  222.     /*选择USCI_Ax为UART模式*/
  223.     UCA0CTL0 &= ~UCSYNC;

  224.     /*配置UART时钟源为SMCLK*/
  225.     UCA0CTL1 |= UCSSEL1;

  226.     /*配置波特率为9600@1MHz*/
  227.     UCA0BR0 = 0x68;
  228.     UCA0BR1 = 0x00;
  229.     UCA0MCTL = 0x31;
  230.     /*使能端口复用*/
  231.     P1SEL |= BIT1 + BIT2;
  232.     P1SEL2 |= BIT1 + BIT2;
  233.     /*清除复位位,使能UART*/
  234.     UCA0CTL1 &= ~UCSWRST;
  235. }
  236. /*
  237. * @fn:     void UARTSendString(uint8_t *pbuff,uint8_t num)
  238. * @brief:  通过串口发送字符串
  239. * @para:   pbuff:指向要发送字符串的指针
  240. *          num:要发送的字符个数
  241. * @return: none
  242. * @comment:通过串口发送字符串
  243. */
  244. void UARTSendString(uint8_t *pbuff,uint8_t num)
  245. {
  246.     uint8_t cnt = 0;
  247.     for(cnt = 0;cnt < num;cnt ++)
  248.     {
  249.         while(UCA0STAT & UCBUSY);
  250.         UCA0TXBUF = *(pbuff + cnt);
  251.     }
  252. }
  253. /*
  254. * @fn:     void PrintFloat(float num)
  255. * @brief:  通过串口发送电压,单位为V,保留两位小数
  256. * @para:   voltage:电压
  257. * @return: none
  258. * @comment:通过串口发送浮点数,可发送1位整数位+3位小数位
  259. */
  260. void PrintVoltage(double voltage)
  261. {
  262.     uint8_t charbuff[] = {0,  '.', 0, 0, 0};
  263.     uint16_t temp = (uint16_t)(voltage * 1000);
  264.     charbuff[0] = (uint8_t)(temp / 1000) + '0';
  265.     charbuff[2] = (uint8_t)((temp % 1000) / 100) + '0';
  266.     charbuff[3] = (uint8_t)((temp % 100) / 10)+ '0';
  267.     charbuff[4] = (uint8_t)(temp % 10) + '0';
  268.     UARTSendString(charbuff, 5);
  269.     UARTSendString("V\n", 2);
  270. }
  271. /*
  272. * @fn:     void PrintFreq(float freq)
  273. * @brief:  通过串口发送频率,单位为Hz,保留两位小数
  274. * @para:   freq:频率
  275. * @return: none
  276. * @comment:通过串口发送频率
  277. */
  278. void PrintFreq(double freq)
  279. {
  280.     uint32_t temp = (uint32_t)(freq);
  281.     uint8_t charbuff[] = {0, 0, 0, 0, 0};//最大999999.99Hz
  282.     int8_t cnt = 0;
  283.     for(cnt = 4; cnt >= 0; cnt --)
  284.     {
  285.         charbuff[cnt] = (uint8_t)(temp % 10) + '0';
  286.         temp /= 10;
  287.     }
  288.     UARTSendString("frequence = ", 12);
  289.     UARTSendString(charbuff, 2);
  290.     UARTSendString(".", 1);
  291.     UARTSendString(charbuff + 2, 3);
  292.     UARTSendString("kHz\n", 4);
  293. }
  294. /**
  295. * main.c
  296. */
  297. int main(void)
  298. {

  299.     WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
  300.     InitSystemClock();
  301.     InitADC();
  302.     InitTimer_A1();             //计数
  303.     InitUART();
  304.     delay_nms(10);
  305.     Print_Name();
  306.     Enable_P1_3();
  307.     __bis_SR_register(GIE);/*打开全局中断*/
  308.     while(1)
  309.     {
  310.         num = 0;
  311.         GetVpp();
  312.         if(fabs((double)(adcvalueMax - adcvalueMin)) < 50)
  313.         {
  314.             flag = 1;   //直流
  315.             frequence = 0.0;
  316.         }
  317.         else if(1 == flag)  flag = 0;
  318.         if(1 != flag)
  319.         {
  320.             GetFreq();
  321.             if(frequence < 0.1)
  322.                 frequence = 150.0;
  323.             else    frequence -= frequence * 135.0 / 10000.0;
  324.             TAcnt = 0;

  325.         }
  326.         GetVirtual();
  327.         tell_Rec();
  328.         if(2 != flag && 1 != flag)
  329.         {
  330.             virtual_ideal_sine = sqrt(pow((adcvalueMax + adcvalueMin) * 2.5 / 2046, 2) + (pow(voltage / 2, 2) / 2));
  331.             virtual_ideal_tri = sqrt((pow(adcvalueMax * 2.5 / 1023, 2) + pow(adcvalueMin * 2.5 / 1023, 2) + adcvalueMax * adcvalueMin * 6.25 / pow(1023, 2)) / 3);
  332.             if(fabs(virtual_fact - virtual_ideal_sine) < 0.02)
  333.                 flag = 3;       //正弦波
  334.             else if(fabs(virtual_fact - virtual_ideal_tri) < 0.02)
  335.                 flag = 4;
  336.             else flag  = 0;
  337.         }
  338.         /*switch(flag)
  339.         {
  340.         case 0:UARTSendString("unknown type\n", 13);  break;
  341.         case 1:UARTSendString("Direct\n", 7);         break;
  342.         case 2:UARTSendString("Rectangle\n", 10);      break;
  343.         case 3:UARTSendString("Sine\n", 5);           break;
  344.         case 4:UARTSendString("Triangle\n", 9);       break;
  345.         default:                                    break;
  346.         }
  347.         UARTSendString("Vpp = ", 6);
  348.         PrintVoltage(voltage);
  349.         PrintFreq(frequence);
  350.         PrintVoltage(virtual_fact);
  351.         delay_nms(1000);
  352.         */
  353.     }
  354.     return 0;
  355. }
  356. #pragma vector = TIMER1_A1_VECTOR
  357. __interrupt void Time_Tick(void)
  358. {
  359. ……………………

  360. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
Wave-Detect.rar (92.52 KB, 下载次数: 67)
回复

使用道具 举报

ID:312136 发表于 2018-4-20 02:57 | 显示全部楼层
这个把串口程序也加进去为什么build 工程时为什么会报错呢
回复

使用道具 举报

ID:312136 发表于 2018-4-20 03:57 | 显示全部楼层
这个是从msp430g2553p1.0输入吗,为什么串口发送数据显示不出来
回复

使用道具 举报

ID:376191 发表于 2018-7-20 20:27 | 显示全部楼层
ljt16 发表于 2018-4-20 03:57
这个是从msp430g2553p1.0输入吗,为什么串口发送数据显示不出来

现在解决了吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表