本实验利用串口的接收空闲中断(IDLE)实现DMA接收串口不定长数据。
usart.c
UART_HandleTypeDef UART1_Handler;
u8 buffer[100];//数据缓冲区
u8 len;//已存储数据长度
void uart_init(u32 bound)
{
UART1_Handler.Instance=USART1;
UART1_Handler.Init.BaudRate=bound;
UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;
UART1_Handler.Init.StopBits=UART_STOPBITS_1;
UART1_Handler.Init.Parity=UART_PARITY_NONE;
UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;
UART1_Handler.Init.Mode=UART_MODE_TX_RX;
HAL_UART_Init(&UART1_Handler); //初始化UART1
HAL_NVIC_EnableIRQ(USART1_IRQn); //使能UART1中断通道
HAL_NVIC_SetPriority(USART1_IRQn,3,3); //抢占优先级3 子优先级3
__HAL_UART_ENABLE_IT(&UART1_Handler, UART_IT_IDLE); //开启接收空闲中断 当串口接收空闲时
// 状态寄存器SR的IDLE为将被置1 并产
// 生中断
}
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef GPIO_Initure;
if(huart->Instance==USART1)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_AFIO_CLK_ENABLE();
GPIO_Initure.Pin=GPIO_PIN_9;
GPIO_Initure.Mode=GPIO_MODE_AF_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_10;
GPIO_Initure.Mode=GPIO_MODE_AF_INPUT;
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
}
}
//UART1中断服务函数
void USART1_IRQHandler(void)
{
if (__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_IDLE)!=RESET)
{
HAL_UART_DMAStop(&UART1_Handler); //停止DMA搬运
__HAL_UART_CLEAR_IDLEFLAG(&UART1_Handler); //清除IDLE中断标志位
len = 100 - __HAL_DMA_GET_COUNTER(&UART1TxDMA_Handler); //已搬运数据长度=缓冲区长度-缓冲区剩余长度
HAL_UART_Receive_DMA(&UART1_Handler,buffer,100); //重新开启DMA搬运
HAL_UART_Transmit(&UART1_Handler,buffer,len,1000); //将缓冲区数据发送
}
}
dma.c
DMA_HandleTypeDef UART1TxDMA_Handler;
void MYDMA_Config(void){
__HAL_RCC_DMA1_CLK_ENABLE();
__HAL_LINKDMA(&UART1_Handler,hdmarx,UART1TxDMA_Handler);
//将DMA的句柄地址赋值给串口句柄的hdmarx 注意这里因为数据是从串口到内存,
//所以是hdmarx而不是hdmatx!!!
UART1TxDMA_Handler.Instance=DMA1_Channel5;//UART1—RX在DMA1的通道5
UART1TxDMA_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY;//外设到内存
UART1TxDMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE;//外设非增量模式
UART1TxDMA_Handler.Init.MemInc=DMA_MINC_ENABLE;//内存增量模式
UART1TxDMA_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_BYTE;//外设数据格式1字节
UART1TxDMA_Handler.Init.MemDataAlignment=DMA_MDATAALIGN_BYTE;//内存数据格式1字节
UART1TxDMA_Handler.Init.Mode=DMA_CIRCULAR;//循环模式
UART1TxDMA_Handler.Init.Priority=DMA_PRIORITY_MEDIUM;//中等优先级
HAL_DMA_Init(&UART1TxDMA_Handler);//初始化DMA
HAL_UART_Receive_DMA(&UART1_Handler,buffer,100);//开启串口接收DMA传输
}
main.c
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "dma.h"
int main(void)
{
HAL_Init();
Stm32_Clock_Init(RCC_PLL_MUL9);
delay_init(72);
uart_init(115200); //初始化串口
MYDMA_Config(); //初始化DMA
while(1){}
}
本人是初学者,有错误欢迎指教!