鱼C论坛

 找回密码
 立即注册
查看: 973|回复: 2

如何添加两个按键,一个控制启停,一个清零?

[复制链接]
发表于 2021-12-1 14:58:48 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. #ifndef __SEG_H

  2. #define __SEG_H

  3. void Seg_Tran(unsigned char *pucSeg_Buf,
  4.         unsigned char *pucSeg_Code) ;

  5. void Seg_Disp(unsigned char *pucSeg_Code,
  6.         unsigned char ucSeg_Pos) ;

  7. #endif
复制代码
  1. sfr P4= 0xC0;
  2. sbit DAT = P4^0;
  3. sbit OE = P4^1;
  4. sbit LCK = P4^2;
  5. sbit SCK = P4^3;
  6. //代码转换: pucSeg_Buf- 显示字符串,pucSeg_ Code-显示字形码
  7. void Seg_Tran(unsigned char *pucSeg_Buf,
  8.         unsigned char *pucSeg_Code)
  9. {
  10.         unsigned char i, j=0, ucSeg_Code;
  11.         for(i=0; i<4; i++, j++)
  12.         {
  13.                 switch(pucSeg_Buf[j])

  14.                 {//低电平点亮段,段码[MS8...LSB]对应码顺序为[dp g f e d c b a]
  15.                         case '0': ucSeg_Code =0xc0; break;                //11000000
  16.                
  17.                         case '1': ucSeg_Code =0xf9; break;     //11111001
  18.                        
  19.                         case '2': ucSeg_Code =0xa4; break;                //10100100
  20.                        
  21.                         case '3': ucSeg_Code = 0xb0; break;        //10110000
  22.                        
  23.                         case '4': ucSeg_Code = 0x99; break;                //10011001
  24.                        
  25.                         case '5': ucSeg_Code = 0x92; break;                //10010010

  26.                         case '6': ucSeg_Code = 0x82; break;        //10000010
  27.                        
  28.                         case '7': ucSeg_Code = 0xf8; break;        //11111000
  29.                        
  30.                         case '8': ucSeg_Code = 0x80; break;                //10000000
  31.                        
  32.                         case '9': ucSeg_Code = 0x90; break;        //10010000
  33.                        
  34.                         case 'A': ucSeg_Code = 0x88; break;        //10001000
  35.                        
  36.                         case 'B': ucSeg_Code = 0x83; break;                //10000011
  37.                        
  38.                         case 'C': ucSeg_Code = 0xc6; break;                //11000110
  39.                        
  40.                         case 'D': ucSeg_Code = 0xA1; break;        //10100001
  41.                        
  42.                         case 'E': ucSeg_Code = 0x86; break;                //10000110
  43.                        
  44.                         case 'F': ucSeg_Code = 0x8E; break;        //10001110
  45.                        
  46.                         case 'H': ucSeg_Code = 0x89; break;        //10001001
  47.                        
  48.                         case 'I': ucSeg_Code =0xC7; break;                //11000111
  49.                        
  50.                         case '-': ucSeg_Code = 0xbf; break;                //10111111
  51.                        
  52.                         default: ucSeg_Code = 0xff;                                //11111111
  53.                 }
  54.                 if(pucSeg_Buf[j+i] == '.')
  55.                 {
  56.                         ucSeg_Code &= 0x7f;
  57.                         j++;
  58.                 }
  59.                 pucSeg_Code[i] = ucSeg_Code;
  60.           }
  61.         }
  62.         //数码管显示:pucSeg_Code-显示字形码,ucSeg_Pos-显示位置
  63. void Seg_Disp(unsigned char *pucSeg_Code,
  64.         unsigned char ucSeg_Pos)
  65. {
  66.         unsigned char i;
  67.         unsigned int temp;


  68.         temp = (1<<(8+ucSeg_Pos)) + pucSeg_Code[ucSeg_Pos];
  69.         LCK = 0;
  70.         for(i=0;i<12;i++)
  71.         {
  72.                 SCK = 0;
  73.                 if(temp & 0x800)
  74.                         DAT = 1;
  75.                 else
  76.                         DAT = 0;
  77.                 temp  <<= 1;
  78.                 SCK = 1;                                                                        //移位
  79.         }
  80.         LCK = 1;                                                                                //锁存
  81.         OE = 0;
  82. }                                                       
复制代码
  1. #include <reg51.h>
  2. #include <STDIO.H>
  3. #include "seg.h"
  4. //sbit P04=P0^4;
  5. //sbit P05=P0^5;

  6. unsigned char ucSec = 0,ucMin =0;
  7. unsigned char pucSeg_Buf[6], pucSeg_Code[4], ucSeg_Pos = 0;
  8. unsigned int uims = 0, uiSeg_Dly = 0;

  9. // T1初始化
  10. void T1_Init (void)                                // 1毫秒@12.000MHz
  11. {

  12.         TL1=0x18;
  13.         TH1=0xFC;                                        //设置定时初值高8位
  14.         TR1=1;                                        // T1开始计时
  15.        
  16. }
  17. // T1 处理

  18. void T1_Proc(void)
  19. {

  20.         if(!TF1)                                        //定时时间未到
  21.           return;
  22.         TF1 = 0;                                        //清除时间到标志
  23.         if(++uims == 1000)                        // 1s到
  24.         {
  25.                 uims = 0;
  26.                 if(++ucSec == 60)                // 1min到
  27.                         ucSec =0;
  28.         }
  29.         if((uims&3) == 0)                        //4ma显示1位
  30.         {
  31.                 Seg_Disp(pucSeg_Code, ucSeg_Pos);
  32.                 if (++ucSeg_Pos == 4)        //循环显示
  33.                         ucSeg_Pos = 0;
  34.         }
  35.         if(++uiSeg_Dly == 500)                //500ms 到
  36.                 uiSeg_Dly = 0;
  37.         }
  38.         //数码管处理(500ms刷新-次)
  39.         void Seg_Proc (void)
  40.         {
  41.                 if(uiSeg_Dly != 0)
  42.                         return;
  43.                 uiSeg_Dly = 1;                        //500ms 到
  44.                 sprintf(pucSeg_Buf,"%02u%02u",\
  45.                 (unsigned int)ucMin,(unsigned int)ucSec);
  46.                 Seg_Tran (pucSeg_Buf, pucSeg_Code);
  47. }
  48. //主函数
  49. void main (void)
  50. {
  51.         T1_Init();

  52.         while(1)
  53.         {                                                                                  
  54.                 T1_Proc();
  55.                 Seg_Proc();
  56.   }
  57. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-12-1 15:19:10 | 显示全部楼层
两个不同的脚连接按键,分别进行判断按键连接的引脚电平是否有变化(低至高或高至低,看硬件连接),检测到变化后一般加15ms的防抖,然后再判断是否确实变化,确实变化后再分别对应相应的启停或清零功能
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-12-3 17:27:49 | 显示全部楼层
直接用两个外部中断,用分别由两个按钮触发,
按钮1负责“启停”,按钮“2”负责清零。
定义2个标志位:
  1. int start_flag; //0:停止   1:开始
  2. int zreo_flag; //0:无效   1:清零
复制代码


(1)主函数首先进行初始化部分,然后while循环,
判断start_flag和zreo_flag的状态,
根据不同状态进行不同动作。
例如:
  1. void main(void)
  2. {
  3.         BSP_Init();//硬件初始化
  4.         Interrupt_Init(); //中断初始化
  5.         //其他的什么初始化
  6.        
  7.         while(1)
  8.         {
  9.                 if(start_flag == 1)
  10.                 {
  11.                         Start(); //启动
  12.                         if(zreo_flag == 1)
  13.                         {
  14.                                 Zero(); // 清零
  15.                         }
  16.                 }
  17.                 else
  18.                 {
  19.                         Close(); // 关闭
  20.                 }
  21.         }

  22. }
复制代码


(2)按下按钮1,触发外部中断0:程序进入中断,判断start_flag的状态,为0则置1,为1则清零。
例如:

  1. void EXTI0(void)
  2. {
  3.         if(start_flag == 1)
  4.                 start_flag = 0;
  5.         else
  6.                 start_flag = 1;

  7.         // 清除中断状态标志位 !!!!
  8. }
复制代码


(3)按下按钮2,触发外部中断1:程序进入中断,判断zreo_flag的状态,为0则置1,为1则清零。写法同(2)。

另外,注意控制启停的按钮的中断优先级应该高于清零的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-25 15:42

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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