1、阻塞式传输
HAL_UART_Transmit();//发送
HAL_UART_Receive();//接收
2、中断传输
HAL_UART_Transmit_IT();//中断发送
HAL_UART_Receive_IT();//中断接收
/*
每发送
*/
3、DMA传输
HAL_UART_Transmit_DMA();
HAL_UART_Receive_DMA();
/*
结合空闲中断,实现不定长数据传输
*/
以DMA传输为例使用STM32CubeMX创建工程
具体过程见:
STM32CubeMX系列(1)–串口工程创建
在上一节的基础上增添一些DMA相关配置即可:
生成工程即可。
代码修改:
①
//在uart.c中添加变量
#include "stdio.h"
#include "gpio.h"
#include "string.h"
#include "stdbool.h"
unsigned char RxDMABuf[BUFSIZE] = {0};
unsigned char TxDMABuf[BUFSIZE] = {0};
uint8_t FIFOUART1[MAXNUM] = {0};
int DMA_RevNum = 0;//DMA实际接收的数据长度
int TX_FLAG = 0; //接收完成,可以发送的标志
struct Queue queue;
/*******************************uart.h************************************/
#define BUFSIZE 100
#define MAXNUM 200
extern unsigned char RxDMABuf[BUFSIZE];
extern unsigned char TxDMABuf[BUFSIZE];
extern uint8_t FIFOUART1[MAXNUM];
extern int DMA_RevNum;//DMA实际接收的数据长度
extern int TX_FLAG;
extern struct Queue queue;
/*消息队列结构体*/
struct Queue{
uint8_t front;
uint8_t rear;
uint8_t* buf;
uint8_t size;
};
②
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
//在上面函数中手动开启串口空闲中断和DMA接收
③
//在下面串口全局中断函数中添加中断服务函数
/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
具体实现
void UART_IDLE_Callback(UART_HandleTypeDef *huart)
{
if(__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET)/*产生空闲中断*/
{
/*指示灯翻转*/
LED0_Toggle;
LED1_Toggle;
__HAL_UART_CLEAR_IDLEFLAG(huart);//清除空闲中断标志位
HAL_UART_DMAStop(huart); //停止DMA传输
if(huart->Instance == USART1)
{
/*实际接收数据个数*/
DMA_RevNum = BUFSIZE - __HAL_DMA_GET_COUNTER(huart->hdmarx);
if(DMA_RevNum >= 1)
{
QueueWrite(&queue,RxDMABuf,DMA_RevNum);//将收到的数据写进FIFO
}
TX_FLAG = 1;/*发送标志位置1*/
memset(RxDMABuf, 0 , sizeof(RxDMABuf));//清空接收数组
}
HAL_UART_Receive_DMA(huart,RxDMABuf,BUFSIZE);//重启DMA接收
}
}
④
//main.c
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
QueneInit(&queue,FIFOUART1);//初始化FIFO
while (1)
{
if(TX_FLAG == 1)
{
/*将数据从FIFO中读取出来并发送到串口*/
QueueRead(&queue,TxDMABuf,DMA_RevNum);
HAL_UART_Transmit_DMA(&huart1, TxDMABuf, DMA_RevNum);
TX_FLAG = 0;
}
}
}
⑤
//FIFO实现
/*
@队列初始化
@
*/
void QueneInit(struct Queue* obj, uint8_t* buf)
{
obj->buf = buf;
obj->front = obj->rear = obj->size = 0;
}
/*
@判断队列是否满
*/
bool QueueIsFull(struct Queue* obj)
{
if((obj->rear + 1) % MAXNUM == obj->front)
return true;
return false;
}
/*
@判断队列是否空
*/
bool QueueIsEmpty(struct Queue* obj)
{
if(obj->rear == obj->front)
return true;
return false;
}
/*
@队列写
*/
void QueueWrite(struct Queue* obj, uint8_t* data, uint8_t len)
{
if(QueueIsFull(obj))
return;
if(obj->rear == MAXNUM)
obj->rear = 0;/*从头开始*/
for(uint8_t i = 0; i < len; i ++)
{
if(QueueIsFull(obj))
return;
if(obj->rear == MAXNUM)
obj->rear = 0;/*从头开始*/
obj->buf[obj->rear++] = *data;
data ++;
obj->size ++;
}
}
/*
@队列读
*/
void QueueRead(struct Queue* obj, uint8_t* data, uint8_t num)
{
if(QueueIsEmpty(obj))
return;
if(obj->front == MAXNUM)
obj->front = 0;
for(uint8_t i = 0; i < num; i ++)
{
if(QueueIsEmpty(obj))
return;
if(obj->front == MAXNUM)
obj->front = 0;
data[i] = obj->buf[obj->front++];
obj->size --;
}
}
推荐文章:一个严谨的STM32串口DMA发送&接收(1.5Mbps波特率)机制
若侵权,告知立删!
版权声明:本文为CSDN博主「sjxpf922」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sjxpf922/article/details/122439830
暂无评论