如何添加两个按键,一个控制启停,一个清零?
#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();
}
} 两个不同的脚连接按键,分别进行判断按键连接的引脚电平是否有变化(低至高或高至低,看硬件连接),检测到变化后一般加15ms的防抖,然后再判断是否确实变化,确实变化后再分别对应相应的启停或清零功能 直接用两个外部中断,用分别由两个按钮触发,
按钮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]