找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

帖子
查看: 9459|回復(fù): 3
打印 上一主題 下一主題
收起左側(cè)

MSP430G2553測信號頻率在LCD1602顯示源代碼

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:294185 發(fā)表于 2018-4-7 20:54 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
MSP430G2553測信號頻率在LCD1602顯示代碼,自制,精度較好。

單片機(jī)源程序如下:
  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. /*函數(shù)聲明*/
  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:  初始化系統(tǒng)時鐘
  39. * @para:   none
  40. * @return: none
  41. * @comment:初始化系統(tǒng)時鐘
  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的分頻系數(shù)置為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.       /*設(shè)置ADC時鐘MCLK*/
  63.       ADC10CTL1 |= ADC10SSEL_2;
  64.       /*ADC 2分頻*/
  65.       ADC10CTL1 |= ADC10DIV_0;
  66.       /*設(shè)置ADC基準(zhǔn)源*/
  67.       ADC10CTL0 |= SREF_1;
  68.       /*設(shè)置ADC采樣保持時間64CLK*/
  69.       ADC10CTL0 |= ADC10SHT_2;
  70.       /*設(shè)置ADC采樣率200k*/
  71.       ADC10CTL0 &= ~ADC10SR;
  72.       /*ADC基準(zhǔn)選擇2.5V*/
  73.       ADC10CTL0 |= REF2_5V;
  74.       /*開啟基準(zhǔn)*/
  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進(jìn)行計數(shù)
  86. * @para:   none
  87. * @return: none
  88. * @comment:初始化Timer_A1
  89. */
  90. void InitTimer_A1(void)
  91. {
  92.     /*設(shè)置時鐘源為SMCLK*/
  93.     TA1CTL |= TASSEL_2;
  94.     /*設(shè)置工作模式為Up Mode*/
  95.     TA1CTL |= MC_1;
  96.     /*設(shè)置定時間隔*/
  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.         /*開始轉(zhuǎn)換*/
  107.         ADC10CTL0 |= ADC10SC|ENC;
  108.         /*等待轉(zhuǎn)換完成*/
  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.     /*開始轉(zhuǎn)換*/
  121.     ADC10CTL0 |= ADC10SC|ENC;
  122.     /*等待轉(zhuǎn)換完成*/
  123.     while(ADC10CTL1&ADC10BUSY);
  124.     while(fabs((double)(adcvalueMax - ADC10MEM)) > 20)
  125.     {
  126.         /*開始轉(zhuǎn)換*/
  127.         ADC10CTL0 |= ADC10SC|ENC;
  128.         /*等待轉(zhuǎn)換完成*/
  129.         while(ADC10CTL1&ADC10BUSY);
  130.     }
  131.     timestamp = GetCurrentTime();
  132.     while(num < 1000)
  133.     {
  134.         while(fabs((double)(ADC10MEM - adcvalueMin)) > 100)
  135.         {
  136.             /*開始轉(zhuǎn)換*/
  137.             ADC10CTL0 |= ADC10SC|ENC;
  138.             /*等待轉(zhuǎn)換完成*/
  139.             while(ADC10CTL1&ADC10BUSY);
  140.         }
  141.         while(fabs((double)(adcvalueMax - ADC10MEM)) > 100)
  142.         {
  143.             /*開始轉(zhuǎn)換*/
  144.             ADC10CTL0 |= ADC10SC|ENC;
  145.             /*等待轉(zhuǎn)換完成*/
  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.         /*開始轉(zhuǎn)換*/
  162.         ADC10CTL0 |= ADC10SC|ENC;
  163.         /*等待轉(zhuǎn)換完成*/
  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.         /*開始轉(zhuǎn)換*/
  175.         ADC10CTL0 |= ADC10SC|ENC;
  176.         /*等待轉(zhuǎn)換完成*/
  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:  得到當(dāng)前計時器計數(shù)大小
  190. * @para:   none
  191. * @return: currenttime = cnt * 50000 + TA1CCR2
  192. * @comment:得到當(dāng)前計時器計數(shù)大小
  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.     /*設(shè)定為下降沿觸發(fā)*/
  214.     P1IES |= BIT3;
  215.     /*清除中斷標(biāo)志位*/
  216.     P1IFG &= ~BIT3;
  217. }
  218. void InitUART(void)
  219. {
  220.     /*復(fù)位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.     /*使能端口復(fù)用*/
  231.     P1SEL |= BIT1 + BIT2;
  232.     P1SEL2 |= BIT1 + BIT2;
  233.     /*清除復(fù)位位,使能UART*/
  234.     UCA0CTL1 &= ~UCSWRST;
  235. }
  236. /*
  237. * @fn:     void UARTSendString(uint8_t *pbuff,uint8_t num)
  238. * @brief:  通過串口發(fā)送字符串
  239. * @para:   pbuff:指向要發(fā)送字符串的指針
  240. *          num:要發(fā)送的字符個數(shù)
  241. * @return: none
  242. * @comment:通過串口發(fā)送字符串
  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:  通過串口發(fā)送電壓,單位為V,保留兩位小數(shù)
  256. * @para:   voltage:電壓
  257. * @return: none
  258. * @comment:通過串口發(fā)送浮點數(shù),可發(fā)送1位整數(shù)位+3位小數(shù)位
  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:  通過串口發(fā)送頻率,單位為Hz,保留兩位小數(shù)
  274. * @para:   freq:頻率
  275. * @return: none
  276. * @comment:通過串口發(fā)送頻率
  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();             //計數(shù)
  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黑下載附件…………
復(fù)制代碼

所有資料51hei提供下載:
Wave-Detect.rar (92.52 KB, 下載次數(shù): 71)


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:312136 發(fā)表于 2018-4-20 02:57 | 只看該作者
這個把串口程序也加進(jìn)去為什么build 工程時為什么會報錯呢
回復(fù)

使用道具 舉報

板凳
ID:312136 發(fā)表于 2018-4-20 03:57 | 只看該作者
這個是從msp430g2553p1.0輸入嗎,為什么串口發(fā)送數(shù)據(jù)顯示不出來
回復(fù)

使用道具 舉報

地板
ID:376191 發(fā)表于 2018-7-20 20:27 | 只看該作者
ljt16 發(fā)表于 2018-4-20 03:57
這個是從msp430g2553p1.0輸入嗎,為什么串口發(fā)送數(shù)據(jù)顯示不出來

現(xiàn)在解決了嗎
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表