zmllzw 发表于 2021-12-1 14:58:48

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

#ifndef __SEG_H

#define __SEG_H

void Seg_Tran(unsigned char *pucSeg_Buf,
        unsigned char *pucSeg_Code) ;

void Seg_Disp(unsigned char *pucSeg_Code,
        unsigned char ucSeg_Pos) ;

#endif
sfr P4= 0xC0;
sbit DAT = P4^0;
sbit OE = P4^1;
sbit LCK = P4^2;
sbit SCK = P4^3;
//代码转换: pucSeg_Buf- 显示字符串,pucSeg_ Code-显示字形码
void Seg_Tran(unsigned char *pucSeg_Buf,
        unsigned char *pucSeg_Code)
{
        unsigned char i, j=0, ucSeg_Code;
        for(i=0; i<4; i++, j++)
        {
                switch(pucSeg_Buf)

                {//低电平点亮段,段码对应码顺序为
                        case '0': ucSeg_Code =0xc0; break;                //11000000
               
                        case '1': ucSeg_Code =0xf9; break;   //11111001
                       
                        case '2': ucSeg_Code =0xa4; break;                //10100100
                       
                        case '3': ucSeg_Code = 0xb0; break;        //10110000
                       
                        case '4': ucSeg_Code = 0x99; break;                //10011001
                       
                        case '5': ucSeg_Code = 0x92; break;                //10010010

                        case '6': ucSeg_Code = 0x82; break;        //10000010
                       
                        case '7': ucSeg_Code = 0xf8; break;        //11111000
                       
                        case '8': ucSeg_Code = 0x80; break;                //10000000
                       
                        case '9': ucSeg_Code = 0x90; break;        //10010000
                       
                        case 'A': ucSeg_Code = 0x88; break;        //10001000
                       
                        case 'B': ucSeg_Code = 0x83; break;                //10000011
                       
                        case 'C': ucSeg_Code = 0xc6; break;                //11000110
                       
                        case 'D': ucSeg_Code = 0xA1; break;        //10100001
                       
                        case 'E': ucSeg_Code = 0x86; break;                //10000110
                       
                        case 'F': ucSeg_Code = 0x8E; break;        //10001110
                       
                        case 'H': ucSeg_Code = 0x89; break;        //10001001
                       
                        case 'I': ucSeg_Code =0xC7; break;                //11000111
                       
                        case '-': ucSeg_Code = 0xbf; break;                //10111111
                       
                        default: ucSeg_Code = 0xff;                                //11111111
                }
                if(pucSeg_Buf == '.')
                {
                        ucSeg_Code &= 0x7f;
                        j++;
                }
                pucSeg_Code = ucSeg_Code;
          }
        }
        //数码管显示:pucSeg_Code-显示字形码,ucSeg_Pos-显示位置
void Seg_Disp(unsigned char *pucSeg_Code,
        unsigned char ucSeg_Pos)
{
        unsigned char i;
        unsigned int temp;


        temp = (1<<(8+ucSeg_Pos)) + pucSeg_Code;
        LCK = 0;
        for(i=0;i<12;i++)
        {
                SCK = 0;
                if(temp & 0x800)
                        DAT = 1;
                else
                        DAT = 0;
                temp<<= 1;
                SCK = 1;                                                                        //移位
        }
        LCK = 1;                                                                                //锁存
        OE = 0;
}                                                       
#include <reg51.h>
#include <STDIO.H>
#include "seg.h"
//sbit P04=P0^4;
//sbit P05=P0^5;

unsigned char ucSec = 0,ucMin =0;
unsigned char pucSeg_Buf, pucSeg_Code, ucSeg_Pos = 0;
unsigned int uims = 0, uiSeg_Dly = 0;

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

        TL1=0x18;
        TH1=0xFC;                                        //设置定时初值高8位
        TR1=1;                                        // T1开始计时
       
}
// T1 处理

void T1_Proc(void)
{

        if(!TF1)                                        //定时时间未到
          return;
        TF1 = 0;                                        //清除时间到标志
        if(++uims == 1000)                        // 1s到
        {
                uims = 0;
                if(++ucSec == 60)                // 1min到
                        ucSec =0;
        }
        if((uims&3) == 0)                        //4ma显示1位
        {
                Seg_Disp(pucSeg_Code, ucSeg_Pos);
                if (++ucSeg_Pos == 4)        //循环显示
                        ucSeg_Pos = 0;
        }
        if(++uiSeg_Dly == 500)                //500ms 到
                uiSeg_Dly = 0;
        }
        //数码管处理(500ms刷新-次)
        void Seg_Proc (void)
        {
                if(uiSeg_Dly != 0)
                        return;
                uiSeg_Dly = 1;                        //500ms 到
                sprintf(pucSeg_Buf,"%02u%02u",\
                (unsigned int)ucMin,(unsigned int)ucSec);
                Seg_Tran (pucSeg_Buf, pucSeg_Code);
}
//主函数
void main (void)
{
        T1_Init();

        while(1)
        {                                                                                  
                T1_Proc();
                Seg_Proc();
}
}

村里小黑 发表于 2021-12-1 15:19:10

两个不同的脚连接按键,分别进行判断按键连接的引脚电平是否有变化(低至高或高至低,看硬件连接),检测到变化后一般加15ms的防抖,然后再判断是否确实变化,确实变化后再分别对应相应的启停或清零功能

番杰 发表于 2021-12-3 17:27:49

直接用两个外部中断,用分别由两个按钮触发,
按钮1负责“启停”,按钮“2”负责清零。
定义2个标志位:
int start_flag; //0:停止   1:开始
int zreo_flag; //0:无效   1:清零

(1)主函数首先进行初始化部分,然后while循环,
判断start_flag和zreo_flag的状态,
根据不同状态进行不同动作。
例如:
void main(void)
{
        BSP_Init();//硬件初始化
        Interrupt_Init(); //中断初始化
        //其他的什么初始化
       
        while(1)
        {
                if(start_flag == 1)
                {
                        Start(); //启动
                        if(zreo_flag == 1)
                        {
                                Zero(); // 清零
                        }
                }
                else
                {
                        Close(); // 关闭
                }
        }

}

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

void EXTI0(void)
{
        if(start_flag == 1)
                start_flag = 0;
        else
                start_flag = 1;

        // 清除中断状态标志位 !!!!
}

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

另外,注意控制启停的按钮的中断优先级应该高于清零的
页: [1]
查看完整版本: 如何添加两个按键,一个控制启停,一个清零?