打印
[其他ST产品]

STM32——USART

[复制链接]
楼主: 键盘手没手
手机看帖
扫描二维码
随时随地手机跟帖
41
键盘手没手|  楼主 | 2024-1-31 13:09 | 只看该作者 |只看大图 回帖奖励 |倒序浏览


状态机2:文本数据包

void USART1_IRQHandler (void)

{

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

static uint8_t PRxPacket=0;

if(USART_GetFlagStatus( USART1, USART_IT_TXE)==SET)

{

uint8_t RxData =USART_ReceiveData(USART1);

if(RxState==0)

{

  if(RxData== '@')//判断包头

{

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

PRxPacket=0;//此时为1

}

}

else if(RxState==1)//防止状态转移时候,两个同时成立

{

  if( PRxPacket=='\r')//判断第一个包尾

{

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

}

else

{

Serial_RxPacket[PRxPacket]=RxData;

PRxPacket++;

}

}

else if(RxState==2)

{

if(RxData=='\n')

{

RxState=0;

Serial_RxFlag=1;

Serial_RxPacket[PRxPacket]='\0';

}

}

USART_ClearITPendingBit(USART1, USART_IT_TXE);

}

}

使用特权

评论回复
42
键盘手没手|  楼主 | 2024-1-31 13:09 | 只看该作者
五、API实现
5.1 API1:实现软串口接收或者发送一个数据;

5.1.1程序规划:
首先明确想实现的功能-实现发送一个字节,发送一个数组,发送一个字符串,发送数字(依次发送每一位);

5.1.1.1建立通信层模块(底层):
初始化串口后,对各部分进行封装;

5.1.1.2应用层
mian函数里调用驱动层函数,实现功能;

5.1.2库函数分析

使用特权

评论回复
43
键盘手没手|  楼主 | 2024-1-31 13:10 | 只看该作者
库函数:
void USART_DeInit(USART_TypeDef* USARTx);//复位
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);//初始化
void USART_StructInit(USART_InitTypeDef* USART_InitStruct);//初始化结构体
void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct);//配置同步时钟输出
void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct);
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);//使能
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);//中断使能
void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState);//开启到DMA的通道
void USART_SetAddress(USART_TypeDef* USARTx, uint8_t USART_Address);//设置 USART 节点的地址。
void USART_WakeUpConfig(USART_TypeDef* USARTx, uint16_t USART_WakeUp);//配置唤醒单元
void USART_ReceiverWakeUpCmd(USART_TypeDef* USARTx, FunctionalState NewState);//使能唤醒单元
void USART_LINBreakDetectLengthConfig(USART_TypeDef* USARTx, uint16_t USART_LINBreakDetectLength);//设置USART LIN模式下的断点检测长度
void USART_LINCmd(USART_TypeDef* USARTx, FunctionalState NewState);//LIN使能
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);//功能:通过USARTx外设传输单个字节数据
注释:DR数据寄存器只有DR[8:0]可用,一次发送1字节的数据
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);//功能:返回由USARTx外设接收的最新数据
注释:DR数据寄存器只有DR[8:0]可用,一次接收16位的数据
void USART_SendBreak(USART_TypeDef* USARTx);//

功能:发送断开帧
注释:如果设置SBK=1,在完成当前数据发送后,将在TX线上发送一个断开符号
单独发送断开符号时:不能发送,波形无变化(持续高电平)
TC中断时发送断开符号:接收端接收,认为是数据0x00
结论是:断开符号对防止接收端把两包看做一包没什么用,无法起到真正的断开作用

void USART_SetGuardTime(USART_TypeDef* USARTx, uint8_t USART_GuardTime);//

功能:设置指定的USART保护时间
注释:以波特时钟为单位的保护时间。在智能卡模式下,需要这个功能,当保护时间过去后,才会设置发送完成标志
UART4和UART5上不存在这一位
void USART_SetPrescaler(USART_TypeDef* USARTx, uint8_t USART_Prescaler);//功能:设置对系统时钟预分频器的数值
注释:红外低功耗模式[7:0]位,红外正常模式数值确定,智能卡模式[4:0]位
位[7:5]在智能卡模式下没有意义;UART4和UART5上不存在这一位
例如:USART_SetPrescaler(USART1 , 00000001);
void USART_SmartCardCmd(USART_TypeDef* USARTx, FunctionalState NewState);//

功能:使能或者失能USARTx的智能卡模式
注释:UART4和UART5上不存在这一位
例如:USART_SmartCardCmd(USART1 , ENABLE);
void USART_SmartCardNACKCmd(USART_TypeDef* USARTx, FunctionalState NewState);//

功能:使能或者失能NACK传输
注释:校验错误时,是否发送NACK位;UART4和UART5上不存在这一位
例如:USART_SmartCardNACKCmd(USART1 , ENABLE);
void USART_HalfDuplexCmd(USART_TypeDef* USARTx, FunctionalState NewState);//

功能:使能或者失能USART半双工通信
注释:是否选择选择单线半双工模式
例如:USART_HalfDuplexCmd(USART1 , ENABLE);
void USART_OverSampling8Cmd(USART_TypeDef* USARTx, FunctionalState NewState);//功能:使能或者失能USART的8X过采样模式
void USART_OneBitMethodCmd(USART_TypeDef* USARTx, FunctionalState NewState);//功能:使能或者失能USART的one bit采样模式
void USART_IrDAConfig(USART_TypeDef* USARTx, uint16_t USART_IrDAMode);//功能:配置USART的IrDA(红外)接口
注释:低功耗与正常模式
void USART_IrDACmd(USART_TypeDef* USARTx, FunctionalState NewState);//功能:使能或者红外模式失能
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);//标志位函数
void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);






使用特权

评论回复
44
键盘手没手|  楼主 | 2024-1-31 13:10 | 只看该作者
5.1.3思路:

5.1.3.1初始化串口

1.RCC开启GPIO和USART的时钟;

2.初始化GPIO,配置GPIO的输出为复用推挽输出(片上外设输出控制引脚电平),输入为上拉输入或者浮空输入;

3.初始化USART,配置USART的模式(接收还是发送),是否需要流控,是否需要校验位和位长;

4.使能USARTcmd;

5.1.3.2输出一个字节:

1.输出一个字节;

2.判断是否发送至移位寄存器,不需要手动清0标志位;

5.1.3.3输出一个数组

1.通过for循环依次输出数组的每一位;

5.1.3.4输出一个字符串for循环依次发送字符串的每一位,直到标志位“\0”;

5.1.3.5发送数字

1.依次发送数字的每一位;

2.通过定义函数表达函数的每一位;

5.1.3.6将输出重定义至串口

使用特权

评论回复
45
键盘手没手|  楼主 | 2024-1-31 13:10 | 只看该作者
5.1.4实现

1.RCC开启GPIO和USART的时钟;

使用特权

评论回复
46
键盘手没手|  楼主 | 2024-1-31 13:10 | 只看该作者
2.初始化GPIO,配置GPIO的输出为复用推挽输出(片上外设输出控制引脚电平),输入为上拉输入或者浮空输入;

使用特权

评论回复
47
键盘手没手|  楼主 | 2024-1-31 13:11 | 只看该作者
3.初始化USART,配置USART的模式(接收还是发送),是否需要流控,是否需要校验位和位长;

使用特权

评论回复
48
键盘手没手|  楼主 | 2024-1-31 13:11 | 只看该作者
4.使能USARTcmd;


使用特权

评论回复
49
键盘手没手|  楼主 | 2024-1-31 13:12 | 只看该作者
5.1.3.2输出一个字节:

1.输出一个字节;

2.判断是否发送至移位寄存器,不需要手动清0标志位;、

使用特权

评论回复
50
键盘手没手|  楼主 | 2024-1-31 13:12 | 只看该作者
5.1.3.3输出一个数组

1.通过for循环依次输出数组的每一位;

使用特权

评论回复
51
键盘手没手|  楼主 | 2024-1-31 13:13 | 只看该作者
5.1.3.4输出一个字符串for循环依次发送字符串的每一位,直到标志位“\0”;

使用特权

评论回复
52
键盘手没手|  楼主 | 2024-1-31 13:13 | 只看该作者
5.1.3.5发送数字

1.依次发送数字的每一位;

使用特权

评论回复
53
键盘手没手|  楼主 | 2024-1-31 13:13 | 只看该作者
2.通过定义函数表达函数的每一位;

使用特权

评论回复
54
键盘手没手|  楼主 | 2024-1-31 13:14 | 只看该作者
5.1.3.6将输出重定义至串口

使用特权

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


收一个数据:

基本于发送数据初始化基础上,开启中断控制输出,到NVIC,配置NVIC后,但是接收数据时候需要产生中断,在中断函数中判断标志位后,读取数据和标志位,清除标志位,最后用俩个函数返回读取的数据和标志位

使用特权

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

使用特权

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


使用特权

评论回复
58
键盘手没手|  楼主 | 2024-1-31 13:16 | 只看该作者
5.3API3串口收发HEX数据包(固定包长)

在串口发送和接收数据API1和API2基础上建立;

如何建立状态机:

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

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

使用特权

评论回复
59
键盘手没手|  楼主 | 2024-1-31 13:16 | 只看该作者
1.定义发送缓存区和接收缓存区;

使用特权

评论回复
60
键盘手没手|  楼主 | 2024-1-31 13:17 | 只看该作者
2.封装数据包,在数据前后分别加上包头和包尾;

使用特权

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

本版积分规则