找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1742|回复: 0
收起左侧

51单片机ADC0832万用表仿真程序设计 可以测量电压电阻电流

[复制链接]
ID:1071027 发表于 2023-4-11 11:20 | 显示全部楼层 |阅读模式
可以随便使用
请大家多多指教 ADC0832芯片
1、本设计基于STC89C51/52(与AT89S51/52、AT89C51/52通用)。
2、支持电压,电流,电阻测量,通过数码管显示它们的数值
3、开关切换测量电压、电流、电阻。通过调节滑动变阻器来改变它们的大小。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.gif 51hei.png 51hei.png

单片机源程序如下:
  1. #include <reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
  2. #include "intrins.h"                                                                                          

  3. #define     u8                          unsigned char
  4. #define     u16                   unsigned int
  5. #define     uchar                          unsigned char
  6. #define     uint                   unsigned int




  7. //按键                 
  8. sbit Key_V=P3^0;                                 //电压模式键
  9. sbit Key_R=P1^4;                                 //电阻模式键
  10. sbit Key_I=P3^5;                                 //电流模式键

  11. sbit Speak=P3^1;                                 //电流模式键

  12. #define KEY_V                 1                //电压模式
  13. #define KEY_R                        2                //电阻模式
  14. #define KEY_I                        3                //电流模式

  15. /***********************************************************************************************************
  16. 数码管显示相关函数
  17. ***********************************************************************************************************/



  18. #define   SMG_NUM   4
  19. u8 code DisplayNum[16]={
  20. 0xc0,                //0
  21. 0x8e                //F
  22. };
  23. //
  24. u8 code DisplayOther[]={
  25. 0xff,                 //0                空
  26. 0x7f,                 //1                "."
  27. 0xbf,                        //2                "-"
  28. 0xa7                        //3                c
  29. };

  30. /********************************************************************
  31. * 名称 : delay_1ms()
  32. * 功能 : 延时1ms函数
  33. * 输入 : q
  34. * 输出 : 无
  35. ***********************************************************************/
  36. void delay_ms(uint q)
  37. {
  38.         uint i,j;
  39.         for(i=0;i<q;i++)
  40.                 for(j=0;j<110;j++);
  41. }
  42. //数码管位选定义
  43. sbit smg_we1 = P2^0;            //数码管1
  44. sbit smg_we2 = P2^1;                        //数码管2
  45. sbit smg_we3 = P2^2;                        //数码管3
  46. sbit smg_we4 = P2^3;                        //数码管4


  47. /***********************数码位选函数*****************************/
  48. //i:        0,数码管1
  49. //                1,数码管2
  50. //                2,数码管3
  51. //                3,数码管4
  52. void smg_we_switch(uchar i)
  53. {
  54.         switch(i)
  55.         {
  56.                 case 0: smg_we1 = 0;  smg_we2 = 1; smg_we3 = 1;  smg_we4 = 1; break;
  57.                 case 1: smg_we1 = 1;  smg_we2 = 0; smg_we3 = 1;  smg_we4 = 1; break;
  58.                 case 2: smg_we1 = 1;  smg_we2 = 1; smg_we3 = 0;  smg_we4 = 1; break;
  59.                 case 3: smg_we1 = 1;  smg_we2 = 1; smg_we3 = 1;  smg_we4 = 0; break;
  60.         }        
  61. }


  62. /********************************************************************
  63. * 名称 : delay_1ms()
  64. * 功能 : 延时1ms函数
  65. * 输入 : q
  66. * 输出 : 无
  67. ***********************************************************************/
  68. void delay_1ms(uint q)
  69. {
  70.         uint i,j;
  71.         for(i=0;i<q;i++)
  72.                 for(j=0;j<110;j++);
  73. }

  74. /********************************************************************
  75. * 名称 : u8 ChangeFor(u8 dat)
  76. * 功能 : 交换一个字节位的位置,用于数码管显示
  77. * 输入 : 需要改变的数
  78. * 输出 : 改变后的数
  79. ***********************************************************************/
  80. #define LED_a                0        //数码管段选的a段接在段选IO口的第0位
  81. #define LED_b                2
  82. #define LED_c                6
  83. #define LED_d                4
  84. #define LED_e                3
  85. #define LED_f                1
  86. #define LED_g                7
  87. #define LED_dp        5

  88. u8 ChangeFor(u8 dat)
  89. {
  90.         u8 temp=0;
  91.         if(dat&0x01)                //判断数据的第一位是否为1
  92.                 temp|=0x01<<LED_a;//如果为1,放到控制数码管a段的位置
  93.         if(dat&0x02)
  94.                 temp|=0x01<<LED_b;
  95.         if(dat&0x04)
  96.                 temp|=0x01<<LED_c;
  97.         if(dat&0x08)
  98.                 temp|=0x01<<LED_d;
  99.         if(dat&0x10)
  100.                 temp|=0x01<<LED_e;
  101.         if(dat&0x20)
  102.                 temp|=0x01<<LED_f;
  103.         if(dat&0x40)
  104.                 temp|=0x01<<LED_g;
  105.         if(dat&0x80)
  106.                 temp|=0x01<<LED_dp;
  107.         return temp;
  108. }
  109. uchar dis_smg[SMG_NUM];                                                //显示缓存数组

  110. /********************************************************************
  111. * 名称 : display()
  112. * 功能 : 数码管显示
  113. * 输入 : 无
  114. * 输出 : 无
  115. ***********************************************************************/
  116. void DisplayScan()
  117. {
  118.         static uchar i;
  119.         P0 = 0xff;                  //消隐
  120.                 smg_we_switch(i);                                    //位选
  121.         P0 =        ChangeFor(dis_smg[i]);                  //段选         
  122.         i++;
  123.         if(i>=SMG_NUM)
  124.                 i=0;
  125. }


  126. /***********************************************************************************************************
  127. ADC0832相关函数
  128. ***********************************************************************************************************/
  129. sbit ADCS         =P1^2; //ADC0832 片选
  130. sbit ADCLK  =P1^0; //ADC0832 时钟
  131. sbit ADDI         =P1^1; //ADC0832 数据输入                /*因为单片机的管脚是双向的,且ADC0832的数据输入输出不同时进行,
  132. sbit ADDO         =P1^1; //ADC0832 数据输出                /*为节省单片机引脚,简化电路所以输入输出连接在同一个引脚上

  133. //========================================================================
  134. // 函数: unsigned int Adc0832(unsigned char channel)
  135. // 应用:                 temp=Adc0832(0);
  136. // 描述: 读取0通道的AD值
  137. // 参数: channel:通道0和通道1选择
  138. // 返回: 选取通道的AD值
  139. // 版本: VER1.0
  140. // 日期: 2015-05-29
  141. // 备注:
  142. //========================================================================
  143. unsigned int Adc0832(unsigned char channel)
  144. {
  145.         uchar i=0;
  146.         uchar j;
  147.         uint dat=0;
  148.         uchar ndat=0;
  149.         uchar  Vot=0;

  150.         if(channel==0)channel=2;
  151.         if(channel==1)channel=3;
  152.         ADDI=1;
  153.         _nop_();
  154.         _nop_();
  155.         ADCS=0;//拉低CS端
  156.         _nop_();
  157.         _nop_();
  158.         ADCLK=1;//拉高CLK端
  159.         _nop_();
  160.         _nop_();
  161.         ADCLK=0;//拉低CLK端,形成下降沿1
  162.         _nop_();
  163.         _nop_();
  164.         ADCLK=1;//拉高CLK端
  165.         ADDI=channel&0x1;
  166.         _nop_();
  167.         _nop_();
  168.         ADCLK=0;//拉低CLK端,形成下降沿2
  169.         _nop_();
  170.         _nop_();
  171.         ADCLK=1;//拉高CLK端
  172.         ADDI=(channel>>1)&0x1;
  173.         _nop_();
  174.         _nop_();
  175.         ADCLK=0;//拉低CLK端,形成下降沿3
  176.         ADDI=1;//控制命令结束
  177.         _nop_();
  178.         _nop_();
  179.         dat=0;
  180.         for(i=0;i<8;i++)
  181.         {
  182.                 dat|=ADDO;//收数据
  183.                 ADCLK=1;
  184.                 _nop_();
  185.                 _nop_();
  186.                 ADCLK=0;//形成一次时钟脉冲
  187.                 _nop_();
  188.                 _nop_();
  189.                 dat<<=1;
  190.                 if(i==7)dat|=ADDO;
  191.         }
  192.         for(i=0;i<8;i++)
  193.         {
  194.                 j=0;
  195.                 j=j|ADDO;//收数据
  196.                 ADCLK=1;
  197.                 _nop_();
  198.                 _nop_();
  199.                 ADCLK=0;//形成一次时钟脉冲
  200.                 _nop_();
  201.                 _nop_();
  202.                 j=j<<7;
  203.                 ndat=ndat|j;
  204.                 if(i<7)ndat>>=1;
  205.         }
  206.         ADCS=1;//拉低CS端
  207.         ADCLK=0;//拉低CLK端
  208.         ADDO=1;//拉高数据端,回到初始状态
  209.         dat<<=8;
  210.         dat|=ndat;

  211.         return(dat);            //return ad data
  212. }



  213. /***********************************************************************************************************
  214. 主函数
  215. ***********************************************************************************************************/
  216. void main (void)
  217. {
  218.         u8 Mode;
  219.         uchar Read_AD;        //用于读取ADC数据
  220.         uchar VIN;                        //电压值变量
  221.         u16 RIN;                                //电阻值变量
  222.         u16 IIN;                                //电流值变量
  223.         u16 i=0;;
  224.         while (1)                                      //主循环
  225.         {               
  226.                 if(Key_V==0)                                //电压按键按下
  227.                 {
  228.                         Key_V=1;                                        //清除按下标记
  229.                         if((Key_R==0)||(Key_I==0))//电阻电流按键也有按下
  230.                         {
  231.                                 Key_I=1;
  232.                                 Key_R=1;
  233.                                 Key_V=1;
  234.                                 Mode=4;                                        //标记为错误模式
  235.                         }
  236.                         else                                                        //电阻电流键都没有按下
  237.                         Mode=1;                                                //标记为电压模式
  238.                 }
  239.                 if(Key_R==0)                                //同电压键
  240.                 {
  241.                         Key_R=1;
  242.                         if((Key_V==0)||(Key_I==0))
  243.                         {
  244.                                 Key_I=1;
  245.                                 Key_R=1;
  246.                                 Key_V=1;
  247.                                 Mode=4;
  248.                         }
  249.                         else
  250.                         Mode=2;
  251.                 }
  252.                 if(Key_I==0)                                //同电压键
  253.                 {
  254.                         Key_I=1;
  255.                         if((Key_V==0)||(Key_R==0))
  256.                         {
  257.                                 Key_I=1;
  258.                                 Key_R=1;
  259.                                 Key_V=1;
  260.                                 Mode=4;
  261.                         }
  262.                         else
  263.                         Mode=3;
  264.                 }
  265.                 if((Key_V==1)&&(Key_R==1)&&(Key_I==1))//都没有按下
  266.                 {
  267.                         Mode=0;                        //标记为空闲模式
  268.                 }
  269.                 if(i==0)
  270.                 {
  271.                 Read_AD=Adc0832(0);                                //读取AD值
  272.                 }
  273.                 i++;
  274.                 if(i>300)
  275.                         i=0;
  276.                         switch(Mode)
  277.                 {
  278.                         case 0:
  279.                                                 //空闲模式
  280.                                                                 dis_smg[0]=DisplayOther[2];//关闭数码管显示
  281.                                                                 dis_smg[1]=DisplayOther[2];
  282.                                                                 dis_smg[2]=DisplayOther[2];
  283.                                                                 dis_smg[3]=DisplayOther[2];
  284.                         break;
  285.                         case 1:
  286.                                                 //电压模式
  287.                                                                 VIN=Read_AD*200/255;                                                                                //换算出电压值
  288.                                                                 dis_smg[0]=DisplayNum[0xa];                                                        //显示电压标志
  289.                                                                 dis_smg[1]=DisplayNum[VIN/100%10];                        //电压十位
  290.                                                                 dis_smg[2]=DisplayNum[VIN/10%10]&0x7f;        //电压个位
  291.                                                                 dis_smg[3]=DisplayNum[VIN%10];                                        //电压十分位
  292.                                                                
  293.                                                                 if(VIN > 100)
  294.                                                                         Speak = 0;
  295.                                                                 else
  296.                                                                         Speak = 1;
  297.                         break;
  298.                         case 2:
  299.                                                 //电阻模式               
  300.                                                                 RIN=Read_AD*100/(255-Read_AD);                                //换算出电阻值
  301.                                                                 dis_smg[0]=DisplayNum[0xb];                       //显示电阻标志
  302.                                                                 dis_smg[1]=DisplayNum[RIN/100%10];    //电阻百位
  303.                                                                 dis_smg[2]=DisplayNum[RIN/10%10];     //电阻十位
  304.                                                                 dis_smg[3]=DisplayNum[RIN%10];        //电阻个位
  305.                                                                 if(RIN>=1000)                                                                                                        //超过或等于1000;
  306.                                                                 {
  307.                                                                         dis_smg[1]=DisplayOther[2];                                        //显示"-"
  308.                                                                         dis_smg[2]=DisplayOther[2];                                        //显示"-"
  309.                                                                         dis_smg[3]=DisplayOther[2];                                        //显示"-"
  310.                                                                 }
  311.                                                                
  312.                                                                 if(RIN > 500)
  313.                                                                         Speak = 0;
  314.                                                                 else
  315.                                                                         Speak = 1;
  316.                         break;
  317.                         case 3:
  318.                                                 //电流模式               
  319.                                                                 IIN=4*Read_AD;//单位mA                                                                //换算出电流值
  320.                                                                 dis_smg[0]=DisplayNum[0xc];           //显示电流标志
  321.                                                                 if(IIN<=200)                                                                                                        //没有超过范围
  322.                                                                 {
  323.                                                                         dis_smg[1]=DisplayNum[IIN/100%10];        //电流百位
  324.                                                                         dis_smg[2]=DisplayNum[IIN/10%10];         //电流十位
  325.                                                                         dis_smg[3]=DisplayNum[IIN%10];            //电流个位
  326.                                                                 }
  327.                                                                 else
  328.                                                                 {
  329.                                                                         dis_smg[1]=DisplayOther[2];                                        //显示"-"
  330. .....代码详见附件.....
复制代码

Keil代码与Proteus7.8与8.13仿真和文档下载:
基于51单片机数字万用表测电压电流电阻仿真设计.7z (1.02 MB, 下载次数: 81)

评分

参与人数 2黑币 +65 收起 理由
lyxxzrb + 15 赞一个!
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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