您的位置 首页 IC

计数器(状态机按键检测)程序

状态机是软件编程中的重要概念,比这个概念更重要的是对它的灵活应用。在一个思路清晰而且高效的程序中,必然有状态机的身影浮现。例

状况机是软件编程中的重要概念,比这个概念更重要的是对它的灵敏运用。在一个思路清晰并且高效的程序中,必定有状况机的身影显现。例如,一个按键指令解析程序就能够被看做状况机:本来在A状况下,触发一个按键后切换到了B状况;再触发另一个键后切换到C状况,或许返回到A状况。这便是最简略的按键状况机的比如。实践的按键解析程序会比这更杂乱,但这并不影响咱们对状况机的知道。

进一步看,击键动作自身能够看做一个状况机。一个击键动作包括按下、颤动、开释等状况。其实状况机的思维不单仅仅用在按键方面,数码管显现动态扫描、LED灯亮灭都存在状况机的思维。运用状况机思维进行单片机编程,比较通用的办法便是运用switch的选择性分支句子来进行状况跳转。
经过计数器这个试验向我们展现状况机的思维。

上图是proteus仿真图,时刻每过1s计数器值主动加1,K1发动和中止计数器,K2选择要修正的位,K3当时位加1,K4当时位减1。
完好代码如下:
#include

typedef unsigned char UINT8;
typedef unsigned int UINT16;
typedef unsigned long UINT32;
typedef char INT8;
typedef int INT16;
typedef long INT32;

#define TIMER0_INITIAL_VALUE 5000 //5ms守时
#define SEG_PORT P0 //数码管占用的IO口
#define KEY_PORT P1 //按键占用的IO口
#define KEY_MASK 0x0F //按键掩码
#define KEY_SEARCH_STATUS 0 //查询按键状况
#define KEY_ACK_STATUS 1 //承认按键状况
#define KEY_REALEASE_STATUS 2 //开释按键状况
#define KEY1 1 //按键1键值
#define KEY2 2 //按键2键值
#define KEY3 3 //按键3键值
#define KEY4 4 //按键4键值

#define HIGH 1
#define LOW 0
#define ON 1
#define OFF 0

sbit DATA = P0^4;
sbit CLK = P0^5;

UINT8 Timer0IRQEvent = 0; //守时器0中止事情
UINT8 Time1SecEvent = 0; //1s守时事情
UINT8 TimeCount = 0; //守时器0计数器,用于计数发生1s守时事情
UINT8 SegCurPosMark = 0; //被选中的数码管
UINT16 CounterValue = 0; //计数器
UINT8 SegCurSel = 0; //当时选中的数码管
UINT8 SegBuf[4] = {0};
code UINT8 SegCode[10] = {~0x3F,~0x06,~0x5B,~0x4F,~0x66,~0x6D,~0x7D,~0x07,~0x7F,~0x6F};
code UINT8 SegSelTbl[4] = {0xFE,0xFD,0xFB,0xF7};
UINT8 bSetTime = 0; //标志位:是否设置计数值

void LS164_DATA(unsigned char x)
{
if(x)
{
DATA = 1;
}
else
{
DATA = 0;
}
}
void LS164_CLK(unsigned char x)
{
if(x)
{
CLK = 1;
}
else
{
CLK = 0;
}
}
/**********************************************************
*函数称号:LS164Send
*输 入:byte单个字节
*输 出:无
*功 能:74LS164发送单个字节
***********************************************************/
void LS164Send(UINT8 byte)
{
UINT8 j;
for(j=0;j<=7;j++)
{
if(byte&(1<<(7-j)))
{
LS164_DATA(HIGH);
}
else
{
LS164_DATA(LOW);
}
LS164_CLK(LOW);
LS164_CLK(HIGH);
}
}
/**********************************************************
*函数称号:SegRefreshDisplayBuf
*输 入:无
*输 出:无
*功 能:数码管改写显现缓存
***********************************************************/
void SegRefreshDisplayBuf(void)
{
SegBuf[0] = CounterValue%10;
SegBuf[1] = CounterValue/10%10;
SegBuf[2] = CounterValue/100%10;
SegBuf[3] = CounterValue/1000%10;
}
/**********************************************************
*函数称号:SegDisplay
*输 入:无
*输 出:无
*功 能:数码管显现数据
***********************************************************/
void SegDisplay(void)
{
UINT8 t;
SEG_PORT = 0x0F; //平息一切数码管

if(bSetTime) //查看是否设置计数值
{
if(SegCurSel == SegCurPosMark)
{
t = SegCode[SegBuf[SegCurSel]] & 0x7F; //加上小数点
}
else
{
t = SegCode[SegBuf[SegCurSel]]; //正常显现当时数值
}
}
else
{
t = SegCode[SegBuf[SegCurSel]]; //正常显现当时数值
}

LS164Send(t);
SEG_PORT = SegSelTbl[SegCurSel]; //点亮当时要显现的数码管
if(++SegCurSel >= 4)
{
SegCurSel = 0;
}
}

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/317468.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部