赞
踩
仿真图有误还未修改,请自行鉴别
实验二 独立按键控制数码管显示
一、实验目的
1、掌握数码管工作原理
2、掌握独立按键的工作原理
二、实验软硬件
1、Keil uVision4或者Keil uVision5;
2、仿真软件Proteus8,烧录软件stc-isp;
3、普中51开发板;
三、学习内容
1、独立按键的输入原理和编程方法;
2、单片机控制数码管显示的原理,数码管轮流显示同时显示的实现;
3、中断和查询法控制灯的亮灭;
四、实验任务
本次实验需要在proteus上仿真,并烧录到开发板。
任务一:
编写程序,使用独立按键,实现以下功能:
1、按键K3按下,8个LED从左向右形成流水灯的效果,
2、按键K4按下,8个LED从右向左形成流水灯的效果,
任务二:
编写程序,使用中断函数实现以下功能:
1、数码管初始显示值为0。当按键K3按下,使数码管计数,记录按下的次数;
2、 当按键次数达到9时,蜂鸣器报警数码管显示值归0;
**注意:**数码管的驱动方式请查看附带PPT自行设计;
任务三:
编写程序,编写一分钟计时程序,并在数码管显示。使用开发板实现以下功能:
1、使用按键K1 K2 K3,做控制,分别为开始计时、暂停计时、计时清零;
2、开始计时(K1):每次从零开始计时
3、暂停计时(K2):按一次暂停计时,再次按下继续从停止时间计时;
4、计时清零(K3):计时清零,显示00;
编写程序,使用独立按键,实现以下功能:
1、按键K3按下,8个LED从左向右形成流水灯的效果,
2、按键K4按下,8个LED从右向左形成流水灯的效果,
由开发板原理图可知K3和K4分别对应单片机P3.2和P3.3单片机
在第一次任务仿真图基础上,稍作修改即可
用if语句判断K3和K4是否按下,哪一个按下便执行对应的代码块
代码实现如下:
#include <stdio.h>
#include <reg52.h>
typedef unsigned int u16;
typedef unsigned char u8;
#define LED P2
/*定义按键控制位*/
sbit K3 = P3^2;
sbit K4 = P3^3;
/*延时函数*/
void delay(unsigned int ms)
{
u16 i,j;
for(i=0;i<ms;++i)
for(j=0;j<110;++j);
}
/*主函数*/
void main()
{
u16 i;
/*左移和右移LED亮灭状态数组*/
char led_L[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
char led_R[] = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
while (1)
{
if(K3 == 0)
{
for(i=0;i<8;i+=1)
{
LED = led_L[i];
delay(500);
}
}
if(K4 == 0)
{
for(i=0;i<8;i+=1)
{
LED = led_R[i];
delay(500);
}
}
}
}
编写程序,使用中断函数实现以下功能:
1、数码管初始显示值为0。当按键K3按下,使数码管计数,记录按下的次数;
2、 当按键次数达到9时,蜂鸣器报警数码管显示值归0;
**注意:**数码管的驱动方式请查看附带PPT自行设计;
根据HC6800-ES V2.0开发板原理图
74HC573数码管控制驱动电路
74LS138八选一选择器原理图
可作Proteus仿真图如下:
数码管显示各部分代码实现详见:从零开始玩转C51之02. 数码管-CSDN博客
中断详解暂时还没写,可移步其他博文。
#include <stdio.h>
#include <intrins.h>
#include <reg52.h>
#define SEG P0
/*定义位选控制位*/
sbit A2=P2^4;
sbit A1=P2^3;
sbit A0=P2^2;
sbit K3 = P3^2;
sbit BEEP = P1^5;
typedef unsigned int u16;
typedef unsigned char u8;
/*存储段选数据*/
u8 code SEG_DATA[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,//共阴0 1 2 3 4 5 6 7 8 9
0x77,0x7c,0x39,0x5e,0x79,0x71};//A B C D E F
/*定义计数变量*/
static u16 cnt=0;
/*延时函数*/
void delay(unsigned int ms)
{
u16 i,j;
for(i=0;i<ms;++i)
for(j=0;j<110;++j);
}
/*设置外部中断0*/
void Int0Init()
{
IT0=1;//跳变沿出发方式(下降沿)
EX0=1;//打开INT0的中断允许。
EA=1;//打开总中断
}
/*主函数*/
void main()
{
u16 i,j;
while (1)
{
Int0Init();
while(1){
SEG = SEG_DATA[cnt%10];//用取余函数,实现0~9周期显示
if(cnt%10 ==9)
{
do{
BEEP = ~BEEP;
delay(1);
}while(K3);
if(K3 == 0)
BEEP = 0;
}
}
}
}
/*外部中断0的中断函数*/
void Int0() interrupt 0
{
if(K3==0)
{
delay(100);//延时消抖,可调节delay时间调整好消抖效果
if(K3==0)
{
cnt++;
}
}
}
编写程序,编写一分钟计时程序,并在数码管显示。使用开发板实现以下功能:
1、使用按键K1 K2 K3,做控制,分别为开始计时、暂停计时、计时清零;
2、开始计时(K1):每次从零开始计时
3、暂停计时(K2):按一次暂停计时,再次按下继续从停止时间计时;
4、计时清零(K3):计时清零,显示00;
#include <stdio.h>
#include <reg52.h>
#include <intrins.h>
#define SEG P0
/*定义位选控制位*/
sbit A2=P2^4;
sbit A1=P2^3;
sbit A0=P2^2;
/*定义按键控制位*/
sbit K1 = P3^1;
sbit K2 = P3^0;
sbit K3 = P3^2;
typedef unsigned int u16;
typedef unsigned char u8;
/*存储段选数据*/
u8 code SEG_DATA[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,//共阴0 1 2 3 4 5 6 7 8 9
0x77,0x7c,0x39,0x5e,0x79,0x71};//A B C D E F
/*定义计时变量*/
u8 gmsec=0;//毫秒级定义
u8 gsec=0;//秒定义
/*延时函数*/
void delay(unsigned int ms)
{
u16 i,j;
for(i=0;i<ms;++i)
for(j=0;j<110;++j);
}
void delay10ms(void) //用于数码管位选扫描显示
{
unsigned char a,b,c;
for(c=1;c>0;c--)
for(b=38;b>0;b--)
for(a=130;a>0;a--);
}
/*定时器0初始化*/
void time0_init(void)
{
TMOD|=0X01;//选择为定时器0模式,工作方式1
TH0=0XDC; //给定时器赋初值,定时10ms
TL0=0X00;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=0;//关闭定时器
}
void time0_start(void)
{
TR0=1;//打开定时器
}
void time0_stop(void)
{
TR0=0;//关闭定时器
TH0=0X00;
TL0=0X00;
}
/*简易按键扫描*/
void key_scan()
{
if(K1 == 0)//从零开始计时
{
time0_start();
gsec = 0;
}
if(K2 == 0)
{
delay(1);//按键消抖
if(K2 == 0)
{
TR0=!TR0;//利用取反运算实现暂停和计时
}
}
if(K3 == 0)
{
time0_stop();//计时清零,显示00
gsec = 0;
}
}
/*动态显示实现两位数显示*/
void display_smg()
{
u16 i;
for(i=0;i<2;i++)
{
switch(i)
{
case(0):
A2=0;A1=0;A0=0;
SEG = SEG_DATA[gsec%10];//显示个位
break;
case(1):
A2=0;A1=0;A0=1;
SEG = SEG_DATA[gsec/10];//显示十位
break;
}
delay10ms();
}
}
/*主函数*/
void main()
{
time0_init();
while(1){
key_scan();
display_smg();
}
}
/*定时器0中断函数*/
void time0() interrupt 1 //定时器0中断函数
{
TH0=0XDC; //给定时器赋初值,定时10ms
TL0=0X00;
gmsec++;//10ms加1次
if(gmsec==100)//定时1秒
{
gmsec=0;
gsec++;//对秒计数
if(gsec == 61)
{
gsec = 0;
}
}
}
虽然代码不是很优雅,但好在能实现功能,等有时间再来优化吧。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。