标题: 第12章 常用单片机接口程序 静态动态显示 独立按键 矩阵按键 [打印本页]
作者: wul 时间: 2016-3-28 21:07
标题: 第12章 常用单片机接口程序 静态动态显示 独立按键 矩阵按键
第12章 常用单片机接口程序
1 静 态 显 示
2 动 态 显 示
3 独立按键
4 矩阵按键
数码管是常用的输出显示器件,按键是常用的信号输入器件。
常见数码管引脚排列如图所示
静态显示电路如下图:
① 数码管要显示某个数字或字符,首先根据单只数码管引脚图,确定需要点亮数 码管的哪几段,从而确定数码管8个引脚电平的高低。
例12.1 74HC595移位显示程序,上电后数码管固定显示123456。
#include "STC15W4K.H" | // | 注意宏定义后面没分号 |
#include "intrins.h" | // | 程序中_nop_()函数需用 |
sbit | Dat=P3^2; | // | 定义串行数据输入端 |
sbit | Clk=P3^3; | // | 定义时钟端 |
sbit | CNT=P3^4; | // | 定义控制端 |
unsigned char DispBuf[6];
unsigned char code DispTab[]={0x03,0x9f,0x25,0x0d,0x19,0x41,0x1f,0x01,0x09,
0x11,0xc1,0x63,0x85,0x61,0x71}; // 定义定形码表
void SendData(unsigned char SDat) // 74HC595传送一个字节的数据
{ // 固定代码,直接复制使用
}
void Disp() // 显示位数在6位内不用修改
{
unsigned char c=0,i=0;
CNT=0; // 为产生脉冲上升沿作准备
for(i=0;i<6;i++) // 显示位数需用根据硬件修改
{
c=DispBuf[ i ]; // 取出待显示字符 SendData(DispTab[c]); // 送出字形码数据
}
CNT=1; // 产生脉冲上升沿,并行输出数据
}
void main()
{
unsigned long i=123456; // 123456
DispBuf[0]=i%10; // 个位 DispBuf[1]=i/10%10; // 十位 DispBuf[2]=i/100%10; // 百位 DispBuf[3]=i/1000%10; // 千位 DispBuf[4]=i/10000%10; // 万位 DispBuf[5]=i/100000%10; // 十万位 Disp();
for(;;)
{
; // 程序停在这里
}
}
2 动态显示
这里介绍的动态显示电路如下图所示,看起来有点像静态显示电路,但比静态 显示电路占用硬件要少,比单片机直接驱动数码管占用IO口也要少。
DAT
结合电路图,控制某一位数码管电源通断的位选码就简单多了,如下所示。
单片机内部数据位 595引脚 | D7 Q0 | D6 Q1 | D5 Q2 | D4 Q3 | D3 Q4 | D2 Q5 | D1 Q6 | D0 Q7 | 位码 |
十万位 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 0xDF |
万位 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0xBF |
千位 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0x7F |
百位 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0xFB |
十位 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0xFD |
个位 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0xFE |
例12.3 单片机上电后数码管显示123456
sbit | Dat=P4^2; | // | 定义串行数据输入端 |
sbit | Clk=P4^4; | // | 定义时钟端 |
sbit | CNT=P4^5; | // | 定义控制端 |
unsigned char code BitTab[]={0xFE,0xFD,0xFB,0x7F,0xBF,0xDF,}; // 位选
code unsigned char DispTab[] = {0x14,0x77,0x4c,0x45,0x27,0x85,0x84,0x57,
0x04,0x05,0x06,0xa4,0x9c,0x64,0x8c,0x8e}; // 字形码
unsigned char DispBuf[6]; // 6字节的显示缓冲区,DispBuf[0]是最低位;
void SendData(unsigned char SendDat) // 74HC595传送一个字节的数据
{ ;// 同例12.1
}
void timer0_init() // 定时器初始化
{
// 2ms定时中断设置
}
void main()
{
timer0_init();
DispBuf[0]=6; DispBuf[1]=5; DispBuf[2]=4;DispBuf[3]=3; DispBuf[4]=2;DispBuf[5]=1;
for(;;)
{
;
}
}
void Timer0() interrupt 1
{
unsigned char tmp; //临时变量
static unsigned char Count=0; //显示程序通过它得知现正显示哪个数码管
// ***************** 重装定时常数 ***************************
TH0=0xf1;
TL0=0x99; // 定时时间为2ms/22.1184MHz
// ******************点亮某位数码管************************** CNT=0; // 为产生脉冲上升沿作准备 SendData(BitTab[Count]); // 最先点亮最右边个位
// ******************输出待显数据************************** tmp=DispBuf[Count]; // 根据当前的计数值取显示缓冲待显示值 tmp=DispTab[tmp]; // 取字形码
SendData(tmp) ;
CNT=1; // 产生脉冲上升沿,并行输出数据
// ******************************************** Count++;
if(Count==6) Count=0;
}
3 独立按键
电路如图所示,单片机引脚作为输入使用,软件首先将接有按键的IO口置1,当键
没有被按下时,单片机引脚上为高电平,而当键被按下后,引脚接地,单片机引 脚上为低电平,通过编程即可获知是否有键按下及按键的位置。
由于机械按键按下和松开瞬间都会产生抖动,为了不让一次按键动作过程中程序产生多
次响应引起混乱,就需要软件去抖动处理,它的思路是:在单片机获得某按键IO口为低 的信息后,不是立即认定该键被按下,而是延时一段时间,通常选择10mS,再次检测IO 口,如果仍为低,则说明该键的确被按下,这避开了按键的前沿抖动,而在检测到按键 释放后(该IO口为高),再延时10mS,消除释放时的后沿抖动,然后再对键值进行处
理,实际的程序中其实一般都是不需要后沿抖动处理的,在后沿抖动的过程中,程序可 能误判为键按下,在键按下后程序会执行前沿延时10mS,所以前沿的10mS延时也就同时 用作了后沿去抖动的10mS。主要程序代码如下:
void main()
{
unsigned char KValue; | // | 存放键值 |
port_mode(); | // | 所有IO口设为准双向弱上拉方式。 |
for(;;) { | | |
KValue=Key(); | // | 调用键盘程序并获得键值 |
if(KValue) | // | 如果该值不等于0,表示有键按下 |
{ | | |
KProce(KValue); | // | 根据键值执行不同的功能 |
}
}
}
unsigned char Key() // 获取键值函数
{
unsigned char KValue; // 存放键值
unsigned char tmp; // 临时变量
P3|=0x3c; // 0x3c=0011 1100,将P3口接键盘的中间四位置1
_nop_();_nop_(); KValue=P3; KValue|=0xc3; | // | // STC指令太快,加上更可靠 0xc3=1100 0011,将未接键的4位置1 |
if(KValue==0xff) // 中间4位均为1,无键按下 |
return(0); | | // 返回 |
delay10ms(); KValue=P3; KValue|=0xc3; | // | // 延时10ms,去键抖 // 与下一行一起作最终返回键值。 0xc3=1100 0011,将未接键的4位置1,最终返回键值。 |
if(KValue==0xff) // 中间4位均为1,无键按下 |
return(0); // 返回,如尚未返回,说明一定有1或更多位被按下
for(;;)
{
tmp=P3; // 等待按键释放
if((tmp|0xc3)==0xff)
break;
}
return(KValue);
}
4 矩阵按键
电路如图所示,只要熟悉了独立按键,矩阵按键也同样的简单。
主要代码如下:
sbit KeyOut1 = P2^7;sbit KeyOut2 = P2^6;sbit KeyOut3 = P2^5;sbit KeyOut4 = P2^4;
sbit KeyIn1 = P2^3;sbit KeyIn2 = P2^2;sbit KeyIn3 = P2^1;sbit KeyIn4 = P2^0; unsigned char
KeyScan()
{
unsigned char key=0xff; // 临时变量
KeyOut1 = 1; KeyOut2 = 1; KeyOut3 = 1; KeyOut4 = 0; // 扫描第1列
if(KeyIn1 == 0)
{
delay10ms(); if(KeyIn1 == 0) key=0x00;
}
if(KeyIn2 == 0)
{
delay10ms(); if(KeyIn2 == 0) key=0x04;
}
if(KeyIn3 == 0)
{
delay10ms(); if(KeyIn3 == 0) key=0x08;
}
if(KeyIn4 == 0)
{
delay10ms(); if(KeyIn4 == 0) key=0x0c;
}
KeyOut1 = 1; KeyOut2 = 1; KeyOut3 = 0; KeyOut4 = 1; // 扫描第2列
if(KeyIn1 == 0)
{
delay10ms(); if(KeyIn1 == 0) key=0x01;
}
……
}
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |