51单片机C语言学习知识程序设计源代码.doc
,.51单片机C语言教程例2.2.1编写程序,点亮第一个发光二极管(part2_1.c P27)#include /52系列单片机头文件sbit led1=P10; /声明单片机P1口的第一位void main() /主函数led1=0; /*点亮第一个发光二极管*/例2.2.2编写程序,点亮P1口的若干二极管(part2_2.c P39)#include /52系列单片机头文件void main() /主函数P1=0xaa; /while(1);例2.5.1利用for语句延时特性,编写第一个发光二极管以间隔1S亮灭闪动的程序(part2_3.c P42)#include /52系列单片机头文件#define uint unsigned int /宏定义sbit led1=P10; /声明单片机P1口的第一位uint i,j;void main() /主函数while(1) /大循环led1=0;/*点亮第一个发光二极管*/for(i=1;i0;i-)/延时for(j=110;j0;j-);led1=1;/*关闭第一个发光二极管*/for(i=1000;i0;i-)/延时for(j=110;j0;j-);例2.6.1编写程序使第一个发光二极管以间隔500ms亮灭闪动。(part2_4.c P48)#include /52系列单片机头文件#define uint unsigned int /宏定义sbit led1=P10; /声明单片机P1口的第一位void delay1s();/声明子函数void main()/主函数while(1) /大循环led1=0;/*点亮第一个发光二极管*/delay1s();/调用延时子函数led1=1;/*关闭第一个发光二极管*/delay1s();/调用延时子函数void delay1s()/子函数体uint i,j;for(i=500;i0;i-)for(j=110;j0;j-);例2.7.1编写程序使第一个二极管以亮200ms、灭800ms的方式闪动。(part2_5.c P49)#include /52系列单片机头文件#define uint unsigned int /宏定义sbit led1=P10; /声明单片机P1口的第一位void delayms(uint);/声明子函数void main()/主函数while(1) /大循环led1=0;/*点亮第一个发光二极管*/delayms(200);/延时200毫秒led1=1;/*关闭第一个发光二极管*/delayms(800);/延时800毫秒void delayms(uint xms)uint i,j;for(i=xms;i0;i-) /i=xms即延时约xms毫秒for(j=110;j0;j-);例2.8.3利用C51自带库_crol_(),以间隔500ms,实现流水灯程序(part2_6.c P53)#include /52系列单片机头文件#include #define uint unsigned int /宏定义#define uchar unsigned charvoid delayms(uint);/声明子函数uchar aa;void main()/主函数aa=0xfe;/赋初值11111110 while(1) /大循环P1=aa;delayms(500); /延时500毫秒aa=_crol_(aa,1); /将aa循环左移1位后再赋给aavoid delayms(uint xms)uint i,j;for(i=xms;i0;i-) /i=xms即延时约xms毫秒for(j=110;j0;j-);例3.2.1编写程序使第一个数码管显示8(part2.1_.1c P59)#include /52系列单片机头文件sbit dula=P26; /申明U1锁存器的锁存端sbit wela=P27; /申明U2锁存器的锁存端void main()wela=1; /打开U2锁存器P0=0xFE; /送入位选信号wela=0; /关闭U2锁存器dula=1; /打开U1锁存器P0=0x7F; /送入段选信号dula=0; /关闭U2锁存器while(1); /程序停止到这里例3.2.2让实验板上6个数码管同时点亮,依次显示0到F,时间间隔为0.5ms,循环下去。(part2.1_2.c P61)#include /52系列单片机头文件#define uchar unsigned char#define uint unsigned intsbit dula=P26; /申明U1锁存器的锁存端sbit wela=P27; /申明U2锁存器的锁存端uchar num;unchar code table=0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71;void delayms(uint);void main()wela=1; /打开U2锁存端P0=0xco;/送入位选信号wela=0; /关闭U2锁存端while(1)for(num=0;num0;i-) /i=xms即延时约xms毫秒for(j=110;j0;j-);例3.3.1第一个数码管显示1,时间为0.5s,然后关闭它,立即让第二个数码管显示2,时间为0.5s,在关闭它一直到最后一个数码管显示6,时间同样为0.5s,关闭它之后再回来显示第一个数码管,一直循环下去。(part2.1_3.c P62)例3.5.2用定时器0的方式1实现第一个发光二极管以200ms间隔闪烁,用定时器1的方式1实现数码管前两位59s循环计时。(part2.1_5.c P75)例4.1.1用数码管前两位显示一个十进制数,变化范围为0059,开始时显示00,每按下S2键一次,数值加1;每按下S3键一次,数值减1;每按下S4键一次,数值归零;按下S5键一次,利用定时器功能使数值开始自动每秒加1,再次按下S5键,数值停止加1,保持显示原数。(part2.2_1.c P82)#include /52系列单片机头文件#define uchar unsigned char#define uint unsigned int sbit key1=P34;sbit key2=P35;sbit key3=P36;sbit key4=P37;sbit dula=P26;/申明U1锁存器的锁存端sbit wela=P27;/申明U2锁存器的锁存端uchar code table=0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71;void delayms(uint);uchar numt0,num;void display(uchar numdis) /显示子函数uchar shi,ge; /分离两个分别要显示的数shi=numdis/10;ge=numdis%10; dula=1;P0=tableshi; /送十位段选数据dula=0;P0=0xff;/送位选数据前关闭所有显示,防止打开位选锁存时wela=1;/原来段选数据通过位选锁存器造成混乱P0=0xfe;/送位选数据wela=0;delayms(5);/延时dula=1;P0=tablege; /送个位段选数据dula=0;P0=0xff;wela=1;P0=0xfd;wela=0;delayms(5);void delayms(uint xms)uint i,j;for(i=xms;i0;i-) /i=xms即延时约xms毫秒for(j=110;j0;j-);void init() /初始化函数TMOD=0x01;/设置定时器0为工作方式1(0000 0001)TH0=(65536-45872)/256;/装初值50ms一次中断TL0=(65536-45872)%256;EA=1; /开总中断ET0=1; /开定时器0中断void keyscan()if(key1=0)delayms(10);if(key1=0)num+;if(num=60)/当到60时重新归0num=0;while(!key1);/等待按键释放if(key2=0)delayms(10);if(key2=0)if(num=0)/当到0时重新归60num=60;num-;while(!key2);if(key3=0)delayms(10);if(key3=0)num=0; /清0while(!key3);if(key4=0)delayms(10);if(key4=0)while(!key4);TR0=TR0;/启动或停止定时器0void main()init();/初始化函数while(1) keyscan();display(num);void T0_time() interrupt 1TH0=(65536-45872)/256;/重装初值TL0=(65536-45872)%256;numt0+;if(numt0=20)/如果到了20次,说明1秒时间到numt0=0;/然后把num清0重新再计20次num+;if(num=60)num=0;例4.2.1实验班上电时,数码管不显示,顺序按下矩阵键盘后,数码管上依次显示0F,六个数码管同时静态显示即可。(part2.2_2.c P87)#include /52系列单片机头文件#define uchar unsigned char#define uint unsigned int sbit dula=P26;/申明U1锁存器的锁存端sbit wela=P27;/申明U2锁存器的锁存端uchar code table=0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71;void delayms(uint xms)uint i,j;for(i=xms;i0;i-) /i=xms即延时约xms毫秒for(j=110;j0;j-);void display(uchar num)P0=tablenum; /显示函数只送段选数据dula=1;dula=0;void matrixkeyscan()uchar temp,key; P3=0xfe; temp=P3; temp=temp&0xf0; if(temp!=0xf0) delayms(10); temp=P3; temp=temp&0xf0; if(temp!=0xf0) temp=P3; switch(temp) case 0xee: key=0; break; case 0xde: key=1; break; case 0xbe: key=2; break; case 0x7e: key=3; break; while(temp!=0xf0) temp=P3; temp=temp&0xf0; display(key); P3=0xfd; temp=P3; temp=temp&0xf0; if(temp!=0xf0) delayms(10); temp=P3; temp=temp&0xf0; if(temp!=0xf0) temp=P3; switch(temp) case 0xed: key=4; break; case 0xdd: key=5; break; case 0xbd: key=6; break; case 0x7d: key=7; break; while(temp!=0xf0) temp=P3; temp=temp&0xf0; display(key); P3=0xfb; temp=P3; temp=temp&0xf0; if(temp!=0xf0) delayms(10); temp=P3; temp=temp&0xf0; if(temp!=0xf0) temp=P3; switch(temp) case 0xeb: key=8; break; case 0xdb: key=9; break; case 0xbb: key=10; break; case 0x7b: key=11; break; while(temp!=0xf0) temp=P3; temp=temp&0xf0; display(key); P3=0xf7; temp=P3; temp=temp&0xf0; if(temp!=0xf0) delayms(10); temp=P3; temp=temp&0xf0; if(temp!=0xf0) temp=P3; switch(temp) case 0xe7: key=12; break; case 0xd7: key=13; break; case 0xb7: key=14; break; case 0x77: key=15; break; while(temp!=0xf0) temp=P3; temp=temp&0xf0; display(key); void main()P0=0; /关闭所有数码管段选dula=1;dula=0;P0=0xc0;/位选中所有数码管wela=1;wela=0; while(1) matrixkeyscan();/不停调用键盘扫描程序 例5.3.1用单片机控制ADC0804进行数模转换,当拧动实验板上A/D旁边的电位时,在数码管的前三位以十进制方式显示出A/D转换后的数字量(8位A/D转换后数值在0255变化)。(part2.3_1.c P107)#include /52系列单片机头文件#include #define uchar unsigned char#define uint unsigned int sbit dula=P26;/申明U1锁存器的锁存端sbit wela=P27;/申明U2锁存器的锁存端sbit adwr=P36;/定义AD的WR端口sbit adrd=P37;/定义AD的RD端口uchar code table=0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71;void delayms(uint xms)uint i,j;for(i=xms;i0;i-) /i=xms即延时约xms毫秒for(j=110;j0;j-);void display(uchar bai,uchar shi,uchar ge) /显示子函数 dula=1;P0=tablebai; /送段选数据dula=0;P0=0xff;/送位选数据前关闭所有显示,防止打开位选锁存时wela=1;/原来段选数据通过位选锁存器造成混乱P0=0x7e;/送位选数据wela=0;delayms(5); /延时dula=1;P0=tableshi;dula=0;P0=0xff;wela=1;P0=0x7d;wela=0;delayms(5);dula=1;P0=tablege;dula=0;P0=0xff;wela=1;P0=0x7b;wela=0;delayms(5);void main()/主程序uchar a,A1,A2,A3,adval;wela=1;P0=0x7f; /置CSAD为0,选通ADCS 以后不必再管ADCSwela=0; while(1)adwr=1;_nop_();adwr=0;/启动AD转换_nop_();adwr=1;for(a=10;a0;a-) /TX-1C实验板AD工作频率较低,所以启动转换后要多留点时间用来转换 /这里把显示部分放这里的原因也是为了延长转换时间display(A1,A2,A3);P1=0xff; /读取P1口之前先给其写全1 adrd=1; /选通ADCS_nop_();adrd=0; /AD读使能_nop_();adval=P1;/AD数据读取赋给P1口adrd=1;A1=adval/100;/分出百,十,和个位A2=adval%100/10;A3=adval%10; 例5.5.1用单片机控制DAC0832芯片输出电流,让发光二级管D12由灭均匀变到最亮,再由最亮均匀熄灭。在最亮和最暗时使用蜂鸣器分别警报一声,完成整个周期时间控制在5S左右,循环变化。(part2.3_2.c P121)#include #define uchar unsigned char#define uint unsigned intsbit dula=P26;/申明U1锁存器的锁存端sbit wela=P27;/申明U2锁存器的锁存端sbit dawr=P36;/定义DA的WR端口sbit dacs=P32;/定义DA的CS端口sbit beep=P23;/定义蜂鸣器端口void delayms(uint xms)uint i,j;for(i=xms;i0;i-) /i=xms即延时约xms毫秒for(j=110;j0;j-);void main()uchar val,flag;dula=0;wela=0;dacs=0;dawr=0;P0=0;while(1)if(flag=0)val+=5;P0=val;/通过P0口给DA数据口赋值if(val=255)flag=1;beep=0;delayms(100);beep=1;delayms(50);elseval-=5;P0=val;/通过P0口给DA数据口赋值if(val=0)flag=0;beep=0;delayms(100);beep=1;delayms(50);例6.5.1在上位机上用串口调试助手发送一个字符X,单片机收到字符后返回给上位机“I get X”,串口波特率设为9600bps。(part2.4_1.c P137)#include #define uchar unsigned char#define uint unsigned intunsigned char flag,a,i;uchar code table=I get ;/uchar code table=I, ,g,e,t, ;void init()TMOD=0x20;TH1=0xfd;TL1=0xfd;TR1=1;REN=1;SM0=0;SM1=1;EA=1;ES=1;void main()init();while(1)if(flag=1)ES=0;for(i=0;i6;i+)SBUF=tablei;while(!TI);TI=0;SBUF=a;while(!TI);TI=0;ES=1;flag=0;void ser() interrupt 4RI=0;a=SBUF;flag=1;例6.6.1单片机上电后等待从上位机串口发来的命令,同时在数码管的前三位以十进制方式显示A/D采集的数值,在未收到上位机发送来的启动A/D转换命令之前数码管始终显示000。当收到上位机以十六进制发送来的01后,向上位机发送字符串“Turn on ad!”同时间隔1s读取一次A/D的值,然后把A/D采集回来的8位二进制转换成十进制表示的实际电压浮点数,并且从串口发送给上位机,形式如“The voltage is 3.398438V”,发送周期也是一秒一次,同时在数码管上也要每秒刷新现实的数值。当收到上位机以十六进制发送过来的02后,向上位机发送字符串“Turn off ad!”,然后停止发送电压值,数码管上显示上次结束时保持的值。当收到上位机发来的其他任何数时,向上位机发送字符串“Error!”。(part2.4_2.c P140)#include #include #include #define uchar unsigned char#define uint unsigned intsbit dula=P26;/申明U1锁存器的锁存端sbit wela=P27;/申明U2锁存器的锁存端sbit adwr=P36;/定义AD的WR端口sbit adrd=P37;/定义AD的RD端口uchar flag,a;unsigned char flag_uart,flag_time,flag_on,a,i,t0_num,ad_val;float ad_vo;uchar code table=0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71;void delayms(uint xms)uint i,j;for(i=xms;i0;i-) /i=xms即延时约xms毫秒for(j=110;j0;j-);void init()TMOD=0x21;/SCON=0x50;TH0=(65536-50000)/256;TL0=(65536-50000)%256;TH1=0xfd;TL1=0xfd;TR1=1;ET0=1;SM0=0;SM1=1;REN=1;EA=1;ES=1;void display(uchar value) /显示子函数uchar bai,shi,ge;bai=value/100;/分出百,十,和个位shi=value%100/10;ge=value%10;dula=1;P0=tablebai; /送段选数据dula=0;P0=0xff;/送位选数据前关闭所有显示,防止打开位选锁存时wela=1;/原来段选数据通过位选锁存器造成混乱P0=0x7e;/送位选数据wela=0;delayms(5); /延时dula=1;P0=tableshi;dula=0;P0=0xff;wela=1;P0=0x7d;wela=0;delayms(5);dula=1;P0=tablege;dula=0;P0=0xff;wela=1;P0=0x7b;wela=0;delayms(5);uchar get_ad()uchar adval;adwr=1;_nop_();adwr=0;/启动AD转换_nop_();adwr=1;P1=0xff; /读取P1口之前先给其写全1 adrd=1; _nop_();adrd=0; /AD读使能_nop_();adval=P1;/AD数据读取adrd=1;return adval; void main()init();wela=1;P0=0x7f; /置CSAD为0,选通ADCS 以后不必再管ADCSwela=0;while(1)if(flag_uart=1)flag_uart=0;ES=0;TI=1;switch(flag_on)case 0: puts(Turn on ad!n);TR0=1;break;case 1: printf(Turn off ad!n);TR0=0;break;case 2: puts(Error!n);break;while(!TI);/必须要加TI=0;ES=1;if(flag_time=1)flag_time=0;ad_val=get_ad();ad_vo=(float)ad_val*5.0/256.0;ES=0;TI=1;printf(The voltage is %fVn,ad_vo);while(!TI);TI=0;ES=1;display(ad_val);void timer0() interrupt 1TH0=(65536-50000)/256;TL0=(65536-50000)%256;t0_num+;if(t0_num=20)t0_num=0;flag_time=1;void ser() interrupt 4RI=0;a=SBUF;flag_uart=1;if(a=1)flag_on=0;else if(a=2)flag_on=1;elseflag_on=2;例7.2.1实现1602液晶的第一行显示“I LOVE MCU!”,
收藏
- 资源描述:
-
,.
51单片机C语言教程
例2.2.1编写程序,点亮第一个发光二极管(part2_1.c P27)
#include //52系列单片机头文件
sbit led1=P1^0; //声明单片机P1口的第一位
void main() //主函数
{
led1=0; /*点亮第一个发光二极管*/
}
例2.2.2编写程序,点亮P1口的若干二极管(part2_2.c P39)
#include //52系列单片机头文件
void main() //主函数
{
P1=0xaa;
//while(1);
}
例2.5.1利用for语句延时特性,编写第一个发光二极管以间隔1S亮灭闪动的程序(part2_3.c P42)
#include //52系列单片机头文件
#define uint unsigned int //宏定义
sbit led1=P1^0; //声明单片机P1口的第一位
uint i,j;
void main() //主函数
{
while(1) //大循环
{
led1=0; /*点亮第一个发光二极管*/
for(i=1;i>0;i--) //延时
for(j=110;j>0;j--);
led1=1; /*关闭第一个发光二极管*/
for(i=1000;i>0;i--) //延时
for(j=110;j>0;j--);
}
}
例2.6.1编写程序使第一个发光二极管以间隔500ms亮灭闪动。(part2_4.c P48)
#include //52系列单片机头文件
#define uint unsigned int //宏定义
sbit led1=P1^0; //声明单片机P1口的第一位
void delay1s(); //声明子函数
void main() //主函数
{
while(1) //大循环
{
led1=0; /*点亮第一个发光二极管*/
delay1s(); //调用延时子函数
led1=1; /*关闭第一个发光二极管*/
delay1s(); //调用延时子函数
}
}
void delay1s() //子函数体
{
uint i,j;
for(i=500;i>0;i--)
for(j=110;j>0;j--);
}
例2.7.1编写程序使第一个二极管以亮200ms、灭800ms的方式闪动。(part2_5.c P49)
#include //52系列单片机头文件
#define uint unsigned int //宏定义
sbit led1=P1^0; //声明单片机P1口的第一位
void delayms(uint); //声明子函数
void main() //主函数
{
while(1) //大循环
{
led1=0; /*点亮第一个发光二极管*/
delayms(200); //延时200毫秒
led1=1; /*关闭第一个发光二极管*/
delayms(800); //延时800毫秒
}
}
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
例2.8.3利用C51自带库_crol_(),以间隔500ms,实现流水灯程序(part2_6.c P53)
#include //52系列单片机头文件
#include
#define uint unsigned int //宏定义
#define uchar unsigned char
void delayms(uint); //声明子函数
uchar aa;
void main() //主函数
{
aa=0xfe; //赋初值11111110
while(1) //大循环
{
P1=aa;
delayms(500); //延时500毫秒
aa=_crol_(aa,1); //将aa循环左移1位后再赋给aa
}
}
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
例3.2.1编写程序使第一个数码管显示8(part2.1_.1c P59)
#include //52系列单片机头文件
sbit dula=P2^6; //申明U1锁存器的锁存端
sbit wela=P2^7; //申明U2锁存器的锁存端
void main()
{
wela=1; //打开U2锁存器
P0=0xFE; //送入位选信号
wela=0; //关闭U2锁存器
dula=1; //打开U1锁存器
P0=0x7F; //送入段选信号
dula=0; //关闭U2锁存器
while(1); //程序停止到这里
}
例3.2.2让实验板上6个数码管同时点亮,依次显示0到F,时间间隔为0.5ms,循环下去。(part2.1_2.c P61)
#include //52系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6; //申明U1锁存器的锁存端
sbit wela=P2^7; //申明U2锁存器的锁存端
uchar num;
unchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delayms(uint);
void main()
{
wela=1; //打开U2锁存端
P0=0xco;//送入位选信号
wela=0; //关闭U2锁存端
while(1)
{
for(num=0;num<16;num++) //16个数循环显示
{
dula=1; //打开U1锁存端
P0=table[num]; //送入段选信号
dula=0; //关闭U1锁存端
delay(500); //延时0.5秒
}
}
}
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
例3.3.1第一个数码管显示1,时间为0.5s,然后关闭它,立即让第二个数码管显示2,时间为0.5s,在关闭它……一直到最后一个数码管显示6,时间同样为0.5s,关闭它之后再回来显示第一个数码管,一直循环下去。(part2.1_3.c P62)
例3.5.2用定时器0的方式1实现第一个发光二极管以200ms间隔闪烁,用定时器1的方式1实现数码管前两位59s循环计时。(part2.1_5.c P75)
例4.1.1用数码管前两位显示一个十进制数,变化范围为00~59,开始时显示00,每按下S2键一次,数值加1;每按下S3键一次,数值减1;每按下S4键一次,数值归零;按下S5键一次,利用定时器功能使数值开始自动每秒加1,再次按下S5键,数值停止加1,保持显示原数。(part2.2_1.c P82)
#include //52系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
sbit key1=P3^4;
sbit key2=P3^5;
sbit key3=P3^6;
sbit key4=P3^7;
sbit dula=P2^6; //申明U1锁存器的锁存端
sbit wela=P2^7; //申明U2锁存器的锁存端
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delayms(uint);
uchar numt0,num;
void display(uchar numdis) //显示子函数
{
uchar shi,ge; //分离两个分别要显示的数
shi=numdis/10;
ge=numdis%10;
dula=1;
P0=table[shi]; //送十位段选数据
dula=0;
P0=0xff; //送位选数据前关闭所有显示,防止打开位选锁存时
wela=1; //原来段选数据通过位选锁存器造成混乱
P0=0xfe; //送位选数据
wela=0;
delayms(5); //延时
dula=1;
P0=table[ge]; //送个位段选数据
dula=0;
P0=0xff;
wela=1;
P0=0xfd;
wela=0;
delayms(5);
}
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
void init() //初始化函数
{
TMOD=0x01;//设置定时器0为工作方式1(0000 0001)
TH0=(65536-45872)/256;//装初值50ms一次中断
TL0=(65536-45872)%256;
EA=1; //开总中断
ET0=1; //开定时器0中断
}
void keyscan()
{
if(key1==0)
{
delayms(10);
if(key1==0)
{
num++;
if(num==60)//当到60时重新归0
num=0;
while(!key1);//等待按键释放
}
}
if(key2==0)
{
delayms(10);
if(key2==0)
{
if(num==0)//当到0时重新归60
num=60;
num--;
while(!key2);
}
}
if(key3==0)
{
delayms(10);
if(key3==0)
{
num=0; //清0
while(!key3);
}
}
if(key4==0)
{
delayms(10);
if(key4==0)
{
while(!key4);
TR0=~TR0;//启动或停止定时器0
}
}
}
void main()
{
init();//初始化函数
while(1)
{
keyscan();
display(num);
}
}
void T0_time() interrupt 1
{
TH0=(65536-45872)/256;//重装初值
TL0=(65536-45872)%256;
numt0++;
if(numt0==20) //如果到了20次,说明1秒时间到
{
numt0=0; //然后把num清0重新再计20次
num++;
if(num==60)
num=0;
}
}
例4.2.1实验班上电时,数码管不显示,顺序按下矩阵键盘后,数码管上依次显示0~F,六个数码管同时静态显示即可。(part2.2_2.c P87)
#include //52系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6; //申明U1锁存器的锁存端
sbit wela=P2^7; //申明U2锁存器的锁存端
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
void display(uchar num)
{
P0=table[num]; //显示函数只送段选数据
dula=1;
dula=0;
}
void matrixkeyscan()
{
uchar temp,key;
P3=0xfe;
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee:
key=0;
break;
case 0xde:
key=1;
break;
case 0xbe:
key=2;
break;
case 0x7e:
key=3;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}
P3=0xfd;
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xed:
key=4;
break;
case 0xdd:
key=5;
break;
case 0xbd:
key=6;
break;
case 0x7d:
key=7;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}
P3=0xfb;
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb:
key=8;
break;
case 0xdb:
key=9;
break;
case 0xbb:
key=10;
break;
case 0x7b:
key=11;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}
P3=0xf7;
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xe7:
key=12;
break;
case 0xd7:
key=13;
break;
case 0xb7:
key=14;
break;
case 0x77:
key=15;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}
}
void main()
{
P0=0; //关闭所有数码管段选
dula=1;
dula=0;
P0=0xc0;//位选中所有数码管
wela=1;
wela=0;
while(1)
{
matrixkeyscan();//不停调用键盘扫描程序
}
}
例5.3.1用单片机控制ADC0804进行数模转换,当拧动实验板上A/D旁边的电位时,在数码管的前三位以十进制方式显示出A/D转换后的数字量(8位A/D转换后数值在0~255变化)。(part2.3_1.c P107)
#include //52系列单片机头文件
#include
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6; //申明U1锁存器的锁存端
sbit wela=P2^7; //申明U2锁存器的锁存端
sbit adwr=P3^6; //定义AD的WR端口
sbit adrd=P3^7; //定义AD的RD端口
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
void display(uchar bai,uchar shi,uchar ge) //显示子函数
{
dula=1;
P0=table[bai]; //送段选数据
dula=0;
P0=0xff; //送位选数据前关闭所有显示,防止打开位选锁存时
wela=1; //原来段选数据通过位选锁存器造成混乱
P0=0x7e; //送位选数据
wela=0;
delayms(5); //延时
dula=1;
P0=table[shi];
dula=0;
P0=0xff;
wela=1;
P0=0x7d;
wela=0;
delayms(5);
dula=1;
P0=table[ge];
dula=0;
P0=0xff;
wela=1;
P0=0x7b;
wela=0;
delayms(5);
}
void main() // 主程序
{
uchar a,A1,A2,A3,adval;
wela=1;
P0=0x7f; //置CSAD为0,选通ADCS 以后不必再管ADCS
wela=0;
while(1)
{
adwr=1;
_nop_();
adwr=0; //启动AD转换
_nop_();
adwr=1;
for(a=10;a>0;a--) //TX-1C实验板AD工作频率较低,所以启动转换后要多留点时间用来转换
{ //这里把显示部分放这里的原因也是为了延长转换时间
display(A1,A2,A3);
}
P1=0xff; //读取P1口之前先给其写全1
adrd=1; //选通ADCS
_nop_();
adrd=0; //AD读使能
_nop_();
adval=P1; //AD数据读取赋给P1口
adrd=1;
A1=adval/100; //分出百,十,和个位
A2=adval%100/10;
A3=adval%10;
}
}
例5.5.1用单片机控制DAC0832芯片输出电流,让发光二级管D12由灭均匀变到最亮,再由最亮均匀熄灭。在最亮和最暗时使用蜂鸣器分别警报一声,完成整个周期时间控制在5S左右,循环变化。(part2.3_2.c P121)
#include
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6; //申明U1锁存器的锁存端
sbit wela=P2^7; //申明U2锁存器的锁存端
sbit dawr=P3^6; //定义DA的WR端口
sbit dacs=P3^2; //定义DA的CS端口
sbit beep=P2^3; //定义蜂鸣器端口
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
void main()
{
uchar val,flag;
dula=0;
wela=0;
dacs=0;
dawr=0;
P0=0;
while(1)
{
if(flag==0)
{
val+=5;
P0=val; //通过P0口给DA数据口赋值
if(val==255)
{
flag=1;
beep=0;
delayms(100);
beep=1;
}
delayms(50);
}
else
{
val-=5;
P0=val; //通过P0口给DA数据口赋值
if(val==0)
{
flag=0;
beep=0;
delayms(100);
beep=1;
}
delayms(50);
}
}
}
例6.5.1在上位机上用串口调试助手发送一个字符X,单片机收到字符后返回给上位机“I get X”,串口波特率设为9600bps。(part2.4_1.c P137)
#include
#define uchar unsigned char
#define uint unsigned int
unsigned char flag,a,i;
uchar code table[]="I get ";
//uchar code table[]={I, ,g,e,t, };
void init()
{
TMOD=0x20;
TH1=0xfd;
TL1=0xfd;
TR1=1;
REN=1;
SM0=0;
SM1=1;
EA=1;
ES=1;
}
void main()
{
init();
while(1)
{
if(flag==1)
{
ES=0;
for(i=0;i<6;i++)
{
SBUF=table[i];
while(!TI);
TI=0;
}
SBUF=a;
while(!TI);
TI=0;
ES=1;
flag=0;
}
}
}
void ser() interrupt 4
{
RI=0;
a=SBUF;
flag=1;
}
例6.6.1单片机上电后等待从上位机串口发来的命令,同时在数码管的前三位以十进制方式显示A/D采集的数值,在未收到上位机发送来的启动A/D转换命令之前数码管始终显示000。当收到上位机以十六进制发送来的01后,向上位机发送字符串“Turn on ad!”同时间隔1s读取一次A/D的值,然后把A/D采集回来的8位二进制转换成十进制表示的实际电压浮点数,并且从串口发送给上位机,形式如“The voltage is 3.398438V”,发送周期也是一秒一次,同时在数码管上也要每秒刷新现实的数值。当收到上位机以十六进制发送过来的02后,向上位机发送字符串“Turn off ad!”,然后停止发送电压值,数码管上显示上次结束时保持的值。当收到上位机发来的其他任何数时,向上位机发送字符串“Error!”。
(part2.4_2.c P140)
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6; //申明U1锁存器的锁存端
sbit wela=P2^7; //申明U2锁存器的锁存端
sbit adwr=P3^6; //定义AD的WR端口
sbit adrd=P3^7; //定义AD的RD端口
uchar flag,a;
unsigned char flag_uart,flag_time,flag_on,a,i,t0_num,ad_val;
float ad_vo;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
void init()
{
TMOD=0x21;
// SCON=0x50;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TH1=0xfd;
TL1=0xfd;
TR1=1;
ET0=1;
SM0=0;
SM1=1;
REN=1;
EA=1;
ES=1;
}
void display(uchar value) //显示子函数
{
uchar bai,shi,ge;
bai=value/100; //分出百,十,和个位
shi=value%100/10;
ge=value%10;
dula=1;
P0=table[bai]; //送段选数据
dula=0;
P0=0xff; //送位选数据前关闭所有显示,防止打开位选锁存时
wela=1; //原来段选数据通过位选锁存器造成混乱
P0=0x7e; //送位选数据
wela=0;
delayms(5); //延时
dula=1;
P0=table[shi];
dula=0;
P0=0xff;
wela=1;
P0=0x7d;
wela=0;
delayms(5);
dula=1;
P0=table[ge];
dula=0;
P0=0xff;
wela=1;
P0=0x7b;
wela=0;
delayms(5);
}
uchar get_ad()
{
uchar adval;
adwr=1;
_nop_();
adwr=0; //启动AD转换
_nop_();
adwr=1;
P1=0xff; //读取P1口之前先给其写全1
adrd=1;
_nop_();
adrd=0; //AD读使能
_nop_();
adval=P1; //AD数据读取
adrd=1;
return adval;
}
void main()
{
init();
wela=1;
P0=0x7f; //置CSAD为0,选通ADCS 以后不必再管ADCS
wela=0;
while(1)
{
if(flag_uart==1)
{
flag_uart=0;
ES=0;
TI=1;
switch(flag_on)
{
case 0: puts("Turn on ad!\n");
TR0=1;
break;
case 1: printf("Turn off ad!\n");
TR0=0;
break;
case 2: puts("Error!\n");
break;
}
while(!TI);//必须要加
TI=0;
ES=1;
}
if(flag_time==1)
{
flag_time=0;
ad_val=get_ad();
ad_vo=(float)ad_val*5.0/256.0;
ES=0;
TI=1;
printf("The voltage is %fV\n",ad_vo);
while(!TI);
TI=0;
ES=1;
}
display(ad_val);
}
}
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
t0_num++;
if(t0_num==20)
{
t0_num=0;
flag_time=1;
}
}
void ser() interrupt 4
{
RI=0;
a=SBUF;
flag_uart=1;
if(a==1)
flag_on=0;
else if(a==2)
flag_on=1;
else
flag_on=2;
}
例7.2.1实现1602液晶的第一行显示“I LOVE MCU!”,
展开阅读全文