- 数据交互
- 信息传递
- 条件:两个端 发送端
一、通信基础知识
1、时钟信号划分
同步通信:通信双方根据同步信号通信,比如双方有一个共同的时钟信号(SPI全双工 I2C半双工)
异步通信:通信双方有自己独立的系统时钟,大家约定好通信的速度。异步通信不需要同步信号,但是并不是说通信的过程不同步(UART)
2、通信方式划分
串行通信:指的是同一时刻只能收或发一个bit位信息。因此只用1根信号线即可。
串行传输:数据一位一位串起来,逐个传输,数据按位顺序传输。
优点:占用引脚资源少
缺点:速度相对较慢
并行通信:指的是同一时刻可以收或发多个bit位的信息,因此需要多根信号线才行
并行传输:使用多根线同时传输一个字的多个位,如 8 根线一次传输 8 个位。
优点:速度快
缺点:占用引脚资源多
3、通信方向划分
单工:要么收,要么发,只能做接收设备或者发送设备。比如收音机
一根信号线只能单向发送或单向接收
半双工:可以收,可以发,但是不能同时收发, 比如对讲机
一根信号线可以接收数据也可以发送数据,但是两者不能同时进行
全双工:可以在同一时刻既接收,又发送。 手机
两根信号线,一根发送数据,另一根接收数据,真正实现同时收发数据,速度快
Tips:总线协议(电气协议)补充
TTL电平:数字电路中,由TTL电子元器件组成电路使用的电平。电平是个电压范围,规定输出高电平>2.4V,输出低电平<0.4V。在室温下,一般输出高电平是3.5V,输出低电平是0.2V。最小输入高电平和低电平:输入高电平>=2.0V,输入低电平<=0.8V,噪声容限是0.4V。
RS-232:RS232电平
1:-15~-3V 0:+3~+15V RS232采用负逻辑电平 非法状态:-3 ~ +3V
RS-485 :半双工、是电气协议(逻辑1:+2V–+6V 逻辑0: -6V— -2V)是二线制差分信号,也就是实际传输的数据是通过判断这两条信号线上的电压差来实现的,RS-485总线弥补了RS-232通信距离短,速率低的缺点,RS-485的速率可高达10Mbit/s,理论通讯距离可达1200米;RS-485和RS-232的单端传输不一样,是差分传输,使用一对双绞线
二、USART
中文参考手册564页
Universal Synchonous Asynchronous receiver transmitter
USART:支持同步/异步通信 、全双工 、串行
UART:支持异步通信(没有时钟线)、全双工 、串行
三、串口通信协议
数据帧格式:
空闲状态:信号线保持高电平
起始位:1位,低电平表示数据包的起始
数据位:8位/9位
校验位(可选):奇偶校验
奇校验:
数据位上的1的个数 + 校验位上1的个数 = 奇数
偶校验:
数据位上的1的个数 + 校验位上1的个数 = 偶数
停止位:1位 将信号线电平拉高,代表一个数据包发送结束,回到空闲状态。
注:除了配置协议还需要配置波特率
波特率:每秒传输的数据位数 bps bit/s 1Byte = 8bit
常用的:9600bit/s 115200bit/s
四、USART功能框图
Tx:数据发送端
Rx:数据接收端
流控概念p
在两个设备正常通信时,由于处理速度不同,就存在这样一个问题,有的快,有的慢,在某些情况下,就可能导致丢失数据的情况。如台式机与单片机之间的通讯,接收端数据缓冲区已满,则此时继续发送来的数据就会丢失。流控制能解决这个问题
nRTS:请求以发送(Request To Send),n表示低电平有效。当本设备准备好接收新数据时就会将nRTS变成低电平;当接收寄存器已满时,nRTS将被设置为高电平。
nCTS:清除以发送(Clear To Send) 为输入信号,低电平有效。用于判断是否可以向对方发送数据,低电平说明本设备可以向对方发送数据。
该引脚只适用于硬件流控制
SCLK:发送器时钟输出引脚。这个引脚仅适用于同步模式。(UART是异步通信)
发送过程:由CPU或DMA向数据发送寄存器(TDR)中写入要发送的数据,由发送移位寄存器将数据按位移到发送端口输出。
接收过程:由CPU和DMA读取接收数据寄存器(RDR)中的数据。
五、相关寄存器
串口控制寄存器
USART_CR 决定帧格式:起始位+数据位+校验位+停止位
(设备功能初始化、通信帧格式配置)
USART_CR1
USART_CR2
USART_CR3
波特率寄存器
USART_BRR 决定通信速度:bit/s
中断和状态寄存器
USART_ISR
数据接收寄存器
USART_RDR 决定接收的数据:将要接收数据的读取
数据发送寄存器
USART_TDR 决定发送的数据:将要发送的数据写入
六、串口发送实验
实验要求
通过单片机以1s间隔向电脑发送“helloworld”
6.1 观察实物
找到通信接口 丝印“P4”
6.2 分析原理图
CH340:电平转换芯片,可以转换TTL电平—USB电平。(3.3V------->12V)
需要安装驱动
数据选择/多路复用器
MX配置
初始化代码分析
6.4 代码编写
- 实现单个字符发送函数uart_putchar();
2)实现字符串发送函数uart_puts();
void uart_putchar(uint8_t ch)
{while(!(USART1->ISR & (1<<7))){} //等待发送寄存器为空//ISR的第7位为1,说明发送数据寄存器为空,此时再写入要发送的数据//当发送数据寄存器为空时,while(!1);跳出循环,向下执行
USART1->TDR = ch;
}
void uart_puts(uint8_t *p)
{while(*p){uart_putchar(*p);
p++;}
}
七、串口收发实验
实验要求
通过串口助手向单片机发送数据,单片机接收到数据后原样返回。
- 实现字符接收函数 uart_getchar()
- 实现字符串接收函数 uart_gets()
void uart_putchar(uint8_t ch)
{while(!(USART1->ISR & (1<<7))){} //等待发送寄存器为空//ISR的第7位为1,说明发送数据寄存器为空,此时再写入要发送的数据//当发送数据寄存器为空时,while(!1);跳出循环,向下执行
USART1->TDR = ch;
}
void uart_puts(uint8_t *p)
{while(*p){uart_putchar(*p);
p++;}
}uint8_t uart_getchar()
{uint8_t c;while(!(USART1->ISR & (1<<5))){}
c = USART1->RDR;return c;
}void uart_gets(uint8_t *p)
{uint8_t ch;while(1){
ch = uart_getchar();if(ch != '\n') //将回车作为输入结束标志{*p = ch;}else{*p = '\0'; //填充字符串的结束标志break;}
p++;}
}
八、printf的重定向
int printf(const char * format,...)
printf函数底层调用的是fputc函数,fputc是将要发送的数据写入到标准输出流stdout
int fputc(int /*c*/, FILE * /*stream*/)
因此如果想让printf将数据输出到串口,需要重写fputc
WEAK弱符号
weak 顾名思义是“弱”的意思,所以如果函数名称前面加上__weak 修饰符,我们一般称这个函数为“弱函数”。
加上了__weak 修饰符的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,那么编译器就会执行__weak 修饰的函数,并且编译器不会报错。
int fputc(int ch,FILE *p)
{while(!(USART1->ISR & (1<<7))){} //等待发送寄存器为空//ISR的第7位为1,说明发送数据寄存器为空,此时再写入要发送的数据//当发送数据寄存器为空时,while(!1);跳出循环,向下执行
USART1->TDR = ch;return ch;
}
九、HAL库函数
串口发送函数
HAL_StatusTypeDef HAL_UART_Transmit (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size, uint32_t Timeout)
功能:以阻塞模式通过串口发送数据
参数:UART_HandleTypeDef * huart 设备的句柄
uint8_t * pData 要输出的缓存区首地址
uint16_t Size 发送的数据量
uint32_t Timeout 超时时间
返回值:发送状态
串口接收函数
HAL_StatusTypeDef HAL_UART_Receive (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size, uint32_t Timeout)
功能:以阻塞模式通过串口接收数据
参数:UART_HandleTypeDef * huart 设备的句柄
uint8_t * pData 输入缓存区首地址
uint16_t Size 接收的数据量
uint32_t Timeout 超时时间
返回值:接收状态
STM32常见通信协议
STM32-通信协议