RS485编码器
使用RS485读取多个编码器
接收数据:空闲中断+DMA
发送数据:DMA
配置串口:
基本与串口通信一致,增加接收和发送DMA,正常模式,另外增加485使能IO
接收数据:
使能空闲中断
__HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE) ;
__HAL_UART_CLEAR_IDLEFLAG(&huart3);
增加空闲中断回调函数,自定义的回调函数在void USART3_IRQHandler(void)函数中调用
//串口空闲中断 void UART3_IDLECallBack(UART_HandleTypeDef *huart) { if(huart == &huart3){ if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET)) { __HAL_UART_CLEAR_IDLEFLAG(&huart3);//清除标志位 HAL_UART_DMAStop(&huart3);//停止DMA //HAL_UART_Transmit(&huart1,uart3RxBuffer2,12,0x1000); Uart3.RxLen=(&huart3)->RxXferSize-(&huart3)->hdmarx->Instance->CNDTR;//len==21 RS485_RX_END = 1; } } } |
在主函数中判断RS485_RX_END处理数据
发送数据:
由于需要与多个编码器通信,如果连续发送数据,读不到编码器的数据,猜想是连续的数据会被识别成1条数据,等待huart->gState = HAL_UART_STATE_READY标志位也失败了,所以使用定时器定时50ms发送数据
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { static uint8_t CmdCNT = 0; uint8_t *SendBuf = NULL; uint8_t *ReceiveBuf = NULL;
HAL_TIM_Base_Stop_IT(&htim1); HAL_UART_DMAStop(&huart3);//停止DMA //切换输出的命令 if(!(ResetRoatFlag & (0x1<<Enc_ID))){ // printf("Read_RS485:%d", Enc_ID); SendBuf = Read_RS485[Enc_ID]; } else{ if(!(CmdCNT&(0x1<<Enc_ID))){ // printf("Start_RS485:%d", Enc_ID); SendBuf = Start_RS485[Enc_ID]; CmdCNT |= (0x1 << Enc_ID); }else{ // printf("Set_RS485:%d", Enc_ID); SendBuf = Set_RS485[Enc_ID]; CmdCNT &= ~(0x1 << Enc_ID); ResetRoatFlag &= ~(0x1 << Enc_ID); } } // 启用DMA接收 switch (Enc_ID){ case RS485_ENC1:ReceiveBuf = uart3RxBuffer1;break; case RS485_ENC2:ReceiveBuf = uart3RxBuffer2;break; case RS485_ENC3:ReceiveBuf = uart3RxBuffer3;break; default:ReceiveBuf = NULL; } if(ReceiveBuf != NULL){ HAL_UART_Receive_DMA(&huart3,ReceiveBuf,sizeof(uart3RxBuffer) - 1) ; SwRS485Mode(RS485_TX_EN); HAL_UART_Transmit_DMA(&huart3,SendBuf,8); (Enc_ID+1) > 2 ? Enc_ID=0 : Enc_ID++; } HAL_TIM_Base_Start_IT(&htim1); } |
主要功能就是切换发送的命令,开启DMA接收,发送数据(多缓存接收)
开启DMA接收HAL_UART_Receive_DMA(&huart3,ReceiveBuf,sizeof(uart3RxBuffer) - 1) ;
切换485使能为发送;
HAL_UART_Transmit_DMA(&huart3,SendBuf,8);发送数据
在发送中断回调函数中切换485使能为接收
流程:定时器中断→开启DMA接收→切换485为发送,DMA发送→发送中断回调函数切换485为接收→空闲中断接收数据,停止DMA→主函数处理数据→定时器中断
但是定时器定时时间不能小于50ms,否则也会接收不到数据,
标签:DMA,编码器,Enc,HAL,UART,huart3,RS485 From: https://www.cnblogs.com/yianyan/p/17834630.html