单片机 串口通信实验

您所在的位置:网站首页 波特率2400为什么是0xf4 单片机 串口通信实验

单片机 串口通信实验

2024-07-02 03:46| 来源: 网络整理| 查看: 265

思考题: 设计两个单片机通过串口方式1进行全双工数据通信,要求将波特率设置为2400,晶振频率为11.0592MHz,请分别编写发送程序和接收程序,接收端需使用液晶屏幕显示接收内容,发送端可循环发送一个字符串(自己定义一个字符串,例如“Welcome to Wuhan”)。

(1)电路图如下: 在这里插入图片描述 (2)设计思路:

1、电路: 两个单片机都是用P0口连接LCD1602数据线的0~7位,P20连接寄存器选择位RS,P21连接读写选择位RW,P2^2连接使能位E。然后甲机的RXD连乙机的TXD,甲机的TXD连乙机的RXD。需要注意的是:P0口,P2作为I/O口输出的时候时输出低电平为0输出高电平为高组态(并非5V,相当于悬空状态)。也就是说不能真正的输出高电平,给所接的负载提供电流,因此必须接上拉电阻。

2、程序: 波特率2400,晶振频率为11.0592MHZ,T1工作在方式1,由公式X=256-(fosc/12)(2^SMOD/(322400)),可以算出初值TH1=TL1=244=0xf4。有关LCD1602的相关函数此处就略了!!

2.1甲机发送数据程序说明: 串口首先要初始化,选择方式1,REN允许接收位置1,即SCON=0x50;T1工作在方式2,即TMOD=0x20;波特率不加倍,即PCON=0x00;设置初值TH1=TL1=0xf4;启动T1,即TR1=1。 然后串口发送数据,CPU将数据写入SBUF,即SBUF=dat;再搞一个陷阱while(!TI)来判断是否发完,下一步TI置0; 调用LCD1602的单字符显示函数dis_char(address++,dat) (address刚开始为0x00)发送下一个数据时地址++,(发送完一个数据 就显示一个数据);显示完第一行 就显示第二行;显示完第二行 清屏后又显示第一行;发送完一帧数据 地址就归零 清屏 从头再来。 注意这里清屏之前要延时一下 ,等前面发送的数据显示完了,再清屏!具体请看代码!!!

2.2乙机接收数据程序说明: 首先也是串口的初始化 ,跟楼上甲机是一样的! 然后是串口接收数据,这里是通过串口中断来接收数据的(interrupt 4)。但是有个不足就是得事先知道发送数据的第一个字符;判断当SBUF==发送数据的第一个字符时,这就说明刚接收完一帧数据或者马上开始接收数据,那这时就将地址address置0并将屏幕清屏;然后读SBUF中的数据,调用LCD1602的单字符显示函数dis_char(address++,receive_char) ;再将RI软件置0。最后同发送的显示格式一样,显示完第一行 就显示第二行;显示完第二行 清屏后又显示第一行;接收完一帧数据 地址就归零 清屏 从头再来。

(3)发送程序代码:

/** 功能描述: 甲机发数据!”**/ #include #include #define uchar unsigned char #define uint unsigned int #define lcd_out P0 /***********端口定义********************************/ sbit rs=P2^0; sbit rw=P2^1; sbit e=P2^2; /***********函数申明***********************************/ void UART_Init(void); void UART_SendData(uchar dat); void UART_SendString(uchar *p); void delay(uint j); void check_busy(void); void write_command(uchar com); void write_data(uchar dat); void LCD_initial(void); void dis_char(uchar ad, uchar input); /***********变量定义********************************/ uchar address=0x00; //显示地址 uchar sting[]="Welcome to Sichuan for hot pot!"; void main(void) { LCD_initial(); //LCD1602 初始化 UART_Init(); //串口初始化 while(1) { UART_SendString(sting); //发送字符串 address=0x00; //发送完数据 地址就归零 从头再来 delay(1000); write_command(0x01); //发送完一帧数据 清屏 } } //串口初始化 void UART_Init(void) { SCON=0x50; TMOD=0x20; PCON=0x00; TH1 =0xf4; TL1 =0xf4; //预置初值,设波特率为2400 TR1 =1; } //串口发送一个字节的数据 void UART_SendData(uchar dat) { SBUF=dat; //发送数据 while(!TI); //判断是否发送完 TI=0; //软件清0 delay(100); dis_char(address++,dat); //发送完一个数据 显示一个数据 if(address==0x10) address=0x40;//显示完第一行 就显示第二行 if(address==0x50){ write_command(0x01); address=0x00;//显示完第二行 清屏后又显示第一行 } } //串口发送多字节数据 void UART_SendString(uchar *p) { while(*p!='\0') { UART_SendData(*p); p++; } } //1ms延时程序 void delay(uint j) { uchar i=250; for(;j>0;j--) { while(--i); i=249; while(--i); i=250; } } //查忙程序 void check_busy(void) { uchar dt; do { dt=0xff; e=0; rs=0; rw=1; e=1; dt=lcd_out; }while(dt&0x80); e=0; } //写控制指令 void write_command(uchar com) { check_busy(); e=0; rs=0; rw=0; lcd_out=com; e=1; _nop_(); e=0; delay(1); } //写数据指令 void write_data(uchar dat) { check_busy(); e=0; rs=1; rw=0; lcd_out=dat; e=1; _nop_(); e=0; delay(1); } //液晶屏初始化 void LCD_initial(void) { write_command(0x38);//8位总线,双行显示,5X7的点阵字符 write_command(0x0C);//开整体显示,光标关,无黑块 write_command(0x06);//光标右移 write_command(0x01);//清屏 delay(1); } // 输出字符 void dis_char(uchar ad, uchar input) { write_command(ad+0x80);//ad是显示位置信息 write_data(input); delay(10); }

(4)接受程序代码:

/** 功能描述: 乙机收数据!”**/ #include #include #define uchar unsigned char #define uint unsigned int #define lcd_out P0 /***********端口定义********************************/ sbit rs=P2^0; sbit rw=P2^1; sbit e=P2^2; /***********函数申明***********************************/ void UART_Init(void); void delay(uint j); void check_busy(void); void write_command(uchar com); void write_data(uchar dat); void LCD_initial(void); void dis_char(uchar ad, uchar input); /***********变量定义********************************/ uchar address=0x00; //显示地址 uchar receive_char; //接收的数据 void main(void) { LCD_initial(); //LCD1602 初始化 UART_Init(); //串口初始化 ES=1;//打开串口中断开关 EA=1;//打开中断总开关 while(1) { if(address==0x10) address=0x40; //显示完第一行 就显示第二行 if(address==0x50){ write_command(0x01); address=0x00;//显示完第二行 清屏后又显示第一行 } } } //利用串口中断来接收数据 并用LCD显示信息 void inter (void) interrupt 4 { if(SBUF=='W'){ //不足就是 得事先知道发送数据的第一个字符 write_command(0x01);//接收完一帧就清屏 address=0x00; //地址也归零 从头再来 } receive_char=SBUF; dis_char(address++, receive_char);//接收一个数据显示一个数据 RI=0; //软件清0 } //串口初始化 void UART_Init(void) { SCON=0x50; TMOD=0x20; PCON=0x00; TH1 =0xf4; TL1 =0xf4; //预置初值,设波特率为2400 TR1 =1; } //1ms延时程序 void delay(uint j) { uchar i=250; for(;j>0;j--) { while(--i); i=249; while(--i); i=250; } } //查忙程序 void check_busy(void) { uchar dt; do { dt=0xff; e=0; rs=0; rw=1; e=1; dt=lcd_out; }while(dt&0x80); e=0; } //写控制指令 void write_command(uchar com) { check_busy(); e=0; rs=0; rw=0; lcd_out=com; e=1; _nop_(); e=0; delay(1); } //写数据指令 void write_data(uchar dat) { check_busy(); e=0; rs=1; rw=0; lcd_out=dat; e=1; _nop_(); e=0; delay(1); } //液晶屏初始化 void LCD_initial(void) { write_command(0x38);//8位总线,双行显示,5X7的点阵字符 write_command(0x0C);//开整体显示,光标关,无黑块 write_command(0x06);//光标右移 write_command(0x01);//清屏 delay(1); } // 输出字符 void dis_char(uchar ad, uchar input) { write_command(ad+0x80);//ad是显示位置信息 write_data(input); delay(10); }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3