实例21 LED显示秒表 课件(6份打包) 《单片机基础与应用》(C语言版) 同步教学

资源下载
  1. 二一教育资源

实例21 LED显示秒表 课件(6份打包) 《单片机基础与应用》(C语言版) 同步教学

资源简介

(共15张PPT)
实例21 LED显示秒表
《单片机基础与应用(C语言版)》
高等教育出版社
一、任务导入
01
任务要求
用单片机控制8个LEDLED,要求8个LED按照BCD(Binary Coded Decimal)码格式循环显示00~59,时间间隔为1s
8个LED实现的BCD显示秒表示意图(BCD码是用二进制形式表示十进制数,例如十进制数45,其BCD码形式为45H。BCD码只是一种表示形式,与其数值没有关系。)
二、任务分析
02
秒表设计的核心是精确的1s定时时间,可以采用定时器/计数器的中断方式实现。BCD码用4位二进制码表示一位十进制数,这4位二进制数的权值为8421,所以BCD码又称为8421码。十进制数码0~9所对应的二进制码见表
十进制数码 0 1 2 3 4 5 6 7 8 9
二进制码 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001
十进制数码与BCD码对应表
三、硬件电路
03
单片机控制8个LED的硬件电路
四、程序设计
04
程序演示
//程序:ex23.c
//功能:采用BCD码格式显示的0~59简易秒表程序
#include //包含头文件REGX51.H,定义了51单片机的所有SFR
//全局变量定义
unsigned char count=0; //对50ms定时时间进行计数
unsigned char miao=0; //秒计数器
void main()
{
unsigned char t;
TMOD=0x10; //置T1为工作方式1
TH1=(65536-50000)/256; //设置T1计数初值高8位,定时时间50ms
TL1=(65536-50000)%256; //设置T1计数初值低8位
ET1=1; //定时器T1中断允许
EA=1; //总中断允许
TR1=1; //启动T1
while(1)
{
t=(((miao/10)<<4)|(miao%10));// 将i转换为BCD码
P1=~t; // 计数值取反后送P1口显示
}
}
程序演示
//函数名:time50ms
//函数功能:在T0工作方式1下定时50ms,采用查询方式实现
//形式参数:无符号整型变量i,控制定时时间,i*50ms
//返回值:无
void time50ms(unsigned char i)
{
unsigned char k;
for(k=0;k{
TH0=(65536-50000)/256; //重新设置T0计数初值高8位,定时时间50ms
TL0=(65536-50000)%256; //重新设置T0计数初值低8位
TR0=1; //启动T0
while(!TF0); //查询计数是否溢出,即定时5ms时间到,TF0=1
TF0=0; //50ms定时时间到,将T0溢出标志位TF0清0
}
}
程序演示
//函数名:time_1
//函数功能:在T1工作方式1下定时50ms,采用中断方式实现,进行秒计数
//形式参数:无
//返回值:无
void timer_1() interrupt 3 using 3 //T1的中断类型号为3
{
TH1=(65536-50000)/256; //重新设置T1计数初值高8位
TL1=(65536-50000)%256; //重新设置T1计数初值低8位
count++; //50ms计数器加1
if(count==20) //1s时间到
{
count=0; //50ms计数器清0
miao++; //秒计数器加1
if(miao==60)miao=0; //miao计数到60,则从0开始计数
}
}
程序演示
感谢您的观看(共12张PPT)
实例22 LED静态显示2位秒表
《单片机基础与应用(C语言版)》
高等教育出版社
实例要求
单片机有4个并行I/O口P0~P3,每个I/O口包括8条I/O口线。采用P1口、P2口来控制2个共阳极LED的段码,公共端com接在+5V上。P1口控制的LED显示十位数,P2口控制的LED显示个位数,从0开始显示,显示到59后,重新从0开始显示。
设计一个00~59的2位秒表,用单片机控制2个LED静态显示。
实例分析
硬件电路
采用P1、P2口来控制2个共阳极LED的段码,com端都接在+5V上
控制程序设计
//程序:ex24.c
//功能:静态LED显示2位秒表
#include //包含头文件REGX51.H,定义了51单片机的所有SFR
//函数名:time50ms
//函数功能:在T0工作方式1下定时50ms,采用查询方式实现
//形式参数:无符号整型变量i,控制定时时间,i*50ms
//返回值:无
void time50ms(unsigned char i)
{
unsigned char k;
for(k=0;kTH0=(65536-50000)/256; //重新设置T0计数初值高8位,定时时间50ms
TL0=(65536-50000)%256; //重新设置T0计数初值低8位
TR0=1; //启动T0
while(!TF0); //查询计数是否溢出,即定时50ms时间到,TF0=1
TF0=0; //50ms定时时间到,将T0溢出标志位TF0清0
}
}
控制程序设计
void main() //主函数
{
unsigned char led[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92, 0x82, 0xf8,0x80,0x90};
//设置数字“0~9”的字型编码
unsigned char i; //设置秒表的计数值
TMOD=0x01; //设置T0为工作方式1,定时功能
P1=0xff; //熄灭LED共阳LED十位
P2=0xff; //熄灭LED共阳LED个位
while(1) //无限循环
{
for(i=0;i<60;i++){ //设置秒表的计数值
P1=led[i/10]; //显示LED十位
P2=led[i%10]; //显示LED个位
time50ms(20); //定时1s
}
}
}
实例23 LED动态显示指定信息
《单片机基础与应用(C语言版)》
高等教育出版社
实例要求
将各位共阳极LED相应的段选控制端并联在一起,仅用一个P1口控制,用八同相三态缓冲器/线驱动器74LS245驱动;将各位LED的公共端,由P2口控制,用2个六反相驱动器74LS04驱动。
用单片机控制8个LED,实现稳定显示生日信息“19950316”的效果。
实例分析
硬件电路
段选控制端并联在一起,用P1口控制,位选口由P2口控制
动态显示过程如下:先选中最左边的第1个LED显示,显示字符1, 即:通过P2=0xfe;经P2.0引脚输出低电平,经反相后变成高电平,连接共阳极LED的公共端,通过P1口送出“1”的共阳极字型编码: P1=0xf9。同理,依次显示第2到第8个LED。反复以上动态扫描过程,即可实现稳定显示效果。
字符 1 9 9 5 0 3 1 6
P2 11111110B 11111101B 11111011B 11110111B 11101111B 11011111B 10111111B 01111111B
P1 0xf9 0x90 0x90 0x92 0xc0 0xb0 0xf9 0x82
控制程序设计
//程序:ex25.c
//功能:动态LED稳定显示8个字符“19950316”
#include //包含头文件REGX51.H,定义了51单片机的所有SFR
//函数名:time1ms
//函数功能:在T0工作方式1下定时1ms,采用查询方式实现
//形式参数:无
//返回值:无
void time1ms( )
{ TMOD=0x01; //设置T0为工作方式1,定时功能
TH0=(65536-1000)/256; //重新设置T0计数初值高8位,定时时间1ms
TL0=(65536-1000)%256; //重新设置T0计数初值低8位
TR0=1; //启动T0
while(!TF0); //查询计数是否溢出,即定时1ms时间到,TF0=1
TF0=0; //1ms定时时间到,将T0溢出标志位TF0清0
}
控制程序设计
//函数名:disp_scan
//函数功能:实现8个LED动态扫描显示一次,显示数字“19950316”
//形式参数:无
//返回值:无
void disp_scan( )
{ unsigned char led[]={0xf9,0x90,0x90,0x92,0xc0,0xb0,0xf9,0x82};
//设置数字“19950316”的字型码
unsigned char i,w;
w=0x01; //位选码初值为01H
for(i=0;i<8;i++)
{ P2=~w; //位选码取反后送位控制口P2口
w<<=1; //位选码左移一位,选中下一位LED
P1=led[i]; //显示字型码送P1口
time1ms( ); //延时1ms
P1=0xff; //关显示,消除拖影
}
}
void main() //主函数
{
while(1)
{
disp_scan(); //反复调用LED动态扫描显示函数,实现稳定显示
}
}
感谢您的观看
Thanks for your attention. (共13张PPT)
实例24 LED动态显示移动广告牌
《单片机基础与应用(C语言版)》
高等教育出版社
实例要求
用单片机控制8个LED向左移动显示生日信息“19950316”。
实例分析
在8个LED上移动显示“19950316”字样,显示过程如图
硬件电路
段选控制端并联在一起,用P1口控制,位选口由P2口控制
控制程序设计
//程序:ex26.c
//功能:动态LED向左滚动显示8个字符“19950316”
#include //包含头文件REGX51.H,定义了51单片机的所有SFR
//函数名:time1ms
//函数功能:在T0工作方式1下定时1ms,采用查询方式实现
//形式参数:无
//返回值:无
void time1ms( )
{ TMOD=0x01; //设置T0为工作方式1,定时功能
TH0=(65536-1000)/256; //重新设置T0计数初值高8位,定时时间1ms
TL0=(65536-1000)%256; //重新设置T0计数初值低8位
TR0=1; //启动T0
while(!TF0); //查询计数是否溢出,即定时1ms时间到,TF0=1
TF0=0; //1ms定时时间到,将T0溢出标志位TF0清0
}
控制程序设计
//函数名:disp2
//函数功能:实现8个LED动态向左滚动显示数字“19950316”一次
//形式参数:无
//返回值:无
void disp2( )
{
unsigned char ledmove[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf9,0x90,0x90,0x92, 0xc0,0xb0,0xf9,0x82,0xff,0xff,0xff,0xff, 0xff,0xff,0xff};
//设置移动字符的字型码
unsigned char com[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//设置位选码
unsigned char i,j,num;
for(num=0;num<15;num++) //显示15屏字符
for(j=0;j<10;j++) //循环显示一屏字符10次,达到延时显示作用
for(i=0;i<8;i++)
{
P2=com[i]; //位选码送位控制口P2口
P1=ledmove[num+i]; //显示字型码送P1口
time1ms(); //延时1ms
P1=0xff; //关显示,消除拖影
}
}
void main() //主函数
{
while(1)
{
disp2();
}
}
实例25 LED动态显示2位秒表
《单片机基础与应用(C语言版)》
高等教育出版社
实例要求
用单片机控制2位LED实现00~59的简易秒表,并利用2个独立式按键实现秒表的启动/停止和清0功能。
实例分析
采用定时器/计数器T0实现50ms定时,采用中断方式编程,中断20次为1s计时。用2个LED共阳极LED来动态显示秒计数值,通过2个独立式按键采用中断方式实现秒表的启动、停止和复位功能。
硬件电路

的输入引脚P3.2和P3.3。在计数过程中,当S0按下时,暂停计数,再次按下时,继续计数(外部中断0)。任何时候按下S1,则从0开始计数(外部中断1)。
采用P0口控制2个LED的8个段选控制端,用P2.0、P2.1分别作为2个LED共阳极LED的位选控制端。2个按键分别连接到外部中断
控制程序设计
//程序:ex27.c
//功能:动态LED显示2位秒表00~59
#include //包含头文件REGX51.H,定义了51单片机的所有SFR
unsigned char msec,sec; //定义msec为50ms计数变量,sec为秒变量
bit b=0; //暂停/继续标志位,b=0暂停,b=1继续
//函数名:delayms
//函数功能:实现软件延时
//形式参数:无符号整型变量i,控制时间为i*1ms
//返回值:无
void delayms(unsigned int i)
{unsigned char k;
while(i--)
for(k=0;k<120;k++); //120次空操作
}
控制程序设计
//函数名:int_0
//函数功能:外部中断0中断函数,用于暂停、继续计数
//形式参数:无
//返回值:无
void int_0() interrupt 0
{
if(b==0){TR0=0;b=1;}
else {TR0=1;b=0;}
}
//函数名:int_1
//函数功能:外部中断1中断函数,用于清0
//形式参数:无
//返回值:无
void int_1() interrupt 2
{
sec=0;
msec=0;
TH0=(65536-50000)/256; //50ms定时初值
TL0=(65536-50000)%256;
TR0=1;
}
//函数名:T0_INT
//函数功能:定时器0中断函数,定时50ms到,自动执行这个函数,判断是否中断20次
//形式参数:无
//返回值:无
void T0_INT(void) interrupt 1 //定时器0中断类型号为1
{
TH0=(65536-50000)/256; //50ms定时初值
TL0=(65536-50000)%256;
msec++; //中断次数增1
if(msec==20) //中断次数到20次吗?
{
msec=0; //是,1秒计时到,50ms计数单元清0
sec++; //秒单元加1
if(sec==60) //到60秒吗?
{
sec=0; //是,秒单元清0
}
}
}
控制程序设计
void main() //主函数
{
unsigned char led[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//定义数字0~9字型显示码
TMOD=0x01; //定时器0工作方式1
TH0=(65536-50000)/256; //50ms定时初值
TL0=(65536-50000)%256;
TR0=1;
ET0=1; //开T0中断
EX0=1; //开外部中断0
IT0=1; //下降沿触发中断
EX1=1; //开外部中断1
IT1=1; //下降沿触发中断
EA=1; //开总中断
while(1)
{
P2=0x01; //选中P2.0控制的LED
P0=led[sec%10]; //显示秒个位
delayms(1); //1ms延时
P0=0xff; //关显示
P2=0x02; //选中P2.1控制的LED
P0=led[sec/10]; //显示秒十位
delayms(1); //1ms延时
P0=0xff; //关显示
}
}
Thanks for your attention.
感谢您的观看(共16张PPT)
实例26 LED点阵显示器稳定显示指定图形
《单片机基础与应用(C语言版)》
高等教育出版社
实例要求
采用单片机控制一块8×8 LED点阵显示模块,稳定显示“爱心”图形。
实例分析
“爱心”图形显示字型码
先给第1行送高电平0x01(行高电平有效),同时给8列送11111111(列低电平有效,从数据高位往低位读数);然后给第2行送高电平0x02,同时给8列送10011001,……最后给第8行送高电平0x80,同时给8列送11111111。每行点亮延时时间为1ms,第8行结束后再从第1行开始循环显示。
硬件电路
采用单片机P1口控制行线,P0口控制列线,在每条X列线上或Y行线上需串接一个300欧姆左右的限流电阻,同时,为提高单片机端口带负载的能力,在端口和外接负载之间增加一个缓冲驱动器,P1口通过74LS245与LED连接,提高了P1口输出的电流,既保证了LED的亮度,又保护了端口引脚。
控制程序设计
//程序:ex28.c
//功能:LED点阵稳定显示一个字符“爱心”图形
#include //包含头文件REGX51.H,定义了51单片机的所有SFR
//函数名:delayms
//函数功能:实现软件延时
//形式参数:无符号整型变量i,控制时间为i*1ms
//返回值:无
void delayms(unsigned int i)
{unsigned char k;
while(i--)
for(k=0;k<120;k++); //120次空操作
}
控制程序设计
void main()
{
unsigned char code led[]={0xff,0x99,0x66,0x7e,0xbd,0xdb,0xe7,0xff};
//心型字形码
unsigned char w,i; //定义行变量w,行数变量i
while(1)
{
w=0x01; //行变量指向第1行
for(i=0;i<8;i++)
{
P1=w; //行数据送P1口
P0=led[i]; //列数据送P0口
delayms(1);
w<<=1; //行变量左移指向下一行
P0=0xff; //关显示
}
}
}
思考题:怎么修改程序实现在一块8×8 LED点阵屏上循环显示数字0~9?
提示:多个字符轮流显示,需要在一个字符显示的基础上,再加循环嵌套。
控制程序设计
//程序:ex29.c
//功能:在8×8LED点阵上循环显示数字0~9
#include //包含头文件REGX51.H,定义了51单片机的所有SFR
//函数名:delayms
//函数功能:实现软件延时
//形式参数:无符号整型变量i,控制时间为i*1ms
//返回值:无
void delayms(unsigned int i)
{unsigned char k;
while(i--)
for(k=0;k<120;k++); //120次空操作
}
控制程序设计
void main()
{
unsigned char code led[]={
0xe7,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xe7, //0
0xff,0xe7,0xc7,0xe7,0xe7,0xe7,0xe7,0xe7, //1
0xff,0x87,0xf3,0xf3,0xc7,0x9f,0x9f,0x83, //2
0xff,0x87,0xf3,0xf3,0xc7,0xf3,0xf3,0x87, //3
0xff,0xf3,0xe3,0xd3,0xb3,0x83,0xf3,0xf3, //4
0xff,0x87,0xbf,0x87,0xf3,0xf3,0xf3,0x87, //5
0xff,0xc7,0x9f,0x87,0x93,0x93,0x93,0xc7, //6
0xff,0x03,0xf3,0xe7,0xe7,0xcf,0xcf,0xcf, //7
0xff,0xc7,0x93,0x93,0xc7,0x93,0x93,0xc7, //8
0xff,0xc7,0x93,0x93,0x93,0xc3,0xf3,0xc7}; //9
unsigned char w;
unsigned int i,j,k,m;
while(1)
{
for(k=0;k<10;k++) //字符个数控制变量
{
for(m=0;m<250;m++) //每个字符扫描显示400次,控制每个字符显示时间
{
w=0x01; //行变量w指向第1行
j=k*8; //指向数组led的第k个字符第1个显示码下标
for(i=0;i<8;i++)
{
P1=w; //行数据送P1口
P0=led[j]; //列数据送P0口
delayms(1);
w<<=1; //行变量左移指向下一行
j++; //指向数组中下一个显示码
P0=0xff; //关显示
}
}
}
}
}
实例27 LED点阵显示器移动显示广告屏
《单片机基础与应用(C语言版)》
高等教育出版社
实例要求
用单片机控制1个8×8 LED点阵显示模块,实现从下向上移动显示手机号码 “13592346786”。
实例分析
滚动显示实际就是多屏图形的循环显示。
(a) (b) (c) (d) (e)
控制程序设计
//程序:ex28.c
//功能:LED点阵稳定显示一个字符“爱心”图形
#include //包含头文件REGX51.H,定义了51单片机的所有SFR
//函数名:delayms
//函数功能:实现软件延时
//形式参数:无符号整型变量i,控制时间为i*1ms
//返回值:无
void delayms(unsigned int i)
{unsigned char k;
while(i--)
for(k=0;k<120;k++); //120次空操作
}
控制程序设计
void main()
{
unsigned char code led[]={
0xe7,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xe7, //0
0xff,0xe7,0xc7,0xe7,0xe7,0xe7,0xe7,0xe7, //1
0xff,0x87,0xf3,0xf3,0xc7,0x9f,0x9f,0x83, //2
0xff,0x87,0xf3,0xf3,0xc7,0xf3,0xf3,0x87, //3
0xff,0xf3,0xe3,0xd3,0xb3,0x83,0xf3,0xf3, //4
0xff,0x87,0xbf,0x87,0xf3,0xf3,0xf3,0x87, //5
0xff,0xc7,0x9f,0x87,0x93,0x93,0x93,0xc7, //6
0xff,0x03,0xf3,0xe7,0xe7,0xcf,0xcf,0xcf, //7
0xff,0xc7,0x93,0x93,0xc7,0x93,0x93,0xc7, //8
0xff,0xc7,0x93,0x93,0x93,0xc3,0xf3,0xc7}; //9
unsigned char w;
unsigned int i,j,k,m;
while(1)
{
for(k=0;k<88;k++) //显示滚动行数控制变量
{
for(m=0;m<100;m++) //每个字符扫描显示100次,控制每个字符显示时间
{
w=0x01;
j=k;
for(i=0;i<8;i++)
{
P1=w; //行数据送P1口
P0=led[j]; //列数据送P0口
delayms(1);
P0=0xff; //关显示
w<<=1; //行变量左移指向下一行
j++; //指向数组中下一个显示码
if(j>87)j=j-88; //如果列数据显示完回到初始
}
}
}
}
}
Thanks for your attention.
感谢您的观看(共11张PPT)
实例28 字符型液晶显示广告牌
《单片机基础与应用(C语言版)》
高等教育出版社
实例要求
用单片机控制LCD1602液晶模块,在第1行正中间显示“HELLO CHINA”字符串。
实例分析
首先,编写LCD基本接口时序操作函数,包括写命令函数lcd_w_cmd()、写数据函数lcd_w_dat()、读状态函数lcd_r_start();其次,按照图6-19所示流程图实现初始化函数lcd_init();然后按照任务要求定位光标,即调用函数lcd_w_cmd(),设置DDRAM地址指针到第1行第4列;最后,依次调用函数lcd_w_dat()分别将多个字符的显示码写入DDRAM实现字符串显示。
控制程序设计
//程序:ex31.c
//功能:LCD液晶显示程序,采用8位数据接口
#include //包含头文件REGX51.H,定义了51单片机的所有SFR
#include //库函数头文件,代码中引用了_nop_()函数
// 定义控制信号端口
sbit RS=P3^0; //P3.0
sbit RW=P3^1; //P3.1
sbit E= P3^2; //P3.2
// 声明调用函数
void lcd_w_cmd(unsigned char com); //写命令字函数
void lcd_w_dat(unsigned char dat); //写数据函数
unsigned char lcd_r_start(); //读状态函数
void lcd_init(); //LCD初始化函数
void delayms(unsigned int i); //可控延时函数
void delay1();
void main() //主函数
{
unsigned char lcd[]="HELLO CHINA";
unsigned char i;
P1=0xff; // 送全1到P0口
lcd_init(); // 初始化LCD
delayms(100);
lcd_w_cmd(0x83); // 设置显示位置,第1行第4列
delayms(100);
for(i=0;i<11;i++) // 显示字符串字符个数
{
lcd_w_dat(lcd[i]);
delayms(100);
}
while(1); // 原地踏步
}
控制程序设计
//函数名:delayms
//函数功能:实现软件延时
//形式参数:无符号整型变量i,控制时间为i*1ms
//返回值:无
void delayms(unsigned int i)
{unsigned char k;
while(i--)
for(k=0;k<120;k++); //120次空操作
}
//函数名:delay1
//函数功能:采用软件实现延时,5个机器周期
//形式参数:无
//返回值:无
void delay1()
{
_nop_();
_nop_();
_nop_();
}
//函数名:int1
//函数功能:lcd初始化
//形式参数:无
//返回值:无
void lcd_init()
{
lcd_w_cmd(0x3c); // 设置工作方式
lcd_w_cmd(0x0e); // 设置光标
lcd_w_cmd(0x01); // 清屏
lcd_w_cmd(0x06); // 设置输入方式
lcd_w_cmd(0x80); // 设置初始显示位置
}
//函数名:lcd_r_start
//函数功能:读状态字
//形式参数:无
//返回值:返回状态字,最高位D7=0,LCD控制器空闲;D7=1,LCD控制器忙
unsigned char lcd_r_start()
{
unsigned char s;
RW=1; //RW=1,RS=0,读LCD状态
delay1();
RS=0;
delay1();
E=1; //E端时序
delay1();
s=P1; //从LCD的数据口读状态
delay1();
E=0;
delay1();
RW=0;
delay1();
return(s); //返回读取的LCD状态字
}
控制程序设计
//函数名:lcd_w_cmd
//函数功能:写命令字
//形式参数:命令字已存入com单元中
//返回值:无
void lcd_w_cmd(unsigned char com)
{
unsigned char i;
do{ // 查LCD忙操作
i=lcd_r_start(); // 调用读状态字函数
i=i&0x80; // 与操作屏蔽掉低7位
delayms(1);
}while(i!=0); // LCD忙,继续查询,否则退出循环
RW=0;
delay1();
RS=0; // RW=1,RS=0,写LCD命令字
delay1();
E=1; //E端时序
delay1();
P1=com; //将com中的命令字写入LCD数据口
delay1();
E=0;
delay1();
RW=1;
delayms(100);
}
//函数名:lcd_w_dat
//函数功能:写数据
//形式参数:数据已存入dat单元中
//返回值:无
void lcd_w_dat(unsigned char dat)
{
unsigned char i;
do{ // 查忙操作
i=lcd_r_start(); // 调用读状态字函数
i=i&0x80; // 与操作屏蔽掉低7位
delayms(1);
}while(i!=0); // LCD忙,继续查询,否则退出循环
RW=0;
delay1();
RS=1; // RW=1,RS=0,写LCD命令字
delay1();
E=1; // E端时序
delay1();
P1=dat; // 将dat中的显示数据写入LCD数据口
delay1();
E=0;
delay1();
RW=1;
delayms(100);
}
《单片机基础与应用(C语言版)》
高等教育出版社
实例29 LED显示按键状态
实例要求
实例分析
4个按键K1~K4的检测状态分为2种,K1和K2按键只需检测按下和释放2种状态,对应LED的点亮和熄灭;K3和K4按下一次的过程是:按键按下,直到按键释放,才作为一次按键动作,所以需要检测按键按下,然后再等待按键释放。按键应用时,大都采用后面一种检测方式。
采用单片机控制4个独立式按键K1~K4实现按键状态显示功能,具体功能如下。
K1按下时对应的LED1点亮,释放时LED1熄灭;K2按下时对应的LED2点亮,释放时LED2熄灭;K3按下并释放时LED3点亮,再次按下并释放时LED3熄灭;K4按下并释放时LED4点亮,再次按下并释放时LED4熄灭。
硬件电路
单片机有4个并行I/O口P0~P3,采用P1口来控制4个LED1~LED4,P3口控制4个独立式按键。
控制程序设计
//程序:ex32.c
//功能:K1按下时对应的LED1点亮,松开时LED1熄灭;K2按下时对应的LED2点亮,松开时LED2
//熄灭;K3按下并释放时LED3点亮,再次按下并释放时LED3熄灭;K4按下并释放时LED4点亮,
//再次按下并释放时LED4熄灭。
#include //包含头文件REGX51.H,定义了51单片机的所有SFR
sbit LED1=P1^0; //定义4个LED连接I/O口
sbit LED2=P1^1;
sbit LED3=P1^2;
sbit LED4=P1^3;
sbit K1=P3^0; //定义4个按键连接I/O口
sbit K2=P3^1;
sbit K3=P3^2;
sbit K4=P3^3;
//函数名:delayms
//函数功能:实现软件延时
//形式参数:无符号整型变量i,控制时间为i*1ms
//返回值:无
void delayms(unsigned int i)
{unsigned char k;
while(i--)
for(k=0;k<120;k++); //120次空操作
}
控制程序设计
void main() //主函数
{
P1=0xff; //熄灭所有LED
while(1)
{ LED1=K1;
LED2=K2;
if(K3==0) //第1次判断K3键按下
{
delayms(10); //延时去抖
if(K3==0) //再次判断K3键
{
while(K3==0); //判断K3是否释放
delayms(10); //延时去抖
LED3=~LED3;
}
}
if(K4==0)
{
delayms(10); //延时去抖
if(K4==0) //再次判断K4键
{
while(K4==0); //判断K4是否释放
delayms(10); //延时去抖
LED4=~LED4;
}
}
delayms(10);
}
}
感谢您的观看(共11张PPT)
实例30 按键控制广告牌显示
《单片机基础与应用(C语言版)》
高等教育出版社
实例要求
实例分析
采用单片机P1、P2口来控制8个动态连接LED,P3口控制4个独立式按键,采用软件延时来消除抖动。
采用单片机控制4个独立式按键K1~K4实现按键控制广告牌显示功能。K1按下并释放时8个LED显示字符串“12345678”;K2按下并释放时8个LED显示生日字符串“19950316”;K3按下并释放时8个LED显示字符串“HELLO”;K4按下并释放时8个LED清屏,不显示。
硬件电路
控制程序设计
//程序:ex33.c
//功能:K1按下并释放时8个LED显示字符串“12345678”;K2按下并释放时8个LED显示生日字//符串“19950316”;K3按下并释放时8个LED显示字符串“HELLO”;K4按下并释放时8个LED清//屏,不显示。
#include //包含头文件REGX51.H,定义了51单片机的所有SFR
//函数名:delayms
//函数功能:实现软件延时
//形式参数:无符号整型变量i,控制时间为i*1ms
//返回值:无
void delayms(unsigned int i)
{unsigned char k;
while(i--)
for(k=0;k<120;k++); //120次空操作
}
控制程序设计
void main() //主函数
{ unsigned char key,a,w,n;
unsigned char display[]={
0xf9,0xA4,0xB0,0x99,0x92,0x82,0xf8,0x80, //变化1,显示字符串"12345678"
0xf9,0x90,0x90,0x92,0xc0,0xb0,0xf9,0x82, //变化2,显示字符串"19950316"
0xff,0xff,0xff,0x89,0x86,0xc7,0xc7,0xc0, //变化3,显示字符串"HELLO"
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; //变化4, 熄灭
P3=0xff; //P3口作为输入口,置全1
while(1)
{key=0;
while(key==0) //循环判断是否有键按下
{key=P3; //读按键状态
key=~key; //按键状态取反
}
delayms(5); //有键按下,延时10ms去抖
do
{
key=P3; //再次读按键状态
key=~key; //按键状态取反
}while(key==0);
switch(key) //根据键值调用不同的处理函数
{case 0x01:a=0;break; //K1按下
case 0x02:a=1;break; //K2按下
case 0x04:a=2;break; //K3按下
case 0x08:a=3;break; //K4按下
default:break;
}
do
{w=0x01;//位选码初值为01H
for(n=0;n<8;n++)
{ P2=~w; //位选码取反后送位控制口P2口
w<<=1; //位选码左移一位,选中下一位LED
P1=display[a*8+n]; //显示字型码送P1口
delayms(1);//延时1ms
P1=0xff;
}
key=P3;//再次读按键状态
key=~key;//按键状态取反
}while(key==0);//没有其他按键按下,一直显示原来的状态
}
}
《单片机基础与应用(C语言版)》
高等教育出版社
实例31 LED显示矩阵式键盘按键号
实例要求
实例分析
为了节约单片机硬件接口资源,当系统需要按键数量较多时,一般采用矩阵键盘接口方式。16个按键采用4×4矩阵键盘连接方式,用逐列扫描法得到键盘的按键号。
采用单片机控制1个LED显示矩阵键盘的按键号0~F。
硬件电路
控制程序设计
//程序:ex34.c
//功能:LED显示矩阵键盘的按键号0-F
#include //包含头文件REGX51.H,定义了51单片机的所有SFR
//函数名:delayms
//函数功能:实现软件延时
//形式参数:无符号整型变量i,控制时间为i*1ms
//返回值:无
void delayms(unsigned int i)
{unsigned char k;
while(i--)
for(k=0;k<120;k++); //120次空操作
}
char scan_key (void); //键盘扫描函数
void main() //主函数
{
unsigned char led[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,
0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
//0~9、A~F的共阳极显示码
unsigned char i;
P1=0xff;
P0=0xff; //P0口低4位做输入口,先输出全1
while(1)
{
i=scan_key(); //调用键盘函数
if(i==-1)continue; //没有键按下,继续循环
else
P1=led[i]; //显示按下键的数字号
}
}
控制程序设计
//函数名:scan_key
//函数功能:判断是否有键按下,如果有键按下,逐列扫描法得到键值
//形式参数:无
//返回值:键值0~15,-1表示无键按下
char scan_key ( )
{
char i, temp,m,n;
bit find=0; //有键按下标志位
P2=0xf0; //向所有的列线上输出低电平
i=P0; //读入行值
i&=0x0f; //屏蔽掉高4位
if(i!=0x0f) //行值不为全1,有键按下
{
delayms(10); //延时消抖
i=P0; //再次读入行值
i&=0x0f; //屏蔽掉高4位
if(i!=0x0f)
{ //第2次判断有键按下
for(i=0;i<4;i++)
{
P2=0xfe<temp=~P0; //读行值,并取反,全1→全0
temp=temp&0x0f; //屏蔽掉行值高4位
if(temp!=0x00) //判断有无键按下,为0则无键按下,否则有键按下
{ m=i; //保存列号至m变量
find=1; //置找到按键标志
switch(temp)//判断哪一行有键按下,记录行号到n变量
{ case 0x01:n=0;break; //第0行有键按下
case 0x02: n=1;break; //第1行有键按下
case 0x04: n=2;break; //第2行有键按下
case 0x08: n=3;break; //第3行有键按下
default:break;
}
break; //有键按下,退出for循环
}
}
}
}
if(find==0) return -1; //无键按下则返回-1
else return(n*4+m); //否则返回键值,键值=列号*4+行号
}
感谢您的观看
Thanks for your attention.

展开更多......

收起↑

资源列表