串口DMA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | static void Usart1Init( int iBaudRate) { #if (TX_USE_MODE == USE_MODE_DMA) || (RX_USE_MODE == USE_MODE_DMA) DMA_InitTypeDef DMA_InitStructure; #endif GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBENR_DMA1EN | RCC_AHBENR_DMA2EN, ENABLE); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //TX GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //RX GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOA, &GPIO_InitStructure); Usart1BaseInit(iBaudRate); #if (TX_USE_MODE != USE_MODE_POL) FifoInit(&gsstUsart1TxFifo, gsucUsart1TxBuf, sizeof (gsucUsart1TxBuf), Usart1TxCrtCtrl, FALSE); #endif #if (RX_USE_MODE != USE_MODE_POL) FifoInit(&gsstUsart1RxFifo, gsucUsart1RxBuf, sizeof (gsucUsart1RxBuf), Usart1RxCrtCtrl, TRUE); #endif #if (TX_USE_MODE == USE_MODE_DMA) DMA_InitStructure.DMA_BufferSize = sizeof (gsucUsart1TxBuf); //DMA通道的DMA缓存的大小 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //数据传输方向,从内存读取发送到外设 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输 //内存 DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(gsucUsart1TxBuf); //DMA内存基地址 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式 //外设 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR); //DMA外设USART1基地址 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据宽度为8位 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变 DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道 x拥有高优先级 DMA_Cmd(DMA1_Channel4, DISABLE); //!!!! DISABLE STATE CNDTR REGISTER CAN BE UPDATE DMA_Init(DMA1_Channel4, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器 DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE); //=====================DMA_IT_TC定义为传输数据给外设地址满了才发生 DMA_Cmd(DMA1_Channel4, DISABLE); //DISABLE USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); #endif #if (RX_USE_MODE == USE_MODE_DMA) DMA_InitStructure.DMA_BufferSize = sizeof (gsucUsart1RxBuf); DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向,从外设读取到内存[外设是数据源] DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(gsucUsart1RxBuf); DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //这句是设置 DMA 的传输模式:连续不断的循环模式,若只想访问一次后就不要访问了(或按指令操作来反问,也就是想要它访问的时候就访问,不要它访问的时候就停止),可以设置成通用模式:DMA_Mode_Normal。 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR); DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; // DMA_Cmd(DMA1_Channel5, DISABLE); //!!!! DISABLE STATE CNDTR REGISTER CAN BE UPDATE DMA_Init(DMA1_Channel5, &DMA_InitStructure); DMA_Cmd(DMA1_Channel5, ENABLE); USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); #elif (RX_USE_MODE == USE_MODE_INT) USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); #endif USART_Cmd(USART1, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #if (TX_USE_MODE == USE_MODE_DMA) NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn; //TX DMA NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #endif } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | /***************************************************************** 函数名称:USART1_IRQHandler 函数描述: 输入参数: 输出参数: 返回说明: 其它说明: *****************************************************************/ void USART1_IRQHandler( void ) { #if (RX_USE_MODE == USE_MODE_INT) if ((USART1->CR1 & USART_FLAG_RXNE) && (USART1->SR & USART_FLAG_RXNE)) { u8 ucData = USART1->DR; UsartRxCheckSymbol(&gsstCnter1, ucData); FifoPushByte(&gsstUsart1RxFifo, ucData); } #endif #if (TX_USE_MODE == USE_MODE_INT) if ((USART1->CR1 & USART_FLAG_TXE) && (USART1->SR & USART_FLAG_TXE)) { int iData = FifoPopByte(&gsstUsart1TxFifo); if (iData >= 0) { USART1->DR = (u8)(iData); } else { USART1->CR1 &= ~USART_FLAG_TXE; } } #endif #if (RX_USE_MODE == USE_MODE_DMA) if ((USART1->CR1 & USART_FLAG_IDLE) && (USART1->SR & USART_FLAG_IDLE)) //空闲才中断 { int iInPoint = USART1->SR; iInPoint = USART1->DR; iInPoint = sizeof (gsucUsart1RxBuf) - DMA1_Channel5->CNDTR; UsartRxDMACheckReset(&gsstUsart1RxFifo, &gsstCnter1, iInPoint); FifoPushSetPoint(&gsstUsart1RxFifo, iInPoint); } #endif } #if (TX_USE_MODE == USE_MODE_DMA) /***************************************************************** 函数名称:DMA1_Channel4_IRQHandler 函数描述: 输入参数: 输出参数: 返回说明: 其它说明: *****************************************************************/ void DMA1_Channel4_IRQHandler( void ) { stUsartDmaOperationArgs_t stArgs = {FALSE, 256, DMA1_Channel4}; //FALSE 不检查 DMA_ClearITPendingBit(DMA1_IT_TC4); FifoSafeOperation(&gsstUsart1TxFifo, UsartTxDMAOperation, &stArgs); } |
static void Usart1Init(int iBaudRate){ #if (TX_USE_MODE == USE_MODE_DMA) || (RX_USE_MODE == USE_MODE_DMA) DMA_InitTypeDef DMA_InitStructure; #endif GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBENR_DMA1EN | RCC_AHBENR_DMA2EN, ENABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //TX GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //RX GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOA, &GPIO_InitStructure);
Usart1BaseInit(iBaudRate); #if (TX_USE_MODE != USE_MODE_POL) FifoInit(&gsstUsart1TxFifo, gsucUsart1TxBuf, sizeof(gsucUsart1TxBuf), Usart1TxCrtCtrl, FALSE); #endif #if (RX_USE_MODE != USE_MODE_POL) FifoInit(&gsstUsart1RxFifo, gsucUsart1RxBuf, sizeof(gsucUsart1RxBuf), Usart1RxCrtCtrl, TRUE); #endif #if (TX_USE_MODE == USE_MODE_DMA) DMA_InitStructure.DMA_BufferSize = sizeof(gsucUsart1TxBuf);//DMA通道的DMA缓存的大小 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//数据传输方向,从内存读取发送到外设 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输//内存 DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(gsucUsart1TxBuf); //DMA内存基地址 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//数据宽度为8位 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址寄存器递增 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//工作在正常缓存模式//外设 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);//DMA外设USART1基地址 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据宽度为8位 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址寄存器不变 DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA通道 x拥有高优先级 DMA_Cmd(DMA1_Channel4, DISABLE); //!!!! DISABLE STATE CNDTR REGISTER CAN BE UPDATE DMA_Init(DMA1_Channel4, &DMA_InitStructure);//根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器 DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);//=====================DMA_IT_TC定义为传输数据给外设地址满了才发生 DMA_Cmd(DMA1_Channel4, DISABLE); //DISABLE USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); #endif
#if (RX_USE_MODE == USE_MODE_DMA) DMA_InitStructure.DMA_BufferSize = sizeof(gsucUsart1RxBuf); DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//数据传输方向,从外设读取到内存[外设是数据源] DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(gsucUsart1RxBuf); DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//这句是设置 DMA 的传输模式:连续不断的循环模式,若只想访问一次后就不要访问了(或按指令操作来反问,也就是想要它访问的时候就访问,不要它访问的时候就停止),可以设置成通用模式:DMA_Mode_Normal。 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR); DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;// DMA_Cmd(DMA1_Channel5, DISABLE); //!!!! DISABLE STATE CNDTR REGISTER CAN BE UPDATE DMA_Init(DMA1_Channel5, &DMA_InitStructure); DMA_Cmd(DMA1_Channel5, ENABLE); USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); #elif (RX_USE_MODE == USE_MODE_INT) USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); #endif USART_Cmd(USART1, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
#if (TX_USE_MODE == USE_MODE_DMA) NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn; //TX DMA NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #endif}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决