找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6695|回复: 0
收起左侧

第12章 常用单片机接口程序 静态动态显示 独立按键 矩阵按键

[复制链接]
ID:111078 发表于 2016-3-28 21:07 | 显示全部楼层 |阅读模式
第12章 常用单片机接口程序
1 静 态 显 示
2 动 态 显 示
3 独立按键
4 矩阵按键
数码管是常用的输出显示器件,按键是常用的信号输入器件。
0.png



常见数码管引脚排列如图所示
1.png


静态显示电路如下图:
2.png


编写字型码关键步骤如下:
① 数码管要显示某个数字或字符,首先根据单只数码管引脚图,确定需要点亮数 码管的哪几段,从而确定数码管8个引脚电平的高低。
3.png

例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口也要少。

0.png 1.png
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,当键
没有被按下时,单片机引脚上为高电平,而当键被按下后,引脚接地,单片机引 脚上为低电平,通过编程即可获知是否有键按下及按键的位置。
0.png
由于机械按键按下和松开瞬间都会产生抖动,为了不让一次按键动作过程中程序产生多

次响应引起混乱,就需要软件去抖动处理,它的思路是:在单片机获得某按键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 矩阵按键
电路如图所示,只要熟悉了独立按键,矩阵按键也同样的简单。

1.png


主要代码如下:
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;
}
……
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表