单片机实验报告-串口实验

2019-04-15 18:23发布

一.实验目的 1.  掌握 51 单片机串口工作原理。 2.  掌握 51 单片机串口初始化编程。 3.  掌握 51 单片机串口的软硬件编程。 二.实验设备和器件 1.KEIL软件 2.PROTEUS仿真软件    3.伟福实验箱 三.实验内容 1编程实现:编程实现:甲、乙双机串行通信,双机的 RXD 和 TXD 相互交叉相连,甲机的 P0 口接 8 个开关,乙机的 P0口接 8 个发光二极管。甲机设置为只发不收的单工方式。要求甲机读入 P0口的 8 个开关的状态后,通过串行口发送到乙机,乙机将接收到的甲机的 8 个开关的状态数据送入 P0 口
  • 电路图:
 
  • 代码:
/*甲机(接开关)代码*/ #include #define uchar unsigned char #define uint unsigned int void main() {uchar temp=0; TMOD=0x20; /*设置定时器T1为方式2*/ TH1=0xfd; /*波特率9600*/ TL1=0xfd; SCON=0x40; /*方式1只发送,不接收*/ PCON=0x00; /*波特率为9600,SMOD=0*/ TR1=1; /*启动T1*/ P0=0xff; /* P1口为输入*/ while(1) {temp=P0; /*读入P0口开关的状态数据*/ SBUF=temp; /*数据送串行口发送*/ while(TI==0); /*如果TI=0,未发送完,循环等待*/ TI=0;}}/*已发送完,再把TI清0*/ /*乙机(接灯)代码*/ #include #define uchar unsigned char #define uint unsigned int void main() {uchar temp=0; TMOD=0x20; /*设置定时器T1为方式2*/ TH1=0xfd; /*波特率9600*/ TL1=0xfd; SCON=0x50; /*方式1接收REN=1*/ PCON=0x00; /*波特率为9600,SMOD=0*/ TR1=1; /*启动T1*/ P0=0xff; /* P0口为输入*/ while(1) {while(RI==0); /* 若RI为0,未接收到数据*/ RI=0; /* 接收到数据,则把RI清0*/ temp=SBUF; /* 读取数据存入temp中*/ P0=temp; /* 接收的数据送P0口控制8个LED的亮与灭*/ }}
  • 分析:
  1. 串口工作于方式1或方式3已知波特率,计算初值的公式:
  则波特率为9600bps,方式1接收和发送SMOD=0,则初值=256-11059200/(384*9600)=253=fdH
  1. REN为允许接收控制位,REN=1,则允许接收,REN=0,则禁止接收,允许发送,在该题中,最开始将乙机的SCON也设置为40H,及REN=0,此时不管开关怎么变换,灯都不会亮,原因是乙机现在无法接收串口数据
  2. 当开关闭合是,串口传送的数据为低电平数据,protuse仿真中,灯即为低电平亮,则不需要取反,eg:当第一个开关闭合时,传送的数据为01111111,则乙机收到数据后,第D0位为低电平,则第一盏灯亮
  (2)参考实验 1,将乙机的显示改为 LED 数码管,将按键输入显示到数码管上,按键输入范围:0~F
  • 电路图:
 
  • 代码:
/*甲机(接开关)代码*/ #include #define uchar unsigned char #define uint unsigned int void main() {uchar temp=0; TMOD=0x20; /*设置定时器T1为方式2*/ TH1=0xfd; /*波特率9600*/ TL1=0xfd; SCON=0x40; /*方式1只发送,不接收*/ PCON=0x00; /*串行口初始化为方式0*/ TR1=1; /*启动T1*/ P0=0x0f; /* P0口为输入*/ while(1) {temp=P0; /*读入P0口开关的状态数据*/ SBUF=temp; /*数据送串行口发送*/ while(TI==0); /*如果TI=0,未发送完,循环等待*/ TI=0;/*已发送完,再把TI清0*/ }} /*乙机(接数码管)代码*/ #include #include #define uchar unsigned char #define uint unsigned int void delay(unsigned int time) {int j = 150; for(;time>0;time--) for(;j>0;j--);} void main( ) {Code uchar codevalue[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; uchar temp=0; TMOD=0x20; TH1=0xfd; TL1=0xfd; SCON = 0x50; PCON = 0x00; TR1=1; while(1) {while(RI==0); RI=0; temp=SBUF; P0=codevalue[temp]; }}
  • 分析:
  1. 数码管共阴极发光二极管的正级接地,要接一个排阻才可以正常使用;共阳极单片机可以直接驱动发光二极管的正级接电源
  2. 在该题中数码管只能显示到F,乙机P0显示的值是codevalue[16]数组中的数,所以只需要4个开关控制,则甲机P0的初始值为0x0f,,初始值不能大于0f,如果大于,则超过了数组的范围,则数码管无法显示。
  3.  
  4. (3)编写程序控制 LCD1602 输出显示数字和英文字符,显示内容为 2 行:第一行:学号;第二行:英文姓名(拼音)
  • 电路图:
 
  • 代码:
#include #define uchar unsigned char sbit RS=P1^7;/*数据命令选择端*/ sbit RW=P1^6;/*读/写选择端*/ sbit E=P1^5;/*使能端*/ void init(void); void wc51r(uchar i); void wc51ddr(uchar i); void fbusy(void); void main() {SP=0x50;init(); wc51r(0x80);wc51ddr('1');wc51ddr('5');wc51ddr('0');wc51ddr('4');wc51ddr('0'); wc51ddr('1');wc51ddr('0');wc51ddr('1');wc51ddr('0');wc51ddr('7'); wc51r(0xc0);wc51ddr('j');wc51ddr('i');wc51ddr('a');wc51ddr('n'); wc51ddr('g');wc51ddr(' ');wc51ddr('z');wc51ddr('h');wc51ddr('e');wc51ddr('n'); while(1);} /*初始化函数*/ void init() {wc51r(0x01);//清屏命令 wc51r(0x38);//设置16*2,5*7点阵,8位数据接口 wc51r(0x0c);//显示控制开关命令:D=1,显示;c=0,光标不显示;B=0,字符不闪烁 wc51r(0x06);}//输入方式设置命令:字符不动,光标自动向右移动 /*检查忙函数*/ void fbusy() {P2=0xff;RS=0;RW=1;//忙标志和地址计数器读出 E=0;E=1; while (P2&0x80) {E=0;E=1;}//忙,等待 } /*写命令函数*/ void wc51r(uchar j) {fbusy(); E=0;RS=0;RW=0;//指令寄存器写入 E=1;P2=j;E=0;} /*写数据函数*/ void wc51ddr(uchar j) { fbusy(); E=0;RS=1;RW=0;//数据寄存器写入 E=1;P2=j;E=0;}
  •  分析:
  1. sp其实是一个寄存器,其中只能保存一个指针,而这个指针就指向了栈空间中的最高层,即栈顶
  2. LCD第一行第一个字符地址为80H,第二行第一个字符地址为C0H
  3. E,使能端,为高电平时,读取液晶模块信息,当E端由高电平跳变成低电平时,液晶模块执行写操作