当前位置: 首页 > 资讯 > >正文

第8章-函数进阶与按键(上:跟堂作业)

来源:哔哩哔哩    时间:2023-08-26 09:46:50


【资料图】

这节太难了,2个多小时分成

由于代码量大,把跟堂作业也搬过来了

课上例子,单键中断消抖读取#include <>typedef unsigned char uchar;typedef unsigned int uint;typedef unsigned long ulong;sbit ADDR0 = P1 ^ 0;sbit ADDR1 = P1 ^ 1;sbit ADDR2 = P1 ^ 2;sbit ADDR3 = P1 ^ 3;sbit ENLED = P1 ^ 4;sbit KEY1 = P2 ^ 4;sbit KEY2 = P2 ^ 5;sbit KEY3 = P2 ^ 6;sbit KEY4 = P2 ^ 7;// 数码管codeuchar code LedChar[] ={    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E};bit KeySta=1;//中断读取按键后放到这儿void main(void){    uchar cnt = 0;    bit backup = 1;    bit keybuf = 1;    ENLED = 0;    ADDR3 = 1;    ADDR2 = 0;    ADDR1 = 0;    ADDR0 = 0;    TMOD=0x01;    TH0=0xF8;    TL0=0xCD;    ET0=EA=TR0=1;    P2 = 0xF7;    P0 = LedChar[cnt];    while (1)    {        if(KeySta != backup)        {            if(backup==0)            {                //松开                cnt++;                if(cnt>=10)                {                    cnt=0;                }                P0=LedChar[cnt];            }            else            {                //按下            }            backup=KeySta;//保存方便,下次比对        }    }}void Timer0_ISR(void)interrupt 1{    static uchar keybuf=0xFF;    TH0=0xF8;    TL0=0xCD;    keybuf=(keybuf<<1)|KEY4;//读取按键状态,累计到这个类似FIFO变量里面    if(keybuf==0)    {        //按下        KeySta=0;    }    else if(keybuf==0xFF)    {        //松开        KeySta=1;    }    else    {        //抖动    }}课上例子,矩阵按键中断消抖读取#include <>typedef unsigned char u8;typedef unsigned int  u16;typedef unsigned long u32;typedef signed char i8;typedef signed int  i16;typedef signed long i32;sbit ADDR0 = P1 ^ 0;sbit ADDR1 = P1 ^ 1;sbit ADDR2 = P1 ^ 2;sbit ADDR3 = P1 ^ 3;sbit ENLED = P1 ^ 4;//4个列,要读取sbit KEYIN1=P2^4;sbit KEYIN2=P2^5;sbit KEYIN3=P2^6;sbit KEYIN4=P2^7;//4个行,要拉低sbit KEYOUT1=P2^3;sbit KEYOUT2=P2^2;sbit KEYOUT3=P2^1;sbit KEYOUT4=P2^0;//保存中断消抖后,读取按键状态u8 KeySta[4][4]={    {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}};// 数码管codeu8 code LedChar[] ={    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E};void main(void){    //保存上一次按键的状态    u8 backup[4][4]=    {        {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}    };    u8 i,j,cnt;    ENLED = 0;    ADDR3 = 1;    ADDR2 = 0;    ADDR1 = 0;    ADDR0 = 0;    TMOD=0x01;    TH0=0xF8;    TL0=0xCD;    ET0=EA=TR0=1;    P0 = LedChar[cnt];    while (1)    {        //扫描上一次状态和现在状态,有区别吗        for(i=0; i<4; i++) //out        {            for(j=0; j<4; j++) //in            {                if(backup[i][j]!=KeySta[i][j])                {                    if(backup[i][j]==0)                    {                        //松开                        P0=LedChar[i*4+j];                    }                    else                    {                        //按下                    }                    backup[i][j]=KeySta[i][j];                }            }        }    }}void Timer0_ISR(void)interrupt 1{    static u8 keyout=0;//控制4个线拉低的    u8 i=0;        //保存按键每一次读取的值    static u8 keybuf[4][4]={        {0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF}    };    TH0=0xF8;    TL0=0xCD;    //读keyout拉低行的,4个列按键状态    keybuf[keyout][0]=(keybuf[keyout][0]<<1)|KEYIN1;//读第1列按键    keybuf[keyout][1]=(keybuf[keyout][1]<<1)|KEYIN2;//读第2列按键    keybuf[keyout][2]=(keybuf[keyout][2]<<1)|KEYIN3;//读第3列按键    keybuf[keyout][3]=(keybuf[keyout][3]<<1)|KEYIN4;//读第4列按键    //判断刚读取的4个按键,是否稳定    for(i=0; i<4; i++)    {        if((keybuf[keyout][i] & 0x0F) == 0x00)//稳定为0        {            KeySta[keyout][i]=0;        }        else if((keybuf[keyout][i] & 0x0F) == 0x0F)//稳定为1        {            KeySta[keyout][i]=1;        }        else        {            //抖动        }    }    //切换下一行拉低,方便下次读取    keyout++;    keyout&=0x03;    switch(keyout)    {    case 0:        KEYOUT4=1;        KEYOUT1=0;        break;    case 1:        KEYOUT1=1;        KEYOUT2=0;        break;    case 2:        KEYOUT2=1;        KEYOUT3=0;        break;    case 3:        KEYOUT3=1;        KEYOUT4=0;        break;    }}//分析,太费内存了把,使用了16*3约50个字节的变量课上例子,加法器,up=加;enter是等于;#include <>typedef unsigned char u8;typedef unsigned int  u16;typedef unsigned long u32;typedef signed char i8;typedef signed int  i16;typedef signed long i32;sbit ADDR0 = P1 ^ 0;sbit ADDR1 = P1 ^ 1;sbit ADDR2 = P1 ^ 2;sbit ADDR3 = P1 ^ 3;sbit ENLED = P1 ^ 4;// 4个列,要读取sbit KEYIN1 = P2 ^ 4;sbit KEYIN2 = P2 ^ 5;sbit KEYIN3 = P2 ^ 6;sbit KEYIN4 = P2 ^ 7;// 4个行,要拉低sbit KEYOUT1 = P2 ^ 3;sbit KEYOUT2 = P2 ^ 2;sbit KEYOUT3 = P2 ^ 1;sbit KEYOUT4 = P2 ^ 0;// 保存中断消抖后,读取按键状态u8 KeySta[4][4] =    {    {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};// 数码管codeu8 code LedChar[16] =    {    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E};// 数码管缓冲区u8 LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};u8 code KeyCodeMap[4][4] = {    {0x31, 0x32, 0x33, 0x26}, // 数字1,2,3,UP    {0x34, 0x35, 0x36, 0x25}, // 数字4,5,6,LEFT    {0x37, 0x38, 0x39, 0x28}, // 数字7,8,9,DOWN    {0x30, 0x1B, 0x0D, 0x27}, // 数字0,ESC,ENTER,RIGHT};void KeyDriver();void main(void){    TMOD = 0x01;    TH0 = 0xFC;    TL0 = 0x66;    ET0 = EA = TR0 = 1;    ENLED = 0;    ADDR3 = 1;    LedBuff[0] = LedChar[0];    while (1)    {        KeyDriver();    }}void ShowNumber(u32 num){    u8 buf[6];    u8 i,j;    for (i = 0; i < 6; i++)    {        buf[i] = num % 10;        num /= 10;    }    for (i = 5; i >= 1; i--)    {        if (buf[i] == 0)        {            LedBuff[i] = 0xFF; // 不显示        }        else        {            break;        }    }    for (j=0; j<=i;j++)    {        LedBuff[j] = LedChar[buf[j]];    }}void KeyAction(u8 keycode){    static u32 result = 0;    static u32 addend = 0;    if ((keycode >= 0x30) && (keycode <= 0x39))    {        // num        addend = (addend * 10) + (keycode - 0x30);        ShowNumber(addend);    }    else if (keycode == 0x26) // up,+    {        result += addend;        addend = 0;        ShowNumber(result);    }    else if (keycode == 0x0D) // enter =    {        result += addend;        addend = 0;        ShowNumber(result);    }    else if (keycode == 0x1B) // esc clear    {        addend = 0;        result = 0;        ShowNumber(0);    }}void KeyDriver(void){    // 保存上一次按键的状态    static u8 backup[4][4] = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};    u8 i, j;    // 扫描上一次状态和现在状态,有区别吗    for (i = 0; i < 4; i++) // out    {        for (j = 0; j < 4; j++) // in        {            if (backup[i][j] != KeySta[i][j])            {                if (backup[i][j] == 0)                {                    KeyAction(KeyCodeMap[i][j]);                }                else                {                    // 按下                }                backup[i][j] = KeySta[i][j];            }        }    }}void KeyScan(void){    static u8 keyout = 0; // 控制4个线拉低的    u8 i = 0;    // 保存按键每一次读取的值    static u8 keybuf[4][4] = {{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}};    // 读keyout拉低行的,4个列按键状态    keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEYIN1; // 读第1列按键    keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEYIN2; // 读第2列按键    keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEYIN3; // 读第3列按键    keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEYIN4; // 读第4列按键    // 判断刚读取的4个按键,是否稳定    for (i = 0; i < 4; i++)    {        if ((keybuf[keyout][i] & 0x0F) == 0x00) // 稳定为0        {            KeySta[keyout][i] = 0;        }        else if ((keybuf[keyout][i] & 0x0F) == 0x0F) // 稳定为1        {            KeySta[keyout][i] = 1;        }        else        {            // 抖动        }    }    // 切换下一行拉低,方便下次读取    keyout++;    keyout &= 0x03;    switch (keyout)    {    case 0:        KEYOUT4 = 1;        KEYOUT1 = 0;        break;    case 1:        KEYOUT1 = 1;        KEYOUT2 = 0;        break;    case 2:        KEYOUT2 = 1;        KEYOUT3 = 0;        break;    case 3:        KEYOUT3 = 1;        KEYOUT4 = 0;        break;    }}void LedScan(void){    static u8 i = 0;    P0 = 0xFF; // 消影    switch (i)    {    case 0:        ADDR2 = 0;        ADDR1 = 0;        ADDR0 = 0;        i++;        P0 = LedBuff[0];        break;    case 1:        ADDR2 = 0;        ADDR1 = 0;        ADDR0 = 1;        i++;        P0 = LedBuff[1];        break;    case 2:        ADDR2 = 0;        ADDR1 = 1;        ADDR0 = 0;        i++;        P0 = LedBuff[2];        break;    case 3:        ADDR2 = 0;        ADDR1 = 1;        ADDR0 = 1;        i++;        P0 = LedBuff[3];        break;    case 4:        ADDR2 = 1;        ADDR1 = 0;        ADDR0 = 0;        i++;        P0 = LedBuff[4];        break;    case 5:        ADDR2 = 1;        ADDR1 = 0;        ADDR0 = 1;        P0 = LedBuff[5];        i = 0;        break;    }}void Timer0_ISR(void) interrupt 1{    TH0 = 0xFC;    TL0 = 0x66;    LedScan();    KeyScan();}//课后作业在下一篇

X 关闭

推荐内容

最近更新

Copyright ©  2015-2022 青年机械网版权所有  备案号:皖ICP备2022009963号-20   联系邮箱:39 60 291 42@qq.com