1 / 107

操作实验 1 用单片机控制一个灯

操作实验 1 用单片机控制一个灯. 教学目标: 学习用 Proteus 仿真设计电路,掌握与 Kril c51 联合调试的方法。. 电路图:. C 程序:. #include<reg51.h> // 包含 51 单片机寄存器定义的头文件 void main(void) { P1=0xfe; //P1=1111 1110B ,即 P1.0 输出低电平 }. 将上题改成控制一个灯的闪烁:. #include<reg51.h> // 包含单片机寄存器的头文件

Download Presentation

操作实验 1 用单片机控制一个灯

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 操作实验1 用单片机控制一个灯 教学目标:学习用Proteus仿真设计电路,掌握与Kril c51联合调试的方法。

  2. 电路图:

  3. C程序: #include<reg51.h> //包含51单片机寄存器定义的头文件 void main(void) { P1=0xfe; //P1=1111 1110B,即P1.0输出低电平 } 将上题改成控制一个灯的闪烁:

  4. #include<reg51.h> //包含单片机寄存器的头文件 void delay(void) //两个void意思分别为无需返回值,没有参数传递 { unsigned int i; //定义无符号整数,最大取值范围65535 for(i=0;i<20000;i++) //做20000次空循环 ; //什么也不做,等待一个机器周期 } void main(void) { while(1) //无限循环 { P1=0xfe; //P1=1111 1110B, P1.0输出低电平 delay(); //延时一段时间 P1=0xff; //P1=1111 1111B, P1.0输出高电平 delay(); //延时一段时间 } }

  5. 操作实验2 用单片机控制8个灯

  6. void main(void) { while(1) { P1=0xfe; //第一个灯亮 delay(); //调用延时函数 P1=0xfd; //第二个灯亮 delay(); //调用延时函数 P1=0xfb; //第三个灯亮 delay(); //调用延时函数 P1=0xf7; //第四个灯亮 delay(); //调用延时函数 P1=0xef; //第五个灯亮 delay(); //调用延时函数 P1=0xdf; //第六个灯亮 delay(); //调用延时函数 P1=0xbf; //第七个灯亮 delay(); //调用延时函数 P1=0x7f; //第八个灯亮 delay(); //调用延时函数 } } 1 用顺序方式编程实现: #include<reg51.h> void delay(void) { unsigned char i,j; for(i=0;i<250;i++) for(j=0;j<250;j++) ; } 2 请用查表方式编程实现:

  7. 利用查表的方法,使端口P1做单一灯的变化:左移2次,右移2次,闪烁2次(延时的时间0.2秒)。利用查表的方法,使端口P1做单一灯的变化:左移2次,右移2次,闪烁2次(延时的时间0.2秒)。

  8. # include<reg51.h> unsigned char code table[]={0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f, 0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f, 0x7f,0xbf,0xdf,0xef, 0xf7,0xfb,0xfd,0xfe, 0x7f,0xbf,0xdf,0xef, 0xf7,0xfb,0xfd,0xfe, 0x00,0xff,0x00,0xff, 0x01}; unsigned char i=0; void delay(void) { unsigned char m,n,s; for(m=20;m>0;m--) for(n=20;n>0;n--) for(s=248;s>0;s--); } void main(void) { while(1) { if(table[i]!=0x01) { P1=table[i]; i++; delay(); } else { i=0; } } }

  9. 中断方式编程: void time0_int(void) interrupt 1 TH0 = (65536-50000)/256; TL0 = (65536-50000)%256; j++; if (j= =10) { if(table[i]!=0x01) { P1=table[i]; i++; delay(); } else { i=0; } } # include<reg51.h> unsigned char code table[]={0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f, 0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f, 0x7f,0xbf,0xdf,0xef, 0xf7,0xfb,0xfd,0xfe, 0x7f,0xbf,0xdf,0xef, 0xf7,0xfb,0xfd,0xfe, 0x00,0xff,0x00,0xff, 0x01}; unsigned char I,j; void main(void) {TMOD=0x01; TH0 = (65536-50000)/256; TL0 = (65536-50000)%256; EA=1;ET0=1; i=0;j=0; TR0=1; while(1); }

  10. 实验一 输入/输出端口的基本应用 点亮与单片机P1.0口相连的发光二极管,延时约0.2S,然后熄灭,再延时约0.2S,再点亮,如此循环下去。(使用定时器和中断方式) 参考流程图:

  11. #include<reg51.h> // 包含51单片机寄存器定义的头文件 sbit D1=P1^0; //将D1位定义为P2.0引脚 /************************************************************** 函数功能:主函数 **************************************************************/ void main(void) { EA=1; //开总中断 ET0=1; //定时器T0中断允许 TMOD=0x01; //使用定时器T0的模式1 TH0=(65536-46083)/256; TL0=(65536-46083)%256; TR0=1; //启动定时器T0 while(1) //无限循环等待中断 ; } /************************************* 函数功能:定时器T0的中断服务程序 *************************************/ void Time0(void) interrupt 1 using 0 { D1=~D1; TH0=(65536-46083)/256; TL0=(65536-46083)%256; }

  12. 设计作业: (1)如果P1口接8个LED,如何让8个LED一起闪烁? (2)编程实现单片机P1口相连的8个发光二极管中的一个循环移位点亮。

  13. Tcy 振荡器 12 S2 C/T 中断请求 TLx (低5位) THx (高8位) S1 TFx Tx TRx 与 GATE 或 INTx 定时/计数器工作方式 ⒈ 工作方式0 13位计数器,由TL0低5位和TH0 8位组成,TL0低5位计数满时不向TL0第6位进位,而是向TH0进位,13位计满溢出,TF0置“1”。最大计数值213 = 8192。

  14. ⒉ 工作方式1 16位计数器,最大计数值为216 = 65536。 方式1的结构与方式0结构相同,只是把13位变成16位, 16位的加法计数器被全部用上。 ⒊ 工作方式2 8位计数器,仅用TL0计数,最大计数值为28= 256,计满溢出后,一方面进位TF0,使溢出标志TF0 = 1;另一方面,使原来装在TH0中的初值装入TL0。 优点:定时初值可自动恢复;缺点:计数范围小。 适用于需要重复定时,而定时范围不大的应用场合。

  15. Tcy 振荡器 12 S2 C/T 中断请求 TLx (8位) S1 TFx Tx 重装初值 TRx 与 8 GATE THx (8位) 或 INTx

  16. ⒋ 工作方式3 方式3仅适用于T0,T1无方式3。 ⑴ T0方式3 在方式3情况下,T0被拆成二个独立的8位计数器TH0、TL0。 ① TL0使用T0原有的控制寄存器资源:TF0,TR0,GATE,C/T,INT0,组成一个8位的定时/计数器; ② TH0借用T1的中断溢出标志TF1,运行控制开关TR1,只能对片内机周脉冲计数,组成另一个8位定时器(不能用作计数器)。 ⑵ T0方式3情况下的T1 T1由于其TF1、TR1被T0的TH0占用,计数器溢出时,只能将输出信号送至串行口,即用作串行口波特率发生器。

  17. Tcy 振荡器 12 S2 C/T 中断请求 TL0 (8位) S1 TF0 T0 TR0 与 GATE 或 S2 INT0 中断请求 TH0 (8位) Fosc/12 TF1 TR1

  18. 操作实验3:定时器的应用 例1:用定时器控制单片机发出1KHZ的音频

  19. #include<reg51.h> // 包含51单片机寄存器定义的头文件 sbit sound=P3^7; //将sound位定义为P3.7引脚 void main(void) { TMOD=0x10; //使用定时器T1的模式1 TH1=(65536-921)/256; TL1=(65536-921)%256; TR1=1; //启动定时器T1 TF1=0; while(1)//无限循环等待查询 { while(TF1==0) ; TF1=0; sound=~sound; TH1=(65536-921)/256; TL1=(65536-921)%256; } }

  20. 中断方式编程 /*************************************** 函数功能:定时器T1的中断服务程序 **************************************/ void Time1(void) interrupt 3 using 0 { sound=~sound; TH1=(65536-921)/256; TL1=(65536-921)%256; } #include<reg51.h> sbit sound=P3^7; /**************************** 函数功能:主函数 *****************************/ void main(void) { EA=1; //开总中断 ET1=1; //定时器T1中断允许 TMOD=0x10; TH1=(65536-921)/256; TL1=(65536-921)%256; TR1=1; //启动定时器T1 while(1); //无限循环等待中断 }

  21. 例2:设计蜂鸣器鸣笛报警程序 /**************************************** 函数功能:主函数 ****************************************/ void main(void) { unsigned int i; while(1) { for(i=0;i<830;i++) { sound=0; //P3.7输出低电平 delay1600(); sound=1; //P3.7输出高电平 delay1600(); } for(i=0;i<200;i++) { sound=0; //P3.7输出低电平 delay800(); sound=1; //P3.7输出高电平 delay800(); } } } #include<reg51.h> sbit sound=P3^7; /**************************************** 函数功能:延时形成1600Hz音频 ****************************************/ void delay1600(void) { unsigned char n; for(n=0;n<100;n++) ; } /**************************************** 函数功能:延时形成800Hz音频 ****************************************/ void delay800(void) { unsigned char n; for(n=0;n<200;n++) ; }

  22. 例3:用定时器的方式控制两个LED以不同周期闪烁例3:用定时器的方式控制两个LED以不同周期闪烁 用T1定时器的中断来控制P1.0、P1.1的两个LED分别以200ms和800ms的周期闪烁。 实现方法: 通过给定时器T1赋适当的初值,设置为50ms产生1次中断。由于控制两个LED以不同的周期闪烁,第一个LED亮、灭周期为100ms,第二个LED亮、灭周期为400ms,所以,需设置两个变量countor1和countor2来分别统计中断次数。

  23. /******************************************** 函数功能:定时器T1的中断服务程序 *******************************************/ void Time1(void) interrupt 3 using 0 { Countor1++; //Countor1自加1 Countor2++; //Countor2自加1 if(Countor1==2) //若累计满2次,即计时满100ms { D1=~D1; Countor1=0; //将Countor1清0,重新从0开始计数 } if(Countor2==8) //若累计满8次,即计时满400ms { D2=~D2; Countor2=0; //将Countor1清0,重新从0开始计数 } TH1=(65536-46083)/256; TL1=(65536-46083)%256; } #include<reg51.h> sbit D1=P1^0; sbit D2=P1^1; unsigned char Countor1; unsigned char Countor2; /************************************* 函数功能:主函数 ***************************************/ void main(void) { EA=1; //开总中断 ET1=1; //定时器T1中断允许 TMOD=0x10; //使用定时器T1的模式1 TH1=(65536-46083)/256; TL1=(65536-46083)%256; TR1=1; //启动定时器T1 Countor1=0; //从0开始累计中断次数 Countor2=0; //从0开始累计中断次数 while(1) ; //无限循环等待中断 }

  24. 实验二:定时/计数器的基本应用 实验内容 利用定时器T0工作在方式3,用TL0计数器对应的8位定时器实现一个发光管以1s闪烁, 用TH0计数器对应的8位定时器实现另一个发光管以0.5s闪烁。 实验电路 :

  25. 参考程序流程图

  26. while(1) //程序停止在这里等待中断发生 { if(num1>=3686)//如果到了3686次,说明1秒时间到 { num1=0; //然后把num1清0重新再计3686次 led1=~led1; //让发光管状态取反 } if(num2>=1843)//如果到了1843次,说明半秒时间到 { num2=0;//然后把num2清0重新再计1843次 led2=~led2; //让发光管状态取反 } } } #include <reg51.h> #define uchar unsigned char #define uint unsigned int sbit led1=P1^0; sbit led2=P1^1; uint num1,num2; void main() { TMOD=0x03; //设置定时器0为工作方式3 TH0=6; //装初值 TL0=6; EA=1; //开总中断 ET0=1; //开定时器0中断 ET1=1; //开定时器1中断 TR0=1; //启动定时器0 TR1=1; //启动定时器0的高8位计数器

  27. void TL0_time() interrupt 1 { TL0=6; //重装初值 num1++; } void TH0_time() interrupt 3 { TH0=6; //重装初值 num2++; }

  28. 实验三:中断系统实验 (用外中断0的中断方式进行数据采集) 用外中断0控制P1口LED亮灭状态。按下S键8灯亮,再按下8灯灭,如此循环。

  29. #include<reg51.h> sbit S=P3^2; //将S位定义为P3.2, /******************************************* 函数功能:主函数 ******************************************/ void main(void) { EA=1; //开放总中断 EX0=1; //允许使用外中断 IT0=1; //选择负跳变来触发外中断 P1=0xff; while(1) ; //无限循环, 防止程序跑飞 } /************************************************************** 函数功能:外中断T0的中断服务程序 **************************************************************/ void int0(void) interrupt 0 using 0 //外中断0的中断编号为0 { P1=~P1; //每产生一次中断请求,P1取反一次。 }

  30. 练习: 用外中断INT0测量负跳变信号累计数。结果在P1口的8个LED上显示(设100个脉冲)。

  31. Countor=0; for(i=0;i<100;i++) //输出100个负跳变 { u=1; delay30ms(); u=0; delay30ms(); } while(1) ; //无限循环, 防止程序跑飞 } /************************************** 函数功能:外中断T0的中断服务程序 ************************************/ void int0(void) interrupt 0 using 0 { Countor++; P1=Countor; } #include<reg51.h> sbit u=P3^0; unsigned char Countor; /************************************************* 函数功能:延时约30ms (3*100*100=30 000μs =30ms) *************************************************/ void delay30ms(void) { unsigned char m,n; for(m=0;m<100;m++) for(n=0;n<100;n++) ; } /******************************************* 函数功能:主函数 ******************************************/ void main(void) { unsigned char i; EA=1; //开放总中断 EX0=1; //允许使用外中断 IT0=1; //选择负跳变来触发外中断

  32. 将上题改成用数码管显示0~9个外中断计数(共阳)。将上题改成用数码管显示0~9个外中断计数(共阳)。

  33. 参考程序: void main(void) { unsigned char i; P2=0xfe; EA=1; //开放总中断 EX0=1; //允许使用外中断 IT0=1; //选择负跳变来触发外中断 Countor=0; for(i=0;i<9;i++) //输出9个负跳变 { u=1; delay120ms(); u=0; delay120ms(); } while(1) ; } void int0(void) interrupt 0 using 0 { Countor++; P0=tab[Countor]; } #include<reg51.h> sbit u=P3^0; unsigned char Countor; unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; /************************************************* 函数功能:延时约120ms (3*200*200=30 000μs 120ms) *************************************************/ void delay120ms(void) { unsigned char m,n; for(m=0;m<200;m++) for(n=0;n<200;n++) ; }

  34. 用外中断0的中断测量外部负脉冲宽度。 实现方法:先设计一个单片机的P1.4脚输出负脉冲(设200us),由第2片单片机的外中断0(P3.2脚)接收并检测负脉冲宽度,结果由P1口8位LED显示。

  35. 测量负脉冲宽度的程序设计 产生200us方波 #include<reg51.h> sbit u=P3^2; //将u位定义为P3.2 void main(void) { TMOD=0x02; EA=1; //开放总中断 EX0=1; //允许使用外中断 IT0=1; //选择负跳变来触发外中断 ET0=1; //允许定时器T0中断 TH0=0; //定时器T0赋初值0 TL0=0; //定时器T0赋初值0 TR0=0; //先关闭T0 while(1) ; //无限循环, 不停检测输入负脉冲宽度 } void int0(void) interrupt 0 using 0 { TR0=1; //外中断一到来,即启动T0计时 TL0=0; //从0开始计时 while(u==0) ; //低电平时,等待T0计时 P1=TL0; //将结果送P1口显示 TR0=0; //关闭T0 } #include<reg51.h> sbit u=P1^4; void main(void) { TMOD=0x02; EA=1; //开总中断 ET0=1; //定时器T0中断允许 TH0=256-56; //定时器T0的高8位赋初值 TL0=256-200; //定时器T0的高8位赋初值 TR0=1; //启动定时器T0 while(1) //无限循环,等待中断 ; } void Time0(void) interrupt 1 using 0 { u=~u; //将P1.4引脚输出电平取反,产生方波 }

  36. 串行口应用串行控制寄存器SCON ① SM0 SM1 —— 串行口工作方式选择位。 ② SM2 —— 多机通信控制位。 ③ REN —— 允许接收控制位。REN=1,允许接收。 ④ TB8 —— 方式2和方式3中要发送的第9位数据。 ⑤ RB8 —— 方式2和方式3中要接收的第9位数据。 ⑥ TI —— 发送中断标志。 ⑦ RI —— 接收中断标志。 3、电源控制寄存器PCON SMOD=1,串行口波特率加倍。PCON寄存器不能进行位寻址。

  37. SM0、SM1:串行口工作方式选择位。用于选择四种工作方式SM0、SM1:串行口工作方式选择位。用于选择四种工作方式

  38. 实验四 单片机串口通信实验 • 基于方式1的单工通信 • 单片机U1通过串行口TXD端将一段流水灯控制码以方式一发送至单片机U2的RXD,U2再利用该控制码点亮P1口的8位数码管。

  39. 发送程序 void main(void) { unsigned char i; TMOD=0x20; SCON=0x40; PCON=0x00; //PCON=0000 0000B,波特率9600 TH1=0xfd; //根据规定给定时器T1赋初值 TL1=0xfd; //根据规定给定时器T1赋初值 TR1=1; //启动定时器T1 while(1) { for(i=0;i<8;i++) //模拟检测数据 { Send(Tab[i]); //发送数据i delay(); //50ms发送一次检测数据 } } } #include<reg51.h> unsigned char code Tab[ ]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; void Send(unsigned char dat) { SBUF=dat; while(TI==0) ; TI=0; } void delay(void) { unsigned char m,n; for(m=0;m<200;m++) for(n=0;n<250;n++) ; }

  40. void main(void) { TMOD=0x20; SCON=0x50; 允许接收(REN=1) PCON=0x00; //PCON=0000 0000B,波特率9600 TH1=0xfd; //根据规定给定时器T1赋初值 TL1=0xfd; //根据规定给定时器T1赋初值 TR1=1; //启动定时器T1 while(1) { P1=Receive(); //将接收到的数据送P1口显示 } } 数据接收程序 #include<reg51.h> unsigned char Receive(void) { unsigned char dat; while(RI==0) //只要接收中断标志位RI没有被置“1” ; //等待,直至接收完毕(RI=1) RI=0; dat=SBUF; return dat; }

  41. [例] 设U1为甲机发送,U2为乙机接收。试编程通过串行口将甲机上的一段流水灯控制码以方式1发送给乙机,乙机再利用该段控制码流水点亮其P1口的8位LED.加奇偶校验。

  42. #include<reg51.h> //包含单片机寄存器的头文件 sbit p=PSW^0; unsigned char code Tab[ ]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; //流水灯控制码,该数组被定义为全局变量 /***************************************************** 函数功能:向PC发送一个字节数据 ***************************************************/ void Send(unsigned char dat) { ACC=dat; TB8=p; SBUF=dat; while(TI==0) ; TI=0; }

  43. void delay(void) { unsigned char m,n; for(m=0;m<200;m++) for(n=0;n<250;n++); } void main(void) { unsigned char i; TMOD=0x20; //TMOD=0010 0000B,定时器T1工作于方式2 SCON=0xc0; //SCON=1100 0000B,串口工作方式3, //SM2置0,不使用多机通信,TB8置0 PCON=0x00; //PCON=0000 0000B,波特率9600 TH1=0xfd; //根据规定给定时器T1赋初值 TL1=0xfd; //根据规定给定时器T1赋初值 TR1=1; //启动定时器T1 while(1) { for(i=0;i<8;i++) //模拟检测数据 { Send(Tab[i]); //发送数据i delay(); } } } //50ms发送一次检测数据

  44. 解:程序如下: #include<reg51.h> sbit p=PSW^0; unsigned char receive(void) { unsigned char dat; while(RI==0) ; RI=0; ACC=SBUF; //将接收缓冲器中的数据存于dat if(RB8==p) { dat=ACC; return dat; } }

  45. void main(void) { TMOD=0x20; //定时器T1工作于方式2 SCON=0xd0; //SCON=1101 0000B,串口工作方式3,允许接收(REN=1) PCON=0x00; //PCON=0000 0000B,波特率9600 TH1=0xfd; //根据规定给定时器T1赋初值 TL1=0xfd; //根据规定给定时器T1赋初值 TR1=1; //启动定时器T1 REN=1; //允许接收 while(1) { P1=receive(); //将接收到的数据送P1口显示 } }

  46. 实验五 单片机显示实验 电路:

  47. #include<reg51.h> // 包含51单片机寄存器定义的头文件 void main(void) { P2=0xfe; //P2.0引脚输出低电平,数码显示器接通电源准备点亮 P0=0x92; //让P0口输出数字"5"的段码92H }

  48. 例:循环显示0~9 while(1) //无限循环 { for(i=0;i<10;i++) { P0=Tab[i]; delay(); } } } #include<reg51.h> void delay(void) { unsigned char i,j; for(i=0;i<255;i++) for(j=0;j<255;j++) ; } void main(void) { unsigned char i; unsigned char code Tab[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //数码管显示0~9的//段码表,程序运行中当数组值不发生变 //化时,前面加关键字code ,可以大大节//约单片机的存储空间 P2=0xfe; //P2.0引脚输出低电平,数码显示器DS0接通电源工作

  49. 例:用串行口扩展并行口软件译码静态显示电路:例:用串行口扩展并行口软件译码静态显示电路:

More Related