单片机 跑马灯实验
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
for(i=0;i<10000;i++);
}
void forward(){
for(n=0;n<=7;n++){
out=D[n];
delay(15);
if(P2!=oldK&&P2!=K[0])
break;
}
out=AllOff;
}
void backward(){
for(n=7;n>=0;n--){
out=D[n];
2、采用I/O口作为输入口时要注意什么?键控的流水灯时为什么要在延时程序中检测是否按键?
当作为输入口时候是单片机接收IC的数据信息,或者是灌电流,这时候要考虑电流的大小是否在单片机的承受范围内。为了防止在延时程序中间有按键按下却检测不到的情况,即放在延时中检测间隔时间短,反应快。
3、为什么延时程序要做一个函数?
void hold(){
n=8;
while(1){
if(P2==K[4]){//一直按着K4键,逆序点亮跑马灯
oldK=K[4];
if(n==-1)n=7;//D0灯亮后点亮D7
while(n>=0){
out=D[n];
n--;
if(delay4(15))break;
}
}
if(P2==K[0]){//未按下K4键,一直正序点亮跑马灯
所用硬件:AT89C52、BUTTON、LED-BLUE、电源
输入:P2.0-K1;P2.1-K2;P2.2-K3;P2.3-K4。低电平有效
输出:P0.0~P0.7-D0~D7。LED组连线采用共阳极,低电平有效
软件设计:
软件延时采用延时函数delay(t),可调整延迟时间:
void delay(uint t){
图41基本的流水灯
2、简单键控的流水灯:
按下K4键即点亮D7灯,若一直按着K4键逆序点亮流水灯,松开则顺序点亮流水灯,且按键状态改变时送当前已亮的灯开始变换顺序而不是从D0或D7灯开始亮灯。(如图4-2)
图4-2简单键控的流水灯
3、键控的流水灯:
K1键按下顺序点亮流水灯,K2键按下逆序点亮流水灯,K3键按下全局灭灯。(如图4-3)
uint i;
while(t--)
for(i=0;i<1000;i++){
if(P2!=oldK&&P2!=K[0])break;//按下了其他键退出循环
}
}
由于涉及到按键变化所以要设置一个变量oldK保留按键键值,要在延时程序中检测是否按键,当按键后立即设置oldK的值。
按键判断采用在while循环中利用条件语句判断P2的值然后执行该键对应的代码段,达到相应的响应。
图43键控的流水灯
五、实验思考题
1、采用I/O口作为输出口时要考虑哪些因素?为什么实验装置中LED要串联一个电阻?
当作为输出口时候就是单片机向外发出数据,或者再产生拉电流,单片机的拉电流一般要比灌电流小,基本上就能点亮2,3个LED,功率很有限,所以一般时候必须用驱动芯片来驱动单片机的外围器件。串联电阻是为了保护电路。
3
上电,不点亮LED,按一下K1键,按正序点亮流水灯。按一下K2键,按倒序点亮流水灯,按一下K3键,全部关闭LED。
二、实验方案
1
考虑到K4键未被使用,所以将实验内容中的三项合并到一个主函数中:K4键代替实验内容第二项中的K1键;单片机一开机即执行实验内容第一项;K1、K2、K3键实现实验内容第三项。
uchar AllOn=0x00;//LED全亮
uchar K[]={0xff,0xfe,0xfd,0xfb,0xf7};//按键开关
uchar oldK;//记录已按键
int n;
2、顺序、逆序点亮流水灯:
void forward(){
for(n=0;n<=7;n++){
out=D[n];
delay(15);
break;
}
}
}
//P2.2_K3键按下关闭全部LED
if(P2==K[3]){
oldK=K[3];
out=AllOff;
}
//P2.3_K4键按下长按逆序点亮流水灯,不按正序点亮流水灯,直到其他键按下停止
if(P2==K[4]){
hold();
}
}
}
}
四、实验结果
1、基本的流水灯:
开机后即重复顺序点亮流水灯,等待其他按键。(如图4-1)
实验一
一、实验内容
1
根据图1电路,编写一段程序,使8个发光二极管D1、D2、D3、D4、D5、D6、D7、D8顺序(正序)点亮:先点亮D1,再点亮D2、D3……D8、D1……,循环点亮。每点亮一个LED,采用软件延时一段时间。
2
不按键,按正序点亮流水灯;按下K1不松手,按倒序点亮流水灯,即先点亮D8,再顺序点亮D7、D6……D1、D8……。松手后,又按正序点亮流水灯。
在调试过程中,我发现定义但未使用的变量或函数编译后会报警告,其余语法与传统C一样,因此在编程过程中并未遇到什么特别的问题,对于本实验涉及到的算法对于我来说也不是什么难事。在软件延时的函数延时方面,我发现对于不同处理函数其延时时间并不是很准确,若要满足准确的延时还需要用到定时器。
总的来说,本次实验完成地很顺利,所有实验内容也全部完成了,我也对单片机的使用及C51的编程有了很大的兴趣,期待下一次的实验也能顺利完成!
if(P2!=oldK&&P2!=K[0])
break;
}
out=AllOff;
}
void backward(){
for(n=7;n>=0;n--){
out=D[n];
delay(15);
if(P2!=oldK&&P2!=K[0])
break;
}
out=AllOff;
}
3、实验内容第二项流水灯灯亮顺序变换:
oldK=K[0];
if(n==8)n=0;//D7灯亮后点亮D0
while(n<=7){
out=D[n];
n++;
if(delay4(15))break;
}
}
if(P2!=K[4]&&P2!=K[0]){//按下了其他键,退出hold函数
break;
}
}
}
void main(){
oldK=K[0];
}
void hold(){
n=8;
while(1){
if(P2==K[4]){//一直按着K4键,逆序点亮跑马灯
oldK=K[4];
if(n==-1)n=7;//D0灯亮后点亮D7
while(n>=0){
out=D[n];
n--;
if(delay4(15))break;
}
}
if(P2==K[0]){//未按下K4键,一直正序点亮跑马灯
delay(15);
if(P2!=oldK&&P2!=K[0])
break;
}
out=AllOff;
}
int delay4(uint t){
uint i;
while(t--)
for(i=0;i<1000;i++){
if(P2!=oldK){//按键变化退出循环
return 1;
}
}
return 0;
oldK=K[1];
while(1){
forward();
if(P2!=K[1]&&P2!=K[0]){//按下了其他键,退出
break;
}
}
}
//P2.1_K2键按下逆序点亮流水灯
if(P2==K[2]){
oldK=K[2];
while(1){
backward();
if(P2!=K[2]&&P2!=K[0]){//按下了其他键,退出
while(1){//开机即正序点亮流水灯
forward();
if(P2!=K[0]){
break;
}
}
2
图21实验原理图
3
图22程序流程图
三、源程序
#include"reg51.h"
#define uchar unsigned char
#defiLeabharlann Baidue uint unsigned int
#define out P0
oldK=K[0];
if(n==8)n=0;//D7灯亮后点亮D0
while(n<=7){
out=D[n];
n++;
if(delay4(15))break;
}
}
if(P2!=K[4]&&P2!=K[0]){//按下了其他键,退出hold函数
break;
}
}
}
4、对应实验内容第一项,开机顺序点亮流水灯:
while(1){//开机即正序点亮流水灯
forward();
if(P2!=K[0]){
break;
}
}
while(1){
out=AllOff;
if((P2&0x0f)!=0x0f){//检测有键按下
delay10ms();//延时10ms再去检测
//P2.0_K1键按下正序点亮流水灯
if(P2==K[1]){
uchar D[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0X7f};//单个LED亮
uchar AllOff=0xff;//LED全灭
uchar AllOn=0x00;//LED全亮
uchar K[]={0xff,0xfe,0xfd,0xfb,0xf7};//按键开关
为了让K4键的效果优化,即状态变化从当前已亮灯开始顺序点亮或逆序点亮,利用全局变量n来记录灯号,利用算法即可实现。
主要算法:
1、全局变量的定义:
uchar D[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0X7f};//单个LED亮
uchar AllOff=0xff;//LED全灭
可以具体事情具体处理,方便灵活的调用。
六、总结
通过本次实验,我不仅更熟悉了Protues及Keil软件的使用,对C51编程的使用也更上一层楼,对于C51的编程语句与传统的C语言编程有一些区别,其中的无符号字符型是我在C语言中从未使用过的,在C51编程中会经常用到,用来给单片机的端口赋值或判断端口的值。对于C51的编程,编译报错也与传统C不同。
uchar oldK;//记录已按键
int n;//记录当前亮的灯号
void delay(uint t){
uint i;
while(t--)
for(i=0;i<1000;i++){
if(P2!=oldK&&P2!=K[0])break;//按下了其他键退出循环
}
}
void delay10ms(){
uint i;
}
void forward(){
for(n=0;n<=7;n++){
out=D[n];
delay(15);
if(P2!=oldK&&P2!=K[0])
break;
}
out=AllOff;
}
void backward(){
for(n=7;n>=0;n--){
out=D[n];
2、采用I/O口作为输入口时要注意什么?键控的流水灯时为什么要在延时程序中检测是否按键?
当作为输入口时候是单片机接收IC的数据信息,或者是灌电流,这时候要考虑电流的大小是否在单片机的承受范围内。为了防止在延时程序中间有按键按下却检测不到的情况,即放在延时中检测间隔时间短,反应快。
3、为什么延时程序要做一个函数?
void hold(){
n=8;
while(1){
if(P2==K[4]){//一直按着K4键,逆序点亮跑马灯
oldK=K[4];
if(n==-1)n=7;//D0灯亮后点亮D7
while(n>=0){
out=D[n];
n--;
if(delay4(15))break;
}
}
if(P2==K[0]){//未按下K4键,一直正序点亮跑马灯
所用硬件:AT89C52、BUTTON、LED-BLUE、电源
输入:P2.0-K1;P2.1-K2;P2.2-K3;P2.3-K4。低电平有效
输出:P0.0~P0.7-D0~D7。LED组连线采用共阳极,低电平有效
软件设计:
软件延时采用延时函数delay(t),可调整延迟时间:
void delay(uint t){
图41基本的流水灯
2、简单键控的流水灯:
按下K4键即点亮D7灯,若一直按着K4键逆序点亮流水灯,松开则顺序点亮流水灯,且按键状态改变时送当前已亮的灯开始变换顺序而不是从D0或D7灯开始亮灯。(如图4-2)
图4-2简单键控的流水灯
3、键控的流水灯:
K1键按下顺序点亮流水灯,K2键按下逆序点亮流水灯,K3键按下全局灭灯。(如图4-3)
uint i;
while(t--)
for(i=0;i<1000;i++){
if(P2!=oldK&&P2!=K[0])break;//按下了其他键退出循环
}
}
由于涉及到按键变化所以要设置一个变量oldK保留按键键值,要在延时程序中检测是否按键,当按键后立即设置oldK的值。
按键判断采用在while循环中利用条件语句判断P2的值然后执行该键对应的代码段,达到相应的响应。
图43键控的流水灯
五、实验思考题
1、采用I/O口作为输出口时要考虑哪些因素?为什么实验装置中LED要串联一个电阻?
当作为输出口时候就是单片机向外发出数据,或者再产生拉电流,单片机的拉电流一般要比灌电流小,基本上就能点亮2,3个LED,功率很有限,所以一般时候必须用驱动芯片来驱动单片机的外围器件。串联电阻是为了保护电路。
3
上电,不点亮LED,按一下K1键,按正序点亮流水灯。按一下K2键,按倒序点亮流水灯,按一下K3键,全部关闭LED。
二、实验方案
1
考虑到K4键未被使用,所以将实验内容中的三项合并到一个主函数中:K4键代替实验内容第二项中的K1键;单片机一开机即执行实验内容第一项;K1、K2、K3键实现实验内容第三项。
uchar AllOn=0x00;//LED全亮
uchar K[]={0xff,0xfe,0xfd,0xfb,0xf7};//按键开关
uchar oldK;//记录已按键
int n;
2、顺序、逆序点亮流水灯:
void forward(){
for(n=0;n<=7;n++){
out=D[n];
delay(15);
break;
}
}
}
//P2.2_K3键按下关闭全部LED
if(P2==K[3]){
oldK=K[3];
out=AllOff;
}
//P2.3_K4键按下长按逆序点亮流水灯,不按正序点亮流水灯,直到其他键按下停止
if(P2==K[4]){
hold();
}
}
}
}
四、实验结果
1、基本的流水灯:
开机后即重复顺序点亮流水灯,等待其他按键。(如图4-1)
实验一
一、实验内容
1
根据图1电路,编写一段程序,使8个发光二极管D1、D2、D3、D4、D5、D6、D7、D8顺序(正序)点亮:先点亮D1,再点亮D2、D3……D8、D1……,循环点亮。每点亮一个LED,采用软件延时一段时间。
2
不按键,按正序点亮流水灯;按下K1不松手,按倒序点亮流水灯,即先点亮D8,再顺序点亮D7、D6……D1、D8……。松手后,又按正序点亮流水灯。
在调试过程中,我发现定义但未使用的变量或函数编译后会报警告,其余语法与传统C一样,因此在编程过程中并未遇到什么特别的问题,对于本实验涉及到的算法对于我来说也不是什么难事。在软件延时的函数延时方面,我发现对于不同处理函数其延时时间并不是很准确,若要满足准确的延时还需要用到定时器。
总的来说,本次实验完成地很顺利,所有实验内容也全部完成了,我也对单片机的使用及C51的编程有了很大的兴趣,期待下一次的实验也能顺利完成!
if(P2!=oldK&&P2!=K[0])
break;
}
out=AllOff;
}
void backward(){
for(n=7;n>=0;n--){
out=D[n];
delay(15);
if(P2!=oldK&&P2!=K[0])
break;
}
out=AllOff;
}
3、实验内容第二项流水灯灯亮顺序变换:
oldK=K[0];
if(n==8)n=0;//D7灯亮后点亮D0
while(n<=7){
out=D[n];
n++;
if(delay4(15))break;
}
}
if(P2!=K[4]&&P2!=K[0]){//按下了其他键,退出hold函数
break;
}
}
}
void main(){
oldK=K[0];
}
void hold(){
n=8;
while(1){
if(P2==K[4]){//一直按着K4键,逆序点亮跑马灯
oldK=K[4];
if(n==-1)n=7;//D0灯亮后点亮D7
while(n>=0){
out=D[n];
n--;
if(delay4(15))break;
}
}
if(P2==K[0]){//未按下K4键,一直正序点亮跑马灯
delay(15);
if(P2!=oldK&&P2!=K[0])
break;
}
out=AllOff;
}
int delay4(uint t){
uint i;
while(t--)
for(i=0;i<1000;i++){
if(P2!=oldK){//按键变化退出循环
return 1;
}
}
return 0;
oldK=K[1];
while(1){
forward();
if(P2!=K[1]&&P2!=K[0]){//按下了其他键,退出
break;
}
}
}
//P2.1_K2键按下逆序点亮流水灯
if(P2==K[2]){
oldK=K[2];
while(1){
backward();
if(P2!=K[2]&&P2!=K[0]){//按下了其他键,退出
while(1){//开机即正序点亮流水灯
forward();
if(P2!=K[0]){
break;
}
}
2
图21实验原理图
3
图22程序流程图
三、源程序
#include"reg51.h"
#define uchar unsigned char
#defiLeabharlann Baidue uint unsigned int
#define out P0
oldK=K[0];
if(n==8)n=0;//D7灯亮后点亮D0
while(n<=7){
out=D[n];
n++;
if(delay4(15))break;
}
}
if(P2!=K[4]&&P2!=K[0]){//按下了其他键,退出hold函数
break;
}
}
}
4、对应实验内容第一项,开机顺序点亮流水灯:
while(1){//开机即正序点亮流水灯
forward();
if(P2!=K[0]){
break;
}
}
while(1){
out=AllOff;
if((P2&0x0f)!=0x0f){//检测有键按下
delay10ms();//延时10ms再去检测
//P2.0_K1键按下正序点亮流水灯
if(P2==K[1]){
uchar D[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0X7f};//单个LED亮
uchar AllOff=0xff;//LED全灭
uchar AllOn=0x00;//LED全亮
uchar K[]={0xff,0xfe,0xfd,0xfb,0xf7};//按键开关
为了让K4键的效果优化,即状态变化从当前已亮灯开始顺序点亮或逆序点亮,利用全局变量n来记录灯号,利用算法即可实现。
主要算法:
1、全局变量的定义:
uchar D[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0X7f};//单个LED亮
uchar AllOff=0xff;//LED全灭
可以具体事情具体处理,方便灵活的调用。
六、总结
通过本次实验,我不仅更熟悉了Protues及Keil软件的使用,对C51编程的使用也更上一层楼,对于C51的编程语句与传统的C语言编程有一些区别,其中的无符号字符型是我在C语言中从未使用过的,在C51编程中会经常用到,用来给单片机的端口赋值或判断端口的值。对于C51的编程,编译报错也与传统C不同。
uchar oldK;//记录已按键
int n;//记录当前亮的灯号
void delay(uint t){
uint i;
while(t--)
for(i=0;i<1000;i++){
if(P2!=oldK&&P2!=K[0])break;//按下了其他键退出循环
}
}
void delay10ms(){
uint i;