赞
踩
本文用来记录博主学习单片机的过程与方法,希望对入门的同学有所帮助
该篇博客主要讲授如何基于proteus(仿真)+keil实现51单片机的点灯操作,本篇为入门篇,所以会介绍如何使用Proteus进行仿真,以及代码编写思路,实现简单的功能效果。
该软件的安装教程就不多赘述,网上资源很多,主要讲解满足51学习的使用,几个常用的功能。
在Proteus搭成这样即可完成本文章下除了5.数码管的其他所有的仿真任务。
1、常见原件库,按p键即可进行搜索,搜索指定元器件代号既可选入。
51单片机:AT89C52
排阻:RP1(主要用于P0口做串口使用的时候需要接上拉电阻)
LED:LED
按键:BUTTON
数码管:display
动态数码管:7SEG
2、电源、地等元件库。
代码如下(示例):
#include <REGX52.H> void delay(void) { unsigned int i = 40000; while(i--); } void main(void) { unsigned char dat = 0x01, i=0; unsigned int direction = 0; //LED共阴,高电平点亮,设置0x01 P1 = dat; //LED共阳,低电平点亮,设置0xfe,取反即可 //P1 = ~data; while(1){ if (direction == 0){ P1 <<= 1; //P1+=1; //低电平点亮 delay(); if (P1 == 0x80){ direction = 1; } } if (direction == 1){ P1 >>= 1; //P1|=0x80;//低电平点亮 delay(); if (P1 == 0x01){ direction = 0; } } } }
代码思路:
51单片机默认io口输出高电平,led灯采用的共阴极接法,所以初始化为0x01,移动1来使得亮的灯移动
定义一个direction 作为方向的判断符号,当direction为0的时候P1左移一位,相反为1的时候P1右移一位。
仿真
在keil中编译学好的代码,则会在本地该工程文件夹下的Object目录下生成一个后缀为.hex的文件,编译结果中也可以看到文件路径。
在Proteus中双击芯片,点击如图所示的位置,选择上述的hex文件即可进行仿真。
代码如下(示例):
#include <REGX52.H> void delay(void) { unsigned int i = 30000; while(i--); } void main(void) { unsigned char dat = 0x01, i=0, lastDat = 0x80, lastLight = 0xff, lastState = 0x01; int direction = 0; P1 = dat; delay(); while(1){ if (lastDat == 0x01){ lastDat = 0x80; lastLight = 0xff; lastState = 0x01; P1 = lastState | (~lastLight); delay(); } if (direction == 0){ lastState <<= 1; //P1 <<= 1; P1 = lastState | (~lastLight); delay(); if (P1 == (lastDat|(~lastLight))){ lastLight >>= 1; lastDat >>= 1; direction = 1; } } if (direction == 1){ lastState >>= 1; //P1 >>= 1; P1 = lastState|(~lastLight); delay(); if (P1 == (0x01|(~lastLight))){ direction = 0; } } //P1 = dat; } }
不仅定义了方向符号,还多定义了一个变量(0xff)右移与P1状态进行或运算来确保尾灯点亮。
#include <REGX52.H>
void button_led(){
P1 = ~P1;#取反
}
void main(){
P1 = 0xff;
while(1){
while(P3_2);//监测按下
while(!P3_2);//弹起,完成一次按键操作
button_led();//执行
}
}
实现功能:当按下一次按键就会使得P1取反,对应的管脚电平改变。
#include <REGX52.H>
void button_led(void) interrupt 0
{
P1 = ~P1;
}
void main(){
EA = 1;
EX0 = 1;
IT0 = 1;
while(1);
}
实现功能:同3一样,通过按键来控制P1系列管脚的电平变化。
INT0对应的编号为0,INT1对应的编号为2,该编号为interrupt后的数字。
这里使用的是共阴极数码管,可以看见数码管段选接的地。
7个位选接在P0的7个位上。
根据数码管的灯接的位置,输入对应的码值就可以构造出对应图形的数字。
#include <REGX52.H> void delay(){ unsigned int i=40000; while(i--); } void main(){ unsigned char code tab[]={0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x76};#0-9码表 unsigned int i=0; while(1){ if (i>10){ i=0; } P0 = tab[i]; delay(); i++; } }
数码管从0-9循环显示。
位选:左边的八个引脚对应的就是八个位选,跟单个数码管的位选功能一样。
段选:左边的1234为段选,段选表示指定指定哪些数码管亮,这里总共有四个数码管,所以有四个段选位,从左到右对应1234,哪个位输入高电平则对应的数码管可以亮。
例子:在数码管上显示4567
原理:循环改变位选,依次从1-4输出高电平,在对应数码管高电平时给位选输入对应的码值显示指定数字,通过这样一直刷新来达到一直显示数字的目的。
代码(该数码管为共阳数码管):
#include <REGX52.H> void main(){ unsigned char duanxuan[] = {0x01, 0x02, 0x04, 0x08}; unsigned int num=0, displayNum[] = {4, 5, 6, 7}; unsigned char code tab[]={ 0xc0,//0 0xf9,//1 0xa4,//2 0xb0,//3 0x99,//4 0x92,//5 0x82,//6 0xf8,//7 0x80,//8 0x90,//9 0x88,//A 0x83,//B 0xc6,//C 0xa1,//D 0x86,//E 0x8e, //F 0x8c, //P 0xc1,//U 0x91,//Y 0x7c,//L ~0x40, //"-" 0x00,//全亮 0xff //熄灭 }; while(1){ if(num == 4){ num = 0; } P2 = 0x00;//消隐 P0 = tab[displayNum[num]]; P2 = duanxuan[num]; num++; } }
效果
使动态数码管显示:“-56-”,通过中断控制按键,按一次56减一个数,当减到45时再按一次回到56。
#include <REGX52.H> unsigned char disNum[] = {20, 5, 6, 20}; void display(){ unsigned char duanxuan[] = {0x01, 0x02, 0x04, 0x08}; unsigned char code tab[]={ 0xc0,//0 0xf9,//1 0xa4,//2 0xb0,//3 0x99,//4 0x92,//5 0x82,//6 0xf8,//7 0x80,//8 0x90,//9 0x88,//A 0x83,//B 0xc6,//C 0xa1,//D 0x86,//E 0x8e, //F 0x8c, //P 0xc1,//U 0x91,//Y 0x7c,//L ~0x40, //"-" 0x00,//全亮 0xff //熄灭 }; int flag = 4; while(flag){ flag--; P2 = 0x00; P0 = tab[disNum[flag]]; P2 = duanxuan[flag]; } } void key() interrupt 2 { if (disNum[2] == 5 && disNum[1] == 4){ disNum[2] = 6; disNum[1] = 5; } else if (disNum[2] == 0){ disNum[2] = 9; disNum[1] = 4; } else{ disNum[2] -= 1; } } void main(){ EA = 1; EX1 = 1; IT1 = 1; while(1){ display(); } }
仿真1
本文章为博主入门单片机的学习记录,希望可以帮助大家一起学习入门51单片机。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。