/** * 东北大学ACTION码盘驱动 * * 本驱动采用ops_9定位系统,负责收发码盘的原始数据,并在任务中解析出相应的位置坐标。 * 解析后的位置坐标将被交给导航处理模块,生成期望的运动向量。 * * 使用手册: * 请参阅相关文档了解如何使用本驱动。 * * 注意: * 本驱动仅适用于东北大学ACTION码盘。 *删去Action_HandleOffline错误处理函数中对结构体清0的函数 */ /* Includes ----------------------------------------------------------------- */ #include "tim.h" #include "Action.h" #include static osThreadId_t thread_alert; uint8_t rxbuf[RS232_FRAME_LENGTH]; static void Ops10msTimerCallback(void *arg){ (void)arg; osThreadFlagsSet(thread_alert,SIGNAL_OPSTIMER_REDY); } /* Private function -------------------------------------------------------- */ static void ACTION_IdleCallback(void) { osThreadFlagsSet(thread_alert,SIGNAL_ACTION_RAW_REDY); } /* Exported functions ------------------------------------------------------- */ int8_t ACTIONRECV_Init(Action_POS_t *pos){ if(pos == NULL) return DEVICE_ERR_NULL; pos->Action_ready =0;//码盘校准标志位初始化 if((thread_alert = osThreadGetId()) == NULL ) return DEVICE_ERR_NULL; pos->action_timer_Id = osTimerNew(Ops10msTimerCallback, osTimerPeriodic,NULL,NULL); osTimerStart(pos->action_timer_Id,10);//此处ticks 理解为1个tick为1ms 此处为每10ms触发一次回调函数 BSP_UART_RegisterCallback(BSP_UART_ACTION,BSP_UART_IDLE_LINE_CB, ACTION_IdleCallback); return DEVICE_OK; } int8_t ACTION_StartReceiving() { if (HAL_UARTEx_ReceiveToIdle_DMA(BSP_UART_GetHandle(BSP_UART_ACTION), (uint8_t *)rxbuf, sizeof(rxbuf)) == HAL_OK) return DEVICE_OK; return DEVICE_ERR; } bool_t ACTION_WaitDmaCplt(void) { return(osThreadFlagsWait(SIGNAL_ACTION_RAW_REDY, osFlagsWaitAll,400) == SIGNAL_ACTION_RAW_REDY); } /* * */ int8_t ACTION_Parse(Action_POS_t *pos) { if (pos == NULL) return DEVICE_ERR_NULL; static union { fp32 pos_data[3]; char rxbuff[12]; } pos_rxbuf; if (rxbuf[0] == 0x0D && rxbuf[1] == 0x0A) { if (rxbuf[26] == 0x0A && rxbuf[27] == 0x0D) { pos_rxbuf.rxbuff[0]=rxbuf[2]; pos_rxbuf.rxbuff[1]=rxbuf[3]; pos_rxbuf.rxbuff[2]=rxbuf[4]; pos_rxbuf.rxbuff[3]=rxbuf[5]; pos_rxbuf.rxbuff[4]=rxbuf[14]; pos_rxbuf.rxbuff[5]=rxbuf[15]; pos_rxbuf.rxbuff[6]=rxbuf[16]; pos_rxbuf.rxbuff[7]=rxbuf[17]; pos_rxbuf.rxbuff[8]=rxbuf[18]; pos_rxbuf.rxbuff[9]=rxbuf[19]; pos_rxbuf.rxbuff[10]=rxbuf[20]; pos_rxbuf.rxbuff[11]=rxbuf[21]; // 数据解析 pos->pos_yaw = pos_rxbuf.pos_data[0]; // 按照安装方向决定正负号 pos->pos_x = pos_rxbuf.pos_data[1]; pos->pos_y = pos_rxbuf.pos_data[2]; pos ->Action_ready =1;//码盘校准完成 } } else { return -1; } return DEVICE_OK; } //该函数用来计算速度(利用获取的位置来计算相应的速度) //此处获取的是真实的位置(mm)后每10ms做一次微分处理 int8_t ACTION_DataRefresh(Action_POS_t *pos){ if (pos == NULL) return DEVICE_ERR_NULL; if (osThreadFlagsGet() & SIGNAL_OPSTIMER_REDY){ osThreadFlagsClear(SIGNAL_OPSTIMER_REDY); //计算每毫秒的速度 该函数每10ms调用 pos->pos_Vx = (pos->pos_x - pos->pos_lastX) / 10; pos->pos_Vy = (pos->pos_y - pos->pos_lastY) / 10; pos->pos_lastX = pos->pos_x; pos->pos_lastY = pos->pos_y; } return DEVICE_OK; } int8_t Action_HandleOffline(Action_POS_t *pos) { if (pos == NULL) return DEVICE_ERR_NULL; (void)pos; // memset(pos, 0, sizeof(*pos)); return 0; } /* 将字符串拼接 */ void Strcat(char str1[], char str2[], uint8_t num) { int i = 0, j = 0; while (str1[i] != '\0') i++; for (j = 0; j < num; j++) { str1[i++] = str2[j]; } } /* 该部分函数用于码盘的重定位系统 */ /* ----------------------------- */ /* 手动标定,用于校正 */ void ACT_Calibration(void) { HAL_UART_Transmit(&huart1, (uint8_t *)"ACTR", 4, 100); } /* 清零 */ /* 将当前位置设置为 (0, 0) */ void ACT_ZeroClear(void) { HAL_UART_Transmit(&huart1, (uint8_t *)"ACT0", 4, 100); } /* 更新 XY 坐标 */ /* 将当前位置更新为指定的 X 和 Y */ void ACT_UpdateXY(float pos_x, float pos_y) { char update_xy[12] = "ACTD"; // 命令前缀为 "ACTD" static union { float XY[2]; // 两个浮点数表示 X 和 Y 坐标 char data[8]; // 将浮点数视为字节数据 } set; set.XY[0] = pos_x; set.XY[1] = pos_y; Strcat(update_xy, set.data, 8); HAL_UART_Transmit(&huart1, (uint8_t *)update_xy, sizeof(update_xy), 100); }