51单片机串口
1.串口通信
1.1串口接线方式
-
RXD:数据输入引脚,数据接受;STC89系列对应P3.0口,上官一号有单独引出
-
TXD:数据发送引脚,数据发送;STC89系列对应P3.1口,上官一号有单独引出
-
接线方式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FMY5yTZI-1690308835514)(C:\Users\xie19\Pictures\Camera Roll\屏幕截图 2023-07-25 185225.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xUfBzHGK-1690308835515)(C:\Users\xie19\Pictures\Camera Roll\屏幕截图 2023-07-25 185247.png)]
2.串口编程要素
-
输入/输出数据缓冲器都叫做SBUF, 都用99H地址码,但是是两个独立的8位寄存器
-
代码体现为: 想要接收数据 char data = SBUF 想要发送数据 SBUF = data
-
回忆UART是异步串行接口,通信双方使用时钟不同,因为双方硬件配置不同,但是需要约定通信速度,叫做波特率
对于电脑来说,别人做好了软件,鼠标点点点就能配置好,而苦逼单片机的波特率配置需要我们写代码点点点配置什么,我们代码也要配置对应参数
3.发送一个字符给PC
#include "reg52.h"
#include "intrins.h"
sfr AUXR=0x8e;
/*
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
*/
void UartInit(void)
{
AUXR=0x01;
SCON=0x40; //配置串口工作方式1,REN使能不接收
TMOD&=0x0F; //配置定时器工作模式
TMOD|=0x20;
TL1=0xFD; //配置定时器初值
TH1=0xFD;
TR1=1;
}
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
char data_msg='a';
UartInit();//C51串口通信初始化
//每隔1s发送一次
while(1)
{
Delay1000ms();
SBUF=data_msg;
//发送数据往寄存器SBUF写数据就ok
}
}
4.发送一个字符串给PC
#include "reg52.h"
#include "intrins.h"
sfr AUXR=0x8e;
/*
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
*/
void UartInit(void)
{
AUXR=0x01;
SCON=0x40; //配置串口工作方式1,REN使能不接收
TMOD&=0x0F; //配置定时器工作模式
TMOD|=0x20;
TL1=0xFD; //配置定时器初值
TH1=0xFD;
TR1=1;
}
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void sendByte(char data_msg)
{
SBUF=data_msg;
while(!TI);
TI=0;
}
void sendString(char *str)
{
while(*str)
{
sendByte(*str);
str++;
}
}
void main()
{
UartInit();//C51串口通信初始化
//每隔1s发送一次
while(1)
{
Delay1000ms();
sendString("nihao pc\r\n");
}
}
5.PC通过串口点亮LED
#include "reg52.h"
#include "intrins.h"
sbit D5=P3^7;
sfr AUXR=0x8e;
/*
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
*/
void UartInit(void)
{
AUXR =0x01;
SCON =0x50; //配置串口工作方式1,REN使能不接收
TMOD&=0x0F; //配置定时器工作模式
TMOD|=0x20;
TL1 =0xFD; //配置定时器初值
TH1 =0xFD;
TR1 =1;
}
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void sendByte(char data_msg)
{
SBUF=data_msg;
while(!TI);
TI=0;
}
void sendString(char *str)
{
while(*str)
{
sendByte(*str);
str++;
}
}
void main()
{
char cmd;
D5=1;//一上电让D5灭
UartInit();//C51串口通信初始化
//每隔1s发送一次
while(1)
{
Delay1000ms();
sendString("nihao pc\r\n");
//怎么知道收到了数据,打开RI中断,有硬件置1(RI=1)
if(RI==1)
{
RI=0;
cmd=SBUF;//从寄存器接收数据
if(cmd=='o')
{
D5=0;
}
if(cmd=='c')
{
D5=1;
}
}
}
}
6.PC通过串口中断点亮LED
#include "reg52.h"
#include "intrins.h"
sbit D5=P3^7;
sfr AUXR=0x8e;
char cmd;
/*
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
*/
void UartInit(void)
{
AUXR =0x01;
SCON =0x50; //配置串口工作方式1,REN使能不接收
TMOD&=0x0F; //配置定时器工作模式
TMOD|=0x20;
TL1 =0xFD; //配置定时器初值
TH1 =0xFD;
TR1 =1;
EA=1;//打开总中断
ES=1;//打开串口中断
}
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void sendByte(char data_msg)
{
SBUF=data_msg;
while(!TI);
TI=0;
}
void sendString(char *str)
{
while(*str)
{
sendByte(*str);
str++;
}
}
void main()
{
D5=1;//一上电让D5灭
UartInit();//C51串口通信初始化
//每隔1s发送一次
while(1)
{
Delay1000ms();
sendString("nihao pc\r\n"); //心跳包;作用:有数据,说明单片机正常
}
}
void uart_handler() interrupt 4
{
if(RI)
{
RI=0;
cmd=SBUF;//从串口寄存器SBUF接收数据
if(cmd=='o')
{
D5=0;
}
if(cmd=='c')
{
D5=1;
}
}
if(TI);
}
7.串口发送字符串点亮LED
#include "reg52.h"
#include "intrins.h"
#include<string.h>
#define SIZE 12
sbit D5=P3^7;
sfr AUXR=0x8e;
char cmd[SIZE];
/*
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
*/
void UartInit(void)
{
AUXR =0x01;
SCON =0x50; //配置串口工作方式1,REN使能不接收
TMOD&=0x0F; //配置定时器工作模式
TMOD|=0x20;
TL1 =0xFD; //配置定时器初值
TH1 =0xFD;
TR1 =1;
EA=1;//打开总中断
ES=1;//打开串口中断
}
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void sendByte(char data_msg)
{
SBUF=data_msg;
while(!TI);
TI=0;
}
void sendString(char *str)
{
while(*str)
{
sendByte(*str);
str++;
}
}
void main()
{
D5=1;//一上电让D5灭
UartInit();//C51串口通信初始化
//每隔1s发送一次
while(1)
{
Delay1000ms();
sendString("nihao pc\r\n"); //心跳包;作用:有数据,说明单片机正常
}
}
void uart_handler() interrupt 4
{
static int i=0;
if(RI)
{
RI=0;
cmd[i]=SBUF;//从串口寄存器SBUF接收数据
i++;
if(i==SIZE)
{
i=0;
}
if(strstr(cmd,"op"))
{
D5=0;
i=0;
memset(cmd,0,SIZE);
}
if(strstr(cmd,"cl"))
{
D5=1;
i=0;
memset(cmd,0,SIZE);
}
}
if(TI);
}