STM32F207运用串口空闲中断+DMA接收不定长数据
来源:互联网 发布:mac版本千牛 编辑:程序博客网 时间:2024/05/21 16:30
1.我们知道DMA可以自动的不在CPU干预下,自动把数据重外设存储到内存(我们这节讲的),内存到外设,内存到内存等。但是DMA接收的是指定长度的,在接收不定长数据的时候DMA就傻眼了。网上有许多方法讲解运用定时器超时检测来接收不定长数据,而我们现在要讲的是运用串口空闲中断+DMA的方式接收不定长数据。
2.我们调试用的是串口1、DMA_Channel_4。具体的配置见下面程序:
DMA接收配置:
void USART1_DMA_Config(void){ DMA_InitTypeDef DMA_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);//开启DMA时钟 DMA_InitStructure.DMA_Channel = DMA_Channel_4;//通道4 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)USART1_DR_Address; //外设地址为[#define USART1_DR_Address (0x40011000+0x04)] DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Data_Buffer; //内存地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//外设到内存 DMA_InitStructure.DMA_BufferSize = 65535; //缓冲大小 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不增 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据大小1byte DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//内存数据大小1byte DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//循环模式 DMA_InitStructure.DMA_Priority = DMA_Priority_High;//优先级高 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;// 不开fifo DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; // DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;// DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;// DMA_Init(DMA2_Stream5, &DMA_InitStructure);//初始化dma2流5 DMA_Cmd(DMA2_Stream5, ENABLE);//开启dma2流5}串口1相关配置及空闲中断配置:
void STM_EVAL_COMInit(void){GPIO_InitTypeDef GPIO_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;USART_InitTypeDef USART_InitStructure; /* Enable GPIO clock */RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);/* Enable UART clock */RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);/* Connect PXx to USARTx_Tx*/GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);/* Connect PXx to USARTx_Rx*/GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);/* Configure USART Tx as alternate function */GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);/* Configure USART Rx as alternate function */GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_Init(GPIOA, &GPIO_InitStructure);USART_InitStructure.USART_BaudRate = 115200;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 configuration */USART_Init(USART1, USART_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 11;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);/* Enable USART */USART_Cmd(USART1, ENABLE);}串口相关配置总函数:
void USART_CONFIG(void){ STM_EVAL_COMInit(); USART1_DMA_Config();//主要是配置外设地址和内存地址以及缓冲区大小,配置好后DMA就会自动的把串口数据存到相应的内存地址。 USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);配置串口1DMA接收}串口1空闲中断服务函数:
void USART1_IRQHandler(void){u16 i; if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)//如果为空闲总线中断 { i = USART1->SR;i = USART1->DR; USART_ClearITPendingBit(USART1, USART_IT_IDLE);DMA_Cmd(DMA2_Stream5, DISABLE);//关闭DMA,防止处理其间有数据 Data_Len=65535-DMA_GetCurrDataCounter(DMA2_Stream5);data_recv_flag_set(); //标志位printf("Data_Len=%d\n\r",Data_Len);//DMA_Cmd(DMA2_Stream5, ENABLE);//开启DMA}}这里需要说明下,我们在配置DMA的时候,数据大小是一个字节,内存缓冲区为65535(特别强调下:DMA最大的缓冲区为65535,再大就溢出了。YY下,如果DMA接收缓冲区上M那就更加好了)。
函数DMA_GetCurrDataCounter(DMA2_Stream5);是获取当前指针计数值,用内存缓冲区大小 - 此计数值 = 接收到的数据长度(这里单位为字节)。需要说明下在读取数据长度的时候需要先把接收DMA关闭,读取完了或者是数据处理完了在打开接收DMA,防止在处理的过程中有数据到来而出错。
大家可以用串口调试助手测试下,记住把旁边的send as hex打上勾,然后发送不定长数据,每次发送完就会进空闲中断,并把接收的数据长度打印出来。如果需要读取数据,可以从Data_Buffer(前面DMA配置的内存地址)中读取出来。
1 0
- STM32F207运用串口空闲中断+DMA接收不定长数据
- STM32F207运用串口空闲中断+DMA接收不定长数据
- STM32F207运用串口空闲中断+DMA接收不定长数据
- Stm32——串口空闲中断+DMA接收不定长数据
- STM32空闲中断+DMA解决接收不定长数据问题
- STM32空闲中断+DMA解决接收不定长数据问题
- STM32F4的HAL库开启串口空闲中断 不定长数据接收很好用
- STM32使用DMA加串口空闲中断接收数据
- 一知半解学CubeMX——UART:空闲中断结合DMA实现不定长数据收发
- STM32CubeMX 串口空闲中断加DMA 实现不定长度收发数据
- STM32利用串口空闲中断在串口DMA配置下接收变长数据
- STM32 HAL 库, 配置串口DMA接收及空闲中断
- stm32串口DMA收发,可以接收不定长数据,格式化输出。
- STM32使用串口1配合DMA接收不定长数据,大大减轻CPU载荷。
- stm32的串口空闲中断接收数据
- stm32的串口空闲中断接收数据
- STM32串口使用IDLE中断接收不定长数据原理与源程序
- STM32使用串口IDLE中断的两种接收不定长数据的方式
- 每天一个linux命令(13):less 命令
- android程序退出后静态变量的处理
- C#面向对象思想深刻剖析
- PHP输入流php://input介绍
- 安卓Permission
- STM32F207运用串口空闲中断+DMA接收不定长数据
- redo logfile operation codes
- android屏幕适配——1920x1200
- JS和PHP互调用
- 每日一题-1
- 多分辨率分析与正交小波-4
- 新的一天,新的开始
- onclick和onfocus的区别
- C++STL学习Pair