环境:stm32f107、mdk
每个串口的DMA收发数据的通道都不一样: 串口配置: u8 receive_data[1280]={0}; u8 RX_data[26] = {0}; void uart_init(u32 bound) { GPIO_InitTypeDef GPIO_InitStruct; USART_InitTypeDef USART_InitStruct; NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE); GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; /*485收发控制线*/ GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); USART_InitStruct.USART_BaudRate = bound; USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_WordLength = USART_WordLength_8b; USART_InitStruct.USART_Parity = USART_Parity_No; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_Init(USART1, &USART_InitStruct); NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; //串口4中断通道 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级 NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2; //响应优先级 NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //使能 //中断向量控制器初始化 NVIC_Init(&NVIC_InitStruct); //开启中断并且初始化 NVIC,使能中断(如果需要开启串口中断才需要这个步骤)。 //配置中断模式 有数据来即中断 //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_ITConfig(USART1,USART_IT_IDLE,ENABLE); USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); USART_Cmd(USART1,ENABLE);//使能串口。 dma_init(); GPIO_ResetBits(GPIOA,GPIO_Pin_11); //DE 拉低485处于接收状态}
void dma_init(void) { DMA_InitTypeDef DMA_Initstructure; /开启DMA时钟/ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
/*DMA配置*/ DMA_Initstructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR); DMA_Initstructure.DMA_MemoryBaseAddr = (u32)receive_data; DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_Initstructure.DMA_BufferSize = 128; 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_High; DMA_Initstructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel5,&DMA_Initstructure);}
中断接收函数:
void USART1_IRQHandler(void) //上行485接收中断 { unsigned char num=0; if(USART_GetITStatus(USART1,USART_IT_IDLE) == SET) { num = USART1->SR; num = USART1->DR; //清USART_IT_IDLE标志 不读的话会 一直进入中断 DMA_Cmd(DMA1_Channel5,DISABLE); //关闭DMA num = 1280 - DMA_GetCurrDataCounter(DMA1_Channel5); //得到真正接收数据个数 //receive_data[num] = ‘\0’; DMA1_Channel5->CNDTR=1280; //重新设置接收数据个数 DMA_Cmd(DMA1_Channel5,ENABLE); //开启DMA DMA_Cmd(DMA1_Channel5,ENABLE); //开启DMA printf("%s \r\n",receive_data ); RX_flg = 1; } }
发送26字节的报文效果如图: 解包主要程序: void unpack_usart(void) { u16 i = 0; u8 j = 0; for(i=0;i<1280;i++) { if((receive_data[i]==0xAA) &&(receive_data[i+1]==0xBB)) { for(j=0;j<26;j++) { RX_data[j] = receive_data[i]; i++; } return; } }
}
j<26 是因为我们需要的报文有效字节为26。
效果能截取有效、完整的一条报文