找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

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

第14章-精密電壓表_電流表_顯示器_計(jì)數(shù)器

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
51單片機(jī)輕松入門—基于STC15W4K系列(C語言版)
李友全
編著 詳見:http://www.torrancerestoration.com/bbs/dpj-37954-1.html

14章 電壓表\電流表\顯示器\計(jì)數(shù)器
通過本模塊的學(xué)習(xí)制作,可以進(jìn)一步熟悉高精度ADC的運(yùn)用,單片機(jī) 內(nèi)部DataFlash的讀寫、動(dòng)態(tài)顯示程序的編寫(包括小數(shù)的顯示)以及自 定義的SPI主從機(jī)數(shù)據(jù)通信原理,測試中,本模塊可以直接插接到第一章

介紹的單片機(jī)實(shí)驗(yàn)板“通用計(jì)數(shù)器/顯示器接口”上使用。


1 功能說明與電路原理分析

同一個(gè)模塊,通過硬件上的簡單設(shè)置可實(shí)現(xiàn)4種不同的功能


K3(P4.2)
K4(P4.3)
模塊功能

K1(P3.6)
K2(P3.7)
電壓表檔位
輸入阻抗
0
0
電流表

0
0
2.0480V
2MΩ
0
1
計(jì)數(shù)器

0
1
20.480V

1
0
顯示器

1
0
204.80V
1MΩ

1

1

電壓表(默認(rèn))

1

1

20.480V(默 認(rèn))

① 電壓表說明:

使用18位MCP3421A0T-E/CH芯片作ADC,通過軟件校準(zhǔn)的方式可使整個(gè)模塊電壓測量誤差 最大值不大于量程的±0.05%,在電路上,2V檔由外部信號(hào)直接輸入ADC,其它檔位使用
1MΩ電阻降壓,然后使用MCP6V01T-E/SN 軌到軌自動(dòng)調(diào)零運(yùn)放作ADC輸入電壓跟隨器,由
于精度要求高,普通運(yùn)放無法滿足要求。

② 電流表說明: 使用0.1Ω/0.5W的電流取樣電阻,可測量0~2A范圍內(nèi)的電流,取樣出來的電壓信號(hào)不經(jīng)過電

壓跟隨器,直接送入ADC芯片。
③ 通用顯示器說明:
外部單片機(jī)通過CLK與DAT兩條信號(hào)線向模塊送入數(shù)據(jù),模塊能顯示0~99999范圍內(nèi)整數(shù)或小 數(shù)值,外部單片機(jī)需要一次向模塊發(fā)送5個(gè)字節(jié)的數(shù)據(jù),第1字節(jié)表示模塊地址,默認(rèn)值為0
,在多個(gè)模塊CLK與DAT并接在一起的情況下,只有與發(fā)送地址相符的模塊才接收與處理總線
上的數(shù)據(jù),第2、3、4字節(jié)是需要顯示的數(shù)據(jù),第2字節(jié)是數(shù)據(jù)高字節(jié),第3字節(jié)是數(shù)據(jù)中間 字節(jié),4字節(jié)是數(shù)據(jù)低字節(jié),第5字節(jié)確定需要顯示的小數(shù)位數(shù),所有字節(jié)都是按高位在前, 低位在后的順序發(fā)送,每一位的發(fā)送是外部單片機(jī)先把數(shù)據(jù)位放到DAT線上,然后拉低CLK線
,模塊內(nèi)部是在CLK下降沿后讀取DAT線上的狀態(tài),經(jīng)測試,模塊在22.1184MHz工作頻率下外

部單片機(jī)數(shù)據(jù)發(fā)送時(shí)鐘脈沖高電平1uS、低電平5uS條件下工作正常,也就是說發(fā)送一組數(shù)據(jù) 的最短時(shí)間需要大約(1 + 5)×8×5 = 240uS,為了提高穩(wěn)定性,可以適當(dāng)降低通信時(shí)鐘頻 率(主要是延長脈沖低電平時(shí)間),但也不能過低,要求一組數(shù)據(jù)必須在0.2秒內(nèi)傳送完成

,超過0.2秒,模塊自動(dòng)清除前面已收到的不完整的數(shù)據(jù),這樣保證了數(shù)據(jù)傳送的可靠性。
④ 計(jì)數(shù)器說明: 外部脈沖信號(hào)通過DAT線送入模塊,每產(chǎn)生一個(gè)脈沖下降沿,計(jì)數(shù)器數(shù)值加1,超過最大值
99999后從0開始循環(huán),要求外部脈沖信號(hào)低電平不能大于0.6V,高電平不能小于2V,高電平 最大值也不能超過40V,模塊具有斷電自動(dòng)存儲(chǔ)數(shù)據(jù)的功能,可通過開關(guān)將CLK線接GND,上
電瞬間即可將顯示的計(jì)數(shù)值清零。


部分程序預(yù)覽(完整代碼請(qǐng)下載附件): 第14章(電壓_電流表_計(jì)數(shù)器_顯示器).rar (821.41 KB, 下載次數(shù): 277)

  1. /*顯示程序,用STC15F2K60S2做顯示芯片
  2. // 硬件說明:P42   P43                                    P36      P37
  3.                          0            0            電流表               0            0            1.9999V
  4.                          0            1            計(jì)數(shù)器                   0            1            19.999V
  5.                          1            0            顯示器                   1            0            199.99V
  6.                          1            1            電壓表                   1            1            999.99V
  7.                        
  8. // 待顯示數(shù)據(jù)由主機(jī)傳來,定義5個(gè)字節(jié)的顯示代碼
  9. // 第一字節(jié)是本機(jī)的地址碼,對(duì)本機(jī)而言,必須是“0”
  10. // 接下來三字節(jié)是要顯示的數(shù)據(jù)(高字節(jié)在前,低字節(jié)在后)
  11. // 第五個(gè)字節(jié)是要顯示的小數(shù)點(diǎn)位置,可能值是0-4,表示顯示幾位小數(shù)
  12. //分別代表:0——不顯示 1——十位,2——百位,3——千位        ,4——萬位 ,個(gè)位后小數(shù)點(diǎn)固定不顯示
  13.             99999     9999.9   999.99   99.999    9.9999
  14. //接線:P07 P06 P05 P04 P03 P02 P01 P00
  15. //          e    d   h   c   g   a   f   b
  16. //0           0    0   1   0   1   0   0   0   0x28
  17. //1     1    1   1   0   1   1   1   0   0xee
  18. //2     0    0   1   1   0   0   1   0   0x32
  19. //3     1    0   1   0   0   0   1   0   0xa2
  20. //4     1    1   1   0   0   1   0   0   0xe4
  21. //5     1    0   1   0   0   0   0   1   0xa1
  22. //6     0    0   1   0   0   0   0   1   0x21
  23. //7     1    1   1   0   1   0   1   0   0xea
  24. //8     0    0   1   0   0   0   0   0   0x20
  25. //9     1    0   1   0   0   0   0   0   0xa0
  26. //A     0    1   1   0   0   0   0   0         0x60
  27. //b     0    0   1   0   0   1   0   1         0x25
  28. //C     0    0   1   1   1   0   0   1          0x39
  29. //d     0    0   1   0   0   1   1   0          0x26
  30. //E     0    0   1   1   0   0   0   1         0x31
  31. //F     0    1   1   1   0   0   0   1         0x71
  32. //H     1    1   1   1   1   1   1   1         0xff

  33. //顯示位接線                P15  P14  P13  P16  P12
  34. //            (高位)1    2    3    4          5(低位)

  35. //P32(INT0)接時(shí)鐘線,P33(INT1)接數(shù)據(jù)線*/

  36. #include "STC15F2K60S2.H "                   // 包含STC15F2K60S2單片機(jī)寄存器定義文件
  37. #include "UART.H"            
  38. #include <intrins.h>
  39. #include "mcp3421.H"
  40. #include "myfun.h"
  41. #include "PowerDown_save.H"
  42. #define         Hidden         16
  43. #define     Address  0                // 本機(jī)地址,不同顯示模塊修改此數(shù)值即可
  44. #define TimeOver 500             // 定義一個(gè)超時(shí)值(5字節(jié)通信),500*2ms=1S,允許最慢2秒傳送完一幀數(shù)據(jù)

  45. sbit         CLK=P3^2;                // 外部輸入的時(shí)鐘端
  46. sbit         DAT=P3^3;                    // 外部輸入的數(shù)據(jù)端

  47. unsigned char code DispCode[]={0x28,0xee,0x32,0xa2,0xe4,0xa1,0x21,0xea,0x20,0xa0,0x60,0x25,0x39,0x26,0x31,0x71,0xff};/*/顯示代碼*/
  48. unsigned char code DispBit[]={0xdf,0xef,0xf7,0xbf,0xfb};         //位碼表 (左邊最高位)11011111(P1)  11101111(P1)  11110111(P1)  10111111(P1) 11111011(P1)(右邊最低位)
  49. unsigned long        DispData=0;                            // 用來顯示的值
  50. unsigned char   DispBuf[5]={0,0,0,0,0};        // 顯示緩沖區(qū) DispBuf[0]是左邊最高位 DispBuf[4]是右邊最低位
  51. unsigned char temp0,temp1,temp2,temp3,temp4;    // 最高位 temp0        ,最低位 temp4,5位最大顯示99 999,只接收3字節(jié),顯示緩沖5字節(jié)。   

  52. unsigned char   RecDatCount;                // 接收的數(shù)據(jù)位數(shù)計(jì)數(shù)器
  53. unsigned char        bdata         RecDat;                // 接收到的數(shù)據(jù)
  54. sbit        RecDat0=RecDat^0;                // 定義接收數(shù)據(jù)的末位為RecDat0,這要求RecDat位于bdata空間中       
  55. bit                ReciveOK ;                                // 接收完成標(biāo)志,為1,說明已接收到完整的5個(gè)字節(jié),可進(jìn)行數(shù)據(jù)處理了
  56. unsigned char        DotCnt=1;                        // 顯示小數(shù)位數(shù)。
  57. unsigned char   InAddress=0;                // 外部輸入地址,確定是否與本機(jī)地址相同
  58. bit                StartOverCount;                        // 一旦有接收中斷,則置位該位,如果收到40位,則清該位
  59. unsigned int           OverCount;                        // 超時(shí)計(jì)數(shù)器,當(dāng)有接收中斷發(fā)生,就讓這個(gè)計(jì)數(shù)器開始計(jì)數(shù)(每個(gè)T0中
  60. // 斷計(jì)數(shù)一次,如果這個(gè)計(jì)數(shù)器計(jì)到了500(即1秒)仍沒有被清除,說明接收有誤,由主程序清 RecDatCount       

  61. extern struct POWER_UP Power_up;                 // 計(jì)數(shù)器變量

  62. // 中斷程序用于完成5字節(jié)數(shù)據(jù)接收(1字節(jié)地址、3字節(jié)長整數(shù)、1字節(jié)小數(shù)位數(shù)說明)
  63. void ReciveDate() interrupt 0        // 外部中斷0(int0)中斷處理程序
  64. {       
  65.         if(StartOverCount==0)  StartOverCount=1;        // 開啟溢出計(jì)時(shí)器
  66.         RecDatCount++;                        // 中斷次數(shù)(0-40)

  67.         RecDat=RecDat<<1;                    // 主機(jī)是先發(fā)送高位,后發(fā)送低位
  68.         if(DAT)
  69.                 RecDat0=1;
  70.         else       
  71.                 RecDat0=0;
  72.         if(RecDatCount==8)                    // 接收完第一個(gè)字節(jié)
  73.         {
  74.                 InAddress=RecDat;                // 保存外部輸入的地址
  75.         }
  76.         else if(RecDatCount==16)        // 第2個(gè)數(shù)據(jù),長整數(shù)最高字節(jié)
  77.         {       
  78.                 if(InAddress==Address)             // 地址相符才處理數(shù)據(jù),方便多模塊并聯(lián)使用
  79.                         DispData=RecDat*65536;                
  80.         }
  81.         else if(RecDatCount==24)        //  第3個(gè)數(shù)據(jù),長整數(shù)中間字節(jié)
  82.         {       
  83.                 if(InAddress==Address)        // 地址相符才處理數(shù)據(jù),方便多模塊并聯(lián)使用
  84.                         DispData=DispData+RecDat*256;
  85.         }        
  86.         else if(RecDatCount==32)        //  第4個(gè)數(shù)據(jù),長整數(shù)最低字節(jié)
  87.         {       
  88.                 if(InAddress==Address)        // 地址相符才處理數(shù)據(jù),方便多模塊并聯(lián)使用
  89.                         DispData+=RecDat;
  90.         }
  91.         else if(RecDatCount==40)         // 否則就是第5個(gè)數(shù)據(jù),即小數(shù)點(diǎn)顯示位數(shù)
  92.         {       
  93.                 if(InAddress==Address)        // 地址相符才處理數(shù)據(jù),方便多模塊并聯(lián)使用
  94.                         DotCnt=RecDat;       
  95.                 ReciveOK=1;                                // 要求刷新顯示器
  96.                 RecDatCount=0;                        // 中斷次數(shù)(0-40)
  97.                 StartOverCount=0;                // 接收到40個(gè)字符,清標(biāo)志
  98.                 OverCount=0;                        // 清超時(shí)計(jì)數(shù)器
  99.                 RecDat=0;
  100.         }
  101. }

  102. void EX0_Init()     // 外中斷0用于數(shù)據(jù)接收 CLK 輸入端口
  103. {
  104.         IT0=1;                        // 外部引腳下降沿觸發(fā)(CLK時(shí)鐘信號(hào))
  105.         EX0=1;                        // 外中斷int0中斷允許
  106.         PX0=1;                        // 將外中斷置為高級(jí)中斷,定時(shí)器T0低級(jí)中斷
  107.         EA=1;                        // 比較器斷0電存儲(chǔ)只能使用低級(jí)中斷,無法更改。
  108. }

  109. void EX1_Init()     // 外中斷1用于數(shù)據(jù)接收 DAT 輸入端口與計(jì)數(shù)器脈沖輸入口
  110. {
  111.         IT1=1;                // 設(shè)置為下降沿觸發(fā),用于計(jì)數(shù)器脈沖輸入
  112.         EX1=1;          // 開外部中斷1
  113.         PX1=1;                        // 將外中斷1置為高級(jí)中斷,定時(shí)器T0低級(jí)中斷
  114.         EA=1;                    // 開總中斷
  115. }

  116. void Timer0_Init()       // 初始化定時(shí)器0用于動(dòng)態(tài)顯示程序
  117. {
  118.         TMOD &= 0xF0;                       // 設(shè)置定時(shí)器模式
  119.         TMOD |= 0x01;                       // 設(shè)置定時(shí)器模式                                                     
  120.         TH0=(65536-4000)/256 ;           // 計(jì)數(shù)脈沖周期 T=1/F= 1/(22.1184/12)= 0.5425uS
  121.         TL0=(65536-4000)%256 ;           // 4000*0.5425=2.17mS
  122.         TR0=1;                                   // T0開始運(yùn)行
  123.         ET0=1;                                   // 定時(shí)器T0中斷允許
  124.     PT0=0;                                   // 將定時(shí)器置為低級(jí)中斷
  125.         EA=1;
  126. }  

  127. // 定時(shí)器 T0 用于完成5位數(shù)碼管論流點(diǎn)亮
  128. void Timer0() interrupt 1        // 定時(shí)器T0的中斷處理代碼
  129. {
  130.         unsigned char temp;                         // 動(dòng)態(tài)顯示中間變量
  131.         static unsigned char Count;                // 用于統(tǒng)計(jì)當(dāng)前正顯示哪一位(先顯示左邊最高位)
  132.         //********* 數(shù)據(jù)接收過程的時(shí)間限制 ************
  133.         if(StartOverCount)                        // 如果要求計(jì)數(shù)的標(biāo)志是1
  134.                 OverCount++;                        // 計(jì)數(shù)器加1
  135.         //********* 正式動(dòng)態(tài)顯示程序 ******************
  136.         P1|=0x7c;                                // 關(guān)斷前次顯示0111 1100       
  137.         temp=DispBit[Count];         
  138.     P1&=temp;                   // 開啟P1位控制
  139.                        
  140.         temp=DispBuf[Count];    // 5位顯示緩沖器BCD碼               
  141.         P0=DispCode[temp];            // 查字形碼表格(0-16)
  142.        
  143.         if(Count<4)                        // 顯示小數(shù)點(diǎn)(最右端小數(shù)點(diǎn)不顯示)
  144.         {
  145.                 if(DotCnt==(4-Count))
  146.                 {
  147.                         P0&=0xDF;            // 點(diǎn)亮小數(shù)點(diǎn)h位置 1101 1111
  148.                 }       
  149.         }
  150.         Count++;
  151.         if(Count==5) Count=0;
  152.         TH0=(65536-4000)/256 ;          // 計(jì)數(shù)脈沖周期 T=1/F= 1/(22.1184/12)= 0.5425uS
  153.         TL0=(65536-4000)%256 ;    // 4000*0.5425=2.17mS
  154. }

  155. void long_to_bcd(unsigned long temp)
  156. {
  157.         unsigned char temp0,temp1,temp2,temp3,temp4;    // 最高位 temp0        ,最低位 temp4,5位最大顯示99 999,只接收3字節(jié),顯示緩沖5字節(jié)。
  158.        
  159.         temp%=100000;                // 如果收到的數(shù)超過10 0000則僅取小于10 0000的值
  160.         temp4 = temp % 10;                // 獲得個(gè)位
  161.         temp3 = temp / 10 % 10;           // 獲得十位
  162.         temp2 = temp / 100 % 10;          // 獲得百位
  163.         temp1 = temp / 1000 % 10;         // 獲得千位
  164.         temp0 = temp / 10000 % 10;        // 獲得萬位                       

  165.         if((temp0==0)&&(DotCnt<4))        // 如果最高位等于0,而顯示的小數(shù)位數(shù)小于4位
  166.                 DispBuf[0]=Hidden;                // 那么最高位應(yīng)該消隱
  167.         else
  168.                 DispBuf[0]=temp0;                // 否則將這個(gè)數(shù)送入最高位

  169.         if((temp0==0)&&(temp1==0)&&(DotCnt<3))        // 最高位、次高位同時(shí)為0,且小數(shù)位數(shù)小于3位
  170.                 DispBuf[1]=Hidden;
  171.         else
  172.                 DispBuf[1]=temp1;

  173.         if((temp0==0)&&(temp1==0)&&(temp2==0)&&(DotCnt<2))       
  174.                                 // 最高位、次高位、第三位均為0,且小數(shù)位數(shù)小于2位時(shí)消隱
  175.                 DispBuf[2]=Hidden;
  176.         else
  177.                 DispBuf[2]=temp2;
  178.                                        
  179.         if((temp0==0)&&(temp1==0)&&(temp2==0)&&(temp3==0)&&(DotCnt<1))       
  180.                                 // 最高位、次高位、第三位、第四位均為0,且小數(shù)位數(shù)小于1位(無)時(shí)消隱
  181.                 DispBuf[3]=Hidden;
  182.         else
  183.                 DispBuf[3]=temp3;

  184.         DispBuf[4]=temp4;                      // 最低位直接顯示                       
  185. }

  186. void main(void)
  187. {   
  188.         //////////////////////// 電壓電流表變量 ///////////////////
  189.         unsigned char        test_data[3]={0x00,0x00,0x00};           // 存放 MCP3421 AD轉(zhuǎn)換結(jié)果
  190.         long aa;                                   // 計(jì)算 MCP3421電壓值的中間變量
  191.         float VIN3421;                           // 計(jì)算出來的MCP3421原始電壓
  192.         long  V3421;               // 顯示時(shí)用于將數(shù)據(jù)擴(kuò)大1000或10000倍                  
  193.         ///////////////////////////////////////////////////////////
  194.         UART_init();                           // 串口初始化(占用定時(shí)器1)9600/22.1184MHz
  195.         printf("串口初始化完畢");
  196.         Timer0_Init();                           // 初始化定時(shí)器0用于動(dòng)態(tài)顯示程序
  197.        
  198.         ReciveOK=1;                           // 要求刷新顯示器
  199.         CLK=1;                                       // 數(shù)據(jù)接收端口初始化
  200.         DAT=1;

  201.         DispData=0X00;                       // 上電顯示0.0000
  202.         DotCnt=4;                  // 上電顯示0.0000

  203.         /*************************************************************************
  204.         // 2A電流表,電流取樣電阻:0.1Ω/0.5W,
  205.         *************************************************************************/
  206.         if ((P42==0)&&(P43==0))                // 電流表
  207.         {        
  208.                 DotCnt=4;                                // 2V檔,保留4位小數(shù),2.0480A        
  209.                 WrToMCP3421(SlaveADDR, 0x9C);           // 1001 1100           18位分辨率
  210.                 delay300ms();        
  211.                 while(1)
  212.                 {
  213.                         aa=test_data[0]<<8;
  214.                         aa=aa+test_data[1];
  215.                         aa=aa<<8;
  216.                         aa=aa+        test_data[2];
  217.                         VIN3421=2.048*aa/131071;                // 得到取樣電阻上的電壓值
  218.                
  219.                         VIN3421=VIN3421/0.1;                  // I=U/R
  220.                         VIN3421=VIN3421-0.000;                    // 要求零輸入零輸出
  221.                         if  (VIN3421<0 ) VIN3421=0;                // 數(shù)碼管沒編寫顯示負(fù)數(shù)的功能,電腦能直接顯示負(fù)數(shù)
  222.                
  223.                         printf("I= :%.5f     ",VIN3421);
  224.                         // 浮點(diǎn)數(shù)轉(zhuǎn)長整數(shù)
  225.                         V3421=VIN3421*10000;                 // 2V檔,保留4位小數(shù)        ,2.0480
  226.                         long_to_bcd(V3421);                                                  
  227.                
  228.                         delay300ms();                            //  延時(shí)避免硬接頻繁操作
  229.                         delay300ms();
  230.                 }
  231.         }
  232.         /*************************************************************************
  233.         //  計(jì)數(shù)器,        DAT為計(jì)數(shù)脈沖輸入端,上電瞬間如果CLK=0則清除計(jì)數(shù)值
  234.         *************************************************************************/
  235.         if ((P42==0)&&(P43==1))                  
  236.         {               
  237.                 DotCnt=0;                         // 計(jì)數(shù)器不顯示小數(shù)
  238.                 ReadFLASH();                                  // 讀取單片機(jī)內(nèi)部FLASH中保存的重要數(shù)據(jù),只需2個(gè)時(shí)鐘。
  239.                 comparator_init();                        // 比較器掉電中斷初始化
  240.                 EraseFLASH();                      // 扇區(qū)擦除需要21mS
  241.                 EX1_Init();                 // 外部計(jì)數(shù)端口初始化
  242.                 while(1);                 
  243.         }
  244.         /*************************************************************************
  245.         // 5位通用顯示器
  246.         *************************************************************************/
  247.         if ((P42==1)&&(P43==0))                         
  248.         {                         
  249.                 DotCnt =4;              // 上電時(shí)顯示0.0000  
  250.                 EX0_Init();                            // 外中斷0用于數(shù)據(jù)接收時(shí)鐘輸入端口  
  251.                 while(1)
  252.                 {
  253.                         if(ReciveOK)                // 如果收到了40位數(shù)據(jù),將數(shù)值轉(zhuǎn)BCD碼放入顯示緩沖器。
  254.                         {
  255.                                 long_to_bcd(DispData);                               
  256.                                 ReciveOK=0;       
  257.                         }
  258.                         if(OverCount>=TimeOver)                    // 出現(xiàn)了超時(shí)錯(cuò)誤
  259.                         {
  260.                                 RecDatCount=0;                            // 將接收計(jì)數(shù)器清零
  261.                                 StartOverCount=0;                    // 接收到40個(gè)字符,清除計(jì)數(shù)標(biāo)志
  262.                                 OverCount=0;                            // 清超時(shí)計(jì)數(shù)器
  263.                         }
  264.                 }
  265.         }

  266.         /*************************************************************************
  267.         // 18位分辨率電壓表
  268.         *************************************************************************/
  269.         if ((P42==1)&&(P43==1))       
  270.         {
  271.                 if ((P36==0)&&(P37==0))    DotCnt=4;            // 2V檔,保留4位小數(shù)        ,2.0480
  272.                 if ((P36==0)&&(P37==1))    DotCnt=3;            // 20V檔,保留3位小數(shù), 20.048
  273.                 if ((P36==1)&&(P37==0))    DotCnt=2;            // 200V檔,保留2位小數(shù), 200.48
  274.                 if ((P36==1)&&(P37==1))    DotCnt=2;            // 1000V檔,保留2位小數(shù), 999.99
  275.                
  276.                 WrToMCP3421(SlaveADDR, 0x9C);           // 1001 1100           18位分辨率
  277.                 delay300ms();
  278.        
  279.                 while(1)
  280.                 {
  281.                         RdFromMCP3421(SlaveADDR, test_data,3);  //連續(xù)讀取3個(gè)字節(jié)數(shù)據(jù)
  282.                         aa=test_data[0]<<8;
  283.                         aa=aa+test_data[1];
  284.                         aa=aa<<8;
  285.                         aa=aa+        test_data[2];
  286.                         VIN3421=2.048*aa/131071;
  287.                         if ((P36==0)&&(P37==0))                   // 2V檔
  288.                         {
  289.                                 VIN3421=VIN3421*1.00;                // 2V檔,無衰減,精密校準(zhǔn)
  290.                                 printf("2V :%.5f     ",VIN3421);
  291.                                 V3421=VIN3421*10000;               // 2V檔,保留4位小數(shù)        ,2.0480
  292.                         }
  293.                         if ((P36==0)&&(P37==1))                   // 20V檔
  294.                         {
  295.                                 VIN3421=VIN3421*10.00;                // 20V檔,10倍衰減+衰減電阻誤差補(bǔ)償
  296.                                 printf("20V :%.4f     ",VIN3421);
  297.                                 V3421=VIN3421*1000;               // 20V檔,保留3位小數(shù)        ,20.480
  298.                         }
  299.                         if ((P36==1)&&(P37==0))                   // 200V檔
  300.                         {
  301.                                 VIN3421=VIN3421*100.00;                // 200V檔,100倍衰減+衰減電阻誤差補(bǔ)償
  302.                                 printf("200V :%.3f     ",VIN3421);
  303.                                 V3421=VIN3421*100;                   // 200V檔,保留2位小數(shù),204.80
  304.                         }
  305.                         if ((P36==1)&&(P37==1))                   // 1000V檔
  306.                         {
  307.                                 VIN3421=VIN3421*1.00;                // 2V檔,無衰減,精密校準(zhǔn)
  308.                                 printf("2V :%.5f     ",VIN3421);
  309.                                 V3421=VIN3421*10000;               // 2V檔,保留4位小數(shù)        ,2.0480
  310.                         }
  311.                
  312.                         VIN3421=VIN3421*10.00;          // 20V檔,10倍衰減+衰減電阻誤差補(bǔ)償
  313.                                                 //
  314.                         VIN3421=VIN3421-0.000;                // 要求零輸入零輸出
  315.                         if  (VIN3421<0 ) VIN3421=0;                // 數(shù)碼管沒編寫顯示負(fù)數(shù)的功能,電腦能直接顯示負(fù)數(shù)
  316.                
  317.                         printf("20V :%.5f     ",VIN3421);
  318.                         // 浮點(diǎn)數(shù)轉(zhuǎn)長整數(shù)
  319.                         if ((P36==0)&&(P37==0))   V3421=VIN3421*10000;            // 2V檔,保留4位小數(shù)        ,2.0480
  320.                         if ((P36==0)&&(P37==1))   V3421=VIN3421*1000;             // 20V檔,保留3位小數(shù), 20.048
  321.                         if ((P36==1)&&(P37==0))   V3421=VIN3421*100;            // 200V檔,保留2位小數(shù), 200.48
  322.                         if ((P36==1)&&(P37==1))   V3421=VIN3421*100;            // 1000V檔,保留2位小數(shù), 999.99

  323.                         long_to_bcd(V3421);                                                  
  324.                
  325.                         delay300ms();                   //  延時(shí)避免硬接頻繁操作
  326.                         delay300ms();
  327.                 }               
  328.         }                
  329. }

  330. void X1_ISR(void) interrupt 2           // 外部中斷1中斷函數(shù)實(shí)現(xiàn)計(jì)數(shù)功能
  331. {
  332.     Power_up.times++;
  333.         long_to_bcd(Power_up.times);
  334. }  
復(fù)制代碼


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏24 分享淘帖 頂2 踩

相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:140358 發(fā)表于 2016-10-4 07:19 來自觸屏版 | 只看該作者
很好!很實(shí)用的
回復(fù)

使用道具 舉報(bào)

板凳
ID:84250 發(fā)表于 2016-12-30 16:56 | 只看該作者
樓主編程風(fēng)格嚴(yán)謹(jǐn),值得我們學(xué)習(xí),贊
回復(fù)

使用道具 舉報(bào)

地板
ID:200118 發(fā)表于 2017-5-24 23:22 | 只看該作者
下載學(xué)習(xí)
回復(fù)

使用道具 舉報(bào)

5#
ID:216902 發(fā)表于 2017-7-3 20:22 | 只看該作者
學(xué)習(xí) MCP3421 ADC
回復(fù)

使用道具 舉報(bào)

6#
ID:421232 發(fā)表于 2018-12-12 19:42 | 只看該作者
謝謝分享
回復(fù)

使用道具 舉報(bào)

7#
ID:288930 發(fā)表于 2019-1-18 13:57 | 只看該作者
謝謝分享!
回復(fù)

使用道具 舉報(bào)

8#
ID:384252 發(fā)表于 2019-4-30 12:00 | 只看該作者
沒有用過18位的ADC,不知道這么高精度的ADC讀出來的值是否會(huì)穩(wěn)定呢?另外,使用18位ADC采樣的電壓值,在數(shù)碼管上顯示會(huì)跳動(dòng)嗎?
回復(fù)

使用道具 舉報(bào)

9#
ID:717268 發(fā)表于 2020-3-27 23:38 | 只看該作者
本人覺得此處使用18位的ADC時(shí),輸出顯示位數(shù)可以擴(kuò)充到十萬為甚至百萬位。
回復(fù)

使用道具 舉報(bào)

10#
ID:800180 發(fā)表于 2020-7-14 09:02 | 只看該作者
STC15F2K60S2芯片引腳功能有沒有
回復(fù)

使用道具 舉報(bào)

11#
ID:501595 發(fā)表于 2020-7-26 08:53 來自觸屏版 | 只看該作者
正好需要,下載下來做一個(gè)看看
回復(fù)

使用道具 舉報(bào)

12#
ID:895892 發(fā)表于 2021-3-24 20:19 | 只看該作者
好教材值得收藏
回復(fù)

使用道具 舉報(bào)

13#
ID:1007039 發(fā)表于 2022-3-8 21:32 | 只看該作者
已下載收藏,慢慢學(xué)習(xí)。
回復(fù)

使用道具 舉報(bào)

14#
ID:968906 發(fā)表于 2023-4-6 16:24 | 只看該作者
沒有用過18位的ADC,不知道這么高精度的ADC讀出來的值是否會(huì)穩(wěn)定呢?另外,使用18位ADC采樣的電壓值,在數(shù)碼管上顯示會(huì)跳動(dòng)嗎?
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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