串口接口
通信的目的:将一个设备的数据传送到另一个设备扩展硬件系统
通讯协议: 制定通信的规则,通信双方按照协议规则进行数据收发。
注意: 差分信号一般传输速度和距离都会非常高。
多设备相当于老师在教师给所有同学讲课,点对点相当于老师找你到办公室谈话。
串口是一种应用十分广泛的通讯接口,串口成分低,容易使用、通讯线路简单,可实现两个设备的项目通讯。
单片机的串口可以使单片机与单片机、单片机与电脑(非常适合调试程序,USART串口协议的一大优势),单片机与各式各样的串口相互通讯,极大地扩展了单片机的应用范围,增强了单片机系统的硬件实力。
TX: Transmit(发送)
RX: Receive(接收)
硬件电路
简单双向串口通讯有两根通信线(发送端TX,接收端RX)
TX与RX要交叉连接
当只需单向的数据传输时,可以只接一根通信线
当电平标准不一致时,需要加电平转换芯片。
电平标准
电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电平与数据的对应关系,串口常用的电平标准有如下三种:
1.TTL 电平: +3.3V或者+5V 表示1,0V表示0
2. RS232电平: -3V—— -15V 表示1,+3—— +15V 表示0
3. RS485电平 : 两线压差+2——+6V表示1,-2—— -6 V表示0(差分信号)
异步通讯: 是一种数据传输方式,其中数据的发送和接受不需要双发时钟同步。也就是说,发送方和接收方可以在不同步的时钟频率下独立操作,并且数据传输时不预先协调的时刻进行的。
串口参数及时序
波特率:串口通讯的速度
起始位:标志一个数据帧的开始,固定为低电平
数据位:数据帧的有效载荷,1为高电平,0为低电平,低位先行
校验位: 用于数据验证,根据数据位计算得来。
停止位:用于数据帧间隔, 固定为高电平
USART (Universal Synchronous/ Asynchronous Receiver/Transmitter) 通用同步/异步收发器
USART是STM32内部集成的硬件外设,可根据数据寄存器的一个字节数据自动生成数据帧时序,从TX引脚发送出去,也可自动接受RX引脚的数据帧时序,拼接为一个字节数据,存放在数据寄存器里。
自带波特率发生器,最高达4.5Mbit/s
可配置数据位长度(8/9),停止位长度(0.5/1/1.5/2)
可选校验位(无校验/奇校验/偶校验)
支持同步模式、硬件流控制,DMA、智能卡、IrDA,LIN
STM32F103C8T6 USART 资源: USART1, USART2, USART3.
USART框图
USART基本结构
数据帧
数据帧 配置停止位
USART电路输入数据策略
USART电路比较复杂,输入的采样频率和波特率一致, 输入要对噪声有一点判断能力
起始位侦测
以波特率的16倍进行采样
忽略了前面没3个里面没有至少有2个0。不算检测验到起始位
开始重新补充下降沿。如果通过了数据采样,接受状态就由空闲变为起始位。之后接受数据位,都在第8、9、10次,进行采样。
数据采样
你看在8、9、10 位进行数据采样。
NE 是噪声标志位
波特率发生器
1.发送器和接收器的波特率由波特率寄存器BRR里的DIV确定
2. 计算公式: 波特率 = fpclk/(16div)
假如要配置波特率为9600 由于USART的频率为72MHz,
那么计算公式就是 9600 = 72000,000/(16div)
div = 72MHz / 9600 / 16 = 468.75
将10进制转化为2进制
将USART硬件
CH340G_VCC是选择供电引脚
但是将跳线帽拔掉,依然可以给CH340供电
代码的编写
想知道怎么配置外设的GPIO的模式,可以到参考手册的外设GPIO配置找
数据模式
1.HEX模式/十六进制/二进制模式 : 以原始数据的形式显示。
2.文本模式/字符模式:以原始数据编码的形式显示。
如何使用printf ,并将printf重定向到串口。
第一种方式
使用use MIcro LIB
将#include<stdio.h> 放在Serial.h 中。
int fputc(int ch,FILE *f)
{
Serial_SendByte(ch);
return ch;
}
第二种方式
char String[100];
sprintf(String,"Num=%d\r\n",666);/// 不涉及重定向
Serial_SendString(String);
第三种方式
添加头文件 #include<stdarg.h>
void Serial_Printf(char *format,…)// 可变参数
{
char String[100];
va_list arg;
va_start(arg,format);
vsprintf(String,format,arg);
va_end(arg);
Serial_SendString(String);
}
(1). va_list 是C语言的一个宏定义,用于表示一个变长参数列表的指针,可以通过宏va_start,va_arg 和 va_end 对变长参数列表进行访问和操作。在函数中需要接受不定数量的参数时,可以使用va_list来处理这些参数。
(2). va_start 是一个宏定义,用于在使用可变参数函数获取可变参数的起始地址。它的作用是初始化一个va_list类型的变量,使其指向可变参数列表的第一个参数。va_start宏需要两个参数,分别是一个va_list类型的变量和可变参数的在最后一个固定参数的地址.
(3).va_arg: 是一个宏,用于获取可变参数列表中的下一个参数值
va_arg(ap, type)
其中,ap 是 va_list 类型的可变参数列表指针,type 是要获取的参数的类型。va_arg 宏返回指定类型的参数值,并将可变参数列表指针 ap 向后移动到下一个参数。注意,调用 va_arg 宏之前必须先调用 va_start 宏初始化可变参数列表指针。
(4). va_end:是一个宏,用于结束使用 va_start 和 va_arg 宏定义的可变参数列表。它的作用是清理 va_list 类型变量,以便该变量可以被再次使用。
(5). vsnprintf 是一个函数,用于将格式化的字符串输出到指定的缓存区中,其参数列表。与printf类似,vsnprintf可以根据格式化字符串中的占位符,将后续的参数转化为对应的字符串并输出到缓存区中,但是与printf 不同的是,vsnprintf可以指定的最大长度,以避免缓存区溢出的问题。
(6).vsprintf 是 C 标准库中的一个函数,用于将格式化的数据写入一个字符串。与 sprintf 不同,vsprintf 允许你传递一个 va_list 类型的参数列表,而不是可变数量的参数。它通常用于编写需要处理可变参数的函数.
int vsprintf(char *str, const char *format, va_list ap);
#include <stdio.h>
#include <stdarg.h>
void my_printf(const char *format, ...) {
char buffer[1024]; // 创建一个缓冲区来存储结果字符串
va_list args; // 声明一个 va_list 类型的变量
va_start(args, format); // 初始化 va_list 变量
vsprintf(buffer, format, args); // 使用 vsprintf 将格式化的数据写入缓冲区
va_end(args); // 清理 va_list 变量
printf("%s", buffer); // 打印结果字符串
}
int main() {
my_printf("Hello %s! You have %d new messages.\n", "Alice", 5);
return 0;
}
(1).参数处理方式:
sprintf 直接接受可变数量的参数。
vsprintf 接受一个 va_list 类型的参数列表。
(2).使用场景:
sprintf 适合直接使用固定数量的参数进行格式化。
vsprintf 适合编写需要处理可变参数的函数,例如自定义的打印函数。
(3).代码复杂度:
sprintf 使用起来比较简单,直接传入格式化字符串和参数即可。
vsprintf 需要使用 va_list、va_start、va_end 等宏来处理参数列表。
如何打印汉字
–no-multibyte-chars
另一种方式
选为GB2312
在串口助手选择:GBK
串口读取
有查询和中断两种方式进入
查询的代码
while(1)
{
if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==SET)
{
RXData = USART_ReceiveData(USART1);
//读DR
OLED_ShowHexNum(1,1,RXData,2);
}
}
USART串口数据包
当发送连续的数据包的时候,串口可能错位。这时候就可以数据进行分割。
这里使用了固定包长,可变包长 ,含包头包尾
如果数据和包头包尾重复,可能引起误判,
第一种 限制载荷数据的范围
第二种 无法避免载荷数据和包头包尾重复,尽量使用固定长度的数据包
如果载荷会出现和包头包尾重复的情况,尽量使用固定包长。
文本数据包
HEX数据包接收
状态机
标签:va,end,USART,list,参数,串口,数据 From: https://blog.csdn.net/wedream23/article/details/140334100