完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
把调试STM32F072串口过程中,出现了一小点问题,记录下来,F0的串口寄存器有些增加的功能以前没用到,F0增加了modbus协议之类的接收超时处理,完美实现了不定长数据包的帧接收。 本次使用USART2进行通讯。 cubeMX中的设置 DMA设置: dma.c中生成 void MX_DMA_Init(void) { /* Init with LL driver */ /* DMA controller clock enable */ LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1); /* DMA interrupt init */ /* DMA1_Channel4_5_6_7_IRQn interrupt configuration */ NVIC_SetPriority(DMA1_Channel4_5_6_7_IRQn, 0); NVIC_EnableIRQ(DMA1_Channel4_5_6_7_IRQn); } USART2设置: usart.c中生成 void MX_USART2_UART_Init(void) { LL_USART_InitTypeDef USART_InitStruct = {0}; LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; /* Peripheral clock enable */ LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART2); LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = LL_GPIO_PIN_2; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; GPIO_InitStruct.Alternate = LL_GPIO_AF_1; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = LL_GPIO_PIN_3; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; GPIO_InitStruct.Alternate = LL_GPIO_AF_1; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART2 DMA Init */ /* USART2_RX Init */ LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_5, LL_DMA_DIRECTION_PERIPH_TO_MEMORY); LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_5, LL_DMA_PRIORITY_MEDIUM); LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_5, LL_DMA_MODE_CIRCULAR); //LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_5, LL_DMA_MODE_NORMAL); LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_5, LL_DMA_PERIPH_NOINCREMENT); LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_5, LL_DMA_MEMORY_INCREMENT); LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_5, LL_DMA_PDATAALIGN_BYTE); LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_5, LL_DMA_MDATAALIGN_BYTE); /* USART2_TX Init */ // LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_4, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); // LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_4, LL_DMA_PRIORITY_MEDIUM); // LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MODE_CIRCULAR); // //LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MODE_NORMAL); // LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_4, LL_DMA_PERIPH_NOINCREMENT); // LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MEMORY_INCREMENT); // LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_4, LL_DMA_PDATAALIGN_BYTE); // LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MDATAALIGN_BYTE); USART_InitStruct.BaudRate = 2000000; USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B; USART_InitStruct.StopBits = LL_USART_STOPBITS_1; USART_InitStruct.Parity = LL_USART_PARITY_NONE; USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX; USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16; LL_USART_Init(USART2, &USART_InitStruct); LL_USART_DisableIT_CTS(USART2); LL_USART_ConfigAsyncMode(USART2); LL_USART_Enable(USART2); } user.c中添加 void USART2_Interrupt_Enable(void) { /* USART2 interrupt Init */ NVIC_SetPriority(USART2_IRQn, 0); NVIC_EnableIRQ(USART2_IRQn); } void USART2_DMA_Recive(uint8_t *p_data, uint16_t length) { LL_USART_Disable(USART2); USART2->CR3 |= USART_CR3_DMAR | USART_CR3_DMAT; USART2->CR1 |= USART_CR1_IDLEIE; /*enable usart2 idle interrupt*/ DMA1_Channel5->CCR &= ~(DMA_CCR_EN); //disable the dma DMA1_Channel5->CPAR = (uint32_t)&(USART2->RDR); //Peripheral address DMA1_Channel5->CMAR = (uint32_t)p_data; //memory address DMA1_Channel5->CNDTR = length; //Set the length DMA1_Channel5->CCR |= DMA_CCR_MINC | DMA_CCR_EN; //enable the DMA LL_USART_Enable(USART2); } void DMA1_Channel4_5_6_7_IRQHandler(void) //此中断始终未进入过 { /* USER CODE BEGIN DMA1_Channel4_5_6_7_IRQn 0 */ /* USER CODE END DMA1_Channel4_5_6_7_IRQn 0 */ /* USER CODE BEGIN DMA1_Channel4_5_6_7_IRQn 1 */ /* USER CODE END DMA1_Channel4_5_6_7_IRQn 1 */ } void USART2_IRQHandler(void) { if((USART2->ISR & USART_ISR_ORE) == USART_ISR_ORE) { USART2->ICR |= USART_ICR_ORECF; } if((USART2->ISR & USART_ISR_IDLE) == USART_ISR_IDLE) //The new frame data receive { USART2->ICR |= USART_ICR_IDLECF; #ifdef USE_APP_VCOM cdc_rx1_in_bytes(vcom_Rxbuf1, U2_DMA_LEN-DMA1_Channel5->CNDTR); /*读取解析数据*/ //memset(vcom_Rxbuf1, 0, VCOM_RX_EP_SIZE); // debug #endif DMA1_Channel5->CCR &= ~(DMA_CCR_EN); //disable the dma LL_DMA_ClearFlag_GI5(DMA1); LL_DMA_ClearFlag_TC5(DMA1); LL_DMA_ClearFlag_HT5(DMA1); LL_DMA_ClearFlag_TE5(DMA1); DMA1_Channel5->CNDTR = U2_DMA_LEN; //Set the length DMA1_Channel5->CCR |= DMA_CCR_EN; //enable the dma } if((USART2->ISR & USART_ISR_RTOF) == USART_ISR_RTOF) { USART2->ICR |= USART_ICR_RTOCF; } } 初始化时调用: USART2_DMA_Recive(vcom_Rxbuf1, U2_DMA_LEN); USART2_Interrupt_Enable(); 运行后,发送16个字符以内时,进入cdc_rx1_in_bytes()接收都是正常的。 超过16个字符时,进入cdc_rx1_in_bytes()当时的长度U2_DMA_LEN-DMA1_Channel5->CNDTR都是16, 若设断点在此处时,接收长度是正常的。加延时也无效,但是在cdc_rx1_in_bytes()里, MEMCPY(at_t.buf, buf, len); at_t.len = len; at_t.buf[len] = ' |