1. 初识串口(204.49)
1.1 串口基本认知
- 串行接口、串口,串行通信接口、串行通讯接口(通常指COM接口),采用串行通信方式的扩展接口。
- 串行接口(Serial Interface)是指数据一位一位地顺序传送。
- 特点是通信线路简单,只要一对传输线就可实现双向通信(可直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。
- 设备间接线通信的一种方式
- 数据一位一位地顺序传送
- 双向通信,全双工(*面试会问,概念记住)
- 传送速度相对较慢
1.2 关于电器标准和协议
- 串行接口按电气标准及协议来分,包括RS-232-C、RS-422、RS485 等。
- RS-232-C、RS-422 与 RS-485 标准只对接口的电气特性做出规定,不涉及接插件、电缆或协议。
RS-232
- 也称标准串口,最常用的一种串行通讯接口,如电脑主机的9针串口
- 最高速率为20kb/s
- 是为点对点(即只用一对 收发设备)通讯而设计的,其传送距离最大为约15米,所以其适合本地设备之间的通信
RS-422
- 由于接收器采用高输入阻抗和发送驱动器比RS232更强的驱动能力,故允许在相同传输线上连接多个接收节点,最多可接10个节点。即一个主设备(Master),其余10个为从设备(Slave),从设备之间不能通信,所以支持点对多的双向通信
- 其最大传输距离为1219米,最大传输速率为10Mb/s。平衡双绞线的长度与传输速率成反比
RS-485
- 是从RS-422基础上发展而来的,无论四线还是二线连接方式,总线上最多接到32个设备
1.3 关于串口的电平
- 异步串行是指UART(Universal Asynchronous Receiver/Transmitter),通用异步接收/发送。
- UART包含TTL电平的串口和RS232电平的串口。
RS232电平
- 逻辑 1 为 -3 ~ -15V 的电压,逻辑 0 为 3 ~ 15V 的电压
- 笔记本通过RS232电平和单片机通信
TTL电平
- TTL是Transistor-Transistor Logic,即晶体管-晶体管逻辑的简称,它是计算机处理器控制的设备内部各部分之间通信的标准技术。
- TTL电平信号应用广泛,是因为其数据表示采用二进制规定,+5V 等价于逻辑“1”,0V等价于逻辑”0”。
- 数字电路中,由TTL电子元器件组成电路的电平是个电压范围,规定:
- 输出高电平>=2.4V,输出低电平<=0.4V;
- 输入高电平>=2.0V,输入低电平<=0.8V
- 笔记本电脑通过TTL电平与单片机通信:
- USB转TTL,使用ch340通信
- 上官一号
2. 概念思维整理补充(206.51)
3. 串口编程的关键要素提点(207.52)
串口通信
3.1 串口接线方式
- RXD:数据输入引脚,数据接收;STC89系列对应P3.0口,上官一号有单独引出
- TXD:数据发送引脚,数据发送;STC89系列对应P3.1口,上官一号有单独引出
- 接线方式
3.2 串口编程要素
印象塑造
- 输入/输出数据缓冲器都叫做SBUF,都用99H地址码,但是是两个独立的8位寄存器
- 代码体现为: 想要接收数据
char data = SBUF
想要发送数据 SBUF = data
- 回忆UART是异步串行接口,通信双方使用时钟不同,因为双方硬件配置不同,但是需要约定通信
速度,叫做波特率 - 对于电脑来说,别人做好了软件,鼠标点点点就能配置好,而单片机的波特率配置需要我们写
代码 - 点点点配置什么,我们代码也要配置对应参数
- 直接写代码先玩一下再学概念和数据时序(208.53)
4. 编程实现每秒发送数据给电脑(208.53)
- 代码(14./串口通信01_发送一个字符a给PC)
#include "reg52.h"
#include "intrins.h"
sfr AUXR=0x8E;
void UartInit(void)
{
PCON &= 0x7F;
SCON = 0x50;
AUXR &= 0xBF;
AUXR &= 0xFE;
TMOD &= 0x0F;
TMOD |= 0x20;
TL1 = 0xFD;
TH1 = 0xFD;
ET1 = 0;
TR1 = 1;
}
void Delay1000ms()
{
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();
while(1){
Delay1000ms();
SBUF=data_msg;
}
}
5. 串口编程寄存器分析(209.54)(*多听多理解)
6. 串口编程01_白己实现串口初始化(210.55)(*多听多理解)
- 代码(14./串口通信01_发送一个字符a给PC2)
#include "reg52.h"
#include "intrins.h"
sfr AUXR=0x8E;
void UartInit()
{
AUXR = 0x01;
SCON = 0x40;
TMOD &= 0x0F;
TMOD |= 0x20;
TH1 = 0xFD;
TL1 = 0xFD;
TR1 = 1;
}
void Delay1000ms()
{
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();
while(1){
Delay1000ms();
SBUF=data_msg;
}
}
7. 串口编程02_发送字符串(211.56)
#include "reg52.h"
#include "intrins.h"
sfr AUXR=0x8E;
void UartInit()
{
AUXR = 0x01;
SCON = 0x40;
TMOD &= 0x0F;
TMOD |= 0x20;
TH1 = 0xFD;
TL1 = 0xFD;
TR1 = 1;
}
void Delay1000ms()
{
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 != '\0'){
sendByte(*str);
str++;
}
}
void main()
{
UartInit();
while(1){
Delay1000ms();
sendString("Hello,Jessie!\r\n");
}
}
8. 串口通信编程03_PC发送指令控制LED(212.57)
- 代码(14./串口通信03_PC通过串口点亮LED)
#include "reg52.h"
#include "intrins.h"
sfr AUXR = 0x8E;
sbit D5 = P3^7;
void UartInit()
{
AUXR = 0x01;
SCON = 0x50;
TMOD &= 0x0F;
TMOD |= 0x20;
TH1 = 0xFD;
TL1 = 0xFD;
TR1 = 1;
}
void Delay1000ms()
{
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 != '\0'){
sendByte(*str);
str++;
}
}
void main()
{
char cmd;
D5=1;
UartInit();
while(1){
Delay1000ms();
sendString("Hello,Jessie!\r\n");
if(RI == 1){
RI=0;
cmd=SBUF;
if(cmd == 'o'){
D5=0;
}
if(cmd == 'c'){
D5=1;
}
}
}
}
9. 串口通信编程04_串口中断实时控制LED(213.58)
- 代码(14./串口通信04_PC串口中断控制LED)
#include "reg52.h"
#include "intrins.h"
sfr AUXR = 0x8E;
sbit D5 = P3^7;
char cmd;
void UartInit()
{
AUXR = 0x01;
SCON = 0x50;
TMOD &= 0x0F;
TMOD |= 0x20;
TH1 = 0xFD;
TL1 = 0xFD;
TR1 = 1;
EA = 1;
ES = 1;
}
void Delay1000ms()
{
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 != '\0'){
sendByte(*str);
str++;
}
}
void main()
{
D5=1;
UartInit();
while(1)
{
Delay1000ms();
sendString("Hello,Jessie!\r\n");
}
}
void UartHepler() interrupt 4
{
if(RI)
{
RI=0;
cmd=SBUF;
if(cmd == 'o'){
D5=0;
}
if(cmd == 'c'){
D5=1;
}
}
if(TI);
}
10. 小白玩串口控制的ASSII避坑(214.59)
- 代码(14./串口通信04_PC串口中断控制LED2)
void UartHepler() interrupt 4
{
if(RI)
{
RI=0;
cmd=SBUF;
if(cmd == 1){
D5=0;
}
if(cmd == 0){
D5=1;
}
}
if(TI);
}
11. 串口支持单词型指令控制(215.60)
- 串口接收通常是字节流的方式进行的,即每个字节逐个传输和接收。要接收一个完整的字符串,你需要在接收端进行缓冲和拼接,以便将连续的字节组合成一个字符串。以下是一种常见的方法:
- 创建一个字符数组(缓冲区),用于存储接收到的字节。缓冲区的大小应该足够大,以容纳你预期的最大字符串长度,同时需要一个额外的字节来存储字符串的终止符,通常是 null 终止符 \0。
#define BUFFER_SIZE 128
char receiveBuffer[BUFFER_SIZE + 1];
- 在串口接收中断处理函数中,当每个字节被接收时,将它存储到缓冲区,并维护一个变量来跟踪当前接收到的字节数。
void UartHelper() interrupt 4 {
if (RI) {
RI = 0;
if (receiveIndex < BUFFER_SIZE) {
receiveBuffer[receiveIndex] = SBUF;
receiveIndex++;
}
}
}
- 在接收数据时,你可以检查是否接收到了预期的终止字符(例如,换行符 \n 或回车符 \r),以确定字符串的结束。一旦接收到终止字符,你可以将接收到的字节序列视为一个完整的字符串。
- 请注意,你需要在接收到终止字符后,在 receiveBuffer 中添加 null 终止符 \0,以便将它转换为 C 风格的字符串。
if (receiveBuffer[receiveIndex - 1] == '\n' || receiveBuffer[receiveIndex - 1] == '\r') {
receiveBuffer[receiveIndex] = '\0';
memset(receiveBuffer, 0, sizeof(receiveBuffer));
receiveIndex = 0;
}
- 这个流程允许你在接收串口数据时将连续的字节组合成一个字符串,并在接收到终止字符后将其视为完整的字符串。接下来,你可以对接收到的字符串进行解析或执行其他操作,具体取决于你的应用需求。
- 两种存储数据方式的区别
- 代码(串口通信05_字符串型指令如何处理)
#include "reg52.h"
#include "intrins.h"
#include <string.h>
#define SIZE 12
sfr AUXR = 0x8E;
sbit D5 = P3^7;
char cmd[SIZE];
void UartInit()
{
AUXR = 0x01;
SCON = 0x50;
TMOD &= 0x0F;
TMOD |= 0x20;
TH1 = 0xFD;
TL1 = 0xFD;
TR1 = 1;
EA = 1;
ES = 1;
}
void Delay1000ms()
{
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 != '\0'){
sendByte(*str);
str++;
}
}
void main()
{
D5=1;
UartInit();
while(1)
{
Delay1000ms();
sendString("Hello,Jessie!\r\n");
}
}
void UartHepler() interrupt 4
{
static int i=0;
if(RI)
{
RI=0;
cmd[i]=SBUF;
i++;
if(i==SIZE)
{
i=0;
}
if(strstr(cmd,"open")){
D5=0;
i=0;
memset(cmd,'\0',SIZE);
}
if(strstr(cmd,"close")){
D5=1;
i=0;
memset(cmd,'\0',SIZE);
}
}
if(TI);
}
12. 串口原理协议概念收尾(216.61)(*多听多理解)
- 串口、校验位、中断
- 编程出问题时,可先阅读手册,再去百度查阅