基于51单片机的串口通信

it2024-04-07  56

串口通信(LCD1602显示)

选用芯片:AT89S52 函数功能:串口通信的使用,通过串口接收数据控制单片机的液晶LCD1602依次显示电脑端发送的数据(字符或字符串),然后再回传给电脑端。 博主才疏学浅,可能会出现设计不足和错误,欢迎大家评论区交流。^ _ ^

/******************************************************************* 此函数功能为:串口通信的使用,通过串口接收数据控制单片机的液晶LCD1602 依次显示电脑端发送的数据(字符或字符串),然后再回传给电脑端。 作者:Crazy Wind 日期:2020.10.21 version:1.0.0 ********************************************************************/ #include"reg52.h" #include"intrins.h" #define uchar unsigned char #define uint unsigned int sbit RS=P2^0; //寄存器选择位RS为P2.0 sbit RW=P2^1; //读写选择位RW为P2.1 sbit E=P2^2; //使能信号位E为P2.2 sbit BF=P0^7; //忙碌标志位BF为P0.7 uchar k=0; uchar zifuc[]={" "}; //给要显示的数组初始值为空 /***************************************************** 函数功能:ms延时 ******************************************************/ void delayms(uint ms) //毫秒延时 { uint i,j; for(i=0;i<ms;i++) { for(j=115;j>0;j--); } } /***************************************************** 函数功能:发送数据a ******************************************************/ void send_char(uchar a) { SBUF=a; //SBUF是数据缓冲寄存器(暂存数据),把数据x输入到SBUF while(!TI); //等待数据发送 TI=0; //每发送8位数据TI就自动置1,需软件清零 } /***************************************************** 函数功能:串口初始化、T1作波特率发生器初始化、打开串口中断 ******************************************************/ void init() { TMOD=0x20; //定时器1工作于8位自动重载模式, 用于产生波特率 TH1=0xFD; //波特率9600 TL1=0xFD; SCON=0x50; //串口工作方式1 允许接收 PCON=0x00; //波特率不倍增 TR1=1; //启动定时器1 EA=1; //打开总中断 ES=1; //打开串口中断 } /***************************************************** 函数功能:判断液晶模块的忙碌状态 返回值:m。m=1,忙碌;m=0,不忙 ******************************************************/ bit BusyTest(void) { bit m; RS=0; //RS为低电平,RW为高电平时,可以读状态 RW=1; E=1; //E=1,才允许读写 _nop_(); //空操作四个机器周期,给硬件反应时间 _nop_(); _nop_(); _nop_(); m=BF; //将忙碌标志电平赋给m E=0; return m; //将忙碌标志电平赋给m } /***************************************************** 函数功能:将模式设置指令或显示地址写入液晶模块 入口参数:z ******************************************************/ void Write_zl(uchar z) { while(BusyTest()==1); //如果忙就等待 RS=0; //RS和RW同时为低电平时,可以写入指令 RW=0; E=0; //使能信号E置低电平(写指令前先赋低电平0) _nop_(); _nop_(); //空操作两个机器周期,给硬件反应时间 P0=z; //将数据送入P0口(数据总线line),即写入指令或地址 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=1; //使能信号E上升沿(0到1)时读取信息 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=0; //使能信号E下降沿(1到0)时执行指令 } /***************************************************** 函数功能:指定字符显示的实际地址 入口参数:x ******************************************************/ void WriteAddress(uchar x) { Write_zl(x|0x80); //显示位置的确定方法规定为"地址码x+80H" } /***************************************************** 函数功能:将数据(字符的标准ASCII码)写入液晶模块 入口参数:y(为字符常量) ******************************************************/ void WriteData(uchar y) { while(BusyTest()==1); //如果忙就等待 RS=1; //RS为高电平,RW为低电平时,可以写入数据 RW=0; E=0; //使能信号E置低电平(写数据前先赋低电平0) _nop_(); _nop_(); //空操作两个机器周期,给硬件反应时间 P0=y; //将数据送入P0口(数据总线line),即将数据写入液晶模块 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=1; //使能信号E上升沿(0到1)时读取信息 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=0; //使能信号E下降沿(1到0)时执行指令 } /***************************************************** 函数功能:对LCD的显示模式进行初始化设置 ******************************************************/ void LcdInit(void) { delayms(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间 Write_zl(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口 delayms(5); //延时5ms  Write_zl(0x38); delayms(5); Write_zl(0x38); //3次写入 设置模式 delayms(5); Write_zl(0x0F); //显示模式设置:显示开,有光标,光标闪烁 delayms(5); Write_zl(0x06); //显示模式设置:光标右移,字符不移 delayms(5); Write_zl(0x01); //清屏幕指令,将以前的显示内容清除 delayms(5); } void main() { uchar c; uchar d; init(); //串口初始化 LcdInit(); //调用LCD初始化函数 delayms(10); Write_zl(0x01); //清屏指令 delayms(5); while(1) { delayms(5); WriteAddress(0x00); //设置显示位置为第一行第1个 delayms(5); /**********在第一行写入**********/ for(c=0;c<16;c++) { WriteData(zifuc[c]); //显示数组1中字符 delayms(1); } WriteAddress(0x40); //设置显示位置为第二行的第1个字 delayms(5); /**********在第二行写入**********/ for(d=16;d<32;d++) { WriteData(zifuc[d]); //显示数组1中字符 delayms(1); } } } /***************************************************** 函数功能:串口接收的中断函数 ******************************************************/ void TNT_Uart() interrupt 4 { uchar b; if(RI==1) //查询是否有数据到来 { RI=0; //每接收8位数据RI就自动置1,需软件清零 b=SBUF; //SBUF是数据缓冲寄存器(暂存数据),把数据输出到b zifuc[k]=b; //b再依次赋给数组zifuc[] send_char(b); //回传给电脑接收到的数据 k++; if(k==32) //装满32位就重装 { k=0; } } }
最新回复(0)