打印
[其他ST产品]

STM32——USART

[复制链接]
楼主: 键盘手没手
手机看帖
扫描二维码
随时随地手机跟帖
21
键盘手没手|  楼主 | 2024-1-31 13:04 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
唤醒单元可以实现多设备通信,当发送指定地址时,唤醒单元开始工作;从而实现多设备通信、

使用特权

评论回复
22
键盘手没手|  楼主 | 2024-1-31 13:04 | 只看该作者
各种中断标志位;

其中中断控制就是控制中断是否能到NVIC;

使用特权

评论回复
23
键盘手没手|  楼主 | 2024-1-31 13:04 | 只看该作者
波特率发生器:

APBx时钟

过程:TE为1发送器波特率控制,RE为1接收器波特率控制,然后再波特率控制器中分为整数部分和小数部分(因为有些波特率整数除不尽可能会有误差,所以有小数部分),然后将分频系数输出对输入进来的时钟频率进行分频,然后/16得到发送器时钟和接收器时钟 ,通向控制部分;

USART引脚复用GPIO参考引脚复用复用;

使用特权

评论回复
24
键盘手没手|  楼主 | 2024-1-31 13:05 | 只看该作者
4.3USART串口外设实现过程



1.RCC开启GPIO和USART外设时钟;

2.初始化GPIO,配置GPIO的输出引脚为复用推挽输出,输入引脚为上拉输入或者浮空输入(最好是上拉输入,给引脚一个默认的电平,防止外部干扰,造成引脚跳变);

3.初始化USART,配置波特率发生器(预分频器,对输入的时钟进行分频),配置发送和接受控制器;

4.使能CMD

使用特权

评论回复
25
键盘手没手|  楼主 | 2024-1-31 13:05 | 只看该作者
4.4USART串口外设时序图分析
输入数据问题:第一就是要在输入数据中间进行采样,才能确保采样的准确性,否则可能电平还在翻转就采样,导致数据不准;

第二数据输入要对噪声有一定的判断能力,如果是噪声,置标志位判断;

STM32中,通过对输入的波特率进行16分进行采样

过程:空闲状态每一位进行16次采样,对应结果一直为1,如果某一个时刻采样为0,那么表示出现下降沿,那么继续在一位中采样16次,并且之后每三位进行一次判断,如果三位中至少有两个为0,则认为为起始位标志,但是出现了噪声,同时将噪声标志位NE置1,如果只有一个0那么默认为前面的标志位0为噪声影响,全部忽略不计重新开始计算;如果通过了起始位侦测,则接收状态由空闲位,变成接收起始位,同时第8、9、10次采样的位置为起始位的正中间,之后每次都在第8、9、10次采样,这样就能保证后续每次采样都在正中间进行采样;、

使用特权

评论回复
26
键盘手没手|  楼主 | 2024-1-31 13:05 | 只看该作者

使用特权

评论回复
27
键盘手没手|  楼主 | 2024-1-31 13:06 | 只看该作者

使用特权

评论回复
28
键盘手没手|  楼主 | 2024-1-31 13:06 | 只看该作者

使用特权

评论回复
29
键盘手没手|  楼主 | 2024-1-31 13:06 | 只看该作者
数据采样流程:1-16,一个数据位有16个采样时钟对应16位,由于起始帧测已经对齐采样时钟,直接在第8、9、10次采样,为了保证数据的可靠,即三次采样,如果都为1则位1,如果都为0则为0,如果不全为1或者0,则根据2:1的原则判断1或者0;

使用特权

评论回复
30
键盘手没手|  楼主 | 2024-1-31 13:07 | 只看该作者


Printf 打印到串口方法

1.重定向方法:

int fputc(int ch,FILE *f)

{

Serial_SendByte(ch);

return ch;

}

更改底层,但是只能应用一个串口;

使用特权

评论回复
31
键盘手没手|  楼主 | 2024-1-31 13:07 | 只看该作者
2.sprintf指定打印位置;把格式化字符输出到一个字符串里;

Char string[100];

Sprint(string,“num=%d”,666);

Serial_SendString(String);

使用特权

评论回复
32
键盘手没手|  楼主 | 2024-1-31 13:07 | 只看该作者
封装Sprintf(可变参数)
Include“stdarg.H”

Void Serial_print(char *format ,......)

{

Char String[100];

Va_list arg;

Va_start(arg,format);

Vsprintf(String,format,arg);

Va_end(arg);

Serial_SendString(String);

}

串口接收模式:使用查询或者中断两种方式;

查询:在主函数循环不断判断RXNE标志位,如果置1表示接收到数据;,在读取寄存器就可以了;

使用特权

评论回复
33
键盘手没手|  楼主 | 2024-1-31 13:08 | 只看该作者
五、数据包


数据包作用:将一个个数据打包起来,方便进行多字节数据通信;

例如陀螺仪数据,发送X,Y,Z,共三个字节需要连续不断的发送,出现一个问题,接收方不知道那个数据对应X那个对应Y,会出现数据错位的情况,把数据分割,xyz当作一组数据,把同一批的数据分割成一个个数据包来接收;

额外添加包头包尾的方式,不改变原有的数据结构;

使用特权

评论回复
34
键盘手没手|  楼主 | 2024-1-31 13:08 | 只看该作者
HEX数据包格式


使用特权

评论回复
35
键盘手没手|  楼主 | 2024-1-31 13:08 | 只看该作者
文本数据包格式

使用特权

评论回复
36
键盘手没手|  楼主 | 2024-1-31 13:08 | 只看该作者

使用特权

评论回复
37
键盘手没手|  楼主 | 2024-1-31 13:08 | 只看该作者
数据包发送

HEX:传输直接,解析数据简单,适合模块发送数据,例如陀螺仪,湿度传感器等;

文本数据包:数据直观易理解,适合人机交换的场合;;蓝牙AT指令,CNC,三D打印机的G代码;

HEX数据包发送

使用特权

评论回复
38
键盘手没手|  楼主 | 2024-1-31 13:08 | 只看该作者
定义一个缓冲数组

在发送输出的数据添加包头包尾,实现数据打包;

void Serial_SendPacket(void)

{

Serial_SendByte(0xFF);//发送包头

Serial_SendArray(Serial_TxPacket,4);//发送一个数组

Serial_SendByte(0xFE);//发送包尾;

}

使用特权

评论回复
39
键盘手没手|  楼主 | 2024-1-31 13:08 | 只看该作者

使用特权

评论回复
40
键盘手没手|  楼主 | 2024-1-31 13:09 | 只看该作者
如何构建状态机:

状态机方法,根据项目要求,定几个状态,然后考虑各个状态在什么情况下进行转移,如何转移;

方法:定义一个状态量,然后判断状态量的值确定处于那种状态,然后考虑转移;

状态机1:HEX数据包发送

void USART1_IRQHandler (void)

{

static uint8_t RxState=0;//状态变量S

static uint8_t PRxPacket=0;//指示接收到哪一个了

if(USART_GetFlagStatus( USART1, USART_IT_TXE)==SET)//发送寄存器TDR为空,置TXE标志位为1;

{

uint8_t RxData =USART_ReceiveData(USART1);//输入的数据给到RXData中;

if(RxState==0)//判断状态S选择不同的过程

{如果接收数据为0xff则是包头,切换状态变量为接收状态;同时清零PRxPacket

  if(RxData==0xFF)//收到包头

{

RxState=1;//转移状态

PRxPacket=0;//从第0个开始接收

}

}

else if(RxState==1)//使用else if而不使用if防止状态转移过程中,两个同时成立

{

Serial_RxPacket[PRxPacket]=RxData;//第N个接收数据

PRxPacket++;//数据转存一次

  if( PRxPacket>=4)//四个载荷数据接收完成

{

RxState=2;//进入下一个状态

}

}

else if(RxState==2)//等待包尾

{

if(RxData==0xFE)//接收到包尾

{

RxState=0;//回到最初的状态

Serial_RxFlag=1;//置一个接收标志位;

}

}

USART_ClearITPendingBit(USART1, USART_IT_TXE);

}

}

void Serial_SendPacket(void)

{

  Serial_SendByte(0xFF);

Serial_SendArray(Serial_RxPacket,4);

Serial_SendByte(0xFE);

}


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则