我正在使用
STM32WB5MMG,但我认为这个问题与 MCU 的无线电部分无关,所以我在更一般的社区发帖。我希望没关系。
我正在使用 HAL_UART_Receive_DMA 函数通过 UART 从 GPS 接收器读取数据。数据以 230400 波特率传入。DMA 配置为 512 字节的简单(非循环)缓冲区。在 HAL_UART_RxCpltCallback 处理程序中,我再次调用 HAL_UART_Receive_DMA 以开始新的传输。
我这样做(而不是使用循环模式),以便我可以通过计算 512 字节的完整“帧”数并添加 (512 - CNDTR) 来计算传输的字节总数。我担心的是,如果我使用循环缓冲区,那么相对于 CNDTR 更新的帧数更新时间会有些模糊。
通常,这工作正常。但是在接收数据几分钟后,CNDTR 似乎停止了更新。我已经检查过 GPS 模块仍然有数据传入。奇怪的是,当CNDTR停止更新时,它总是等于511(即比缓冲区长度小1)。
我偶然发现了一种获得类似结果的方法......
- 在调试模式下运行固件
- 打破我通常处理传入数据的地方
- 去掉断点继续执行
- 再次设置断点
当调试器第二次中断时,同样,CNDTR 停留在 511。这似乎是由于某种溢出,这让我认为对于我遇到的实际问题可能也是如此。
但是,永远不会调用 HAL_UART_ErrorCallback,并且当错误发生时,似乎没有任何寄存器指示溢出(具体查看 DMA2 和 DMAMUX1 SFR)。
粗略地说,这是我的代码结构:
- #define GNSS_RX_BUF_LEN 512 // Circular buffer for UART
- #define GNSS_UPDATE_MSEC 10
- #define GNSS_UPDATE_RATE (GNSS_UPDATE_MSEC*1000/CFG_TS_tiCK_VAL)
- uint8_t gnssRxData[GNSS_RX_BUF_LEN]; // data buffer
- uint32_t gnssRxIndex = 0; // read index
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
- {
- // Begin DMA transfer
- HAL_UART_Receive_DMA(&huart1, gnssRxData, GNSS_RX_BUF_LEN);
- }
- void GNSS_Init(void)
- {
- // Begin DMA transfer
- HAL_UART_Receive_DMA(&huart1, gnssRxData, GNSS_RX_BUF_LEN);
- // Initialize GNSS task
- UTIL_SEQ_RegTask(1<
- // Initialize GNSS update timer
- HW_TS_Create(CFG_TIM_PROC_ID_ISR, &timer_id, hw_ts_Repeated, GNSS_Timer);
- HW_TS_Start(timer_id, GNSS_UPDATE_RATE);
- }
- static void GNSS_Timer(void)
- {
- // Call update task
- UTIL_SEQ_SetTask(1<}
- static void GNSS_Update(void)
- {
- uint32_t cndtr = huart1.hdmarx->Instance->CNDTR;
- uint32_t writeIndex = GNSS_RX_BUF_LEN - cndtr;
- while (gnssRxIndex != writeIndex)
- {
- // Handle a byte and increment gnssRxIndex
- }
- }
任何帮助将不胜感激。如果发生超限,我不完全确定我会在哪里捕获它——我认为 SFR 会改变,但也许不会?我希望这个问题对外面的人来说很熟悉。