在使用STM32的时候,使用串口外设的场合是非常常见的,串口发送我想大家都非常熟悉了,直接重写fputc函数就可以了:
int fputc(int ch,FILE *f) { while(!(USART3->SR&UART_FLAG_TXE));//1 USART3->DR=ch;//2 return ch; }
int fputc(int ch,FILE *f) { HAL_UART_Transmit(&huart3,&ch,1,100); return ch; }效果完全一样。
static void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; HAL_UART_Init(&huart1); __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); HAL_NVIC_SetPriority(USART1_IRQn,0,0); HAL_NVIC_EnableIRQ(USART1_IRQn); } static void MX_DMA_Init(void) { __HAL_RCC_DMA1_CLK_ENABLE(); HAL_NVIC_SetPriority(DMA1_Channel5_IRQn,0,0); HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn); } static void MX_GPIO_Init(void) { __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); } void HAL_UART_MspInit(UART_HandleTypeDef* huart) { GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_USART1_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); hdma_usart1_rx.Instance = DMA1_Channel5; hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart1_rx.Init.Mode = DMA_NORMAL; hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW; HAL_DMA_Init(&hdma_usart1_rx); __HAL_LINKDMA(huart,hdmarx,hdma_usart1_rx); }
这里最关键的地方,要使能串口空闲中断以及配置串口中断优先级:
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); HAL_NVIC_SetPriority(USART1_IRQn,0,0); HAL_NVIC_EnableIRQ(USART1_IRQn);
void USART1_IRQHandler() { uint32_t temp; if(USART1==huart1.Instance) { if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)) { __HAL_UART_CLEAR_IDLEFLAG(&huart1); HAL_UART_DMAStop(&huart1); temp=__HAL_DMA_GET_COUNTER(&hdma_usart1_rx); rx_len=BUFFERSIZE-temp; recv_end_flag=1; } } }
#define BUFFERSIZE 255 uint8_t rx_buf[BUFFERSIZE]; uint8_t recv_end_flag=0,rx_len;
void UART1_DMA_Get() { if(recv_end_flag==1) { recv_end_flag=0; printf("帧长度:%d 帧内容:%s\n",rx_len,rx_buf); } HAL_UART_Receive_DMA(&huart1,(uint8_t*)rx_buf,BUFFERSIZE); }
看看L476的代码,与F103差异不大:
static void MX_USART2_UART_Init(void) { huart2.Instance = USART2; huart2.Init.BaudRate = 115200; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; HAL_UART_Init(&huart2); __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); HAL_NVIC_SetPriority(USART2_IRQn,0,0); HAL_NVIC_EnableIRQ(USART2_IRQn); } static void MX_DMA_Init(void) { __HAL_RCC_DMA1_CLK_ENABLE(); HAL_NVIC_SetPriority(DMA1_Channel6_IRQn,0,0); HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn); } static void MX_GPIO_Init(void) { __HAL_RCC_GPIOA_CLK_ENABLE(); } void USART2_IRQHandler() { uint32_t temp; if(USART2==huart2.Instance) { if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE)) { __HAL_UART_CLEAR_IDLEFLAG(&huart2); HAL_UART_DMAStop(&huart2); temp=__HAL_DMA_GET_COUNTER(&hdma_usart2_rx); rx_len=BUFFERSIZE-temp; recv_end_flag=1; } } }
看看F469的代码,大同小异:
static void MX_USART3_UART_Init(void)
{
huart3.Instance = USART3;
huart3.Init.BaudRate = 115200;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart3);
__HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE);
HAL_NVIC_SetPriority(USART3_IRQn,0,0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
}
static void MX_DMA_Init(void)
{
__HAL_RCC_DMA1_CLK_ENABLE();
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}
static void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOB_CLK_ENABLE();
}
void USART3_IRQHandler()
{
uint32_t temp;
if(USART3==huart3.Instance)
{
if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE))
{
__HAL_UART_CLEAR_IDLEFLAG(&huart3);
HAL_UART_DMAStop(&huart3);
temp=__HAL_DMA_GET_COUNTER(&hdma_usart3_rx);
rx_len=BUFFERSIZE-temp;
recv_end_flag=1;
}
}
}
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_USART3_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
hdma_usart3_rx.Instance = DMA1_Stream1;
hdma_usart3_rx.Init.Channel = DMA_CHANNEL_4;
hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart3_rx.Init.Mode = DMA_NORMAL;
hdma_usart3_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_usart3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_usart3_rx);
__HAL_LINKDMA(huart,hdmarx,hdma_usart3_rx);
}
看看效果:
总结:实现这个串口不定长接收,最大的功劳要给DMA外设,因为所有工作都是围绕DMA缓存区进行的,但是,目前此方法的实现还是需要依赖HAL库,后续我会继续探索,争取使用效率更高的LL库实现。
原创作品,未经权利人授权禁止转载。详情见转载须知。 举报文章
我要举报该内容理由
×