本文主要讲述在一些dma运用在串口上的一些问题
dma开启循环模式后,在空闲中断下虽然能接收到一帧数据,但在不知道数据长短或出现了异常数据的情况下,且循环模式下,其输入数组的地址是递增的。因为一帧的数据可能存在差错,与预估长度不同,故提取正确数据存在一定麻烦。
故下面提供一种较为好用的方法。
uint8_t dbus_buf[DBUS_BUFLEN];
void dbus_idle_callback(UART_HandleTypeDef *huart)
{
if(huart==&DBUS_HUART)
{
__HAL_DMA_DISABLE(huart->hdmarx);
if((DBUS_MAX_LEN-__HAL_DMA_GET_COUNTER(huart->hdmarx))==DBUS_BUFLEN)
{
//添加数据处理
printf("%s\r\n",dbus_buf);
}
memset(dbus_buf,0,sizeof(dbus_buf));
huart->hdmarx->Instance->CNDTR=DBUS_MAX_LEN;
__HAL_DMA_ENABLE(huart->hdmarx);
}
}
/**
* @description: 在USART1_IRQHandler中调用此函数
* @param {UART_HandleTypeDef} *huart: uart IRQHandler id
* @return {*}
*/
void dbus_IRQHandler(UART_HandleTypeDef *huart)
{
if(huart==&DBUS_HUART)
{
if(__HAL_UART_GET_FLAG(&DBUS_HUART,UART_FLAG_IDLE))
{
__HAL_UART_CLEAR_FLAG(&DBUS_HUART,UART_FLAG_IDLE);
dbus_idle_callback(&DBUS_HUART);
}
}
}
dbus为所用数据接收串口
注要在初始化时添加
__HAL_UART_ENABLE_IT(&DBUS_HUART,UART_IT_IDLE);
HAL_UART_Receive_DMA(&DBUS_HUART,dbus_buf,DBUS_MAX_LEN);
开启空闲中断,并开启dma和最大传输数据
并在stm32g4xx_it.h中
* @brief This function handles USART1 global interrupt / USART1 wake-up interrupt through EXTI line 25.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
dbus_IRQHandler(&DBUS_HUART);
/* USER CODE END USART1_IRQn 1 */
}
加入空闲中断处理dbus_IRQHandler(&DBUS_HUART);
huart->hdmarx->Instance->CNDTR
上为dma设置要传输的数据量。在每个数据传输后,这个数值递减。
本方法原理即通过在每一帧数据接收后,将其归于初始值。使dma输入数组的值从数组头开始,不再接在上一帧数据后。便可精准的判断每一帧数据进行分析。
__HAL_DMA_SET_COUNTER(huart->hdmarx, DBUS_MAX_LEN);
其实设置传输数据量有专门的函数如上,但有时这函数又不存在,不太清楚。