《单片机串行通信实验报告(实验要求、原理、仿真图及例程).doc》由会员分享,可在线阅读,更多相关《单片机串行通信实验报告(实验要求、原理、仿真图及例程).doc(26页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、.嵌入式系统原理与实验实验指导实验三调度器设计基础一、 实验目的和要求1. 熟练使用Keil C51 IDE集成开发环境,熟练使用Proteus软件。2. 掌握Keil与Proteus的联调技巧。3. 掌握串行通信在单片机系统中的使用。4. 掌握调度器设计的基础知识:函数指针。二、 实验设备1. PC机一套2. Keil C51开发系统一套3. Proteus 仿真系统一套三、 实验容1. 甲机通过串口控制乙机LED闪烁(1) 要求a. 甲单片机的K1按键可通过串口分别控制乙单片机的LED1闪烁,LED2闪烁,LED1和LED2同时闪烁,关闭所有的LED。b. 两片8051的串口都工作在模式1
2、,甲机对乙机完成以下4项控制。i. 甲机发送“A”,控制乙机LED1闪烁。ii. 甲机发送“B”,控制乙机LED2闪烁。iii. 甲机发送“C”,控制乙机LED1,LED2闪烁。iv. 甲机发送“C”,控制乙机LED1,LED2停止闪烁。c. 甲机负责发送和停止控制命令,乙机负责接收控制命令并完成控制LED的动作。两机的程序要分别编写。d. 两个单片机都工作在串口模式1下,程序要先进行初始化,具体步骤如下:i. 设置串口模式(SCON)ii. 设置定时器1的工作模式(TMOD)iii. 计算定时器1的初值iv. 启动定时器v. 如果串口工作在中断方式,还必须设置IE和ES,并编写中断服务程序。
3、(2) 电路原理图Figure 1 甲机通过串口控制乙机LED闪烁的原理图(3) 程序设计提示a. 模式1下波特率由定时器控制,波特率计算公式参考:b. 可以不用使用中断方式,使用查询方式实现发送与接收,通过查询TI和RI标志位完成。2. 单片机与PC串口通讯及函数指针的使用(1) 要求:a. 编写用单片机求取整数平方的函数。b. 单片机把计算结果向PC机发送字符串。c. PC机接收计算结果并显示出来。d. 可以调用Keil C51 stdio.h 中的printf来实现字符串的发送。e. 单片机的数码港显示发送的次数,每9次清零。(2) 参考电路原理图Figure2 单片机与PC串口通讯及函
4、数指针的使用原理图(3) 程序设计要求a. 编写求平方函数时,采用函数指针来编写。b. 参考头文件模式,完善设计项目文件结构。四、 思考题1. 如果实验1如何使用实验2的成果来改写?2. 请结合实例说明什么是函数指针及如何使用函数指针。五、 实验报告要求1. 简述编写C程序,并联合调试程序的过程。2. 解释编写的实验程序的代码,描述实验结果。3. 解答思考题。4. 简述实验的心得。嵌入式系统原理及实验实验报告Lab 3调度器设计基础一、 甲机通过串口控制乙机LED闪烁(一) 实现原理1. 总体思路通过发送缓冲寄存器SBUF,以及接收缓冲寄存器SBUF,将在甲机上初始化的要发送的数据A,B,C,
5、D存入一个数组,通过超级循环设定的一个按键控制函数,依次发送给乙机,由乙机接收并让相应的LED灯闪烁。2. 硬件设计上图所示的是单击Play以后开始仿真,此时没有按键按下,甲机乙机均处于等待状态之下。*上图所示按键第一次按下,甲机发送字符A,D1灯闪烁,乙机接收字符A,并显示相应与甲机D1灯位置对应的D2灯闪烁。*以上两幅图是在一起的,也许是LED灯启动以及延迟还有甲、乙机发送接收数据时间差等各方面的差异,甲机的D3灯和乙机的D4灯亮不到一块去,它们交替着闪烁,此闪彼灭。总之,以上两幅图所呈现的,是当按键第二次按下,甲机发送字符B,并闪烁D3灯,乙机接收字符B,并闪烁相应的D4灯。*上图所示按
6、键第三次按下,控制甲机发送字符C,并同时闪烁D1和D3灯,与此同时,乙机接收甲机发来的字符C,并同时闪烁D2、D4灯。图中所示的是LED灯一闪一灭时的亮状态,灭状态的截图此处省去。*上图所示按键第四次按下,甲机向乙机发送字符D,同时使得D1、D3灯灭掉,乙机接收完字符D之后,也使得其控制的D2、D4灯停止闪烁。3. 软件设计流程图: 开始是否有按键按下? 否 是第几次按下按键? 1 2 3 4甲机发送字符:ABCDLED1 LED3 LED1 LED1&LED3全灭闪烁 闪烁 &LED3 都闪烁 乙机接收相应字符ABCDLED2 LED4 LED2 LED2&LED4全灭闪烁 闪烁 &LED4
7、 都闪烁关键代码段+解释:甲机代码段/*/按键控制函数void button(void)/按键控制函数debouncing();/调用消抖函数if(n=1)SBUF=sendi;/发送第i个数据while(TI=0);/查询等待发送是否完成 TI=0;/发送完成,TI由软件清0n=0;switch(i)case 0: while(debouncing()=0)D1=D1;delay_ms(150);break;/甲机D3灯灭状态,D1灯不断闪烁,直到有新的按键按下为止case 1: D1=1;while(1)D3=D3;delay_ms(150);if(debouncing()break;br
8、eak;/甲机D1灯灭状态,D3灯不断闪烁,直到有新的按键按下为止case 2: D3=1;while(1)D1=D1;D3=D3;delay_ms(150);if(debouncing()break;break;/甲机D1、D3灯一起不断闪烁,直到有新的按键按下为止case 3: D1=1;D3=1;break;/甲机D1、D3灯均处于灭状态default: ;i+;if(i=4)/使控制功能能循环反复地执行i=0;/使控制功能能循环反复地执行*/*/甲机相关初始化TMOD=0x20;/定时器T1工作于方式2TL1=0xf4;/波特率为2400bpsTH1=0xf4;TR1=1;SCON=0
9、x40;/定义串行口工作于方式1*/乙机代码段/*/乙机接收显示函数void disp(void)/乙机接收显示函数REN=1;/允许接收while(RI=0);/查询等待接收标志为1,表示接收到数据 bufferi=SBUF;/接收数据RI=0;/RI由软件清0 switch(i) case 0: while(!RI)D2=D2;delay_ms(150);break;/乙机D4灯灭状态,D2灯不断闪烁,直到乙机接收到新传来的数据为止case 1: D2=1;while(1)D4=D4;delay_ms(150);if(RI)break;break;/乙机D2灯灭状态,D4灯不断闪烁,直到乙
10、机接收到新传来的数据为止case 2: D4=1;while(1)D2=D2;D4=D4;delay_ms(150);if(RI)break;break;/甲机D2、D4灯一起不断闪烁,直到乙机接收到新传来的数据为止case 3: D2=1;D4=1;break;/乙机D2、D4灯均处于灭状态default: ; i+;if(i=4)/使控制功能能循环反复地执行 i=0;/使控制功能能循环反复地执行 */*/乙机相关初始化TMOD=0x20;/定时器T1工作于方式2TL1=0xf4;/波特率为2400bpsTH1=0xf4;TR1=1;SCON=0x40;/定义串行口工作于方式1*/(二) 调
11、试1. 调试的方式软件仿真调试现象: 单击Play以后开始仿真,此时没有按键按下,甲机乙机均处于等待状态之下。 P1.0口按键第一次按下以后,甲机D1灯闪烁,同时乙机D2灯也闪烁。 当按键第二次按下,甲机闪烁D3灯,乙机闪烁D4灯。 按键第三次按下时,甲机同时闪烁D1和D3灯,与此同时,乙机同时闪烁D2、D4灯。 按键第四次按下,甲机的D1、D3灯同时灭掉,乙机控制的D2、D4灯也都停止闪烁。 若接下来还有按键按下,那将回到,如此循环执行下去。(三) 实验再思考1. 进一步改进的设想可以用串行口中断服务程序来实现。2. 实验的收获学会了双机串行口通信3. 实验不能解决的疑问的确有个疑问:若是我
12、把程序中的任何一个switch语句改成如下形式:switch(SBUF) case A: ; break; case B: ; break; case C: ; break; case D: ; break;default: ;这样的switch语句无论出现在甲机还是乙机的程序里面,都无法实现相应的任何控制功能了。SBUF存储数据的情况具体是怎样的呢?switch语句不能够引用SBUF吗?二、 单片机与PC串口通讯及函数指针的使用(一) 实现原理1. 总体思路按键接的是P3.2复用口,于是就想到用外部中断0控制。所以,将数码管显示程序以及串口通讯程序都一起放入外部中断INT0服务程序当中,就可
13、以实现实验要求。另外,在C51程序编写当中还应当特别注意以下几点:TH1=0xf3;TL1=0xf3;/设置串行口波特率为2400bps,定时器初值,波特率设置 非常严格/要是设置错了,在发送和接收的时候,就会出现莫名其妙的符号,比如说:xxxxxxx 诸如此类.O_O调用printf之前应该关闭串口中断使能 ES=0;/禁止串行口中断 TI=1;/必须置高TI,RI RI=1; printf(%d*%d=%d,n,n,c);putchar(n); while(!TI);/等待printf语句执行完毕 while(!RI);/等待printf语句执行完毕2. 硬件设计上图所示有关串口COMPI
14、M的相关参数设置应该注意的地方*上图所示虚拟终端相关参数设置应该注意的地方,虚拟终端相关参数设置应该与串口的相关参数设置一致,也应该与C51编程中串口初始化时设定的波特率的数值一致,即都应该是2400bps。注意,虚拟终端的RXD应当与串口第3脚TXD(即发送端)连接,否则仿真时无法虚拟终端调试窗口无法显示printf语句容。*上图所示的是单击Play以后开始仿真,此时没有按键按下,数码管静止在显示0的状态当中,此时没有任何的数据发送和接收。*上图所示当第一次按下按键时,触发外部中断,单片机调用函数指针指向的求取整数平方的函数,并将计算结果发送给PC机,此时虚拟终端显示:12=1; 即1=1;
15、 (似乎虚拟终端显示框要显示的文字在这个截图里面有点小,看不太清楚),数码管此时显示发送次数为1。*上图所示当第5次按键按下,数码管显示发送次数为5,此时也可以清楚地观察到虚拟终端调试窗口的显示:1*1=12*2=43*3=94*4=165*5=25*数码管显示每9次清零,求整数平方数也是09循环,上图所示虚拟终端显示结果有异常情况。到目前为止,我改写过多种printf语句形式,可是还是解决不了上图所示的异常显示问题。为什么会显示成:$62=36;172=49;82=64;Q92=81; (o)呢?好奇怪!?*如上图所示,就算我改了printf语句形式,也还是会有同样的问题出现。*上图所示是数
16、码管每9次清零,然后再执行到3的情况,从虚拟终端调试窗口可见09求平方已经循环执行到了第二轮的3。3. 软件设计流程图: 开始初始化定时器1、串口、外部中断0 等待中断 是否有外部中断?否是转入外部中断0中断服务程序 按键消抖 函数指针调用求整数平方函数 在数码管上显示发送次数 发送求取结果 查询等待发送是否完成 发送完成,TI由软件清0 在虚拟终端上显示求平方结果 中断返回 关键代码段+解释:/*/串口初始化TH1=0xf3;TL1=0xf3;/设置串行口波特率为2400bps,定时器初值,波特率设置非常严格 /要是设置错了,在发送和接收的时候,就会出现莫名其妙的符号,比如说:xxxxxxx
17、 诸如此类.O_OSCON=0x50;/0101,0000:串行口方式1EN=1允许接收,8位异步通信方式,8-bit UART,TI= 0; RI=0 PCON=0x00;/SMOD=0EA=1;/开总中断允许位ES=1;/开串行口中断*/*/求取整数平方函数uint pow2(uint x)/求取整数平方函数uint q;q=x*x;return q;/return返回平方数结果*/*/虚拟终端显示void vir_ter(uint n,uint c)/虚拟终端显示ES=0;/禁止串行口中断TI=1;/必须置高TI,RI,TI=1发送填充字节,中断“不”使能RI=1;printf(%d*%
18、d=%d,n,n,c);/*.调用printf之前应该关闭串口中断使能putchar(n);while(!TI);/等待printf语句执行完毕while(!RI);/等待printf语句执行完毕ES=1;TI=0;RI=0; */*/外部中断INT0中断服务程序void intsvr0(void) interrupt 0 /外部中断INT0debouncing();/调用消抖函数c=(*p)(n);/用函数指针形式调用求取整数平方函数disp(n);/在数码管上显示发送次数SBUF=c;/发送求取结果while(TI=0);/查询等待发送是否完成 TI=0;/发送完成,TI由软件清0vir_
19、ter(n,c);/在虚拟终端上显示求平方结果*/(二) 调试1. 调试的方式软件仿真调试现象: 单击Play以后开始仿真,此时没有按键按下,数码管静止在显示0的状态当中,此时没有任何的数据发送和接收。 P3.2口按键第一次按下以后,触发外部中断,单片机调用函数指针指向的求取整数平方的函数,并将计算结果发送给PC机,此时虚拟终端显示:12=1; 即1=1; 不端按下按键触发外部中断,当外部中断一到来,单片机就执行调用函数指针指向的求取整数平方数的函数,并将求取结果发送给串口。单片机09不断循环求取整数平方数,并也循环显示在虚拟终端调试窗口上,数码管显示求取整数平方数结果发送次数,每9次清零。2
20、. 遇到问题的处理虚拟终端的RXD应当与串口第3脚TXD(即发送端)连接,否则仿真时无法虚拟终端调试窗口无法显示printf语句容。虚拟终端相关参数设置应该与串口的相关参数设置一致,也应该与C51编程中串口初始化时设定的波特率的数值一致,在此次实验报告中即都应该是2400bps。在编写C51程序时,TH1=0xf3;TL1=0xf3;/设置串行口波特率为2400bps。波特率的设置非常严格,要是设置错了,在发送和接收的时候,就会出现莫名其妙的符号,比如说:xxxxxxx 诸如此类.O_O(三) 实验再思考1. 进一步改进的设想目前还没有设计得出外部中断服务程序和串行口中断服务程序同时一起用的C
21、51程序,遇到很多问题。希望老师今后能指导我们关于双重中断程序的编写,我自己捣鼓了好久还没捣鼓出来。2. 实验的收获收获当然很多,诸如:虚拟终端的RXD应当与串口第3脚TXD(即发送端)连接等等都是我对单片机新的认识,新的收获。还有:SBUF=c;/发送求取结果while(TI=0);/查询等待发送是否完成 TI=0;/发送完成,TI由软件清0ES=0;/禁止串行口中断TI=1;/必须置高TI,RI,TI=1发送填充字节,中断“不”使能RI=1;printf(%d*%d=%d,n,n,c);/调用printf之前应该关闭串口中断使能putchar(n);while(!TI);/等待printf
22、语句执行完毕while(!RI);/等待printf语句执行完毕以上语句应该熟记,是使能虚拟终端的常用语句。3. 实验不能解决的疑问上图所示便是最大的疑问!(四) 附录(粘贴完整代码)甲机通过串口控制乙机LED闪烁甲机完整代码-Target 1-Source Group+F.cF.h+main.c/F.h/#include#define uchar unsigned char#define uint unsigned intsbit D1 = P00;sbit D3 = P03;sbit P1_0 = P10;uint debouncing(void);void button(void);vo
23、id delay_ms(uint xms);/F.c/#includeF.huint n=0;uchar i=0;extern uchar send4;/声明全局变量void delay_ms(uint xms)/ms级延时函数 uint x,y; for(x=xms;x0;x-)for(y=130;y0;y-);uint debouncing(void)/debouncing:消除抖动的意思,按键消抖函数:若确实有按键按下,函数返回值为1;否则返回值为0if(P1_0=0)/有键按下吗?delay_ms(10); /延时消抖if(P1_0=0)/确实是有键按下n=1;while(P1_0=0
24、);/等待按键松开return 1;/若有按键按下,函数返回值为1else return 0;/若无按键按下,函数返回值为0else return 0;/若无按键按下,函数返回值为0void button(void)/按键控制函数debouncing();/调用消抖函数if(n=1) SBUF=sendi;/发送第i个数据 while(TI=0);/查询等待发送是否完成 TI=0;/发送完成,TI由软件清0n=0;switch(i) case 0: while(debouncing()=0)D1=D1;delay_ms(150);break;/甲机D3灯灭状态,D1灯不断闪烁,直到有新的按键按
25、下为止case 1: D1=1;while(1)D3=D3;delay_ms(150);if(debouncing()break;break;/甲机D1灯灭状态,D3灯不断闪烁,直到有新的按键按下为止case 2: D3=1;while(1)D1=D1;D3=D3;delay_ms(150);if(debouncing()break;break;/甲机D1、D3灯一起不断闪烁,直到有新的按键按下为止case 3: D1=1;D3=1;break;/甲机D1、D3灯均处于灭状态default: ;i+;if(i=4)/使控制功能能循环反复地执行i=0;/使控制功能能循环反复地执行/main.c/
26、#includeF.hvoid main()uchar send=A,B,C,D;/定义要发送的数据TMOD=0x20;/定时器T1工作于方式2TL1=0xf4;/波特率为2400bpsTH1=0xf4;TR1=1;SCON=0x40;/定义串行口工作于方式1D1=1;/初始化D1灯状态为熄灭D3=1;/初始化D3灯状态为熄灭while(1)button();/调用按键控制函数乙机完整代码-Target 1-Source GroupM.h+M.c+main.c/M.h/#include#define uchar unsigned char#define uint unsigned intsbi
27、t D2 = P00;sbit D4 = P03;void initLED(void);void flashLED(void);void disp(void);void delay_ms(uint xms);/M.c/#includeM.huchar i=0;uchar buffer=0x00,0x00,0x00,0x00;/定义接收数据缓冲区void disp(void)/乙机接收显示函数REN=1;/允许接收while(RI=0);/查询等待接收标志为1,表示接收到数据 bufferi=SBUF;/接收数据RI=0;/RI由软件清0 switch(i) case 0: while(!RI)
28、D2=D2;delay_ms(150);break;/乙机D4灯灭状态,D2灯不断闪烁,直到乙机接收到新传来的数据为止case 1: D2=1;while(1)D4=D4;delay_ms(150);if(RI)break;break;/乙机D2灯灭状态,D4灯不断闪烁,直到乙机接收到新传来的数据为止case 2: D4=1;while(1)D2=D2;D4=D4;delay_ms(150);if(RI)break;break;/甲机D2、D4灯一起不断闪烁,直到乙机接收到新传来的数据为止case 3: D2=1;D4=1;break;/乙机D2、D4灯均处于灭状态default: ;i+;
29、if(i=4)/使控制功能能循环反复地执行i=0;/使控制功能能循环反复地执行void delay_ms(uint xms)/ms级延时函数 uint x,y; for(x=xms;x0;x-)for(y=130;y0;y-);/main.c/#includeM.hvoid main()TMOD=0x20;/定时器T1工作于方式2TL1=0xf4;/波特率为2400bpsTH1=0xf4;TR1=1;SCON=0x40;/定义串行口工作于方式1D2=1;/初始化D2灯状态为熄灭D4=1;/初始化D4灯状态为熄灭while(1)disp();/调用LED灯显示函数 单片机与PC串口通讯及函数指针
30、的使用-Target 1-Source Group+main.c+PC.cPC.h/PC.h/#include #include #define uchar unsigned char#define uint unsigned int#define N 9sbit P3_2=P32;uint pow2(uint x);void disp(uint i);void vir_ter(uint i,uint c);void debouncing(void);void delay_ms(uint xms);/ PC.c/#include PC.huchar led10=0x3f,0x06,0x5b,0
31、x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f;uint n=0;uint pow2(uint x)/求取整数平方函数uint q;q=x*x;return q;/return返回平方数结果void disp(uint i)/发送次数数码管显示函数P0=ledi;/数值显示码送至控制口P0void vir_ter(uint n,uint c)/虚拟终端显示ES=0;/禁止串行口中断TI=1;/必须置高TI,RI,TI=1发送填充字节,中断“不”使能RI=1;printf(%d*%d=%d,n,n,c);/*.调用printf之前应该关闭串口中断使能putchar(n);wh
32、ile(!TI);/等待printf语句执行完毕while(!RI);/等待printf语句执行完毕ES=1;TI=0;RI=0;void debouncing(void)/debouncing:消除抖动的意思,按键消抖函数if(P3_2=0)/有键按下吗?delay_ms(10); /延时消抖if(P3_2=0)/确实是有键按下n+;if(n=10)/使按键控制功能能循环反复地执行n=0;while(P3_2=0);/等待按键松开void delay_ms(uint xms) /ms级延时子程序 uint x,y; for(x=xms;x0;x-)for(y=130;y0;y-);/main
33、.c/#include PC.huint c=0x00;uint (*p)(uint x);/定义函数指针,即指向函数的指针,该指针存放的是函数的入口地址extern uchar led10;/声明全局变量extern uint n;/声明全局变量void main()TMOD|=0x20;/定时器T1工作于方式2,8位自动重载方式,在这里用|=是为不影响T0的工作TH1=0xf3;TL1=0xf3;/设置串行口波特率为2400bps,定时器初值,波特率设置非常严格 /要是设置错了,在发送和接收的时候,就会出现莫名其妙的符号,比如说:xxxxxxx 诸如此类.O_OTR1=1;/启动定时器T1SCON=0x50;/0101,0000:串行口方式1EN=1允许接收,8位异步通信方式,8-bit UART,TI= 0; RI=0 PCON=0x00;/SMOD