找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1117|回复: 6
打印 上一主题 下一主题
收起左侧

单片机运用ADC判断不同按键,按下时数码管显示不同数字程序, 求解答

[复制链接]
跳转到指定楼层
楼主
ID:1041297 发表于 2023-2-3 10:56 来自手机 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
大伙们我下面实现的功能是:按下第一个按键,从0加到80
按下第二个按键,从80减到10
按下第三个按键,显示10
我下面的代码当按下第一个按键时,会一直加到80,但是数码管不能同时显示这两位,只能显示一位,按下第二个按键也是一样,第三个按键也是一样
请大伙给个代码例程或者给我讲讲哪些错误的地方需要改,按键是由ADC来判断的
  1. //段
  2. sbit pin_seg1 = P0^2;
  3. sbit pin_seg2 = P0^1;
  4. sbit pin_seg3 = P0^5;
  5. sbit pin_seg4 = P2^1;
  6. sbit pin_seg5 = P2^4;
  7. sbit pin_seg6 = P0^3;
  8. sbit pin_seg7 = P0^4;
  9. sbit pin_seg8 = P2^0;

  10. //位
  11. sbit pin_com1 = P1^7; //第一个数码管
  12. sbit pin_com2 = P2^7; //第二个数码管
  13. sbit pin_com3 = P2^5; //第三个数码管
  14. sbit pin_com4 = P0^0; //第四个数码管
  15. sbit pin_com5 = P1^6; //两个点
  16. unsigned int ADCValue = 0x0000;
  17. bit AdcFlag = 0;

  18.             //------------------------0,---1;-----2;----3;----4;----5;----6;----7;----8;----9;----10---11;--12;--13;---14;---15
  19. unsigned char code bcd[]={0x3f,0x30,0x5b,0x79,0x74,0x6d,0x6f,0x38,0x7f,0x7d,0x77,0x79,0x39,0x5e,0x4f,0x71};      
  20. /*****************************************************
  21. *函数名称:void Delay_50us(unsigned int n)
  22. *函数功能:延时函数
  23. *入口参数:n
  24. *出口参数:void
  25. *****************************************************/  
  26. void Delay_50us(unsigned int n)           
  27. {
  28.         unsigned char i;
  29.         while(n--)
  30.         {
  31.                 for(i=0;i<15;i++);
  32.         }
  33. }

  34. /**************************************ADC采样口选择*****************************************/
  35. #if (IC_MODEL == SC92F7323)
  36.         enum Channel {AIN0=0,AIN1,AIN2,AIN3,AIN4,AIN5,AIN6,AIN7,AIN8,AIN9,VDD4=15};
  37. #endif

  38. #if (IC_MODEL == SC92F7322)
  39.         enum Channel {AIN0=0,AIN1,AIN4=4,AIN5,AIN6,AIN7,AIN8,AIN9,VDD4=15};
  40. #endif
  41.         
  42. #if (IC_MODEL == SC92F7321)
  43.         enum Channel {AIN0=0,AIN1,AIN2,AIN3,AIN8=8,AIN9,VDD4=15};
  44. #endif
  45.         
  46. #if (IC_MODEL == SC92F7320)
  47.         enum Channel {AIN0=0,AIN1,AIN6=6,AIN7,VDD4=15};
  48. #endif
  49.         

  50. /*****************************************************
  51. *函数名称:void ADC_Init(unsigned int Channel)
  52. *函数功能:ADC初始化
  53. *入口参数:Channel
  54. *出口参数:void
  55. *****************************************************/
  56. void ADC_Init(unsigned int Channel)
  57. {
  58.         ADCCON = 0X80|Channel;                //开启ADC,ADC采样频率为2M ,选择Channel位ADC采样口
  59.         if(Channel<8)
  60.         {
  61.                 ADCCFG0 = 1<<Channel;   //设置Channel作为采样口
  62.         }
  63.         else
  64.         {
  65.                 ADCCFG1 = 1<<(Channel-8);   //设置Channel作为采样口
  66.         }
  67.         IE |= 0X40;        //开启ADC中断
  68. }

  69. /*****************************************************
  70. *函数名称:void GetAdcValue(void)
  71. *函数功能:ADC测试
  72. *入口参数:void
  73. *出口参数:void
  74. *函数作用:获取ADC的值
  75. *****************************************************/
  76. unsigned int GetAdcValue(void)
  77. {
  78.         ADC_Init(AIN6);   //设置通道6为ADC输入
  79.         ADCCON |= 0X40;   //开始ADC转换
  80.         while(!AdcFlag);        //等待 ADC转换完成;
  81.         AdcFlag = 0;
  82.         ADCValue = (ADCVH<<4)+(ADCVL>>4);
  83.         return ADCValue;
  84. }

  85. void ADC_Interrupt(void) interrupt 6
  86. {
  87.         static unsigned char TIME1 = 0;
  88.         ADCCON &= ~(0X10);  //清中断标志位
  89.         AdcFlag = 1;
  90. }



  91. /*****************************************************
  92. *函数名称:void Seg_selection2(void)
  93. *函数功能:将传进来的num值,分别赋值给各个引脚
  94. *入口参数:void
  95. *出口参数:void
  96. *****************************************************/
  97. void Seg_selection(unsigned char num)  //num是a~h
  98. {
  99.         pin_seg1 = num & 0x01;num=num>>1;   //num^0是a段
  100.         pin_seg2 = num & 0x01;num=num>>1;   //num^1是b段
  101.         pin_seg3 = num & 0x01;num=num>>1;   //num^2是c段
  102.         pin_seg4 = num & 0x01;num=num>>1;   //num^3是d段
  103.         pin_seg5 = num & 0x01;num=num>>1;   //num^4是e段
  104.         pin_seg6 = num & 0x01;num=num>>1;   //num^5是f段
  105.         pin_seg7 = num & 0x01;num=num>>1;   //num^6是g段
  106.         pin_seg8 = num & 0x01;num=num>>1;   //num^7是h段
  107. }


  108. /*****************************************************
  109. *函数名称:void Pos_selection(void)
  110. *函数功能:点亮某一位数码管
  111. *入口参数:void
  112. *出口参数:void
  113. *****************************************************/
  114. void Pos_selection(unsigned char num)   //num的1~5位分别对应数码管的1~5位
  115. {
  116.         pin_com1 = num & 0x01;num=num>>1;   //num^0是第一个数码管
  117.         pin_com2 = num & 0x01;num=num>>1;   //num^1是第二个数码管
  118.         pin_com3 = num & 0x01;num=num>>1;   //num^2是第三个数码管
  119.         pin_com4 = num & 0x01;num=num>>1;   //num^3是第四个数码管
  120.         pin_com5 = num & 0x01;num=num>>1;   //num^4是第两个点
  121. }

  122. //***********************************************************
  123. //数码管处理显示
  124. void  Display(void)               
  125. {
  126.         unsigned int Key_value;
  127.         static unsigned char Current_num = 0;
  128.         Key_value = GetAdcValue();  //获取ADC的值
  129.         if(Key_value > 2000 && Key_value < 2200)  //第一个按键
  130.         {
  131.                 Current_num++;
  132.                 if(Current_num > 0 && Current_num < 80)
  133.                 {
  134.                         Pos_selection(0x00);   //消影
  135.                         Seg_selection(bcd[Current_num%10]);  //显示Current_num的个位
  136.                         Pos_selection(0x02);   //第二位数码管
  137.                         Delay_50us(2000);
  138.                         
  139.                         Pos_selection(0x00);   //消影
  140.                         Seg_selection(bcd[Current_num/10]);   //显示Current_num的十位
  141.                         Pos_selection(0x01);   //第一位数码管
  142.                         Delay_50us(2000);
  143.                 }        
  144.                 else
  145.                 {
  146.                         Current_num = 0;
  147.                 }
  148.         }
  149.         if(Key_value > 2600 && Key_value < 3000)  //第二个按键
  150.         {
  151.                 Current_num--;
  152.                 if(Current_num > 10 && Current_num < 80)  
  153.                 {
  154.                         Pos_selection(0x00);   //消影
  155.                         Seg_selection(bcd[Current_num%10]);  
  156.                         Pos_selection(0x02);   //第二位数码管
  157.                         Delay_50us(2000);
  158.                         
  159.                         Pos_selection(0x00);   //消影
  160.                         Seg_selection(bcd[Current_num/10]);  
  161.                         Pos_selection(0x01);   //第一位数码管
  162.                         Delay_50us(2000);
  163.                 }        
  164.                 else
  165.                 {
  166.                         Current_num = 0;
  167.                 }
  168.         }
  169.         if(Key_value > 3000 && Key_value < 3500)  //第三个按键
  170.         {
  171.                 Pos_selection(0x00);   //消影
  172.                 Seg_selection(0x30);   //显示1
  173.                 Pos_selection(0x01);   //第一位数码管
  174.                 Delay_50us(2000);      //延时
  175.                
  176.                 Pos_selection(0x00);   //消影
  177.                 Seg_selection(0x3F);   //显示1
  178.                 Pos_selection(0x02);   //第一位数码管
  179.                 Delay_50us(2000);      //延时
  180.                
  181.         }
  182. }


  183. void main(void)
  184. {
  185.         IO_Init();
  186.         EA = 1;
  187.         while(1)
  188.         {
  189.                 Display();
  190.         }

  191. }


复制代码





IMG_20230203_104622.jpg (1.15 MB, 下载次数: 46)

IMG_20230203_104622.jpg

IMG_20230203_100934.jpg (907.35 KB, 下载次数: 51)

IMG_20230203_100934.jpg
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2023-2-4 14:07 | 只看该作者
代码和原理图都是错的,给你一个容易理解的不规则端口驱动数码管的代码参考。


  1. #include <reg51.H>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. #define key_S 3                                        //宏定义短按(约15ms)
  5. #define key_L key_S*40                        //宏定义长按(约600ms)
  6. #define key_I key_S*20                        //宏定义长按连+间隔(约300ms)

  7. sbit K1=P2^6;//连接按键

  8. sbit dula0=P0^2;
  9. sbit dula1=P0^1;
  10. sbit dula2=P0^5;
  11. sbit dula3=P2^1;
  12. sbit dula4=P2^4;
  13. sbit dula5=P0^3;
  14. sbit dula6=P0^4;
  15. sbit dula7=P2^0;//连接冒号

  16. sbit wela0=P0^0;
  17. sbit wela1=P2^5;
  18. sbit wela2=P2^7;
  19. sbit wela3=P1^7;


  20. uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//共阳LED段码表
  21. uchar data dis_buf[4];//显示数据缓存
  22. char shi=12,fen=30,sec=0;//时,分,秒
  23. uchar Cnt5ms;//5ms时基
  24. uchar KeySec;//键值
  25. uint num=0;//计数
  26. bit flashing=0;//闪烁标志

  27. //定时器初始化程序
  28. void Timer0Init(void)                //5毫秒@12.000MHz
  29. {
  30.         TMOD |= 0x01;                //设置定时器模式
  31.         TL0 = 0x78;                //设置定时初始值
  32.         TH0 = 0xEC;                //设置定时初始值
  33.         TF0 = 0;                //清除TF0标志
  34.         TR0 = 1;                //定时器0开始计时
  35. }

  36. void keyscan()
  37. {
  38.         static unsigned int time=0;//计数变量
  39.         if(!K1)//按键按下
  40.         {
  41.                 time++;
  42.                 if(time>=key_L)//长按
  43.                 {
  44.                         switch(KeySec)
  45.                         {
  46.                                 case 1: shi++;if(shi>23)shi=0; break;
  47.                                 case 2: fen++;if(fen>59)fen=0; break;
  48.                         }
  49.                         time=key_I;//连+间隔
  50.                         num=1000;//自复位变量赋值(5秒)
  51.                 }
  52.         }
  53.         else                                //松手
  54.         {
  55.                 if(time>key_S && time<key_I)//短按
  56.                 {
  57.                         KeySec++;
  58.                         if(KeySec>2)
  59.                         {
  60.                                 KeySec=0;
  61.                                 Cnt5ms=0;
  62.                                 sec=0;
  63.                         }
  64.                         num=1000;//自复位变量赋值(5秒)
  65.                 }
  66.                 time=0;

  67.         }
  68. }
  69. void dula(uchar i)        //写入8位段码
  70. {   
  71.         dula0=i&0x01;i>>=1;
  72.         dula1=i&0x01;i>>=1;
  73.         dula2=i&0x01;i>>=1;
  74.         dula3=i&0x01;i>>=1;
  75.         dula4=i&0x01;i>>=1;
  76.         dula5=i&0x01;i>>=1;
  77.         dula6=i&0x01;i>>=1;
  78.         dula7=i&0x01;
  79. }
  80. void wela(uchar i)        //写入4位位码
  81. {
  82.         wela0=i&0x01;i>>=1;
  83.         wela1=i&0x01;i>>=1;
  84.         wela2=i&0x01;i>>=1;
  85.         wela3=i&0x01;
  86. }

  87. void display()//数码管动态显示函数
  88. {
  89.         static uchar i=0;

  90.         switch(i)//分解数据
  91.         {
  92.                 case 0: dis_buf[0] = table[shi/10%10];break;
  93.                 case 1: dis_buf[1] = table[shi%10];   break;
  94.                 case 2: dis_buf[2] = table[fen/10%10];break;
  95.                 case 3: dis_buf[3] = table[fen%10];   break;
  96.         }

  97.         wela(0x00);//位码消隐

  98.         switch(KeySec)//送段码
  99.         {
  100.                 case 0: if(KeySec==0)dula(dis_buf[i]);break; //正常走时
  101.                 case 1: if(flashing && (i==0||i==1) && K1)dula(0xff);
  102.                                 else dula(dis_buf[i]);break;         //调整时闪烁
  103.                 case 2: if(flashing && (i==2||i==3) && K1)dula(0xff);
  104.                                 else dula(dis_buf[i]);break;         //调整分闪烁
  105.                 default: break;
  106.         }
  107.         if(!KeySec && flashing)dula7=1;//冒号闪烁               
  108.         else dula7=0;

  109.         wela(0x01<<i);//送位码
  110.         i=++i%4;    //循环计数
  111. }

  112. void Timing()
  113. {
  114.         Cnt5ms++;
  115.         if(KeySec!=0)
  116.         {
  117.                 num--;
  118.                 if(num==0)//按键停止操作5秒自动恢复正常显示
  119.                 {
  120.                         KeySec=0;
  121.                         Cnt5ms=0;
  122.                         sec=0;
  123.                 }
  124.                 if(Cnt5ms%50==0)   //0.25s 快闪调时
  125.                         flashing=~flashing;
  126.         }
  127.         else if(Cnt5ms%100==0)//0.5s  慢闪显秒
  128.                         flashing=~flashing;

  129.         if(Cnt5ms==200)//1s
  130.         {
  131.                 Cnt5ms=0;
  132.                 sec++;
  133.                 if(sec>=60)
  134.                 {
  135.                         sec=0;
  136.                         fen++;
  137.                         if(fen>=60)
  138.                         {
  139.                                 fen=0;
  140.                                 shi++;
  141.                                 if(shi>23)
  142.                                         shi=0;
  143.                         }
  144.                 }
  145.         }
  146. }

  147. void main()//主函数
  148. {
  149.         Timer0Init();//初始化定时器
  150.         while(1)
  151.         {
  152.                 if(TF0)//查询定时器中断请求位
  153.                 {
  154.                         TF0=0;
  155.                         TL0 = 0x78;                //设置定时初始值
  156.                         TH0 = 0xEC;                //设置定时初始值
  157.                         Timing();                //计时函数
  158.                         keyscan();                //按键扫描函数
  159.                         display();                //数码管显示函数
  160.                 }
  161.         }
  162. }
复制代码



回复

使用道具 举报

板凳
ID:1047633 发表于 2023-2-7 11:04 来自手机 | 只看该作者
为什么要用ADC判断按键??
回复

使用道具 举报

地板
ID:1034262 发表于 2023-2-7 15:29 | 只看该作者
用ADC做按键,要回溯过去两三个采样点的值,计算变化率,变化率小于一定值,才认为ADC值已经稳定,可以判断按键了,非常可靠的。
回复

使用道具 举报

5#
ID:883242 发表于 2023-2-7 15:56 | 只看该作者
AllA1 发表于 2023-2-7 11:04
为什么要用ADC判断按键??

节约单片机IO端口数量来降成本,小家电里面常见的设计。
回复

使用道具 举报

6#
ID:301191 发表于 2023-2-21 21:00 | 只看该作者
顶一下
回复

使用道具 举报

7#
ID:161164 发表于 2023-2-21 22:06 | 只看该作者
代码结构不太好
按键和显示混在一起
  1. //***********************************************************
  2. //数码管处理显示
  3. void  Display(void)
  4. {
  5.         unsigned int Key_value;
  6.         static unsigned char Current_num = 0;
  7.         static unsigned char Delay = 0;
  8.         static bit Swap = 0;
  9.         Key_value = GetAdcValue();  //获取ADC的值
  10.         if(Key_value > 2000 && Key_value < 2200)  //第一个按键
  11.         {
  12.                 if(++Delay >= 100)
  13.                 {
  14.                         Delay = 0;
  15.                         Current_num++;
  16.                 }
  17.                 if(Current_num > 0 && Current_num < 80)
  18.                 {
  19.                         if(Swap)
  20.                         {
  21.                                 Pos_selection(0x00);   //消影
  22.                                 Seg_selection(bcd[Current_num%10]);  //显示Current_num的个位
  23.                                 Pos_selection(0x02);   //第二位数码管
  24.                                 Delay_50us(20);
  25.                         }
  26.                         else
  27.                         {
  28.                                 Pos_selection(0x00);   //消影
  29.                                 Seg_selection(bcd[Current_num/10]);   //显示Current_num的十位
  30.                                 Pos_selection(0x01);   //第一位数码管
  31.                                 Delay_50us(20);
  32.                         }
  33.                         Swap = !Swap;
  34.                 }
  35.                 else
  36.                 {
  37.                         Current_num = 0;
  38.                 }
  39.         }
  40.         if(Key_value > 2600 && Key_value < 3000)  //第二个按键
  41.         {
  42.                 if(++Delay >= 100)
  43.                 {
  44.                         Delay = 0;
  45.                         Current_num--;
  46.                 }
  47.                 if(Current_num > 10 && Current_num < 80)
  48.                 {
  49.                         if(Swap)
  50.                         {
  51.                                 Pos_selection(0x00);   //消影
  52.                                 Seg_selection(bcd[Current_num%10]);  //显示Current_num的个位
  53.                                 Pos_selection(0x02);   //第二位数码管
  54.                                 Delay_50us(20);
  55.                         }
  56.                         else
  57.                         {
  58.                                 Pos_selection(0x00);   //消影
  59.                                 Seg_selection(bcd[Current_num/10]);   //显示Current_num的十位
  60.                                 Pos_selection(0x01);   //第一位数码管
  61.                                 Delay_50us(20);
  62.                         }
  63.                         Swap = !Swap;
  64.                 }
  65.                 else
  66.                 {
  67.                         Current_num = 0;
  68.                 }
  69.         }
  70.         if(Key_value > 3000 && Key_value < 3500)  //第三个按键
  71.         {

  72.                 if(Swap)
  73.                 {
  74.                         Pos_selection(0x00);   //消影
  75.                         Seg_selection(0x30);   //显示1
  76.                         Pos_selection(0x01);   //第一位数码管
  77.                         Delay_50us(20);      //延时
  78.                 }
  79.                 else
  80.                 {
  81.                         Pos_selection(0x00);   //消影
  82.                         Seg_selection(0x3F);   //显示1
  83.                         Pos_selection(0x02);   //第一位数码管
  84.                         Delay_50us(20);      //延时
  85.                 }
  86.                 Swap = !Swap;

  87.         }
  88. }
复制代码


回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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