打印
[应用方案]

单片机矩阵键盘扫描

[复制链接]
474|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
juliestephen|  楼主 | 2023-5-15 10:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <reg52.h>
#include <intrins.h>

#define MAIN_Fosc       11059200UL  //宏定义主时钟HZ

sbit CS = P3^7;
sbit DCLK = P2^1;
sbit DIN =  P2^0;
sbit DOUT = P2^5;
sbit DU = P2^6;//数码管段选
sbit WE = P2^7;//数码管段选
/*====================================
使用typedef给已有数据类型取别名
====================================*/
typedef unsigned char INT8U;
typedef unsigned char uchar;
typedef unsigned char u8;

typedef unsigned int INT16U;
typedef unsigned int uint;
typedef unsigned int u16;

uint voltage;//电压值

#define AD_CH0 0x94
#define AD_CH1 0xd4
#define AD_CH2 0xa4
#define AD_CH3 0xe4
//通道0光敏cmd:0x94  通道1热敏cmd:0xd4  通道2电位器cmd:0xa4 通道3外部输入AIN3 cmd:0xe4

//共阴数码管段选表0-9
uchar code SMGduan[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};
//数码管位选码
uchar code SMGwei[] = {0xfe, 0xfd, 0xfb, 0xf7};

/*====================================
函数:void Delay_Ms(INT16U ms)
参数:ms,毫秒延时形参
描述:12T 51单片机自适应主时钟毫秒级延时函数
====================================*/
void Delay_Ms(INT16U ms)
{
     INT16U i;
     do{
          i = MAIN_Fosc / 96000;
          while(--i);   //96T per loop
     }while(--ms);
}

/*====================================
函数  :display(uchar i)
参数  :i 显示变量取值0-9999
返回值   :无
描述  :数码管动态显示函数
====================================*/
void display(uint i)
{
    uchar q, b, s, g;
    static uchar wei;
    q = i / 1000;
    b = i % 1000 / 100;
    s = i % 100 / 10;
    g = i % 10;   
    P0 = 0XFF;//清除断码
    WE = 1;//打开位选锁存器
    P0 = SMGwei[wei];
    WE = 0;//锁存位选数据
    P0 = 0XFF;//清除断码
    switch(wei)
    {
        case 0: DU = 1; P0 = SMGduan[q] | 0x80; DU = 0; break;//0x80加上小数点
        case 1: DU = 1; P0 = SMGduan;    DU = 0; break;
        case 2: DU = 1; P0 = SMGduan;    DU = 0; break;
        case 3: DU = 1; P0 = SMGduan[g];    DU = 0; break;     
    }
    wei++;
    if(wei == 4)
        wei = 0;
}

/*====================================
函数  :SPI_Write(uchar DAT)
参数  :DAT需要发送的数据
返回值   :无
描述  :发送一个字节数据
====================================*/
void SPI_Write(uchar DAT)
{
    uchar i;
    for(i=0; i<8; i++) //分别写8次,每次写1位
    {
        DCLK = 0;//拉低时钟总线,允许DIN变化
        if(DAT & 0x80)//先写数据最高位
            DIN = 1;  //写1
        else
            DIN = 0;  //写0
        DCLK = 1;     //拉高时钟,让从机读DIN
        DAT <<= 1;    //为发送下一位左移1位
    }
}
/*====================================
函数  :ReadByte()
参数  :无
返回值   :返回读出的数据
描述  :
====================================*/
uint SPI_Read()
{
    uchar i;
    uint DAT;
    for(i=0; i<12; i++)//分别读12次,每次读一位
    {
        DAT <<= 1; //数据左移1位,准备接收一位
        DCLK = 1;   //拉高时钟总线,读取SDA上的数据
        DCLK = 0;   //拉低时钟总线,允许从机控制SDA变化
        if(DOUT)
            DAT |= 0X01;//为1则写1,否则不行执行写1,通过左移补0
    }
    return(DAT); //返回读出的数据
}

/*====================================
函数  :ReadAD(uchar cmd)
参数  :cmd XPT2046控制字节
返回值   :AD转出的数字量
描述  :读指定通道的输入的模拟量专为数字量
====================================*/
uint ReadAD(uchar cmd)
{
    uint DAT;
    CS = 0;
    SPI_Write(cmd);
    DCLK = 0;   //拉低时钟总线
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    DAT = SPI_Read();
    CS = 1;
    return(DAT);//返回读出数据
           
}

void main()//main函数自身会循环
{  
    uchar i;
    while(1)
    {
        if(i >= 100)//延时500毫秒  为了使得数码管的示数稳定
        {
            i = 0;
            voltage = ReadAD(AD_CH0);   //通道0光敏cmd:0x94  通道1热敏cmd:0xd4  通道2电位器cmd:0xa4 通道3外部输入AIN3 cmd:0xe4
            voltage = voltage * 1.2207 ; //  (5v/4096 12位)得到1.2207 即每一个数码量对应的电压
        }
        display(voltage);
        Delay_Ms(5);
        i++;
    }
}

使用特权

评论回复
沙发
jf101| | 2023-7-25 13:40 | 只看该作者
楼主这个划横线的程序时怎么回事?

使用特权

评论回复
板凳
星辰大海不退缩| | 2023-7-25 14:58 | 只看该作者
实现矩阵键盘逐行扫描需要用到单片机的IO口和定时器功能

使用特权

评论回复
地板
AdaMaYun| | 2023-7-26 11:39 | 只看该作者
楼主复制粘贴的程序出问题了,建议排查一下

使用特权

评论回复
5
LOVEEVER| | 2023-7-26 17:34 | 只看该作者
矩阵键盘其实是逐行扫描的,原理很简单

使用特权

评论回复
6
wangzsa| | 2023-8-31 20:22 | 只看该作者
程序出问题了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

1086

帖子

2

粉丝