UAV2201~UAV2205编程与仿真51MCU初学者训练
练习001:51单片机Proteus仿真:点亮一个灯
1、器件清单
Proteus关键词 | 元器件 |
---|---|
CAP | 固定电容 |
CAP-ELEC | 电解电容 |
AT89C51 | AT89C51单片机 |
CRYSTAL | 晶振 |
BUTTON | 复位按键 |
RES | 电阻 |
RESPACK | 排阻 |
LED-YELLOW | 黄色发光二极管 |
2、电路
3、代码
//例子01 #include <reg52.h> //单片机头文件 sbit LED=P2^0; //定义LED为端口P2^0 void main() //主程序 { while(1) //无限循环 { LED=0; //P0^0输出低电平,发光二极管点亮 //LED=1; //P0^0输出高电平,发光二极管关闭 } }
//例子02
#include <reg52.h> sbit D7 = P2^7; unsigned int a; void main() { while(1) { D7 = 0; a = 20000; while(a--); D7 = 1; a = 20000; while(a--); } }
//例子03 #include <reg52.h>
void delay() { unsigned int z=20000; while(z--); } void main() { while(1) { P2 = 0XFE; delay(); P2 = 0xFF; delay(); } }
//例子04 #include <reg52.h>
void delay(unsigned int z) { while(z--); } void main() { while(1) { P2 = ~((1<<0)|(1<<2)|(1<<7)); delay(27765);//精确延迟250ms,在12MHz时钟 P2 = 0xFF; delay(27765); } }
//例子05 #include <reg52.h> void delay(void) { unsigned int x,y; for(x=100;x>0;x--) { for(y=600;y>0;y--) { ; } } } void main() { while(1) { P2 = 0x55;//01010101 delay(); //延迟480ms P2 = 0xaa;//10101010 delay(); //延迟480ms } }
//例子06 #include <reg52.h> void delay(void); void main() { while(1) { P2 = ~P2; delay(); } } void delay(void) { unsigned int x,y; for(x=100;x>0;x--) for(y=600;y>0;y--); }
//例子07 #include <reg52.h> void delay(unsigned int z); void main() { while(1) { P2 = 0xF0; delay(100);//精确延迟1s P2 = 0x0F; delay(100);// } } void delay(unsigned int z)//z=1,精确度10ms { unsigned char i,j,k; for(i=z;i>0;i--) for(j=4;j>0;j--) for(k=248;k>0;k--); }
//高精度延迟函数适用于STC89系列单片机
void Delay500ms() //@12.000MHz { unsigned char data i, j, k; _nop_(); i = 4; j = 205; k = 187; do { do { while (--k); } while (--j); } while (--i); }
练习002:51单片机Proteus仿真:流水灯
1、器件清单(参考练习001)
2、电路
1、画一条总线
2、将线路连接到总线
按住ctrl划线,画斜线连接线需要把”自动连接器”也称“自动连线”按钮放开。
3、将相应节点一一连接
Tool–Property Assignment Tool属性赋值工具
3、代码
//例子01、基础移位法
#include <reg52.h> void delay(unsigned int z); void main(void) { while(1) { P2 = ~(1<<0); delay(20); P2 = ~(1<<1); delay(20); P2 = ~(1<<2); delay(20); P2 = ~(1<<3); delay(20); P2 = ~(1<<4); delay(20); P2 = ~(1<<5); delay(20); P2 = ~(1<<6); delay(20); P2 = ~(1<<7); delay(20); } } void delay(unsigned int z) //当z=1,延迟时间10ms { unsigned char i,j,k; for(i=z;i>0;i--) for(j=4;j>0;j--) for(k=248;k>0;k--); }
//例子02、for语句移位
void main(void) { unsigned char i; while(1) { for(i=0;i<8;i++) { P2 = ~(1<<i); delay(50); } } }
//例子03、if语句
void main(void) { unsigned char a; while(1) { if(a==0x00)a=0x01; P2 = ~a; a=a<<1; delay(20); } }
//例子04、流水灯右移
#include <reg52.h> //单片机头文件 void Delay(); //延时子程序说明 void main() //主程序 { unsigned char i,temp; P2=0xff; //二进制1111 1111 while(1) //无限循环 { temp=0x80; //二进制10000000 for(i=0;i<8;i++) { P2=~temp; //取反0111 1111 Delay(); //延时函数 temp=temp>>1; //右移一位 } } } /*延时子程序使LED在变化时有一个停留时间,通过一个外循环和内循环的空操作,共循环255×255次*/ void Delay() { unsigned char i,j; for(i=0;i<255;i++) //外循环255次 for(j=0;j<255;j++); //内循环255次 }
//例子05、流水灯左移
#include <reg52.h> void delay(unsigned int z); void main(void) { unsigned char i,temp; while(1) { temp=0xfe; for(i=0;i<8;i++) { P2 = temp; delay(30); temp =(temp<<1)|0x01;//右移编写temp = (temp>>1)|0x80; } } } void delay(unsigned int z) //当z=1,延迟时间10ms { unsigned char i,j,k; for(i=z;i>0;i--) for(j=4;j>0;j--) for(k=248;k>0;k--); }
//例子06、流水灯采用C51内部移位子函数
#include <reg52.h> #include <intrins.h> void delay(unsigned int z); void main(void) { unsigned char temp=0xfe; while(1) { P2 = temp; delay(30); temp =_crol_(temp,1);//循环左移函数_crol_循环右移函数_cror_ } } void delay(unsigned int z) //当z=1,延迟时间10ms { unsigned char i,j,k; for(i=z;i>0;i--) for(j=4;j>0;j--) for(k=248;k>0;k--); }
//例程07 流水灯运用数组调用实现 #include <reg52.h> unsigned char Tab[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; void delay(unsigned int xms) { unsigned int i,j; for(i=xms;i>0;i--) for(j=123;j>0;j--); } void main() { unsigned char i; while(1) { for(i=0;i<8;i++) { P2 = ~Tab[i]; delay(100); } } }
//例子08、流水灯运用一维数组实现,反向显示跑马灯
#include <reg52.h> void delay(unsigned int z); void main() { unsigned char display1[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; unsigned char display2[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; unsigned char i,j; while(1) { for(i=0;i<8;i++) { P2=display1[i]; delay(30); } for(j=0;j<8;j++) { P2 = display2[j]; delay(30); } } }
//例子08、花样年华流水灯,任意LED动态显示(略)
练习003:51单片机Proteus仿真:一位数码管计数
1、器件清单
Proteus关键词 | 元器件 |
---|---|
AT89C51 | AT89C51单片机 |
RES | 电阻 |
BUTTON | 按键 |
7SEG-COM-AN-GRN | 数码管(绿色) |
数码管接线结构图
数码管有两种,共阴和共阳,很好区分的,公共端在上边的就是共阳的,习惯上画VCC时是放在上边的,公共端在下边的就是共阴了,画地时习惯上放在下边的。再说数码管的7段,从上边的横开始起叫A,按顺时针方向依此为ABCDEFG,最后说左边的引脚,从上边开始向下,依此是ABCDEFG。这样就对应上了,根据显示数字的需要在各段加有效电平就显示出相应的数字了。如下面的图是一种测试方法。左边的两个就是共阳的,右边的一个就是共阴的。
2、电路(左图自动,右图手动)
3、代码
//例子01、单个数码管循环显示字符0-F,运用if语句(自动计数0-9) #include <reg52.h> unsigned char smg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92, 0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; //共阳极8段 void delay(unsigned int z); void main(void) { unsigned char i; while(1) { P2 = smg[i];//送相应数码管段表值 delay(50); i++; if(i>=16)i=0;//if(i>9) i=0; } } void delay(unsigned int z) //当z=1,延迟时间10ms { unsigned char i,j,k; for(i=z;i>0;i--) for(j=4;j>0;j--) for(k=248;k>0;k--); }
//例子02、1位数码管自动计数,运用for语句,包含小数点 #include <reg52.h> unsigned char code Tab[]={0xC0,0xF9,0xA4,0XB0,0x99,0x92, 0x82,0xF8,0x80,0x90}; //0-9,共阳数码管码段表 bit point_on = 0;//点亮小数点 void delay(unsigned int z) //当z=1,延迟时间10ms { unsigned char i,j,k; for(i=z;i>0;i--) for(j=4;j>0;j--) for(k=248;k>0;k--); } void main(void) { unsigned char i=0; while (1) { for (i=0;i<=9;i++) { P2 = Tab[i]; if (point_on) { P2 &= 0x7f; } delay(50); } point_on = ~point_on; } }
//例子03、4位数码管,动态扫描方法,显示0123 #include <reg52.h> unsigned char code Tab[]={0xC0,0xF9,0xA4,0XB0,0x99,0x92, 0x82,0xF8,0x80,0x90}; //0-9,共阳数码管码段表 void delay(unsigned int z) //当z=1,延迟时间10ms { unsigned char i,j,k; for(i=z;i>0;i--) for(j=4;j>0;j--) for(k=248;k>0;k--); } void main(void) { unsigned char i=0; while (1) { for (i=0;i<4;i++) { P2 = Tab[i]; P1 = ~(1<<i); delay(1); P1 = 0xff; } } }
//例子04、4位数码管,动态扫描法,独立编写显示子函数,显示任意数1314 #include <reg52.h> unsigned char code Tab[]={0xC0,0xF9,0xA4,0XB0,0x99,0x92, 0x82,0xF8,0x80,0x90}; //0-9,共阳数码管码段表 void delay(unsigned int z) //当z=1,延迟时间10ms { unsigned char i,j,k; for(i=z;i>0;i--) for(j=4;j>0;j--) for(k=248;k>0;k--); } void display() { P2 = Tab[8]; //输入需要显示的数字 P1 = ~(1<<0); //选择显示位 delay(1); P1 = 0xff; P2 = Tab[5]; //输入需要显示的数字 P1 = ~(1<<1); //选择显示位 delay(1); P1 = 0xff; P2 = Tab[2]; //输入需要显示的数字 P1 = ~(1<<2); //选择显示位 delay(1); P1 = 0xff; P2 = Tab[0]; //输入需要显示的数字 P1 = ~(1<<3); //选择显示位 delay(1); P1 = 0xff; } void main(void) { while (1) { display(); } }
//例子05、4位数码管,显示函数封装为子函数,可以显示任意的四位数 void display(unsigned int dat) { P2 = Tab[dat/1000%10]; //显示数字千位 P1 = ~(1<<0); //选择显示位 delay(1); P1 = 0xff; P2 = Tab[dat/100%10]; //显示数字百位 P1 = ~(1<<1); //选择显示位 delay(1); P1 = 0xff; P2 = Tab[dat/10%10]; //显示数字十位 P1 = ~(1<<2); //选择显示位 delay(1); P1 = 0xff; P2 = Tab[dat%10]; //显示数字个位 P1 = ~(1<<3); //选择显示位 delay(1); P1 = 0xff; } void main(void) { while(1) { display(1314); } }
练习004:51单片机Proteus仿真:按键控制流水灯、按键控制数码管
1、器件清单
2、电路图
3、源代码
//例子01、按键控制,按键P00和P01按下后,流水灯左右移动(含软件消抖) #include <reg52.h> unsigned char smg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92, 0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; //共阳极8段 void delay(unsigned int z); sbit key1=P0^0; //定义按键位置 sbit key2=P0^1; sbit key3=P0^2; sbit key4=P0^3; void main(void) { char i; while(1) { if(key1==0) //判断KEY1是否按下 { delay(3); //延时20ms,屏蔽抖动区 if(key1==0) //再次判断KEY1是否按下 { P2 = ~(1<<i); if(++i>=8)i=0; } while(!key1); //等待按键释放 } else if(!key2) { delay(3); if(!key2) { P2 = ~(1<<i); if(i--<=0)i=8; } while(!key2); } else { P2 &= 0xff; } } } void delay(unsigned int z) //当z=1,延迟时间10ms { unsigned char i,j,k; for(i=z;i>0;i--) for(j=4;j>0;j--) for(k=248;k>0;k--); }
//例子02、按键控制,按键P00和P01按下后,数码管计数(含软件消抖),键盘读取编写子函数 #include <reg52.h> unsigned char smg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92, 0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; //共阳极8段 void delay(unsigned int z); sbit key1=P0^0; //定义按键位置 sbit key2=P0^1; sbit key3=P0^2; sbit key4=P0^3; unsigned char readkey(void) { if(!key1) //判断KEY1是否按下 { delay(3); //延时20ms,屏蔽抖动区 if(!key1) //再次判断KEY1是否按下 { while(!key1); //等待按键释放 return 1; //返回键值1 } } else if(!key2) //判断KEY2是否按下 { delay(3); //延时20ms,屏蔽抖动区 if(!key2) //再次判断KEY2是否按下 { while(!key2); //等待按键释放 return 2; //返回键值2 } } return 0; //没有按键按下,返回键值0 } void main(void) { unsigned char num,temp; while(1) { temp = readkey(); if(temp == 1) //判断KEY1是否按下 { num++; if(num==10)num=0; } else if(temp == 2) { if(num==0)num=10; num--; } else { ; } P2 = smg[num]; } } void delay(unsigned int z) //当z=1,延迟时间10ms { unsigned char i,j,k; for(i=z;i>0;i--) for(j=4;j>0;j--) for(k=248;k>0;k--); }
练习004:51单片机Proteus仿真:外部中断控制演示
1、器件清单
2、电路图
3、源代码
//例子01、1位数码管手动计数代码,采用外部中断法 #include <reg52.h> unsigned char code Tab[]={0xC0,0xF9,0xA4,0XB0,0x99, 0x92,0x82,0xF8,0x80,0x90}; //0-9,共阳数码管码段表 unsigned char p=1; void Delay()//简单延时子程序 { unsigned char i; for(i=300;i>0;i--); } void main()//主程序 { EA=1;//开总允许开关 IT0=1;EX0=1;//开外部中断0和外部中断0允许分开关 IT1=1;EX1=1;//开外部中断1和外部中断1允许分开关 while(1) { P2=Tab[p]; //输出码段表 Delay(); } } void intersvr0(void) interrupt 0 using 1 //外部中断0处理子程序 { p++; if(p>9) p=9; } void intersvr1(void) interrupt 2 using 1 //外部中断1处理子程序 { p--; if(p<1) p=1; }
//例子02、中断演示。正常主程序每隔0.5s,数码管依次显示0-F中的1个;当按键K2被按下时,流水灯流动 #include <reg52.h> unsigned char Tab[]={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; void delay(unsigned int z) { unsigned char i,j,k; for(i=z;i>0;i--) for(j=4;j>0;j--) for(k=248;k>0;k--); } void main(void) { unsigned char i; EA=1; EX1=1; IT1=0; while(1) { P0=Tab[i]; P1=0XC0; if(++i>9)i=0; delay(50); } } void intl(void) interrupt 2 { unsigned char i; for(i=0;i<8;i++) { P2=~(1<<i); delay(20); } }