finish all bsp utilities

This commit is contained in:
NeoZng 2022-11-01 22:32:15 +08:00
parent c113ca81e0
commit a2b7558047
13 changed files with 514 additions and 436 deletions

View File

@ -79,90 +79,90 @@ void MX_FREERTOS_Init(void);
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_CAN1_Init();
MX_CAN2_Init();
MX_SPI1_Init();
MX_TIM4_Init();
MX_TIM5_Init();
MX_USART3_UART_Init();
MX_RNG_Init();
MX_RTC_Init();
MX_TIM1_Init();
MX_TIM10_Init();
MX_USART1_UART_Init();
MX_USART6_UART_Init();
/* USER CODE BEGIN 2 */
RC_init(&huart3);
can_instance_config can_config = {.can_handle = &hcan1,
.tx_id = 1};
Motor_Control_Setting_s motor_config = {.angle_feedback_source = MOTOR_FEED,
.close_loop_type = SPEED_LOOP | CURRENT_LOOP,
.speed_feedback_source = MOTOR_FEED,
.reverse_flag = MOTOR_DIRECTION_NORMAL};
Motor_Controller_Init_s controller_init = {.current_PID = {
.Improve = 0,
.Kp = 1,
.Ki = 0,
.Kd = 0,
.DeadBand = 0,
.MaxOut = 4000,
},
.speed_PID = {
.Improve = 0,
.Kp = 1,
.Ki = 0,
.Kd = 0,
.DeadBand = 0,
.MaxOut = 4000,
}};
Motor_Type_e type = M3508;
DWT_Init(168);
dji_motor_instance *djimotor = DJIMotorInit(can_config, motor_config, controller_init, type);
/* USER CODE END 2 */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_CAN1_Init();
MX_CAN2_Init();
MX_SPI1_Init();
MX_TIM4_Init();
MX_TIM5_Init();
MX_USART3_UART_Init();
MX_RNG_Init();
MX_RTC_Init();
MX_TIM1_Init();
MX_TIM10_Init();
MX_USART1_UART_Init();
MX_USART6_UART_Init();
/* USER CODE BEGIN 2 */
RC_init(&huart3);
can_instance_config can_config = {.can_handle = &hcan1,
.tx_id = 1};
Motor_Control_Setting_s motor_config = {.angle_feedback_source = MOTOR_FEED,
.close_loop_type = SPEED_LOOP | CURRENT_LOOP,
.speed_feedback_source = MOTOR_FEED,
.reverse_flag = MOTOR_DIRECTION_NORMAL};
Motor_Controller_Init_s controller_init = {.current_PID = {
.Improve = 0,
.Kp = 1,
.Ki = 0,
.Kd = 0,
.DeadBand = 0,
.MaxOut = 4000,
},
.speed_PID = {
.Improve = 0,
.Kp = 1,
.Ki = 0,
.Kd = 0,
.DeadBand = 0,
.MaxOut = 4000,
}};
Motor_Type_e type = M3508;
DWT_Init(168);
dji_motor_instance *djimotor = DJIMotorInit(can_config, motor_config, controller_init, type);
/* USER CODE END 2 */
/* Call init function for freertos objects (in freertos.c) */
// MX_FREERTOS_Init();
/* Call init function for freertos objects (in freertos.c) */
// MX_FREERTOS_Init();
// /* Start scheduler */
// osKernelStart();
// /* Start scheduler */
// osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
DJIMotorSetRef(djimotor, get_remote_control_point()->rc.ch[0]);
MotorControlTask();
HAL_Delay(20);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
DJIMotorSetRef(djimotor, get_remote_control_point()->rc.ch[0]);
MotorControlTask();
HAL_Delay(20);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
@ -171,42 +171,42 @@ int main(void)
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 6;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 6;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
@ -219,13 +219,13 @@ void SystemClock_Config(void)
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
@ -238,9 +238,9 @@ void Error_Handler(void)
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

View File

@ -1,17 +1,30 @@
/**
* @file bsp_usart.c
* @author neozng
* @brief bsp层的实现
* @version beta
* @date 2022-11-01
*
* @copyright Copyright (c) 2022
*
*/
#include "bsp_usart.h"
#include "stdlib.h"
/* usart service instance,modules' info would be recoreded here using ModuleRegister() */
/* usart service instance, modules' info would be recoreded here using USARTRegister() */
/* usart服务实例,所有注册了usart的模块信息会被保存在这里 */
static usart_instance *instance[DEVICE_USART_CNT];
/**
* @brief usart service will start automatically, after each module registered
*
*
* @param _instance instance owned by module
* @param _instance instance owned by module,
*/
static void USARTServiceInit(usart_instance *_instance)
{
HAL_UARTEx_ReceiveToIdle_DMA(_instance->usart_handle, _instance->recv_buff, _instance->recv_buff_size);
// 关闭dma half transfer中断防止两次进入HAL_UARTEx_RxEventCallback()
__HAL_DMA_DISABLE_IT(_instance->usart_handle->hdmarx, DMA_IT_HT);
}
@ -22,21 +35,21 @@ void USARTRegister(usart_instance *_instance)
instance[instance_idx++] = _instance;
}
/* @todo 当前仅进行了形式上的封装,后续要进一步考虑是否将module的行为与bsp完全分离 */
void USARTSend(usart_instance *_instance, uint8_t *send_buf, uint16_t send_size)
{
HAL_UART_Transmit_DMA(_instance->usart_handle, send_buf, send_size);
}
/**
* @brief everytiem when dma/idle happens,this function will be called
* here, for each uart, specific callback is refered for further process
* etc:visual protocol resolve/remote control resolve/referee protocol resolve
* @brief dma/idle中断发生时.uart实例会调用对应的回调进行进一步的处理
* ://
*
* @note because DMA half transfer iterrupt(DMA_IT_HT) would call this function too, so we just
* @note because DMA half transfer iterrupt(DMA_IT_HT) would call this callback function too, so we just
* disable it when transfer complete using macro: __HAL_DMA_DISABLE_IT(huart->hdmarx,DMA_IT_HT)
*
* @param huart uart handle indicate which uart is being handled
* @param Size not used temporarily
* @param huart uart handle indicate which uart is being handled
* @param Size not used temporarily,,
*/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
@ -58,7 +71,7 @@ void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
*
* @note most frequent error ex: parity/overrrun/frame error
*
* @param huart uart handle type,indicate where error comes from
* @param huart uart handle type, indicate where error comes from
*/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{

View File

@ -4,41 +4,38 @@
#include "struct_typedef.h"
#include "main.h"
#define DEVICE_USART_CNT 3
#define USART_RX_LIMIT 128 // if your protocol needs bigger buff, modify here
#define DEVICE_USART_CNT 3 // C板至多分配3个串口
#define USART_RXBUFF_LIMIT 128 // if your protocol needs bigger buff, modify here
/* application callback,which resolves specific protocol */
/* application callback,which resolves specific protocol,解析协议的回调函数 */
typedef void (*usart_module_callback)();
/* usart_instance struct,each app would have one instance */
typedef struct
{
uint8_t recv_buff[USART_RX_LIMIT];
uint8_t recv_buff_size;
UART_HandleTypeDef *usart_handle;
usart_module_callback module_callback;
uint8_t recv_buff[USART_RXBUFF_LIMIT]; // 预先定义的最大buff大小,如果太小请修改USART_RXBUFF_LIMIT
uint8_t recv_buff_size; // 模块接收一包数据的大小
UART_HandleTypeDef *usart_handle; // 实例对应的usart_handle
usart_module_callback module_callback; // 解析收到的数据的回调函数
} usart_instance;
/**
* @brief calling this func would regiter a module to usart_service
* this function provides completely wrap and abstract for those module who use usart as commu method
*
* @param id module id.attention,each id is mapped to a specific usart port(ex:remote control->usart3)
* @param prbuff pointer to where the raw recv data stored
* @param rbuffsize size of recv data buff
* @param psbuff pointer to where the data to be sent stored
* @param callback func pointer,this func would be called in USART_service.c/HAL_UARTEx_RxEventCallback()
* to resolve raw data using protocol provides by specific app calling Moduleregister()
* @brief .
*
* @param _instance module拥有的串口实例,,usart_instance的struct定义
*/
void USARTRegister(usart_instance* _instance);
void USARTRegister(usart_instance *_instance);
/**
* @todo buff和size,?
* ,,buffer大小以及何时发送.
*
* @brief api for sending data through a specific serial port,indicated by the first parameter:id
* ,usart实例,buff以及这一帧的长度
*
* @param id specify which usart would be used
* @param send_size how many bytes to send
*/
void USARTSend(usart_instance* _instance, uint8_t* send_buf,uint16_t send_size);
void USARTSend(usart_instance *_instance, uint8_t *send_buf, uint16_t send_size);
#endif

View File

@ -1,37 +1,38 @@
/**
* @file controller.c
* @author wanghongxi
* @author modified by neozng
* @brief PID控制器定义
* @version beta
* @date 2022-11-01
*
* @copyrightCopyright (c) 2022 HNU YueLu EC all rights reserved
*/
#include "controller.h"
#include <memory.h>
/******************************* PID CONTROL *********************************/
// PID优化环节函数声明
static void f_Trapezoid_Intergral(PID_t *pid);
static void f_Integral_Limit(PID_t *pid);
static void f_Derivative_On_Measurement(PID_t *pid);
static void f_Changing_Integration_Rate(PID_t *pid);
static void f_Output_Filter(PID_t *pid);
static void f_Derivative_Filter(PID_t *pid);
static void f_Output_Limit(PID_t *pid);
static void f_Proportion_Limit(PID_t *pid);
static void f_PID_ErrorHandle(PID_t *pid);
static void f_Trapezoid_Intergral(PID_t *pid); // 梯形积分
static void f_Integral_Limit(PID_t *pid); // 积分限幅
static void f_Derivative_On_Measurement(PID_t *pid); // 微分先行(仅使用反馈微分)
static void f_Changing_Integration_Rate(PID_t *pid); // 变速积分
static void f_Output_Filter(PID_t *pid); // 输出滤波
static void f_Derivative_Filter(PID_t *pid); // 微分滤波(采集时)
static void f_Output_Limit(PID_t *pid); // 输出限幅
static void f_PID_ErrorHandle(PID_t *pid); // 堵转保护
/**
* @brief
* @brief PID,,
*
* @param pid
* @param config
* @param pid PID实例
* @param config PID初始化设置
*/
void PID_Init(PID_t* pid,PID_Init_config_s *config)
void PID_Init(PID_t *pid, PID_Init_config_s *config)
{
// utilize the quality of struct that its memeory is continuous
memcpy(pid, config, sizeof(PID_Init_config_s));
memset(&pid->Measure,0,sizeof(PID_t)-sizeof(PID_Init_config_s));
// // DWT定时器计数变量清零
// // reset DWT Timer count counter
// pid->DWT_CNT = 0;
// // 设置PID异常处理 目前仅包含电机堵转保护
// pid->ERRORHandler.ERRORCount = 0;
// pid->ERRORHandler.ERRORType = PID_ERROR_NONE;
// set rest of memory to 0
memset(&pid->Measure, 0, sizeof(PID_t) - sizeof(PID_Init_config_s));
}
/**

View File

@ -1,19 +1,18 @@
/**
******************************************************************************
* @file controller.h
* @author Wang Hongxi
* @version V1.1.3
* @date 2021/7/3
* @brief
******************************************************************************
* @attention
*
******************************************************************************
*/
******************************************************************************
* @file controller.h
* @author Wang Hongxi
* @version V1.1.3
* @date 2021/7/3
* @brief
******************************************************************************
* @attention
*
******************************************************************************
*/
#ifndef _CONTROLLER_H
#define _CONTROLLER_H
#include "main.h"
#include "stdint.h"
#include "string.h"
@ -26,36 +25,37 @@
#define abs(x) ((x > 0) ? x : -x)
#endif
/******************************* PID CONTROL *********************************/
// PID 优化环节使能标志位
typedef enum pid_Improvement_e
{
NONE = 0X00, //0000 0000
Integral_Limit = 0x01, //0000 0001
Derivative_On_Measurement = 0x02, //0000 0010
Trapezoid_Intergral = 0x04, //0000 0100
Proportional_On_Measurement = 0x08, //0000 1000
OutputFilter = 0x10, //0001 0000
ChangingIntegrationRate = 0x20, //0010 0000
DerivativeFilter = 0x40, //0100 0000
ErrorHandle = 0x80, //1000 0000
NONE = 0b00000000, // 0000 0000
Integral_Limit = 0b00000001, // 0000 0001
Derivative_On_Measurement = 0b00000010, // 0000 0010
Trapezoid_Intergral = 0b00000100, // 0000 0100
Proportional_On_Measurement = 0b00001000, // 0000 1000
OutputFilter = 0b00010000, // 0001 0000
ChangingIntegrationRate = 0b00100000, // 0010 0000
DerivativeFilter = 0b01000000, // 0100 0000
ErrorHandle = 0b10000000, // 1000 0000
} PID_Improvement_e;
/* PID 报错类型枚举*/
typedef enum errorType_e
{
PID_ERROR_NONE = 0x00U,
Motor_Blocked = 0x01U
} ErrorType_e;
typedef struct
typedef struct
{
uint64_t ERRORCount;
ErrorType_e ERRORType;
} PID_ErrorHandler_t;
typedef struct
/* PID结构体 */
typedef struct
{
//---------------------------------- init config block
//---------------------------------- init config block
// config parameter
float Kp;
float Ki;
@ -64,13 +64,13 @@ typedef struct
float MaxOut;
float IntegralLimit;
float DeadBand;
float CoefA; //For Changing Integral
float CoefB; //ITerm = Err*((A-abs(err)+B)/A) when B<|err|<A+B
float CoefA; // For Changing Integral
float CoefB; // ITerm = Err*((A-abs(err)+B)/A) when B<|err|<A+B
float Output_LPF_RC; // RC = 1/omegac
float Derivative_LPF_RC;
uint8_t Improve;
//-----------------------------------
//-----------------------------------
// for calculating
float Measure;
float Last_Measure;
@ -96,7 +96,7 @@ typedef struct
} PID_t;
/* 用于PID初始化的结构体*/
typedef struct
typedef struct
{
// config parameter
float Kp;
@ -106,8 +106,8 @@ typedef struct
float MaxOut;
float IntegralLimit;
float DeadBand;
float CoefA; //For Changing Integral
float CoefB; //ITerm = Err*((A-abs(err)+B)/A) when B<|err|<A+B
float CoefA; // For Changing Integral
float CoefB; // ITerm = Err*((A-abs(err)+B)/A) when B<|err|<A+B
float Output_LPF_RC; // RC = 1/omegac
float Derivative_LPF_RC;
@ -115,32 +115,22 @@ typedef struct
} PID_Init_config_s;
/**
* @brief PID实例
*
* @param pid PID实例指针
* @param config PID初始化配置
*/
void PID_Init(PID_t *pid, PID_Init_config_s *config);
void PID_Init(PID_t* pid,PID_Init_config_s* config);
/**
* @brief PID输出
*
* @param pid PID实例指针
* @param measure
* @param ref
* @return float PID计算输出
*/
float PID_Calculate(PID_t *pid, float measure, float ref);
/*************************** Tracking Differentiator ***************************/
typedef struct
{
float Input;
float h0;
float r;
float x;
float dx;
float ddx;
float last_dx;
float last_ddx;
uint32_t DWT_CNT;
float dt;
} TD_t;
void TD_Init(TD_t *td, float r, float h0);
float TD_Calculate(TD_t *td, float input);
#endif
#endif

View File

@ -16,7 +16,7 @@
#include "bsp_temperature.h"
#include "spi.h"
INS_t INS;
static INS_t INS;
IMU_Param_t IMU_Param;
PID_t TempCtrl = {0};
@ -31,6 +31,11 @@ float RefTemp = 40;
static void IMU_Param_Correction(IMU_Param_t *param, float gyro[3], float accel[3]);
attitude_t *GetINSptr()
{
return (attitude_t *)&INS.Roll;
}
void INS_Init(void)
{
// while (BMI088_init(&hspi1, 1) != BMI088_NO_ERROR);
@ -51,7 +56,7 @@ void INS_Init(void)
.Ki = 20,
.Kd = 0,
.Improve = 0x01}; // enable integratiaon limit
PID_Init(&TempCtrl,&config);
PID_Init(&TempCtrl, &config);
// noise of accel is relatively big and of high freq,thus lpf is used
INS.AccelLPF = 0.0085;

View File

@ -23,12 +23,20 @@
#define INS_TASK_PERIOD 1
typedef struct
{
float Roll;
float Pitch;
float Yaw;
float YawTotalAngle;
} attitude_t;
typedef struct
{
float q[4]; // 四元数估计值
float Gyro[3]; // 角速度
float Accel[3]; // 加速度
float Gyro[3]; // 角速度
float Accel[3]; // 加速度
float MotionAccel_b[3]; // 机体坐标加速度
float MotionAccel_n[3]; // 绝对系加速度
@ -49,10 +57,9 @@ typedef struct
float YawTotalAngle;
} INS_t;
/**
* @brief ,demo中可无视
*
* @brief
*
*/
typedef struct
{
@ -65,16 +72,79 @@ typedef struct
float Roll;
} IMU_Param_t;
extern INS_t INS;
/**
* @brief 姿,apps通过初始化时保存该指针以实现数据访问
*
* @return attitude_t*
*/
attitude_t *GetINSptr();
/**
* @brief
*
*/
void INS_Init(void);
/**
* @brief ,1kHz频率运行
* p.s. osDelay(1);
*
*/
void INS_Task(void);
/**
* @brief
*
*/
void IMU_Temperature_Ctrl(void);
/**
* @brief ,dq/dt=0.5Ωq
*
* @param q
* @param gx
* @param gy
* @param gz
* @param dt
*/
void QuaternionUpdate(float *q, float gx, float gy, float gz, float dt);
/**
* @brief ZYX
*
* @param q
* @param Yaw
* @param Pitch
* @param Roll
*/
void QuaternionToEularAngle(float *q, float *Yaw, float *Pitch, float *Roll);
/**
* @brief ZYX欧拉角转换为四元数
*
* @param Yaw
* @param Pitch
* @param Roll
* @param q
*/
void EularAngleToQuaternion(float Yaw, float Pitch, float Roll, float *q);
/**
* @brief
*
* @param vecBF body frame
* @param vecEF earth frame
* @param q
*/
void BodyFrameToEarthFrame(const float *vecBF, float *vecEF, float *q);
/**
* @brief
*
* @param vecEF
* @param vecBF
* @param q
*/
void EarthFrameToBodyFrame(const float *vecEF, float *vecBF, float *q);
#endif

View File

@ -1,5 +1,8 @@
#include "dji_motor.h"
#define PI2 3.141592f
#define ECD_ANGLE_COEF 3.835e-4 // ecd/8192*pi
static uint8_t idx = 0; // register idx,是该文件的全局电机索引,在注册时使用
/* DJI电机的实例,此处仅保存指针,内存的分配将通过电机实例初始化时通过malloc()进行 */
@ -33,7 +36,7 @@ static uint8_t sender_enable_flag[6] = {0};
* @brief id冲突时,ID
* @todo segger jlink
*/
static void IDcrash_Handler()
static void IDcrash_Handler(uint8_t conflict_motor_idx, uint8_t temp_motor_idx)
{
while (1)
{
@ -67,7 +70,7 @@ static void MotorSenderGrouping(can_instance_config *config)
}
// 计算接收id并设置分组发送id
config->rx_id = 0x200 + motor_id+1;
config->rx_id = 0x200 + motor_id + 1;
sender_enable_flag[motor_grouping] = 1;
dji_motor_info[idx]->message_num = motor_send_num;
dji_motor_info[idx]->sender_group = motor_grouping;
@ -76,7 +79,7 @@ static void MotorSenderGrouping(can_instance_config *config)
for (size_t i = 0; i < idx; i++)
{
if (dji_motor_info[i]->motor_can_instance.can_handle == config->can_handle && dji_motor_info[i]->motor_can_instance.rx_id == config->rx_id)
IDcrash_Handler();
IDcrash_Handler(i, idx);
}
break;
@ -100,7 +103,7 @@ static void MotorSenderGrouping(can_instance_config *config)
for (size_t i = 0; i < idx; i++)
{
if (dji_motor_info[i]->motor_can_instance.can_handle == config->can_handle && dji_motor_info[i]->motor_can_instance.rx_id == config->rx_id)
IDcrash_Handler();
IDcrash_Handler(i, idx);
}
break;
@ -110,22 +113,33 @@ static void MotorSenderGrouping(can_instance_config *config)
}
/**
* @todo
* @brief can_instance对反馈报文进行解析
*
* @param _instance instance,
*/
static void DecodeDJIMotor(can_instance *_instance)
{
uint8_t *rxbuff = _instance->rx_buff;
static uint8_t *rxbuff;
static dji_motor_measure *measure;
for (size_t i = 0; i < DJI_MOTOR_CNT; i++)
{
if (&dji_motor_info[i]->motor_can_instance == _instance)
{
dji_motor_info[i]->motor_measure.last_ecd = dji_motor_info[i]->motor_measure.ecd;
dji_motor_info[i]->motor_measure.ecd = (uint16_t)(rxbuff[0] << 8 | rxbuff[1]);
dji_motor_info[i]->motor_measure.speed_rpm = (uint16_t)(rxbuff[2] << 8 | rxbuff[3]);
dji_motor_info[i]->motor_measure.given_current = (uint16_t)(rxbuff[4] << 8 | rxbuff[5]);
dji_motor_info[i]->motor_measure.temperate = rxbuff[6];
rxbuff = _instance->rx_buff;
measure = &dji_motor_info[i]->motor_measure;
// resolve data and apply filter to current and speed
measure->last_ecd = measure->ecd;
measure->ecd = (uint16_t)(rxbuff[0] << 8 | rxbuff[1]);
measure->speed_rpm = (1 - SPEED_SMOOTH_COEF) * measure->speed_rpm + SPEED_SMOOTH_COEF * (int16_t)(rxbuff[2] << 8 | rxbuff[3]);
measure->given_current = (1 - CURRENT_SMOOTH_COEF) * measure->given_current + CURRENT_SMOOTH_COEF * (uint16_t)(rxbuff[4] << 8 | rxbuff[5]);
measure->temperate = rxbuff[6];
// multi round calc
if (measure->ecd - measure->last_ecd > 4096)
measure->total_round--;
else if (measure->ecd - measure->last_ecd < -4096)
measure->total_round++;
measure->total_angle = measure->total_round * PI2 + measure->ecd * ECD_ANGLE_COEF; // @todo simplify the calculation
break;
}
}
@ -138,6 +152,7 @@ dji_motor_instance *DJIMotorInit(can_instance_config can_config,
Motor_Type_e type)
{
dji_motor_info[idx] = (dji_motor_instance *)malloc(sizeof(dji_motor_instance));
memset(dji_motor_info[idx], 0, sizeof(dji_motor_instance));
// motor basic setting
dji_motor_info[idx]->motor_type = type;
@ -159,15 +174,15 @@ dji_motor_instance *DJIMotorInit(can_instance_config can_config,
}
// 改变反馈来源
void DJIMotorChangeFeed(dji_motor_instance *motor,Closeloop_Type_e loop,Feedback_Source_e type)
void DJIMotorChangeFeed(dji_motor_instance *motor, Closeloop_Type_e loop, Feedback_Source_e type)
{
if(loop==ANGLE_LOOP)
if (loop == ANGLE_LOOP)
{
motor->motor_settings.angle_feedback_source=type;
motor->motor_settings.angle_feedback_source = type;
}
if(loop==SPEED_LOOP)
if (loop == SPEED_LOOP)
{
motor->motor_settings.speed_feedback_source=type;
motor->motor_settings.speed_feedback_source = type;
}
}
@ -176,14 +191,13 @@ void DJIMotorSetRef(dji_motor_instance *motor, float ref)
{
motor->motor_controller.pid_ref = ref;
}
// 计算三环PID,发送控制报文
void DJIMotorControl()
{
{
// 预先通过静态变量定义避免反复释放分配栈空间,直接保存一次指针引用从而减小访存的开销
static uint8_t group, num;
static int16_t set;
static dji_motor_instance* motor;
static dji_motor_instance *motor;
static Motor_Control_Setting_s *motor_setting;
static Motor_Controller_s *motor_controller;
static dji_motor_measure *motor_measure;
@ -193,33 +207,33 @@ void DJIMotorControl()
{
if (dji_motor_info[i])
{
motor=dji_motor_info[i];
motor_setting=&motor->motor_settings;
motor_controller=&motor->motor_controller;
motor_measure=&motor->motor_measure;
motor = dji_motor_info[i];
motor_setting = &motor->motor_settings;
motor_controller = &motor->motor_controller;
motor_measure = &motor->motor_measure;
if (motor_setting->close_loop_type & ANGLE_LOOP) // 计算位置环
{
if (motor_setting->angle_feedback_source == OTHER_FEED)
pid_measure=*motor_controller->other_angle_feedback_ptr;
pid_measure = *motor_controller->other_angle_feedback_ptr;
else // MOTOR_FEED
pid_measure=motor_measure->total_angle;
pid_measure = motor_measure->total_angle;
// 更新pid_ref进入下一个环
motor_controller->pid_ref=PID_Calculate(&motor_controller->angle_PID,pid_measure,motor_controller->pid_ref);
motor_controller->pid_ref = PID_Calculate(&motor_controller->angle_PID, pid_measure, motor_controller->pid_ref);
}
if (motor_setting->close_loop_type & SPEED_LOOP) // 计算速度环
{
if (motor_setting->speed_feedback_source == OTHER_FEED)
pid_measure=*motor_controller->other_speed_feedback_ptr;
pid_measure = *motor_controller->other_speed_feedback_ptr;
else
pid_measure=motor_measure->speed_rpm;
motor_controller->pid_ref=PID_Calculate(&motor_controller->speed_PID,pid_measure,motor_controller->pid_ref);
pid_measure = motor_measure->speed_rpm;
motor_controller->pid_ref = PID_Calculate(&motor_controller->speed_PID, pid_measure, motor_controller->pid_ref);
}
if (motor_setting->close_loop_type & CURRENT_LOOP) //计算电流环
{
motor_controller->pid_ref=PID_Calculate(&motor_controller->current_PID,motor_measure->given_current,motor_controller->pid_ref);
motor_controller->pid_ref = PID_Calculate(&motor_controller->current_PID, motor_measure->given_current, motor_controller->pid_ref);
}
set = (int16_t)motor_controller->pid_ref;
@ -230,7 +244,7 @@ void DJIMotorControl()
group = motor->sender_group;
num = motor->message_num;
sender_assignment[group].tx_buff[num] = 0xff & set >> 8;
sender_assignment[group].tx_buff[num+1] = 0xff & set;
sender_assignment[group].tx_buff[num + 1] = 0xff & set;
}
else // 遇到空指针说明所有遍历结束,退出循环
break;

View File

@ -1,7 +1,20 @@
/**
* @file dji_motor.h
* @author neozng
* @brief DJI智能电机头文件
* @version 0.1
* @date 2022-11-01
*
* @copyright Copyright (c) 2022 HNU YueLu EC all rights reserved
*
*/
#ifndef DJI_MOTOR_H
#define DJI_MOTOR_H
#define DJI_MOTOR_CNT 12
#define SPEED_SMOOTH_COEF 0.85f // better to be greater than 0.8
#define CURRENT_SMOOTH_COEF 0.98f // this coef must be greater than 0.95
#include "bsp_can.h"
#include "controller.h"
@ -45,7 +58,6 @@ typedef struct
} dji_motor_instance;
/**
* @brief DJI智能电机,,application初始化的时候调用此函数
* initStructure然后传入此函数.
@ -55,20 +67,20 @@ typedef struct
* ....};
* 线(6),,(500Hz),
* DJIMotorControl().
*
*
* @attention M3508和M2006的反馈报文都是0x200+id,GM6020的反馈是0x204+id,id不要冲突.
* ,IDcrash_Handler(),debug来判断是否出现冲突.
*
*
* @param config can设置,DJI电机仅需要将tx_id设置为电调闪动次数(c620,615,610)(GM6020)
* id,!
*
*
* @param motor_setting ,,使
*
*
* @param controller_init ,PID的参数.
* ,NULL即可
*
*
* @param type ,m2006,m3508和gm6020
*
*
* @return dji_motor_instance* ,便,DJIMotorSetRef()
*/
dji_motor_instance *DJIMotorInit(can_instance_config config,
@ -76,32 +88,28 @@ dji_motor_instance *DJIMotorInit(can_instance_config config,
Motor_Controller_Init_s controller_init,
Motor_Type_e type);
/**
* @brief application层的应用调用,.
* ,1,
*
*
* @param motor
* @param ref
*/
void DJIMotorSetRef(dji_motor_instance *motor, float ref);
/**
* @brief ,IMU()
*
*
* @param motor
* @param loop
* @param type
*/
void DJIMotorChangeFeed(dji_motor_instance *motor,Closeloop_Type_e loop,Feedback_Source_e type);
void DJIMotorChangeFeed(dji_motor_instance *motor, Closeloop_Type_e loop, Feedback_Source_e type);
/**
* @brief motor_task调用运行在rtos上,motor_stask内通过osDelay()
* @todo
* @todo
*/
void DJIMotorControl();
#endif // !DJI_MOTOR_H

View File

@ -1,6 +1,21 @@
/**
* @file motor_def.h
* @author neozng
* @brief
* @version beta
* @date 2022-11-01
*
* @copyright Copyright (c) 2022 HNU YueLu EC all rights reserved
*
*/
#ifndef MOTOR_DEF_H
#define MOTOR_DEF_H
/**
* @brief ,,使
* : CURRENT_LOOP|SPEED_LOOP
*/
typedef enum
{
CURRENT_LOOP = 0b0001,
@ -13,18 +28,21 @@ typedef enum
___ = 0b0111
} Closeloop_Type_e;
/* 反馈来源设定,若设为OTHER_FEED则需要指定数据来源指针,详见Motor_Controller_s*/
typedef enum
{
MOTOR_FEED = 0,
OTHER_FEED = 1
} Feedback_Source_e;
/* 电机正反转标志 */
typedef enum
{
MOTOR_DIRECTION_NORMAL = 0,
MOTOR_DIRECTION_REVERSE = 1
} Reverse_Flag_e;
/* 电机控制设置,包括闭环类型,反转标志和反馈来源 */
typedef struct
{
Closeloop_Type_e close_loop_type;
@ -34,6 +52,7 @@ typedef struct
} Motor_Control_Setting_s;
/* 电机控制器,包括其他来源的反馈数据指针,3环控制器和电机的参考输入*/
typedef struct
{
float *other_angle_feedback_ptr;
@ -43,10 +62,10 @@ typedef struct
PID_t speed_PID;
PID_t angle_PID;
// 将会作为每个环的输入和输出
float pid_ref;
float pid_ref; // 将会作为每个环的输入和输出顺次通过串级闭环
} Motor_Controller_s;
/* 电机类型枚举 */
typedef enum
{
GM6020 = 0,
@ -56,6 +75,11 @@ typedef enum
HT04 = 4
} Motor_Type_e;
/**
* @brief ,PID的配置以及两个反馈数据来源指针
* ,pid config
* ,Motor_Control_Setting_s启用其他数据来源标志
*/
typedef struct
{
float *other_angle_feedback_ptr;

View File

@ -1,3 +1,13 @@
/**
* @file motor_task.h
* @author neozng
* @brief ,,MotorControlTask()
* @version beta
* @date 2022-11-01
*
* @copyright Copyright (c) 2022
*
*/
#ifndef MOTOR_TASK_H
#define MOTOR_TASK_H

View File

@ -2,90 +2,19 @@
#include "string.h"
#include "bsp_usart.h"
#define RC_CHANNAL_ERROR_VALUE 700
#define REMOTE_CONTROL_FRAME_SIZE 18u
#define RC_abs(x) (x)>0?(x):(-x)
#define RC_USART_SERVICE_ID 1
#define REMOTE_CONTROL_FRAME_SIZE 18u // 遥控器接收的buffer大小
//remote control data
// 遥控器数据
static RC_ctrl_t rc_ctrl;
// 遥控器拥有的串口实例
static usart_instance rc_usart_instance;
/**
* @brief remote control protocol resolution
* @param[in] sbus_buf: raw data point
* @param[out] rc_ctrl: remote control data struct point
* @retval none
*/
static void sbus_to_rc(volatile const uint8_t *sbus_buf, RC_ctrl_t *rc_ctrl);
/**
* @brief protocol resolve callback
* this func would be called when usart3 idle interrupt happens
*
* @brief remote control protocol resolution
* @param[in] sbus_buf: raw data point
* @param[out] rc_ctrl: remote control data struct point
* @retval none
*/
static void ReceiveCallback()
{
sbus_to_rc(rc_usart_instance.recv_buff,&rc_ctrl);
}
void RC_init(UART_HandleTypeDef* rc_usart_handle)
{
rc_usart_instance.module_callback=ReceiveCallback;
rc_usart_instance.usart_handle=rc_usart_handle;
rc_usart_instance.recv_buff_size=REMOTE_CONTROL_FRAME_SIZE;
USARTRegister(&rc_usart_instance);
}
const RC_ctrl_t *get_remote_control_point(void)
{
return &rc_ctrl;
}
uint8_t RC_data_is_error(void)
{
if (RC_abs(rc_ctrl.rc.ch[0]) > RC_CHANNAL_ERROR_VALUE)
{
goto error;
}
if (RC_abs(rc_ctrl.rc.ch[1]) > RC_CHANNAL_ERROR_VALUE)
{
goto error;
}
if (RC_abs(rc_ctrl.rc.ch[2]) > RC_CHANNAL_ERROR_VALUE)
{
goto error;
}
if (RC_abs(rc_ctrl.rc.ch[3]) > RC_CHANNAL_ERROR_VALUE)
{
goto error;
}
if (rc_ctrl.rc.s[0] == 0)
{
goto error;
}
if (rc_ctrl.rc.s[1] == 0)
{
goto error;
}
return 0;
error:
rc_ctrl.rc.ch[0] = 0;
rc_ctrl.rc.ch[1] = 0;
rc_ctrl.rc.ch[2] = 0;
rc_ctrl.rc.ch[3] = 0;
rc_ctrl.rc.ch[4] = 0;
rc_ctrl.rc.s[0] = RC_SW_DOWN;
rc_ctrl.rc.s[1] = RC_SW_DOWN;
rc_ctrl.mouse.x = 0;
rc_ctrl.mouse.y = 0;
rc_ctrl.mouse.z = 0;
rc_ctrl.mouse.press_l = 0;
rc_ctrl.mouse.press_r = 0;
rc_ctrl.key.v = 0;
return 1;
}
static void sbus_to_rc(volatile const uint8_t *sbus_buf, RC_ctrl_t *rc_ctrl)
{
if (sbus_buf == NULL || rc_ctrl == NULL)
@ -95,17 +24,18 @@ static void sbus_to_rc(volatile const uint8_t *sbus_buf, RC_ctrl_t *rc_ctrl)
rc_ctrl->rc.ch[0] = (sbus_buf[0] | (sbus_buf[1] << 8)) & 0x07ff; //!< Channel 0
rc_ctrl->rc.ch[1] = ((sbus_buf[1] >> 3) | (sbus_buf[2] << 5)) & 0x07ff; //!< Channel 1
rc_ctrl->rc.ch[2] = ((sbus_buf[2] >> 6) | (sbus_buf[3] << 2) | //!< Channel 2
(sbus_buf[4] << 10)) &0x07ff;
(sbus_buf[4] << 10)) &
0x07ff;
rc_ctrl->rc.ch[3] = ((sbus_buf[4] >> 1) | (sbus_buf[5] << 7)) & 0x07ff; //!< Channel 3
rc_ctrl->rc.s[0] = ((sbus_buf[5] >> 4) & 0x0003); //!< Switch left
rc_ctrl->rc.s[1] = ((sbus_buf[5] >> 4) & 0x000C) >> 2; //!< Switch right
rc_ctrl->rc.s[0] = ((sbus_buf[5] >> 4) & 0x0003); //!< Switch left
rc_ctrl->rc.s[1] = ((sbus_buf[5] >> 4) & 0x000C) >> 2; //!< Switch right
rc_ctrl->mouse.x = sbus_buf[6] | (sbus_buf[7] << 8); //!< Mouse X axis
rc_ctrl->mouse.y = sbus_buf[8] | (sbus_buf[9] << 8); //!< Mouse Y axis
rc_ctrl->mouse.z = sbus_buf[10] | (sbus_buf[11] << 8); //!< Mouse Z axis
rc_ctrl->mouse.press_l = sbus_buf[12]; //!< Mouse Left Is Press ?
rc_ctrl->mouse.press_r = sbus_buf[13]; //!< Mouse Right Is Press ?
rc_ctrl->key.v = sbus_buf[14] | (sbus_buf[15] << 8); //!< KeyBoard value
rc_ctrl->rc.ch[4] = sbus_buf[16] | (sbus_buf[17] << 8); //NULL
rc_ctrl->rc.ch[4] = sbus_buf[16] | (sbus_buf[17] << 8); // NULL
rc_ctrl->rc.ch[0] -= RC_CH_VALUE_OFFSET;
rc_ctrl->rc.ch[1] -= RC_CH_VALUE_OFFSET;
@ -114,3 +44,26 @@ static void sbus_to_rc(volatile const uint8_t *sbus_buf, RC_ctrl_t *rc_ctrl)
rc_ctrl->rc.ch[4] -= RC_CH_VALUE_OFFSET;
}
/**
* @brief protocol resolve callback
* this func would be called when usart3 idle interrupt happens
* sbus_to_rc的简单封装
*
*/
static void ReceiveCallback()
{
sbus_to_rc(rc_usart_instance.recv_buff, &rc_ctrl);
}
void RC_init(UART_HandleTypeDef *rc_usart_handle)
{
rc_usart_instance.module_callback = ReceiveCallback;
rc_usart_instance.usart_handle = rc_usart_handle;
rc_usart_instance.recv_buff_size = REMOTE_CONTROL_FRAME_SIZE;
USARTRegister(&rc_usart_instance);
}
const RC_ctrl_t *get_remote_control_point(void)
{
return &rc_ctrl;
}

View File

@ -1,98 +1,91 @@
/**
****************************(C) COPYRIGHT 2016 DJI****************************
* @file remote_control.c/h
* @brief SBUS的协议传输DMA传输方式节约CPU
* 线DMA
*
* @note
* @history
* Version Date Author Modification
* V1.0.0 Dec-26-2018 RM 1. done
* V1.0.0 Nov-11-2019 RM 1. support development board tpye c
*
@verbatim
==============================================================================
==============================================================================
@endverbatim
****************************(C) COPYRIGHT 2016 DJI****************************
*/
* @file remote_control.h
* @author DJI 2016
* @author modified by neozng
* @brief
* @version beta
* @date 2022-11-01
*
* @copyright Copyright (c) 2016 DJI corp
* @copyright Copyright (c) 2022 HNU YueLu EC all rights reserved
*
*/
#ifndef REMOTE_CONTROL_H
#define REMOTE_CONTROL_H
#include "struct_typedef.h"
#include "main.h"
#define RC_CH_VALUE_MIN ((uint16_t)364)
#define RC_CH_VALUE_OFFSET ((uint16_t)1024)
#define RC_CH_VALUE_MAX ((uint16_t)1684)
#define RC_CH_VALUE_MIN ((uint16_t)364)
#define RC_CH_VALUE_OFFSET ((uint16_t)1024)
#define RC_CH_VALUE_MAX ((uint16_t)1684)
/* ----------------------- RC Switch Definition----------------------------- */
#define RC_SW_UP ((uint16_t)1)
#define RC_SW_MID ((uint16_t)3)
#define RC_SW_DOWN ((uint16_t)2)
#define switch_is_down(s) (s == RC_SW_DOWN)
#define switch_is_mid(s) (s == RC_SW_MID)
#define switch_is_up(s) (s == RC_SW_UP)
#define RC_SW_UP ((uint16_t)1)
#define RC_SW_MID ((uint16_t)3)
#define RC_SW_DOWN ((uint16_t)2)
#define switch_is_down(s) (s == RC_SW_DOWN)
#define switch_is_mid(s) (s == RC_SW_MID)
#define switch_is_up(s) (s == RC_SW_UP)
/* ----------------------- PC Key Definition-------------------------------- */
#define KEY_PRESSED_OFFSET_W ((uint16_t)1 << 0)
#define KEY_PRESSED_OFFSET_S ((uint16_t)1 << 1)
#define KEY_PRESSED_OFFSET_A ((uint16_t)1 << 2)
#define KEY_PRESSED_OFFSET_D ((uint16_t)1 << 3)
#define KEY_PRESSED_OFFSET_SHIFT ((uint16_t)1 << 4)
#define KEY_PRESSED_OFFSET_CTRL ((uint16_t)1 << 5)
#define KEY_PRESSED_OFFSET_E ((uint16_t)1 << 7)
#define KEY_PRESSED_OFFSET_Q ((uint16_t)1 << 6)
#define KEY_PRESSED_OFFSET_R ((uint16_t)1 << 8)
#define KEY_PRESSED_OFFSET_F ((uint16_t)1 << 9)
#define KEY_PRESSED_OFFSET_G ((uint16_t)1 << 10)
#define KEY_PRESSED_OFFSET_Z ((uint16_t)1 << 11)
#define KEY_PRESSED_OFFSET_X ((uint16_t)1 << 12)
#define KEY_PRESSED_OFFSET_C ((uint16_t)1 << 13)
#define KEY_PRESSED_OFFSET_V ((uint16_t)1 << 14)
#define KEY_PRESSED_OFFSET_B ((uint16_t)1 << 15)
#define KEY_PRESSED_OFFSET_W ((uint16_t)1 << 0)
#define KEY_PRESSED_OFFSET_S ((uint16_t)1 << 1)
#define KEY_PRESSED_OFFSET_A ((uint16_t)1 << 2)
#define KEY_PRESSED_OFFSET_D ((uint16_t)1 << 3)
#define KEY_PRESSED_OFFSET_SHIFT ((uint16_t)1 << 4)
#define KEY_PRESSED_OFFSET_CTRL ((uint16_t)1 << 5)
#define KEY_PRESSED_OFFSET_E ((uint16_t)1 << 7)
#define KEY_PRESSED_OFFSET_Q ((uint16_t)1 << 6)
#define KEY_PRESSED_OFFSET_R ((uint16_t)1 << 8)
#define KEY_PRESSED_OFFSET_F ((uint16_t)1 << 9)
#define KEY_PRESSED_OFFSET_G ((uint16_t)1 << 10)
#define KEY_PRESSED_OFFSET_Z ((uint16_t)1 << 11)
#define KEY_PRESSED_OFFSET_X ((uint16_t)1 << 12)
#define KEY_PRESSED_OFFSET_C ((uint16_t)1 << 13)
#define KEY_PRESSED_OFFSET_V ((uint16_t)1 << 14)
#define KEY_PRESSED_OFFSET_B ((uint16_t)1 << 15)
/* ----------------------- Data Struct ------------------------------------- */
typedef struct
{
struct
{
int16_t ch[5];
char s[2];
} rc;
struct
{
int16_t x;
int16_t y;
int16_t z;
uint8_t press_l;
uint8_t press_r;
} mouse;
struct
{
uint16_t v;
} key;
struct
{
int16_t ch[5];
char s[2];
} rc;
struct
{
int16_t x;
int16_t y;
int16_t z;
uint8_t press_l;
uint8_t press_r;
} mouse;
struct
{
uint16_t v;
} key;
} RC_ctrl_t;
/* ----------------------- Internal Data ----------------------------------- */
/* ------------------------- Internal Data ----------------------------------- */
/**
* @brief register remote control into usart_serive
*
* @attention remember to assign the correct handler
*
* @brief ,
*
* @attention ,C板上使用USART3
*
*/
void RC_init(UART_HandleTypeDef* rc_usart_handle);
void RC_init(UART_HandleTypeDef *rc_usart_handle);
/**
* @brief Get the remote control point object,then you can access data
*
* @return const RC_ctrl_t*
* @brief
*
* @return const RC_ctrl_t*
*/
extern const RC_ctrl_t *get_remote_control_point(void);
/**
* @brief check whether there is an error in rc data
*
* @return uint8_t
* @brief
*
* @return uint8_t
*/
extern uint8_t RC_data_is_error(void);