STC学习:导航按键与数字按键综合控制数码管

程序设计目标及运行效果说明
程序设计目标:利用IAP15F2K60S2芯片的ADC口对来自导航按键不同方向的电压值进行采集,并将采集后的转换结果获取高三位值,将此值作为导航按键方向判断标准。程序主要是将导航按键和数字按键综合控制数码管,区别导航按键和数字按键的区别。

程序运行效果说明:
导航按键的上键:控制数码管上数字的数值增加1;
导航按键的下键:控制数码管上数字的数值减少1;
K1键:数码管上的数字右移一位;
K2键:数码管上的数字左移一位;
K3键:按一下K1,K2键锁死,再按一下K1,K2键解锁。

程序实现相关电路及工作原理说明
本案例需要使用ADC进行导航按键的电压采集,并将采集后的转换结果送到数码管及发光二极管的显示。
1.导航按键电路及工作原理说明
在这里插入图片描述
导航按键在上图的标注为MINI_KEY5,导航按键的每一个方向被按下,都会引起实际电压的改变,从而根据这个原理,与A/D转换器配合,可以判断哪个部位被按下,获取按下后A/D转换的结果。

2.AD数据采集电路及采集步骤说明
在这里插入图片描述
ADC数据采集的步骤:
1.将ADC0~7的模拟量送到比较器中,用DAC(数/模转换器)转换的模拟量与输入的模拟量通过比较器进行比较。
2.转换结束后,将比较结果放入转换结果寄存器(ADC_RES和ADC_RESL)。
3.同时,需要将ADC_FLAG软件清零。
4.注意硬件会自动将ADC_START清零,如果需要进行下一次转换,则需要将ADC_START置位。

特别说明:

(1)数码管所显示的ADC转换结果并不是电压值,而是电压进行转换后所得的一个值。如果需要实际的电压值可以参照STC15F2K60S2数据手册的760页上面的公式进行计算得出。

(2)ADC转换结果是一个10位数据,若ADRJ=0,则ADC_RES存放高八位,ADC_RESL存放低两位。若ADRJ=1,则ADC_RESL存放低八位,ADC_RES存放高两位。本案例采用的是ADRJ=0,而且只取了高八位结果。

3.数码管与发光二极管说明
这个案例中,使用了一个技巧将发光二极管和3位数码管进行同时显示:将发光二极管作为数码管位选的第四位,从而在数码管显示的同时,发光二极管也能同时显示。

测试方法
(1)用STC ISP默认设置,打开工程中的HEX并下载

(2)下载后观察现象为:(从左至右边的数码管依次命名为Seg0~Seg7,Seg0 = L7~L5, Seg(6-7) = L4~L3)
在这里插入图片描述
用途
可以作为按键控制时钟,收音机等。

代码如下:

#include<STC15F2K60S2.H>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define cstAdcPower 0X80     /*ADC电源开关*/
#define cstAdcFlag 0X10      /*当A/D转换完成后,cstAdcFlag要软件清零*/
#define cstAdcStart 0X08     /*当A/D转换完成后,cstAdcStart会自动清零,所以要开始下一次转换,则需要置位*/
#define cstAdcSpeed90 0X60   /*ADC转换速度 90个时钟周期转换一次*/
#define cstAdcChs17 0X07     /*选择P1.7作为A/D输入*/
sbit sbtLedSel=P2^3;     /*数码管和发光二极管选择位*/
sbit sbtSel0=P2^0;
sbit sbtSel1=P2^1;
sbit sbtSel2=P2^2;
sbit sbtKey1=P3^2;
sbit sbtKey2=P3^3;
uchar ucSegSelectState;         /*段选标志*/
uchar ucDigSelectState;         /*位选标志*/
bit btKey3Flag;             /*key3键按下标志*/
//0123456789ABCDEF
uchar arrSegSelect[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
//选择哪一位数码管
uchar arrDigSelect[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
void Init()//初始化
{
    P0M1=0x00;
    P0M0=0xff;
    P2M1=0x00;
    P2M0=0xff;
    sbtLedSel=0;      //选择数码管作为输出
    P1ASF=0x80;       //P1.7作为模拟功能A/D使用
    ADC_RES=0;        //转换结果清零
    ADC_CONTR=0x8F;   //cstAdcPower=1
    CLK_DIV=0X00;     //ADRJ=0    ADC_RES存放高八位结果
    btKey3Flag=0;
    ucDigSelectState=0;
    ucSegSelectState=0;
    IT0=0;            //设置IT0上升沿触发
    IT1=0;
    EA=1;             //CPU开放中断
}
void Delay5ms()     //@11.0592MHz  延时5ms
{
    unsigned char i,j;
    i=54;
    j=199;
    do
    {
        while(--j);
    }
    while (--i);
}
void Delay100ms()       //@11.0592MHz  延时100ms
{
    unsigned char i,j,k;
    _nop_();
    _nop_();
    i=5;
    j=52;
    k=195;
    do
    {
        do
        {
            while(--k);
        }
        while(--j);
    }
    while(--i);
}
/*---------获取AD值子函数--------*/
unsigned char GetADC()
{
    uchar ucAdcRes;
    ADC_CONTR=cstAdcPower|cstAdcStart|cstAdcSpeed90|cstAdcChs17;//没有将cstAdcFlag置1,用于判断A/D是否结束
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    while(!(ADC_CONTR&cstAdcFlag)); //等待直到A/D转换结束
    ADC_CONTR&=~cstAdcFlag;           //cstAdcFlagE软件清0
    ucAdcRes=ADC_RES;                 //获取AD的值
    return ucAdcRes;
}
/*---------获取导航按键值子函数--------*/
uchar NavKeyCheck()
{
    unsigned char key;
    key=GetADC();     //获取AD的值
    if(key!=255)    //有按键按下时
    {
        Delay5ms();
        key=GetADC();
        if(key!=255)            //按键消抖 仍有按键按下
        {
            key=key&0xE0;       //获取高3位,其他位清零
            key= _cror_(key,5); //循环右移5位 获取A/D转换高三位值,减小误差
            return key;
        }
    }
    return 0x07;        //没有按键按下时返回值0x07
}
/*---------导航按键处理子函数--------*/
void NavKey_Process()
{
    uchar ucNavKeyCurrent;  //导航按键当前的状态
    uchar ucNavKeyPast;     //导航按键前一个状态
    ucNavKeyCurrent=NavKeyCheck();    //获取当前ADC值
    if(ucNavKeyCurrent!=0x07)       //导航按键是否被按下 不等于0x07表示有按下
    {
        ucNavKeyPast=ucNavKeyCurrent;
        while(ucNavKeyCurrent!=0x07)        //等待导航按键松开
            ucNavKeyCurrent=NavKeyCheck();
        switch(ucNavKeyPast)
        {
            case 0x00:                     //K3
                if(btKey3Flag==0)
                    btKey3Flag=1;
                else
                    btKey3Flag=0;
                break;
            case 0x05:                     //上键:显示的数字加1
                if(ucSegSelectState==15)
                    ucSegSelectState=0;
                else
                    ucSegSelectState++;
                break;
            case 0x02:                     //下键:显示的数字减1
                if(ucSegSelectState==0)
                    ucSegSelectState=15;
                else
                    ucSegSelectState--;
                break;
        }
    }
    Delay100ms();
}
void main()
{
    Init();
    P0=0x00;
    while(1)
    {
        NavKey_Process();         //获取按键按下情况
        P2=arrDigSelect[ucDigSelectState];           //显示位
        P0=arrSegSelect[ucSegSelectState];       //显示数字
        if(btKey3Flag==0)   //KEY3=0则K1,K2键解锁,否则K1,K2键锁死
        {
            if(sbtKey1==0)    //sbtKey1按下,显示位右移一位
            {
                Delay5ms();
                if(sbtKey1==0)
                {
                    while(!sbtKey1);
                    if(ucDigSelectState==7)
                        ucDigSelectState=0;
                    else
                        ucDigSelectState++;
                }
            }
            if(sbtKey2==0)   //sbtKey2按下,显示位左移一位
            {
                Delay5ms();
                if(sbtKey2==0)
                {
                    while(!sbtKey2);
                    if(ucDigSelectState==0)
                        ucDigSelectState=7;
                    else
                        ucDigSelectState--;
                }
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

布布要成为最负责的男人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值