STM32

您所在的位置:网站首页 从串口接收缓冲器中将数据读入到变量temp中 STM32

STM32

2024-07-01 05:26| 来源: 网络整理| 查看: 265

STM32——采用DMA的方式实现串口收发数据 概述

想必看到这篇博客的你已经知道了DMA的好处了吧,所以这儿就不过多地讲述DMA对于缓解MCU压力有多么重要的用途,DMA在很多方面都可以使用,如IIC,SPI,USART等,这儿主要给出DMA在USART上面的一个实例。

代码实现

主要代码直接在一个程序中实现

全局变量以及宏定义 #define DEFAULT_BAUD 115200 #define UART_RX_LEN 128 /*串口接收DMA缓存*/ uint8_t Uart_Rx[UART_RX_LEN] = {0}; /*串口发送DMA缓存*/ uint8_t Uart_Send_Buffer[100]={0}; uint8_t Data_Receive_Usart=0; DMA和USART的初始化的函数 void usart_dma_init(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; /* 配置GPIO的模式和IO口 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; //TX GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化串口输入IO GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10; //RX GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //模拟输入 GPIO_Init(GPIOA,&GPIO_InitStructure); /*初始化串口接收和发送函数*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE); USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_InitStructure.USART_BaudRate = DEFAULT_BAUD; /*初始化串口*/ USART_Init(USART1,&USART_InitStructure); /*中断配置*/ USART_ITConfig(USART1,USART_IT_TC,DISABLE); USART_ITConfig(USART1,USART_IT_RXNE,DISABLE); USART_ITConfig(USART1,USART_IT_IDLE,ENABLE); //配置UART1中断 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3); NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //通道设置为串口1中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //中断占先等级0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //中断响应优先级0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //打开中断 NVIC_Init(&NVIC_InitStructure); /*DMA发送中断设置*/ NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /*DMA1通道4配置发送*/ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_DeInit(DMA1_Channel4); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart_Send_Buffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = 100; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel4,&DMA_InitStructure); DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE); //DMA_Cmd(DMA1_Channel4, ENABLE);//使能通道4,一般发送的时候再使能 /*DMA1通道5配置接收*/ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_DeInit(DMA1_Channel5); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart_Rx; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = UART_RX_LEN; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel5,&DMA_InitStructure); /*使能通道5*/ DMA_Cmd(DMA1_Channel5,ENABLE); //采用DMA方式发送 USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //采用DMA方式接收 USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); //启动串口 USART_Cmd(USART1, ENABLE); } DMA发送使能函数 /**@ brief 使能发送数据 * * 启动DMA数据发送功能 * * @param size表示需要发送的DMA中数据的个数 */ void uart_dma_send_enable(uint16_t size) { DMA1_Channel4->CNDTR = (uint16_t)size; DMA_Cmd(DMA1_Channel4, ENABLE); } 串口接收的中断函数 /**@ brief串口1接收中断 * * 收到一帧数据进入一次,进行DMA的读取 * */ void USART1_IRQHandler(void) { uint32_t temp = 0; uint16_t i = 0; if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) { //USART_ClearFlag(USART1,USART_IT_IDLE); temp = USART1->SR; temp = USART1->DR; //清USART_IT_IDLE标志 DMA_Cmd(DMA1_Channel5,DISABLE); temp = UART_RX_LEN - DMA_GetCurrDataCounter(DMA1_Channel5); for (i = 0;i < temp;i++) { Data_Receive_Usart = Uart_Rx[i]; //+++对收到的数据加一后回发出去 Uart_Send_Buffer[i]=Data_Receive_Usart+1; uart_dma_send_enable(temp); //+++ } //设置传输数据长度 DMA_SetCurrDataCounter(DMA1_Channel5,UART_RX_LEN); //打开DMA DMA_Cmd(DMA1_Channel5,ENABLE); } } DMA发送中断 /**@ brief DMA发送中断 * * 发送数据,将DMA中的数据发送出去 * */ void DMA1_Channel4_IRQHandler(void) { if(DMA_GetITStatus(DMA1_FLAG_TC4)==SET) { DMA_ClearFlag(DMA1_FLAG_GL4); DMA_Cmd(DMA1_Channel4, DISABLE); } }

到此为止主要代码就已经结束了,基本上能够满足测试要求

项目工程下载

串口1的DMA实现 点击下载

串口2的DMA实现 点击下载

串口3的DMA实现 点击下载



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3