一、原理说明
STM32自带通讯接口

通讯目的

通信方式:
全双工:通信时可以双方同时通信。
半双工:通信时同一时间只能一个设备发送数据,其他设备接收。
单工:只能一个设备发送到另一个设备,例如USART只有TX线。
时钟类型:
异步:约定传输速率,例如波特率相同,约定起始信号(和结束信号、帧头帧尾等进行约束和校验)进行传输。
优点是节省了硬件资源,缺点是在传输过程中停止会传输失败,不能中途暂停,而且难以用软件模拟,只能使用硬件传输。
同步:有一根单独的时钟线,通过时钟信号控制传输时的速率。
优点是在传输过程中可以中断(停止时钟信号即可停止),停止后可以继续传输,并且可以使用软件模拟时钟信号和通信,无硬件资源时可以牺牲引脚来使用。
传输类型:
单端:通过信号和GND的电平差来区分高低电平,需要把通信双方的GND接到一起,否则容易受到干扰。
差分:通过两根线的差分电平来判断高低电平通信,抗干扰信号更强,传输距离更远。
(USB尽量共地)
设备拓扑类型:
点对点:设备1-1通信,可能需要寻址,以确定
点对多:设备1-n通信
多对多:设备n-n通信
串口协议:

CH340可以将串口转换为USB协议,可以直接插在电脑上。
陀螺仪传感器可以测量角速度加速度等姿态参数,可以接串口和I2C。
蓝牙串口模块,可以和蓝牙设备互联,实现手机遥控单片机的功能。
串口接线图:

电平标准:

串口协议的软件定义:

RB8和TB8是奇偶校验位,可选择是否使用。一般需要校验位,则选择9bit数据,不需要校验位则选择8bit。
波特率:每秒传输码元的个数,可能每个码元包含信息量不止1bit,单位为码元/s,或者为bund。
比特率:每秒传输bit的速率。单位bit/s,或者bps。在二进制调制的情况下一个码元就是一个bit。
奇偶校验:
奇校验表示,包括校验位和数据位,发送的1为奇数个。例如发送0x0F,则发送 111100001
串口波形实例:
起始位为低电平,默认线上高电平,结束位为高电平(方便区分两个连续数据包)。


STM32的USART外设:

UART和USART类似,但是只支持时钟输出,不支持时钟输入。
同步模式是支持CLK时钟输出、硬件流控制表示传输时可通过从设备反馈 来控制主设备的发送 防止从设备处理慢导致数据丢失。DMA是串口支持DMA数据转运。STM32的串口协议也可支持智能卡、IrDA(红外通信)、LIN(局域网)等设备。
STM32-USART内部原理:

发送数据寄存器TDR和接收数据寄存器RDR使用同一块存储区域。nRTS高速主机当前是否可以接收数据。nCTS用于接收从机nRTS信号的引脚,判断从机当前是否可以接收。n代表低电平有效。串口使用SCLK可以兼容SPI。若不知道对方波特率,可以通过SCLK计算得到并传出输出。
唤醒单元用来实现串口挂载多设备,可以给串口分配地址。总线上对应发送的地址设备会进行通信。
TXE发送寄存器空。
RXNE接收寄存器非空。

USART波形及配置:
一般配置9bit字长,都会使用校验位。若不是用校验位,则第九位为载荷bit。
选择8bit字长最好无校验位,若有校验位,那么有效载荷7bit。每次发送不够1byte。

停止位高电平,一般用1bit。
USART结构图:
USART起始位侦测原理:


波特率分频(分频后还有16倍分频):
例如USART1波特率9600,那么9600 = 72000000/(16*DIV);DIV = 468.785。放入寄存器为111010100.11
USB转串口模块的内部电路图:

不同数据模式:

二、实例
1、串口发送,OLED接收
接线图:

引脚定义:


重构printf函数:

printf输出汉字需要增加--no-multibyte-chars配置,防止中文乱码
--no-multibyte-chars

接收时需要用相同的编码方式

若utf-8兼容性不好,可更换GB2312编码方式。串口接收汉字,需要收发的两方编码方式相同。
main.c
#include "stdio.h"
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
uint8_t SendDataA[3] = {0x01,0x02,0x03};
char *Char = "Hello Word!!!";
int32_t zNum = 23213;
int main(void){
OLED_Init();
Serial_Init();
OLED_ShowString(1,1,"AD0:0000");
OLED_ShowString(2,1,"AD1:0000");
while(1){
Delay_ms(1000);
//Serial_SendByte(0x41);//发送十六进制0x41
//Serial_SendByte('A');//发送字符A,同0x41.逻辑为发送A-底层0x41发送-串口底层接收0x41-可现实字符或十六进制数
//Serial_SendByte(SendDataA[0]);//发送1byte数据
//Serial_SendByteArray(&SendDataA[0],3);//发送指定长度字节数组
//Serial_SendString(Char);发送字符串
//Serial_SendSignedNum(zNum,4);
//printf打印串口方法1
//printf("Num = %d\r\n" , 666);// \r\n为字符换行,printf通过重定向打印串口
//printf打印串口方法2
//不使用重定向格式化字符串来串口打印,所有的串口都有可以用
//char String[100];
//sprintf(String,"Num = %d\r\n" , 666);//使用sprintf进行格式化,然后使用串口进行输出
//Serial_SendString(String);//打印Num = 666\r\n
//printf打印串口方法3
//Serial_printf("Num = %d\r\n" ,

最低0.47元/天 解锁文章
6万+

被折叠的 条评论
为什么被折叠?



