/** ****************************(C) COPYRIGHT 2019 DJI**************************** * @file remote_control.c/h * @brief 遥控器处理,遥控器是通过类似SBUS的协议传输,利用DMA传输方式节约CPU * 资源,利用串口空闲中断来拉起处理函数,同时提供一些掉线重启DMA,串口 * 的方式保证热插拔的稳定性。 * @note 该任务是通过串口中断启动,不是freeRTOS任务 * @history * Version Date Author Modification * V1.0.0 Dec-01-2019 RM 1. 完成 * @verbatim ============================================================================== ============================================================================== @endverbatim ****************************(C) COPYRIGHT 2019 DJI**************************** */ #include "ledi.h" #include "bsp/calc_lib.h" #include "bsp/uart.h" #include "device.h" extern UART_HandleTypeDef huart3; extern DMA_HandleTypeDef hdma_usart3_rx; static void sbus_to_rc(volatile const uint8_t *sbus_buf, LD_t *rc_ctrl); void RC_init(uint8_t *rx1_buf, uint8_t *rx2_buf, uint16_t dma_buf_num); LD_t rc_ctrl; uint8_t sbus_rx_buf[2][RC_FRAME_LENGTH]; uint8_t remote_ready = 0;//ң¿؆÷׼±¸ͪ³ɠ //´®¿ڤma˫»º³凸³õʼ»¯ void remote_control_init(void) { RC_init(sbus_rx_buf[0], sbus_rx_buf[1], RC_FRAME_LENGTH); } static uint16_t this_time_rx_len = 0; void USART3_IRQHandler(void) { //have received data if(huart3.Instance->SR & UART_FLAG_RXNE) { //ȧ¹ûʇ½ӊՖжϔ򍨹ý¶Áȡdr¼Ĵ憷ǥÁ㍊ __HAL_UART_CLEAR_FEFLAG(&huart3); } else if(USART3->SR & UART_FLAG_IDLE) { //ʹӃǥ³ýpe±ꖾλµĺ¯ʽʇҲΪpe idleµȼ¸¸ö֐¶϶¼ʇ¿¿ψ¶Áȡsrԙ¶ÁȡdrǥÁ㵄 __HAL_UART_CLEAR_PEFLAG(&huart3); if( (hdma_usart3_rx.Instance->CR & DMA_SxCR_CT) == RESET) { //current memory buffer used is memory0 //disable dma to change dma register __HAL_DMA_DISABLE(&hdma_usart3_rx); //get received data length, length = set_data_length - remain_length this_time_rx_len = SBUS_RX_BUF_NUM - hdma_usart3_rx.Instance->NDTR; //reset set_data_length hdma_usart3_rx.Instance->NDTR = SBUS_RX_BUF_NUM; //change memory0 to memory1 hdma_usart3_rx.Instance->CR |= DMA_SxCR_CT; //enable dma __HAL_DMA_ENABLE(&hdma_usart3_rx); if(this_time_rx_len ==RC_FRAME_LENGTH) { sbus_to_rc(sbus_rx_buf[0], &rc_ctrl); remote_ready = 1; } } else { __HAL_DMA_DISABLE(&hdma_usart3_rx); this_time_rx_len = SBUS_RX_BUF_NUM - hdma_usart3_rx.Instance->NDTR; hdma_usart3_rx.Instance->NDTR = SBUS_RX_BUF_NUM; //change memory1 to memory0 DMA1_Stream1->CR &= ~(DMA_SxCR_CT); __HAL_DMA_ENABLE(&hdma_usart3_rx); if(this_time_rx_len ==RC_FRAME_LENGTH) { sbus_to_rc(sbus_rx_buf[1], &rc_ctrl); remote_ready = 1; } } } } //void UART3IdleCallback(void) { // USART3_IRQHandler(); //} void RC_init(uint8_t *rx1_buf, uint8_t *rx2_buf, uint16_t dma_buf_num) { //enable the dma transfer for the receiver request SET_BIT(huart3.Instance->CR3, USART_CR3_DMAR); //enable idle interrupt __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); //disable dma, to change the dma register __HAL_DMA_DISABLE(&hdma_usart3_rx); while(hdma_usart3_rx.Instance->CR & DMA_SxCR_EN) { __HAL_DMA_DISABLE(&hdma_usart3_rx); } hdma_usart3_rx.Instance->PAR = (uint32_t) & (USART3->DR); //memory buffer 1 hdma_usart3_rx.Instance->M0AR = (uint32_t)(rx1_buf); //momory buffer 2 hdma_usart3_rx.Instance->M1AR = (uint32_t)(rx2_buf); //data length hdma_usart3_rx.Instance->NDTR = dma_buf_num; //enable double memory buffer SET_BIT(hdma_usart3_rx.Instance->CR, DMA_SxCR_DBM); //enable dma __HAL_DMA_ENABLE(&hdma_usart3_rx); } bool REMOTE_WaitDmaCplt(uint32_t timeout) { return (osThreadFlagsWait(SIGNAL_DR16_RAW_REDY, osFlagsWaitAll, timeout) == SIGNAL_DR16_RAW_REDY); } static void sbus_to_rc(volatile const uint8_t *sbus_buf, LD_t *rc_ctrl) { if (sbus_buf == NULL || rc_ctrl == NULL) { return; } rc_ctrl->ch[0] = (sbus_buf[1] | (sbus_buf[2] << 8)) & 0x07ff; //Channel 1 rc_ctrl->ch[3] = ((sbus_buf[2] >> 3) | (sbus_buf[3] << 5)) & 0x07ff; //Channel 2 rc_ctrl->ch[1] = ((sbus_buf[3] >> 6) | (sbus_buf[4] << 2) | //Channel 3 (sbus_buf[5] << 10)) &0x07ff; rc_ctrl->ch[2] = ((sbus_buf[5] >> 1) | (sbus_buf[6] << 7)) & 0x07ff; //Channel 4 rc_ctrl->sw[6] = ((int16_t)sbus_buf[6] >> 4 | ((int16_t)sbus_buf[7] << 4 )) & 0x07FF; //Channel 5 rc_ctrl->sw[0] = ((int16_t)sbus_buf[7] >> 7 | ((int16_t)sbus_buf[8] << 1 ) | (int16_t)sbus_buf[9] << 9 ) & 0x07FF; //Channel 6 rc_ctrl->sw[5] = ((int16_t)sbus_buf[9] >> 2 | ((int16_t)sbus_buf[10] << 6 )) & 0x07FF;; //Channel 7 rc_ctrl->sw[4] = ((int16_t)sbus_buf[10] >> 5 | ((int16_t)sbus_buf[11] << 3 )) & 0x07FF; //Channel 8 rc_ctrl->sw[3] = ((int16_t)sbus_buf[12] << 0 | ((int16_t)sbus_buf[13] << 8 )) & 0x07FF; //Channel 9 rc_ctrl->sw[2] = ((int16_t)sbus_buf[13] >> 3 | ((int16_t)sbus_buf[14] << 5 )) & 0x07FF; //Channel 10 rc_ctrl->sw[1] = ((int16_t)sbus_buf[14] >> 6 | ((int16_t)sbus_buf[15] << 2 ) | (int16_t)sbus_buf[16] << 10 ) & 0x07FF; //Channel 11 rc_ctrl->sw[7] = ((int16_t)sbus_buf[16] >> 1 | ((int16_t)sbus_buf[17] << 7 )) & 0x07FF; //Channel 12 rc_ctrl->ch[1] = map_fp32(rc_ctrl->ch[1],352,1695,-1,1); //lx rc_ctrl->ch[0] = map_fp32(rc_ctrl->ch[0],352,1695,-1,1); //ly rc_ctrl->ch[2] = map_fp32(rc_ctrl->ch[2],352,1695,-1,1); //rx rc_ctrl->ch[3] = map_fp32(rc_ctrl->ch[3],352,1695,-1,1); //ry //ˀǸ(-30,30) if(rc_ctrl->ch[0]>-0.01&&rc_ctrl->ch[0]<0.01) rc_ctrl->ch[0]=0; if(rc_ctrl->ch[1]>-0.01&&rc_ctrl->ch[1]<=0.01) rc_ctrl->ch[1]=0; if(rc_ctrl->ch[2]>-0.01&&rc_ctrl->ch[2]<=0.01) rc_ctrl->ch[2]=0; if(rc_ctrl->ch[3]>-0.01&&rc_ctrl->ch[3]<=0.01) rc_ctrl->ch[3]=0; //MRobot remote_ready = 1; } int8_t LD_HandleOffline( LD_t *ld) { if (ld == NULL) return DEVICE_ERR_NULL; memset(&ld, 0, sizeof(LD_t)); return 0; } // #include "ledi.h" // #include "bsp/calc_lib.h" // #include "bsp/uart.h" // extern UART_HandleTypeDef huart3; // extern DMA_HandleTypeDef hdma_usart3_rx; // static void sbus_to_rc(volatile const uint8_t *sbus_buf, LD_t *rc_ctrl); // void RC_init(uint8_t *rx1_buf, uint8_t *rx2_buf, uint16_t dma_buf_num); // LD_t rc_ctrl; // uint8_t sbus_rx_buf[2][RC_FRAME_LENGTH]; // uint8_t remote_ready = 0;//遥控器准备完成 // //串口dma双缓冲区初始化 // void remote_control_init(void) // { // RC_init(sbus_rx_buf[0], sbus_rx_buf[1], RC_FRAME_LENGTH); // } // static uint16_t this_time_rx_len = 0; // void USART3_IRQHandler(void) // { // //have received data // if(huart3.Instance->SR & UART_FLAG_RXNE) // { // //如果是接收中断则通过读取dr寄存器清零 // __HAL_UART_CLEAR_FEFLAG(&huart3); // } // else if(USART3->SR & UART_FLAG_IDLE) // { // //使用清除pe标志位的函数是因为pe idle等几个中断都是靠先读取sr再读取dr清零的 // __HAL_UART_CLEAR_PEFLAG(&huart3); // if( (hdma_usart3_rx.Instance->CR & DMA_SxCR_CT) == RESET) // { // //current memory buffer used is memory0 // //disable dma to change dma register // __HAL_DMA_DISABLE(&hdma_usart3_rx); // //get received data length, length = set_data_length - remain_length // this_time_rx_len = SBUS_RX_BUF_NUM - hdma_usart3_rx.Instance->NDTR; // //reset set_data_length // hdma_usart3_rx.Instance->NDTR = SBUS_RX_BUF_NUM; // //change memory0 to memory1 // hdma_usart3_rx.Instance->CR |= DMA_SxCR_CT; // //enable dma // __HAL_DMA_ENABLE(&hdma_usart3_rx); // if(this_time_rx_len ==RC_FRAME_LENGTH) // { // sbus_to_rc(sbus_rx_buf[0], &rc_ctrl); // } // } // else // { // __HAL_DMA_DISABLE(&hdma_usart3_rx); // this_time_rx_len = SBUS_RX_BUF_NUM - hdma_usart3_rx.Instance->NDTR; // hdma_usart3_rx.Instance->NDTR = SBUS_RX_BUF_NUM; // //change memory1 to memory0 // DMA1_Stream1->CR &= ~(DMA_SxCR_CT); // __HAL_DMA_ENABLE(&hdma_usart3_rx); // if(this_time_rx_len ==RC_FRAME_LENGTH) // { // sbus_to_rc(sbus_rx_buf[1], &rc_ctrl); // remote_ready = 1; // } // } // } // } // //void UART3IdleCallback(void) { // // USART3_IRQHandler(); // //} // void RC_init(uint8_t *rx1_buf, uint8_t *rx2_buf, uint16_t dma_buf_num) // { // //enable the dma transfer for the receiver request // SET_BIT(huart3.Instance->CR3, USART_CR3_DMAR); // //enable idle interrupt // __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); // //disable dma, to change the dma register // __HAL_DMA_DISABLE(&hdma_usart3_rx); // while(hdma_usart3_rx.Instance->CR & DMA_SxCR_EN) // { // __HAL_DMA_DISABLE(&hdma_usart3_rx); // } // hdma_usart3_rx.Instance->PAR = (uint32_t) & (USART3->DR); // //memory buffer 1 // hdma_usart3_rx.Instance->M0AR = (uint32_t)(rx1_buf); // //momory buffer 2 // hdma_usart3_rx.Instance->M1AR = (uint32_t)(rx2_buf); // //data length // hdma_usart3_rx.Instance->NDTR = dma_buf_num; // //enable double memory buffer // SET_BIT(hdma_usart3_rx.Instance->CR, DMA_SxCR_DBM); // //enable dma // __HAL_DMA_ENABLE(&hdma_usart3_rx); // } // static void sbus_to_rc(volatile const uint8_t *sbus_buf, LD_t *rc_ctrl) // { // if (sbus_buf == NULL || rc_ctrl == NULL) // { // return; // } // rc_ctrl->ch[0] = (sbus_buf[1] | (sbus_buf[2] << 8)) & 0x07ff; //Channel 1 // rc_ctrl->ch[1] = ((sbus_buf[2] >> 3) | (sbus_buf[3] << 5)) & 0x07ff; //Channel 2 // rc_ctrl->ch[2] = ((sbus_buf[3] >> 6) | (sbus_buf[4] << 2) | //Channel 3 // (sbus_buf[5] << 10)) &0x07ff; // rc_ctrl->ch[3] = ((sbus_buf[5] >> 1) | (sbus_buf[6] << 7)) & 0x07ff; //Channel 4 // rc_ctrl->sw[0] = ((int16_t)sbus_buf[6] >> 4 | ((int16_t)sbus_buf[7] << 4 )) & 0x07FF; //Channel 5 // rc_ctrl->sw[1] = ((int16_t)sbus_buf[7] >> 7 | ((int16_t)sbus_buf[8] << 1 ) | (int16_t)sbus_buf[9] << 9 ) & 0x07FF; //Channel 6 // rc_ctrl->sw[2] = ((int16_t)sbus_buf[9] >> 2 | ((int16_t)sbus_buf[10] << 6 )) & 0x07FF;; //Channel 7 // rc_ctrl->sw[3] = ((int16_t)sbus_buf[10] >> 5 | ((int16_t)sbus_buf[11] << 3 )) & 0x07FF; //Channel 8 // rc_ctrl->sw[4] = ((int16_t)sbus_buf[12] << 0 | ((int16_t)sbus_buf[13] << 8 )) & 0x07FF; //Channel 9 // rc_ctrl->sw[5] = ((int16_t)sbus_buf[13] >> 3 | ((int16_t)sbus_buf[14] << 5 )) & 0x07FF; //Channel 10 // rc_ctrl->sw[6] = ((int16_t)sbus_buf[14] >> 6 | ((int16_t)sbus_buf[15] << 2 ) | (int16_t)sbus_buf[16] << 10 ) & 0x07FF; //Channel 11 // rc_ctrl->sw[7] = ((int16_t)sbus_buf[16] >> 1 | ((int16_t)sbus_buf[17] << 7 )) & 0x07FF; //Channel 12 // // rc_ctrl->sw[2] = map(rc_ctrl->sw[2],306,1694,1694,306); // // rc_ctrl->sw[3] = map(rc_ctrl->sw[3],306,1694,1694,306); // // rc_ctrl->ch[1] = map(rc_ctrl->ch[1],-693,694,-700,700); //x // // rc_ctrl->ch[0] = map(rc_ctrl->ch[0],-694,693,-700,700); //y // // rc_ctrl->ch[2] = map(rc_ctrl->ch[2],200,1800,-700,700); //x // // rc_ctrl->ch[3] = map(rc_ctrl->ch[3],-694,693,-700,700); //y // rc_ctrl->ch[1] = -map_fp32(rc_ctrl->ch[1],252,1639,-1,1); //x // rc_ctrl->ch[0] = map_fp32(rc_ctrl->ch[0],306,1693,-1,1); //y // rc_ctrl->ch[2] = -map_fp32(rc_ctrl->ch[2],74,1422,-1,1); // rc_ctrl->ch[3] = map_fp32(rc_ctrl->ch[3],194,1580,-1,1); //x // //死区(-30,30) // if(rc_ctrl->ch[0]>-0.01&&rc_ctrl->ch[0]<0.01) rc_ctrl->ch[0]=0; // if(rc_ctrl->ch[1]>-0.01&&rc_ctrl->ch[1]<=0.01) rc_ctrl->ch[1]=0; // if(rc_ctrl->ch[2]>-0.05&&rc_ctrl->ch[2]<=0.05) rc_ctrl->ch[2]=0; // if(rc_ctrl->ch[3]>-0.01&&rc_ctrl->ch[3]<=0.01) rc_ctrl->ch[3]=0; // //MRobot // remote_ready = 1; // }