1. 配置CubeMX工程USART
首先配置时钟,配置同学习笔记二。
配置USART1:选择串口模式为Asynchronous(异步):
配置波特率,字节位数,校验方式和停止位:
配置DMA:点击Add添加串口1接收中断及发送中断,DMA模式为普通
配置中断优先级:
在NVIC页面勾选串口1中断
点击系统查看中的NVIC
在NVIC设置区中选中USART1中断,在红圈中设置优先级,注意不要与其他外设的优先级产生冲突
设置完成后生成代码,打开工程
2. 添加用户代码
在USART.C及USART.h中分别加入要用到的外部变量
USART.c中:
/* USER CODE BEGIN 0 */
volatile uint8_t Usart1_RX_Cnt;//串口1接收的列表计数
volatile uint8_t Usart1_RX_Pro;//串口1接收已处理的列表计数
volatile uint8_t Usart1_TX_Cnt;//串口1发送的列表计数
volatile uint8_t Usart1_TX_Pro;//串口1发送已处理的列表计数
uint8_t USART1_Tx_Temp[USART1_TxBuffer_Size];//串口1数据发送缓存
uint8_t USART1_Tx_Buffer[USART1_List_Size][USART1_TxBuffer_Size]; //串口1数据发送缓存数组
uint8_t USART1_Rx_Buffer[USART1_List_Size][USART1_RxBuffer_Size]; //串口1数据接收缓存数组
uint16_t USART1_Rx_Lenth[USART1_List_Size];//串口1数据接收长度
uint16_t USART1_Tx_Lenth[USART1_List_Size];//串口1数据发送长度
/* USER CODE END 0 */
/* USER CODE BEGIN 1 */
/************************************************
*函数名:my_printf
*函数功能:字符串打印重定向
*输入:目标指针,字符串
*输出:字符串长度
************************************************/
uint16_t my_printf(char* buf,char* fmt,...)
{
va_list ap;
va_start(ap,fmt);
vsprintf((char*)buf,fmt,ap);
va_end(ap);
return strlen((const char*)buf); //此次发送数据的长度
}
/************************************************
*函数名:USART_Init
*函数功能:串口初始化
*输入:无
*输出:无
************************************************/
void USART_Init(void)
{
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,USART1_Rx_Buffer[Usart1_RX_Cnt],USART1_RxBuffer_Size);//USART1使用DMA传输
__HAL_UART_ENABLE_IT(&huart1,UART_IT_ERR);//USART1开启错误处理中断
}
/************************************************
*函数名:USART1_MsgToQueue
*函数功能:将USART1_Tx_Temp数据传入USART1发送队列
*输入:数据长度
*输出:无
************************************************/
void USART1_MsgToQueue(uint8_t* Sendbuffer,uint16_t lenth)
{
USART1_Tx_Lenth[Usart1_TX_Cnt] = lenth;
for(uint16_t i=0;i<lenth;i++)
{
USART1_Tx_Buffer[Usart1_TX_Cnt][i] = Sendbuffer[i];
}
if(Usart1_TX_Cnt==(USART1_List_Size-1))Usart1_TX_Cnt=0;
else Usart1_TX_Cnt++;
}
/************************************************
*函数名:USART1_MsgSend
*函数功能:USART1数据发送
*输入:无
*输出:无
************************************************/
void USART1_MsgSend(void)
{
if(Usart1_TX_Pro != Usart1_TX_Cnt)
{
HAL_UART_Transmit_DMA(&huart1,USART1_Tx_Buffer[Usart1_TX_Pro],USART1_Tx_Lenth[Usart1_TX_Pro]);//按队列顺序输出
if(Usart1_TX_Pro==(USART1_List_Size-1))Usart1_TX_Pro=0;
else Usart1_TX_Pro++;
}
}
/************************************************
*函数名:USART1_Recv
*函数功能:USART1接收数据处理
*输入:无
*输出:无
************************************************/
void USART1_Recv(void)
{
uint16_t Lenth;
if(Usart1_RX_Cnt != Usart1_RX_Pro)
{
Lenth = my_printf((char*)USART1_Tx_Temp,"\r\nUsart1_RX_LEN=%d\r\n接收数据:",USART1_Rx_Lenth[Usart1_RX_Pro]);//打印接收长度
USART1_MsgToQueue(USART1_Tx_Temp,Lenth);
USART1_MsgToQueue(USART1_Rx_Buffer[Usart1_RX_Pro],USART1_Rx_Lenth[Usart1_RX_Pro]);
if(Usart1_RX_Pro==(USART1_List_Size-1))Usart1_RX_Pro=0;
else Usart1_RX_Pro++;
}
}
/* USER CODE END 1 */
USART.h中:
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "string.h"
#include "stdarg.h"
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
#define USART1_List_Size 32 //队列深度
#define USART1_RxBuffer_Size 255 //接收数组大小
#define USART1_TxBuffer_Size 255 //接收数组大小
/* USER CODE END Private defines */
/* USER CODE BEGIN Prototypes */
extern volatile uint8_t Usart1_RX_Cnt;//串口1接收的列表计数
extern volatile uint8_t Usart1_RX_Pro;//串口1接收已处理的列表计数
extern volatile uint8_t Usart1_TX_Cnt;//串口1发送的列表计数
extern volatile uint8_t Usart1_TX_Pro;//串口1发送已处理的列表计数
extern uint8_t USART1_Tx_Temp[USART1_TxBuffer_Size];//串口1数据发送缓存
extern uint8_t USART1_Tx_Buffer[USART1_List_Size][USART1_TxBuffer_Size]; //串口1数据发送缓存数组
extern uint8_t USART1_Rx_Buffer[USART1_List_Size][USART1_RxBuffer_Size]; //串口1数据接收缓存数组
extern uint16_t USART1_Rx_Lenth[USART1_List_Size];
extern uint16_t USART1_Tx_Lenth[USART1_List_Size];
void USART_Init(void);
uint16_t my_printf(char* buf,char* fmt,...);
void USART1_MsgToQueue(uint8_t* Sendbuffer,uint16_t lenth);
void USART1_MsgSend(void);
void USART1_Recv(void);
/* USER CODE END Prototypes */
在stm32f1xx_it.c中插入代码:
/* USER CODE BEGIN Includes */
#include "usart.h"
/* USER CODE END Includes */
/************************************************
*函数名:HAL_UARTEx_RxEventCallback
*函数功能:串口接收回调
*输入:UART_HandleTypeDef *huart, uint16_t Size
*输出:无
************************************************/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
/************ USART1接收 ************/
if(huart->Instance == USART1)
{
USART1_Rx_Lenth[Usart1_RX_Cnt] = Size;
if(Usart1_RX_Cnt==(USART1_List_Size-1))Usart1_RX_Cnt=0;
else Usart1_RX_Cnt++;
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,USART1_Rx_Buffer[Usart1_RX_Cnt],USART1_RxBuffer_Size);//USART1使用DMA传输
}
}
/************************************************
*函数名:HAL_UART_ErrorCallback
*函数功能:串口错误中断回调
*输入:UART_HandleTypeDef *huart
*输出:无
************************************************/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
__HAL_UART_CLEAR_OREFLAG(huart);
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,USART1_Rx_Buffer[Usart1_RX_Cnt],USART1_RxBuffer_Size);//USART1使用DMA传输
}
}
在main.c中初始化部分插入开启USART1空闲中断和DMA传输:
/* USER CODE BEGIN 2 */
USART_Init();
/* USER CODE END 2 */
3. 测试代码
在主循环中加入:
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
USART1_Recv(); //接收处理
USART1_MsgSend(); //发送处理
HAL_Delay(50);//处理速度
}
/* USER CODE END 3 */
测试效果(未更新):
4.遇到的问题:
一开始调试代码都写好了怎么调试都不通!!!!!!!!
最后发现是口插错了==
以后贴片器件还是画在Bottom层吧==
5.更新日志
在后面的项目中总结出了效率更高、更稳定等串口使用方法,故更新。
测试demo:https://download.youkuaiyun.com/download/weixin_44087298/87671515。
参考文章:
打印函数:https://www.cnblogs.com/hjf-log/p/12522796.html
其他函数:https://blog.youkuaiyun.com/qq_33728095/article/details/97778147