高级会员
- 积分
- 948
- 金钱
- 948
- 注册时间
- 2022-4-20
- 在线时间
- 356 小时
|
11金钱
代码是复制的比较新的原子哥的hal库F103串口实验代码,增加了一个DMA接收功能。
整个程序的功能是:通过DMA接收串口助手发来的消息,然后把消息发回(非DMA模式)串口助手。
故障现象:只有第一次的消息可以被完整发送,后面的每次都会少发两个字节。但在调试时,通过打断点的方式观察,消息又会每次都被完整发送。
希望大佬帮忙看一看,谢谢。
具体代码如下:
主函数:
- int main(void)
- {
- HAL_Init(); /* 初始化HAL库 */
- sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟为72Mhz */
- delay_init(72); /* 延时初始化 */
- usart_init(115200); /* 串口初始化为115200 */
- dma_init(DMA1_Channel5); /* DMA接收初始化 */
-
- __HAL_UART_ENABLE_IT(&g_uart1_handle, UART_IT_IDLE); /* 开启USART1空闲中断 */
- HAL_UART_Receive_DMA(&g_uart1_handle, g_usart_rx_buf, USART_REC_LEN); /* 开启DMA接收,并且设定接收数组 */
-
- while (1)
- {
- if (g_usart_rx_sta != 0)
- {
- HAL_UART_Transmit_IT(&g_uart1_handle, g_usart_rx_buf, g_usart_rx_sta);
- g_usart_rx_sta = 0;
- }
- }
- }
复制代码 串口初始化:
- void usart_init(uint32_t baudrate)
- {
- /*UART 初始化设置*/
- g_uart1_handle.Instance = USART_UX; /* USART_UX */
- g_uart1_handle.Init.BaudRate = baudrate; /* 波特率 */
- g_uart1_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 字长为8位数据格式 */
- g_uart1_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
- g_uart1_handle.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */
- g_uart1_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */
- g_uart1_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
- HAL_UART_Init(&g_uart1_handle); /* HAL_UART_Init()会使能UART1 */
- }
- /**
- * @brief UART底层初始化函数
- * [url=home.php?mod=space&uid=271674]@param[/url] huart: UART句柄类型指针
- * [url=home.php?mod=space&uid=60778]@note[/url] 此函数会被HAL_UART_Init()调用
- * 完成时钟使能,引脚配置,中断配置
- * @retval 无
- */
- void HAL_UART_MspInit(UART_HandleTypeDef *huart)
- {
- GPIO_InitTypeDef gpio_init_struct;
- if (huart->Instance == USART_UX) /* 如果是串口1,进行串口1 MSP初始化 */
- {
- USART_TX_GPIO_CLK_ENABLE(); /* 使能串口TX脚时钟 */
- USART_RX_GPIO_CLK_ENABLE(); /* 使能串口RX脚时钟 */
- USART_UX_CLK_ENABLE(); /* 使能串口时钟 */
- gpio_init_struct.Pin = USART_TX_GPIO_PIN; /* 串口发送引脚号 */
- gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
- gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
- gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* IO速度设置为高速 */
- HAL_GPIO_Init(USART_TX_GPIO_PORT, &gpio_init_struct);
-
- gpio_init_struct.Pin = USART_RX_GPIO_PIN; /* 串口RX脚 模式设置 */
- gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;
- HAL_GPIO_Init(USART_RX_GPIO_PORT, &gpio_init_struct); /* 串口RX脚 必须设置成输入模式 */
-
- HAL_NVIC_EnableIRQ(USART_UX_IRQn); /* 使能USART1中断通道 */
- HAL_NVIC_SetPriority(USART_UX_IRQn, 0, 0); /* 组2,最低优先级:抢占优先级0,子优先级0 */
- }
- }
复制代码 串口引脚定义及中断回调函数:
- #define USART_TX_GPIO_PORT GPIOA
- #define USART_TX_GPIO_PIN GPIO_PIN_9
- #define USART_TX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */
- #define USART_RX_GPIO_PORT GPIOA
- #define USART_RX_GPIO_PIN GPIO_PIN_10
- #define USART_RX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */
- #define USART_UX USART1
- #define USART_UX_IRQn USART1_IRQn
- #define USART_UX_IRQHandler USART1_IRQHandler
- #define USART_UX_CLK_ENABLE() do{ __HAL_RCC_USART1_CLK_ENABLE(); }while(0) /* USART1 时钟使能 */
- //中断回调函数
- void USART_UX_IRQHandler(void)
- {
- if (__HAL_UART_GET_FLAG(&g_uart1_handle,UART_FLAG_IDLE))
- {
- g_usart_rx_sta = USART_REC_LEN - (__HAL_DMA_GET_COUNTER(&g_dma_handle));
- HAL_DMA_Abort(g_uart1_handle.hdmarx); /* 传输完成以后关闭串口DMA */
- HAL_UART_Receive_DMA(&g_uart1_handle, g_usart_rx_buf, USART_REC_LEN); /* 开启DMA接收,并且设定接收数组 */
-
- }
- HAL_UART_IRQHandler(&g_uart1_handle);
- }
复制代码 DMA配置:
- void dma_init(DMA_Channel_TypeDef* DMAx_CHx)
- {
- if ((uint32_t)DMAx_CHx > (uint32_t)DMA1_Channel7) /* 大于DMA1_Channel7, 则为DMA2的通道了 */
- {
- __HAL_RCC_DMA2_CLK_ENABLE(); /* DMA2时钟使能 */
- }
- else
- {
- __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA1时钟使能 */
- }
-
- __HAL_LINKDMA(&g_uart1_handle, hdmarx, g_dma_handle); /* 将DMA与USART1联系起来(接收DMA) */
-
- /* Rx DMA配置 */
- g_dma_handle.Instance = DMAx_CHx; /* USART1_RX使用的DMA通道为: DMA1_Channel5 */
- g_dma_handle.Init.Direction = DMA_PERIPH_TO_MEMORY; /* DIR = 0 , 外设到存储器模式 */
- g_dma_handle.Init.PeriphInc = DMA_PINC_DISABLE; /* 外设非增量模式 */
- g_dma_handle.Init.MemInc = DMA_MINC_ENABLE; /* 存储器增量模式 */
- g_dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; /* 外设数据长度:8位 */
- g_dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; /* 存储器数据长度:8位 */
- g_dma_handle.Init.Mode = DMA_NORMAL; /* DMA模式:正常模式 */
- g_dma_handle.Init.Priority = DMA_PRIORITY_MEDIUM; /* 中等优先级 */
- HAL_DMA_Init(&g_dma_handle);
- }
复制代码
|
|