找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3052|回复: 5
收起左侧

PADAUK应广单片机PMS132 ADC电压表制作 附源程序

[复制链接]
ID:974778 发表于 2022-2-18 14:21 | 显示全部楼层 |阅读模式
使用PADAUK 应广PMS132单片机制作的简易电压表,测量范围在0-5V。使用ADC做外电压检测并且将ADC数值显示在8位数码管的高4位,在8位数码管的低4位显示电压值。下面是仿真器仿真和代码,详细请参考附件。
制作出来的实物图如下:
51hei图片20220218141805.jpg 51hei图片20220218141815.jpg 51hei图片20220218142107.png
单片机源程序如下:
  1. #include        "extern.h"
  2. #define data_1 pb
  3. #define duan_B pa.7
  4. #define wei_A pa.6
  5. byte wei,duan,b;
  6. word Reload_T16;
  7. word        Voltage_data;
  8. word        data;
  9. word        time;
  10. word        num;
  11. dword        AD_Val_Sum;
  12. word        AD_average_Val;

  13. void        weiTable(void)
  14. {
  15.         _Pcadd
  16.         {
  17.                 ret                0xfe;//第一位         1111 1110
  18.                 ret         0xfd;//第二位         1111 1101
  19.                 ret                0xfb;//3                1111 1011
  20.                 ret         0xf7;//4                1111 0111
  21.                 ret                0xef;//5                1110 1111
  22.                 ret         0xdf;//6                1101 1111
  23.                 ret                0xbf;//7                1011 1111
  24.                 ret         0x7f;//8                 0111 1111
  25.         }
  26. }

  27. void        duanTable(void)//8位共阴极数码管 段码
  28. {        A+=1;
  29.         _Pcadd
  30.         {
  31.                
  32.                 ret                0x3f;//0                //无小数点
  33.                 ret         0x06;//1
  34.                 ret                0x5b;//2
  35.                 ret         0x4f;//3
  36.                 ret                0x66;//4
  37.                 ret         0x6d;//5
  38.                 ret                0x7d;//6
  39.                 ret         0x07;//7
  40.                 ret                0x7f;//8
  41.                 ret         0x6f;//9

  42.                 ret                0xbf;//0                //带小数点
  43.                 ret         0x86;//1
  44.                 ret                0xdb;//2
  45.                 ret         0xcf;//3
  46.                 ret                0xe6;//4
  47.                 ret         0xed;//5
  48.                 ret                0xfd;//6
  49.                 ret         0x87;//7
  50.                 ret                0xff;//8
  51.                 ret         0xef;//9

  52.                 ret         0x40;//-

  53.         }
  54. }

  55. void LedDis(void)
  56. {
  57.         data_1 = 0x00;        //去重影
  58.         duan_B = 1;
  59.         duan_B = 0;

  60.         A = wei;                //取位码
  61.         weiTable();
  62.         data_1 = A;
  63.         wei_A = 1;
  64.         wei_A = 0;

  65.         A = duan;                //取段码
  66.         duanTable();
  67.         data_1 = A;
  68.         duan_B = 1;
  69.         duan_B = 0;
  70. }

  71. void T16init(void)
  72. {
  73.         $ T16M IHRC,/16,bit15;
  74.         reload_T16 = 32768 - 1000;        //1ms
  75.         stt16 Reload_T16;
  76.         INTEN.T16 = 1;
  77.         INTRQ.T16 = 0;
  78.         
  79. }

  80. void        TM2_PWM(void)
  81. {
  82.         tm2ct = 0;                                                //计数寄存器,通过每次进中断修改该值来获得精准的时间
  83.         tm2b = 9;                                                //上限寄存器,计数值超出上限寄存器的设定值时会产生中断;
  84.         $ TM2C SYSCLK,Disable,PWM;                //时钟源选择,输出脚选择,模式选择PWM模式;
  85.         $ TM2S 8BIT,/4,/25;        
  86.                                         //计算公式为 1/{时钟源*2/[2*(TM2B+1)*预分频*分频]}
  87.                                         //                    = 1/(1M*2/(2*TM2B+1)*4*25) = 1/(1000000*2/(2*(49+1)*4*25)) = 0.005s
  88.         INTEN.TM2 = 1;
  89.         INTRQ.TM2 = 0;
  90. }


  91. void        ADC_init(void)
  92. {
  93.         //注:选择的通道需设置为输入,无上拉电阻,停用数字输入使能;
  94.         PAC.4 = 0;
  95.         PAPH.4 = 0;
  96.         PADIER = 0b1110_1001;

  97.         $ ADCC        Enable,PA4;        //启用ADC
  98.         $ ADCM        12bit,/2;
  99.         $ ADCRGC VDD;                //选择ADC输入信号的参考电压为VDD

  100.         .delay 400;                        

  101. }

  102. void        ADC_data(void)
  103. {
  104.         //开始ADC转换
  105.         AD_START = 1;                //开始ADC转换
  106.         while(!AD_DONE)                //等待ADC转换结果
  107.                 NULL;
  108.         //当AD_DONE高电位时读取ADC结果
  109.         data$0 = ADCRL;                //将ADC的值赋给data
  110.         data$1 = ADCRH;
  111.         data = data >> 4;        
  112. }

  113. DWORD        mul_t4;
  114. WORD        mul_x2;
  115. WORD        mul_y2;
  116. void        Word_Mul_Word (void)
  117. {        //        mul_t4[D]        =        mul_x2[W] * mul_y2[W]
  118.         mul_t4$3        =        0;
  119.         mul_t4$2        =        0;

  120.         BYTE        cnt;
  121.         cnt        =        16;

  122.         do
  123.         {
  124.                 mul_x2        >>=        1;
  125.                 if (CF)
  126.                 {
  127.                         mul_t4        +=        (mul_y2 << 16);
  128.                 }
  129.                 mul_t4        >>>=        1;
  130.         } while (--cnt);
  131. }

  132. DWORD        div_src4;
  133. WORD        div_val2, div_res2;
  134. void        DWord_Div_Word (void)
  135. {        //        div_src4[D] / div_val2[W]        =        div_src4[D] * div_val2[W] + div_res2[W]
  136.         BYTE        div_cnt, div_tmp;
  137.         div_cnt                =        0;
  138.         div_res2        =        0;

  139.         do
  140.         {
  141.                 div_src4        <<=                1;
  142.                 div_res2        <<<=        1;
  143.                 div_tmp                <<<=        1;
  144.                 div_cnt++;
  145.                 A        =        (div_res2 - div_val2) >> 8;

  146.                 if (div_tmp.0 || ! CF)
  147.                 {
  148.                         div_res2$1        =        A;
  149.                         div_res2$0        -=        div_val2$0;
  150.                         div_src4.0        =        1;
  151.                 }
  152.         } while (! div_cnt.5);
  153. }


  154. WORD        div_src2;
  155. BYTE        div_val, div_res;

  156. void        Word_Div_Byte (void)
  157. {        //        div_src2[W] / div_val[B]        =        div_src2[W] * div_val[B] + div_res[B]
  158.         BYTE        div_cnt, div_tmp;
  159.         div_cnt        =        0;
  160.         div_res        =        0;

  161.         do
  162.         {
  163.                 div_src2        <<=        1;
  164.                 slc                div_res;
  165.                 slc                div_tmp;
  166.                 div_cnt++;
  167.                 A        =        div_res        - div_val;

  168.                 if (div_tmp.0 || !CF)
  169.                 {
  170.                         div_res                =        A;
  171.                         div_src2.0        =        1;
  172.                 }
  173.         } while (! div_cnt.4);
  174. }


  175. BYTE        div_src3, div_val3, div_res3;
  176. void        Byte_Div_Byte (void)
  177. {        //        div_src[B] / div_val[B]        =        div_src[B] * div_val[B] + div_res[B]
  178.         BYTE        div_cnt;
  179.         div_cnt        =        0;
  180.         div_res3        =        0;
  181.         A                =        -div_val3;
  182.         div_src3        <<=        1;
  183.         do
  184.         {
  185.                 slc                div_res3;
  186.                 div_cnt++;

  187.                 div_res3        +=        A;
  188.                 if (!CF)        div_res3        -=        A;

  189.                 div_src3        <<<=        1;
  190.         } while (! div_cnt.3);
  191. }

  192. WORD        div_src_adc1;
  193. WORD        div_val_adc1, div_res_adc1;

  194. static        void        Word_adc1_Div_Word_adc1 (void)
  195. {        //        div_src2[W] / div_val2[W]        =        div_src2[W] * div_val2[W] + div_res2[W]
  196.         BYTE        div_cnt;
  197.         div_cnt                =        0;
  198.         div_res_adc1        =        0;

  199.         do
  200.         {
  201.                 div_src_adc1        <<=                1;
  202.                 div_res_adc1        <<<=        1;
  203.                 div_cnt++;
  204.                 A        =        (div_res_adc1 - div_val_adc1) >> 8;

  205.                 if (! CF)
  206.                 {
  207.                         div_res_adc1$1        =        A;
  208.                         div_res_adc1$0        -=        div_val_adc1$0;
  209.                         div_src_adc1.0        =        1;
  210.                 }
  211.         } while (! div_cnt.4);
  212. }

  213. WORD        div_src_adc2;
  214. WORD        div_val_adc2, div_res_adc2;

  215. static        void        Word_adc2_Div_Word_adc2 (void)
  216. {        //        div_src2[W] / div_val2[W]        =        div_src2[W] * div_val2[W] + div_res2[W]
  217.         BYTE        div_cnt;
  218.         div_cnt                =        0;
  219.         div_res_adc2        =        0;

  220.         do
  221.         {
  222.                 div_src_adc2        <<=                1;
  223.                 div_res_adc2        <<<=        1;
  224.                 div_cnt++;
  225.                 A        =        (div_res_adc2 - div_val_adc2) >> 8;

  226.                 if (! CF)
  227.                 {
  228.                         div_res_adc2$1        =        A;
  229.                         div_res_adc2$0        -=        div_val_adc2$0;
  230.                         div_src_adc2.0        =        1;
  231.                 }
  232.         } while (! div_cnt.4);
  233. }


  234. BYTE        div_src_adc3, div_val_adc3, div_res_adc3;

  235. void        Byte_adc3_Div_Byte_adc3 (void)
  236. {        //        div_src[B] / div_val[B]        =        div_src[B] * div_val[B] + div_res[B]
  237.         BYTE        div_cnt;
  238.         div_cnt        =        0;
  239.         div_res_adc3        =        0;
  240.         A                =        -div_val_adc3;
  241.         div_src_adc3        <<=        1;
  242.         do
  243.         {
  244.                 slc                div_res_adc3;
  245.                 div_cnt++;

  246.                 div_res_adc3        +=        A;
  247.                 if (!CF)        div_res_adc3        -=        A;

  248.                 div_src_adc3        <<<=        1;
  249.         } while (! div_cnt.3);
  250. }

  251. void data_sum(void)
  252. {
  253.         num        =        128;
  254.         AD_Val_Sum        =        0;
  255.         while(num--)
  256.         {
  257.         //        Get_AD_Val();
  258.                 AD_Val_Sum        +=        data;
  259.                 .delay        1000;        //1ms
  260.         }
  261.         AD_average_Val        =        AD_Val_Sum>>7;        //除以128
  262.         

  263. }

  264. void        ADC_calcu(void)//数据计算
  265. {

  266.         mul_x2 = AD_average_Val;
  267.         mul_y2 = 500;//参考电压的100倍
  268.         Word_Mul_Word();
  269.         div_src4 = mul_t4;
  270.         div_val2 = 0xFFF;//分辨率12为0xFFF
  271.         DWord_Div_Word();
  272.         Voltage_data = div_src4;//测得的电压是实际电压100倍
  273.         nop;
  274. }


  275. void        FPPA0 (void)
  276. {
  277.         .ADJUST_IC        SYSCLK=IHRC/16, IHRC=16MHz, VDD=5V;
  278.         ADC_init();
  279.         T16init();
  280.         TM2_PWM();
  281.         pa=0b1110_1001;
  282.         pac=0b1110_1001;
  283.         pb=0xff;
  284.     pbc=0xff;
  285.         ENGINT;

  286.         b=0;
  287.         time=0;
  288.         div_res3=0;
  289.         div_src3=0;
  290.         div_src2=0;
  291.         div_res_adc3=0;
  292.         div_src_adc3=0;
  293.         div_src_adc2=0;
  294.         div_src_adc1=0;
  295.         AD_average_Val=0;
  296.         data=0;
  297.         duan=0;
  298.         wei=0;



  299.         while (1)
  300.         {        
  301.                 data_sum();
  302.                 ADC_calcu();
  303.         }
  304. }


  305. void        Interrupt (void)
  306. {
  307.         pushaf;

  308.         if (Intrq.T16)
  309.         {        
  310.                 stt16 Reload_T16;

  311.                 b++;
  312.                 if(b>8)
  313.                 {b=0;}

  314.                 LedDis();

  315.                 //逐位扫描显示
  316.                 switch(b)
  317.        {                  
  318.           case 0:         
  319.                                 duan=div_res3;                                        //电压小数第二位
  320.                                 wei=8;
  321.                         break;   
  322.           case 1:
  323.                                 duan=div_src3;                                        //电压小数第一位
  324.                                 wei=7;
  325.                         break;
  326.           case 2:
  327.                                 duan=div_src2+10;                                //电压个数位
  328.                                 wei=6;
  329.                         break;
  330.           case 3:
  331.                                 duan=20;                                                //-
  332.                                 wei=5;
  333.                         break;
  334.           case 4:
  335.                                 duan=div_res_adc3;                        //adc个位
  336.                                 wei=4;
  337.                         break;
  338.           case 5:
  339.                                 duan=div_src_adc3;                        //adc十位
  340.                                 wei=3;
  341.                         break;
  342.           case 6:
  343.                                 duan=div_src_adc2;                        //adc百位
  344.                                 wei=2;
  345.                         break;
  346.           case 7:
  347.                                 duan=div_src_adc1;                        //adc千位
  348.                                 wei=1;
  349.                         break;
  350.           default:break;     
  351.          }        
  352.         
  353.                 Intrq.T16        =        0;
  354.                 //...
  355.         }

  356.         if(Intrq.TM2)
  357.         {
  358.                 tm2ct = 0;                                //定周期模式,可以省略

  359.                 ADC_data();
  360.                
  361.                 time++;
  362.                 if(time>300)
  363.                 {
  364.                         time=0;
  365.                         
  366.                         //取ADC值
  367.                         div_src_adc1=AD_average_Val;
  368.                         div_val_adc1=1000;
  369.                         Word_adc1_Div_Word_adc1 ();
  370.                         div_src_adc2=div_res_adc1;
  371.                         div_val_adc2=100;
  372.                         Word_adc2_Div_Word_adc2 ();
  373.                         div_src_adc3=div_res_adc2;
  374.                         div_val_adc3=10;
  375.                         Byte_adc3_Div_Byte_adc3 ();

  376.                         //取电压值
  377.                         div_src2=Voltage_data;        //取百位
  378.                         div_val=100;
  379.                         Word_Div_Byte ();
  380.                         div_src3=div_res;                //用取百位后的余数取个位,十位
  381.                         div_val3=10;
  382.                         Byte_Div_Byte ();
  383.                 }
  384.                
  385.                
  386.                 Intrq.TM2        =        0;
  387.         }

  388.         popaf;
  389. }
复制代码
51hei.png
代码下载: PMS132电压表.rar (18.42 KB, 下载次数: 97)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:262 发表于 2022-2-23 02:08 | 显示全部楼层
用的芯片自带ADC吗?
回复

使用道具 举报

ID:974778 发表于 2022-3-26 15:18 | 显示全部楼层
heicad 发表于 2022-2-23 02:08
用的芯片自带ADC吗?

是的,自带12通道的12位ADC
回复

使用道具 举报

ID:915590 发表于 2022-8-3 18:03 | 显示全部楼层
有原理图吗?
回复

使用道具 举报

ID:323213 发表于 2023-11-13 22:23 | 显示全部楼层
楼主 学习学习可以改用5管脚188;2353数码管吗?
回复

使用道具 举报

ID:1102110 发表于 2023-12-2 10:11 | 显示全部楼层
electmo 发表于 2023-11-13 22:23
楼主 学习学习可以改用5管脚188;2353数码管吗?

可以用188数码管,csdn有相关的资料你可以搜一下
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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