加入底盘,屏幕能亮了
This commit is contained in:
parent
e4908c41b3
commit
a708f48a59
@ -55,6 +55,10 @@ target_sources(${CMAKE_PROJECT_NAME} PRIVATE
|
||||
./User/bsp/time.c
|
||||
./User/component/user_math.c
|
||||
./User/module/config.c
|
||||
./User/task/init.c
|
||||
./User/task/display.c
|
||||
./User/task/user_task.c
|
||||
|
||||
|
||||
|
||||
./User/LCD/lcd.c
|
||||
@ -64,6 +68,7 @@ target_sources(${CMAKE_PROJECT_NAME} PRIVATE
|
||||
./User/LCD/touch.c
|
||||
./User/lvgl/examples/porting/lv_port_disp_template.c
|
||||
./User/lvgl/examples/porting/lv_port_indev_template.c
|
||||
./User/lvgl/stress/lv_demo_stress.c
|
||||
${LVGL_C}
|
||||
|
||||
|
||||
|
||||
@ -96,7 +96,7 @@
|
||||
* (when HSE is used as system clock source, directly or through the PLL).
|
||||
*/
|
||||
#if !defined (HSE_VALUE)
|
||||
#define HSE_VALUE 25000000U /*!< Value of the External oscillator in Hz */
|
||||
#define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */
|
||||
#endif /* HSE_VALUE */
|
||||
|
||||
#if !defined (HSE_STARTUP_TIMEOUT)
|
||||
|
||||
@ -56,6 +56,7 @@ void CAN1_RX0_IRQHandler(void);
|
||||
void CAN1_RX1_IRQHandler(void);
|
||||
void USART1_IRQHandler(void);
|
||||
void TIM8_TRG_COM_TIM14_IRQHandler(void);
|
||||
void DMA2_Stream0_IRQHandler(void);
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
@ -64,6 +64,11 @@ void MX_DMA_Init(void)
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/* DMA interrupt init */
|
||||
/* DMA2_Stream0_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
|
||||
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 2 */
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
#include "task/user_task.h"
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
@ -96,6 +97,7 @@ void MX_FREERTOS_Init(void) {
|
||||
|
||||
/* USER CODE BEGIN RTOS_THREADS */
|
||||
/* add threads, ... */
|
||||
osThreadNew(Task_Init, NULL, &attr_init); // 创建初始化任务
|
||||
/* USER CODE END RTOS_THREADS */
|
||||
|
||||
/* USER CODE BEGIN RTOS_EVENTS */
|
||||
@ -114,11 +116,7 @@ void MX_FREERTOS_Init(void) {
|
||||
void StartDefaultTask(void *argument)
|
||||
{
|
||||
/* USER CODE BEGIN StartDefaultTask */
|
||||
/* Infinite loop */
|
||||
for(;;)
|
||||
{
|
||||
osDelay(1);
|
||||
}
|
||||
osThreadTerminate(osThreadGetId());
|
||||
/* USER CODE END StartDefaultTask */
|
||||
}
|
||||
|
||||
|
||||
@ -42,12 +42,25 @@
|
||||
void MX_GPIO_Init(void)
|
||||
{
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
|
||||
/* GPIO Ports Clock Enable */
|
||||
__HAL_RCC_GPIOH_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOE_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
|
||||
|
||||
/*Configure GPIO pin : PB0 */
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_0;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 2 */
|
||||
|
||||
@ -141,8 +141,8 @@ void SystemClock_Config(void)
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||||
RCC_OscInitStruct.PLL.PLLM = 25;
|
||||
RCC_OscInitStruct.PLL.PLLN = 336;
|
||||
RCC_OscInitStruct.PLL.PLLM = 4;
|
||||
RCC_OscInitStruct.PLL.PLLN = 168;
|
||||
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
|
||||
RCC_OscInitStruct.PLL.PLLQ = 4;
|
||||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
|
||||
|
||||
@ -60,6 +60,7 @@ void SysTick_Port (void);
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
extern CAN_HandleTypeDef hcan1;
|
||||
extern DMA_HandleTypeDef hdma_memtomem_dma2_stream0;
|
||||
extern UART_HandleTypeDef huart1;
|
||||
extern TIM_HandleTypeDef htim14;
|
||||
|
||||
@ -221,6 +222,20 @@ void TIM8_TRG_COM_TIM14_IRQHandler(void)
|
||||
/* USER CODE END TIM8_TRG_COM_TIM14_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles DMA2 stream0 global interrupt.
|
||||
*/
|
||||
void DMA2_Stream0_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN DMA2_Stream0_IRQn 0 */
|
||||
|
||||
/* USER CODE END DMA2_Stream0_IRQn 0 */
|
||||
HAL_DMA_IRQHandler(&hdma_memtomem_dma2_stream0);
|
||||
/* USER CODE BEGIN DMA2_Stream0_IRQn 1 */
|
||||
|
||||
/* USER CODE END DMA2_Stream0_IRQn 1 */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
|
||||
@ -604,68 +604,77 @@ void lcd_set_window(uint16_t sx, uint16_t sy, uint16_t width, uint16_t height)
|
||||
* @param 无
|
||||
* @retval 无
|
||||
*/
|
||||
void lcd_init(void)
|
||||
|
||||
__weak void lcd_init(void)
|
||||
{
|
||||
GPIO_InitTypeDef gpio_init_struct;
|
||||
FSMC_NORSRAM_TimingTypeDef fsmc_read_handle;
|
||||
FSMC_NORSRAM_TimingTypeDef fsmc_write_handle;
|
||||
|
||||
LCD_CS_GPIO_CLK_ENABLE(); /* LCD_CS脚时钟使能 */
|
||||
LCD_WR_GPIO_CLK_ENABLE(); /* LCD_WR脚时钟使能 */
|
||||
LCD_RD_GPIO_CLK_ENABLE(); /* LCD_RD脚时钟使能 */
|
||||
LCD_RS_GPIO_CLK_ENABLE(); /* LCD_RS脚时钟使能 */
|
||||
LCD_BL_GPIO_CLK_ENABLE(); /* LCD_BL脚时钟使能 */
|
||||
// lcddev.id =0x7789;
|
||||
// lcd_ex_st7789_reginit();
|
||||
// lcd_display_dir(1);
|
||||
// LCD_BL(1);
|
||||
// lcd_clear(WHITE);
|
||||
// return;
|
||||
|
||||
gpio_init_struct.Pin = LCD_CS_GPIO_PIN;
|
||||
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 推挽复用 */
|
||||
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
|
||||
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
|
||||
gpio_init_struct.Alternate = GPIO_AF12_FSMC; /* 复用为FSMC */
|
||||
HAL_GPIO_Init(LCD_CS_GPIO_PORT, &gpio_init_struct); /* 初始化LCD_CS引脚 */
|
||||
|
||||
gpio_init_struct.Pin = LCD_WR_GPIO_PIN;
|
||||
HAL_GPIO_Init(LCD_WR_GPIO_PORT, &gpio_init_struct); /* 初始化LCD_WR引脚 */
|
||||
|
||||
gpio_init_struct.Pin = LCD_RD_GPIO_PIN;
|
||||
HAL_GPIO_Init(LCD_RD_GPIO_PORT, &gpio_init_struct); /* 初始化LCD_RD引脚 */
|
||||
|
||||
gpio_init_struct.Pin = LCD_RS_GPIO_PIN;
|
||||
HAL_GPIO_Init(LCD_RS_GPIO_PORT, &gpio_init_struct); /* 初始化LCD_RS引脚 */
|
||||
|
||||
gpio_init_struct.Pin = LCD_BL_GPIO_PIN;
|
||||
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
|
||||
HAL_GPIO_Init(LCD_BL_GPIO_PORT, &gpio_init_struct); /* LCD_BL引脚模式设置(推挽输出) */
|
||||
|
||||
g_sram_handle.Instance = FSMC_NORSRAM_DEVICE;
|
||||
g_sram_handle.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
|
||||
|
||||
g_sram_handle.Init.NSBank = FSMC_NORSRAM_BANK4; /* 使用NE4 */
|
||||
g_sram_handle.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE; /* 地址/数据线不复用 */
|
||||
g_sram_handle.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16; /* 16位数据宽度 */
|
||||
g_sram_handle.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE; /* 是否使能突发访问,仅对同步突发存储器有效,此处未用到 */
|
||||
g_sram_handle.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW; /* 等待信号的极性,仅在突发模式访问下有用 */
|
||||
g_sram_handle.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS; /* 存储器是在等待周期之前的一个时钟周期还是等待周期期间使能NWAIT */
|
||||
g_sram_handle.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE; /* 存储器写使能 */
|
||||
g_sram_handle.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE; /* 等待使能位,此处未用到 */
|
||||
g_sram_handle.Init.ExtendedMode = FSMC_EXTENDED_MODE_ENABLE; /* 读写使用不同的时序 */
|
||||
g_sram_handle.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE; /* 是否使能同步传输模式下的等待信号,此处未用到 */
|
||||
g_sram_handle.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE; /* 禁止突发写 */
|
||||
|
||||
/* FSMC读时序控制寄存器 */
|
||||
fsmc_read_handle.AddressSetupTime = 0x0F; /* 地址建立时间(ADDSET)为15个fsmc_ker_ck(1/168=6)即6*15=90ns */
|
||||
fsmc_read_handle.AddressHoldTime = 0x00; /* 地址保持时间(ADDHLD) 模式A是没有用到 */
|
||||
fsmc_read_handle.DataSetupTime = 60; /* 数据保存时间(DATAST)为60个fsmc_ker_ck=6*60=360ns */
|
||||
/* 因为液晶驱动IC的读数据的时候,速度不能太快,尤其是个别奇葩芯片 */
|
||||
fsmc_read_handle.AccessMode = FSMC_ACCESS_MODE_A; /* 模式A */
|
||||
|
||||
/* FSMC写时序控制寄存器 */
|
||||
fsmc_write_handle.AddressSetupTime = 9; /* 地址建立时间(ADDSET)为9个fsmc_ker_ck=6*9=54ns */
|
||||
fsmc_write_handle.AddressHoldTime = 0x00; /* 地址保持时间(ADDHLD) 模式A是没有用到 */
|
||||
fsmc_write_handle.DataSetupTime = 9; /* 数据保存时间(DATAST)为9个fsmc_ker_ck=6*9=54ns */
|
||||
/* 注意:某些液晶驱动IC的写信号脉宽,最少也得50ns */
|
||||
fsmc_write_handle.AccessMode = FSMC_ACCESS_MODE_A; /* 模式A */
|
||||
|
||||
HAL_SRAM_Init(&g_sram_handle, &fsmc_read_handle, &fsmc_write_handle);
|
||||
// GPIO_InitTypeDef gpio_init_struct;
|
||||
// FSMC_NORSRAM_TimingTypeDef fsmc_read_handle;
|
||||
// FSMC_NORSRAM_TimingTypeDef fsmc_write_handle;
|
||||
//
|
||||
// LCD_CS_GPIO_CLK_ENABLE(); /* LCD_CS脚时钟使能 */
|
||||
// LCD_WR_GPIO_CLK_ENABLE(); /* LCD_WR脚时钟使能 */
|
||||
// LCD_RD_GPIO_CLK_ENABLE(); /* LCD_RD脚时钟使能 */
|
||||
// LCD_RS_GPIO_CLK_ENABLE(); /* LCD_RS脚时钟使能 */
|
||||
// LCD_BL_GPIO_CLK_ENABLE(); /* LCD_BL脚时钟使能 */
|
||||
//
|
||||
// gpio_init_struct.Pin = LCD_CS_GPIO_PIN;
|
||||
// gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 推挽复用 */
|
||||
// gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
|
||||
// gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
|
||||
// gpio_init_struct.Alternate = GPIO_AF12_FSMC; /* 复用为FSMC */
|
||||
// HAL_GPIO_Init(LCD_CS_GPIO_PORT, &gpio_init_struct); /* 初始化LCD_CS引脚 */
|
||||
//
|
||||
// gpio_init_struct.Pin = LCD_WR_GPIO_PIN;
|
||||
// HAL_GPIO_Init(LCD_WR_GPIO_PORT, &gpio_init_struct); /* 初始化LCD_WR引脚 */
|
||||
//
|
||||
// gpio_init_struct.Pin = LCD_RD_GPIO_PIN;
|
||||
// HAL_GPIO_Init(LCD_RD_GPIO_PORT, &gpio_init_struct); /* 初始化LCD_RD引脚 */
|
||||
//
|
||||
// gpio_init_struct.Pin = LCD_RS_GPIO_PIN;
|
||||
// HAL_GPIO_Init(LCD_RS_GPIO_PORT, &gpio_init_struct); /* 初始化LCD_RS引脚 */
|
||||
//
|
||||
// gpio_init_struct.Pin = LCD_BL_GPIO_PIN;
|
||||
// gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
|
||||
// HAL_GPIO_Init(LCD_BL_GPIO_PORT, &gpio_init_struct); /* LCD_BL引脚模式设置(推挽输出) */
|
||||
//
|
||||
// g_sram_handle.Instance = FSMC_NORSRAM_DEVICE;
|
||||
// g_sram_handle.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
|
||||
//
|
||||
// g_sram_handle.Init.NSBank = FSMC_NORSRAM_BANK4; /* 使用NE4 */
|
||||
// g_sram_handle.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE; /* 地址/数据线不复用 */
|
||||
// g_sram_handle.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16; /* 16位数据宽度 */
|
||||
// g_sram_handle.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE; /* 是否使能突发访问,仅对同步突发存储器有效,此处未用到 */
|
||||
// g_sram_handle.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW; /* 等待信号的极性,仅在突发模式访问下有用 */
|
||||
// g_sram_handle.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS; /* 存储器是在等待周期之前的一个时钟周期还是等待周期期间使能NWAIT */
|
||||
// g_sram_handle.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE; /* 存储器写使能 */
|
||||
// g_sram_handle.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE; /* 等待使能位,此处未用到 */
|
||||
// g_sram_handle.Init.ExtendedMode = FSMC_EXTENDED_MODE_ENABLE; /* 读写使用不同的时序 */
|
||||
// g_sram_handle.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE; /* 是否使能同步传输模式下的等待信号,此处未用到 */
|
||||
// g_sram_handle.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE; /* 禁止突发写 */
|
||||
//
|
||||
// /* FSMC读时序控制寄存器 */
|
||||
// fsmc_read_handle.AddressSetupTime = 0x0F; /* 地址建立时间(ADDSET)为15个fsmc_ker_ck(1/168=6)即6*15=90ns */
|
||||
// fsmc_read_handle.AddressHoldTime = 0x00; /* 地址保持时间(ADDHLD) 模式A是没有用到 */
|
||||
// fsmc_read_handle.DataSetupTime = 60; /* 数据保存时间(DATAST)为60个fsmc_ker_ck=6*60=360ns */
|
||||
// /* 因为液晶驱动IC的读数据的时候,速度不能太快,尤其是个别奇葩芯片 */
|
||||
// fsmc_read_handle.AccessMode = FSMC_ACCESS_MODE_A; /* 模式A */
|
||||
//
|
||||
// /* FSMC写时序控制寄存器 */
|
||||
// fsmc_write_handle.AddressSetupTime = 9; /* 地址建立时间(ADDSET)为9个fsmc_ker_ck=6*9=54ns */
|
||||
// fsmc_write_handle.AddressHoldTime = 0x00; /* 地址保持时间(ADDHLD) 模式A是没有用到 */
|
||||
// fsmc_write_handle.DataSetupTime = 9; /* 数据保存时间(DATAST)为9个fsmc_ker_ck=6*9=54ns */
|
||||
// /* 注意:某些液晶驱动IC的写信号脉宽,最少也得50ns */
|
||||
// fsmc_write_handle.AccessMode = FSMC_ACCESS_MODE_A; /* 模式A */
|
||||
//
|
||||
// HAL_SRAM_Init(&g_sram_handle, &fsmc_read_handle, &fsmc_write_handle);
|
||||
delay_ms(50);
|
||||
|
||||
/* 尝试9341 ID的读取 */
|
||||
@ -786,21 +795,21 @@ void lcd_init(void)
|
||||
lcd_ssd_backlight_set(100); /* 背光设置为最亮 */
|
||||
}
|
||||
|
||||
/* 初始化完成以后,提速 */
|
||||
if (lcddev.id == 0x7789 || lcddev.id == 0x9341 || lcddev.id == 0x1963) /* 7789/9341/1963 提速 */
|
||||
{
|
||||
/* 重新配置写时序控制寄存器的时序 */
|
||||
fsmc_write_handle.AddressSetupTime = 3; /* 地址建立时间(ADDSET)为3个fsmc_ker_ck=6*3=18ns */
|
||||
fsmc_write_handle.DataSetupTime = 3; /* 数据保持时间(DATAST)为3个fsmc_ker_ck=6*3=18ns */
|
||||
FSMC_NORSRAM_Extended_Timing_Init(g_sram_handle.Extended, &fsmc_write_handle, g_sram_handle.Init.NSBank, g_sram_handle.Init.ExtendedMode);
|
||||
}
|
||||
else if (lcddev.id == 0x5310 || lcddev.id == 0x7796 || lcddev.id == 0x5510 || lcddev.id == 0x9806) /* 如果是这几个IC, 则设置WR时序为最快 */
|
||||
{
|
||||
/* 重新配置写时序控制寄存器的时序 */
|
||||
fsmc_write_handle.AddressSetupTime = 2; /* 地址建立时间(ADDSET)为2个fsmc_ker_ck=6*2=12ns */
|
||||
fsmc_write_handle.DataSetupTime = 2; /* 数据保持时间(DATAST)为2个fsmc_ker_ck=6*2=12ns */
|
||||
FSMC_NORSRAM_Extended_Timing_Init(g_sram_handle.Extended, &fsmc_write_handle, g_sram_handle.Init.NSBank, g_sram_handle.Init.ExtendedMode);
|
||||
}
|
||||
// /* 初始化完成以后,提速 */
|
||||
// if (lcddev.id == 0x7789 || lcddev.id == 0x9341 || lcddev.id == 0x1963) /* 7789/9341/1963 提速 */
|
||||
// {
|
||||
// /* 重新配置写时序控制寄存器的时序 */
|
||||
// fsmc_write_handle.AddressSetupTime = 3; /* 地址建立时间(ADDSET)为3个fsmc_ker_ck=6*3=18ns */
|
||||
// fsmc_write_handle.DataSetupTime = 3; /* 数据保持时间(DATAST)为3个fsmc_ker_ck=6*3=18ns */
|
||||
// FSMC_NORSRAM_Extended_Timing_Init(g_sram_handle.Extended, &fsmc_write_handle, g_sram_handle.Init.NSBank, g_sram_handle.Init.ExtendedMode);
|
||||
// }
|
||||
// else if (lcddev.id == 0x5310 || lcddev.id == 0x7796 || lcddev.id == 0x5510 || lcddev.id == 0x9806) /* 如果是这几个IC, 则设置WR时序为最快 */
|
||||
// {
|
||||
// /* 重新配置写时序控制寄存器的时序 */
|
||||
// fsmc_write_handle.AddressSetupTime = 2; /* 地址建立时间(ADDSET)为2个fsmc_ker_ck=6*2=12ns */
|
||||
// fsmc_write_handle.DataSetupTime = 2; /* 数据保持时间(DATAST)为2个fsmc_ker_ck=6*2=12ns */
|
||||
// FSMC_NORSRAM_Extended_Timing_Init(g_sram_handle.Extended, &fsmc_write_handle, g_sram_handle.Init.NSBank, g_sram_handle.Init.ExtendedMode);
|
||||
// }
|
||||
|
||||
lcd_display_dir(0); /* 默认为竖屏 */
|
||||
LCD_BL(1); /* 点亮背光 */
|
||||
|
||||
@ -71,8 +71,8 @@
|
||||
* 修改LCD_FSMC_NEX, 对应的LCD_CS_GPIO相关设置也得改
|
||||
* 修改LCD_FSMC_AX , 对应的LCD_RS_GPIO相关设置也得改
|
||||
*/
|
||||
#define LCD_FSMC_NEX 4 /* 使用FSMC_NE4接LCD_CS,取值范围只能是: 1~4 */
|
||||
#define LCD_FSMC_AX 6 /* 使用FSMC_A6接LCD_RS,取值范围是: 0 ~ 25 */
|
||||
#define LCD_FSMC_NEX 1 /* 使用FSMC_NE4接LCD_CS,取值范围只能是: 1~4 */
|
||||
#define LCD_FSMC_AX 16 /* 使用FSMC_A6接LCD_RS,取值范围是: 0 ~ 25 */
|
||||
|
||||
#define LCD_FSMC_BCRX FSMC_Bank1->BTCR[(LCD_FSMC_NEX - 1) * 2] /* BCR寄存器,根据LCD_FSMC_NEX自动计算 */
|
||||
#define LCD_FSMC_BTRX FSMC_Bank1->BTCR[(LCD_FSMC_NEX - 1) * 2 + 1] /* BTR寄存器,根据LCD_FSMC_NEX自动计算 */
|
||||
@ -101,8 +101,8 @@ extern uint32_t g_back_color; /* 背景颜色.默认为白色 */
|
||||
|
||||
/* LCD背光控制 */
|
||||
#define LCD_BL(x) do{ x ? \
|
||||
HAL_GPIO_WritePin(LCD_BL_GPIO_PORT, LCD_BL_GPIO_PIN, GPIO_PIN_SET) : \
|
||||
HAL_GPIO_WritePin(LCD_BL_GPIO_PORT, LCD_BL_GPIO_PIN, GPIO_PIN_RESET); \
|
||||
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0, GPIO_PIN_SET) : \
|
||||
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0, GPIO_PIN_RESET); \
|
||||
}while(0)
|
||||
|
||||
/* LCD地址结构体 */
|
||||
|
||||
@ -18,12 +18,12 @@
|
||||
*********************/
|
||||
#ifndef MY_DISP_HOR_RES
|
||||
#warning Please define or replace the macro MY_DISP_HOR_RES with the actual screen width, default value 320 is used for now.
|
||||
#define MY_DISP_HOR_RES 480
|
||||
#define MY_DISP_HOR_RES 320
|
||||
#endif
|
||||
|
||||
#ifndef MY_DISP_VER_RES
|
||||
#warning Please define or replace the macro MY_DISP_HOR_RES with the actual screen height, default value 240 is used for now.
|
||||
#define MY_DISP_VER_RES 320
|
||||
#define MY_DISP_VER_RES 240
|
||||
#endif
|
||||
|
||||
|
||||
@ -115,8 +115,8 @@ void lv_port_disp_init(void)
|
||||
|
||||
// /* Example for 2) */
|
||||
static lv_disp_draw_buf_t draw_buf_dsc_2;
|
||||
static lv_color_t buf_2_1[MY_DISP_HOR_RES * 40]; /*A buffer for 10 rows*/
|
||||
static lv_color_t buf_2_2[MY_DISP_HOR_RES * 40]; /*An other buffer for 10 rows*/
|
||||
static lv_color_t buf_2_1[MY_DISP_HOR_RES * 20]; /*A buffer for 10 rows*/
|
||||
static lv_color_t buf_2_2[MY_DISP_HOR_RES * 20]; /*An other buffer for 10 rows*/
|
||||
lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 40); /*Initialize the display buffer*/
|
||||
|
||||
// /* Example for 3) also set disp_drv.full_refresh = 1 below*/
|
||||
|
||||
@ -13,10 +13,10 @@ extern "C" {
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lvgl.h"
|
||||
#include "lvgl.h"
|
||||
|
||||
#if LV_USE_DEMO_WIDGETS
|
||||
#include "widgets/lv_demo_widgets.h"
|
||||
#include "lvgl/examples/lv_examples.h"
|
||||
#endif
|
||||
|
||||
#if LV_USE_DEMO_BENCHMARK
|
||||
|
||||
6
controler/User/task/config.yaml
Normal file
6
controler/User/task/config.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
- delay: 0
|
||||
description: ''
|
||||
freq_control: false
|
||||
function: Task_lvgl
|
||||
name: lvgl
|
||||
stack: 1024
|
||||
49
controler/User/task/display.c
Normal file
49
controler/User/task/display.c
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
lvgl Task
|
||||
|
||||
*/
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include "task/user_task.h"
|
||||
/* USER INCLUDE BEGIN */
|
||||
#include "lvgl/lvgl.h"
|
||||
#include "lvgl/stress/lv_demo_stress.h"
|
||||
#include "lvgl/examples/porting/lv_port_disp_template.h"
|
||||
#include "LCD/lcd.h"
|
||||
/* USER INCLUDE END */
|
||||
|
||||
/* Private typedef ---------------------------------------------------------- */
|
||||
/* Private define ----------------------------------------------------------- */
|
||||
/* Private macro ------------------------------------------------------------ */
|
||||
/* Private variables -------------------------------------------------------- */
|
||||
/* USER STRUCT BEGIN */
|
||||
|
||||
/* USER STRUCT END */
|
||||
|
||||
/* Private function --------------------------------------------------------- */
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void Task_lvgl(void *argument) {
|
||||
(void)argument; /* 未使用argument,消除警告 */
|
||||
|
||||
lcd_init();
|
||||
lv_init();
|
||||
|
||||
lv_port_disp_init();
|
||||
|
||||
lv_demo_stress();
|
||||
// osDelay(LVGL_INIT_DELAY); /* 延时一段时间再开启任务 */
|
||||
|
||||
/* USER CODE INIT BEGIN */
|
||||
|
||||
/* USER CODE INIT END */
|
||||
|
||||
while (1) {
|
||||
// lcd_fill(100, 100,200,200,RED);
|
||||
lv_task_handler();
|
||||
// lv_timer_handler();
|
||||
/* USER CODE BEGIN */
|
||||
|
||||
/* USER CODE END */
|
||||
}
|
||||
|
||||
}
|
||||
42
controler/User/task/init.c
Normal file
42
controler/User/task/init.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
Init Task
|
||||
任务初始化,创建各个线程任务和消息队列
|
||||
*/
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include "task/user_task.h"
|
||||
|
||||
/* USER INCLUDE BEGIN */
|
||||
|
||||
/* USER INCLUDE END */
|
||||
|
||||
/* Private typedef ---------------------------------------------------------- */
|
||||
/* Private define ----------------------------------------------------------- */
|
||||
/* Private macro ------------------------------------------------------------ */
|
||||
/* Private variables -------------------------------------------------------- */
|
||||
/* Private function --------------------------------------------------------- */
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* \brief 初始化
|
||||
*
|
||||
* \param argument 未使用
|
||||
*/
|
||||
void Task_Init(void *argument) {
|
||||
(void)argument; /* 未使用argument,消除警告 */
|
||||
/* USER CODE INIT BEGIN */
|
||||
|
||||
/* USER CODE INIT END */
|
||||
osKernelLock(); /* 锁定内核,防止任务切换 */
|
||||
|
||||
/* 创建任务线程 */
|
||||
task_runtime.thread.lvgl = osThreadNew(Task_lvgl, NULL, &attr_lvgl);
|
||||
|
||||
// 创建消息队列
|
||||
/* USER MESSAGE BEGIN */
|
||||
task_runtime.msgq.user_msg= osMessageQueueNew(2u, 10, NULL);
|
||||
/* USER MESSAGE END */
|
||||
|
||||
osKernelUnlock(); // 解锁内核
|
||||
osThreadTerminate(osThreadGetId()); // 任务完成后结束自身
|
||||
}
|
||||
16
controler/User/task/user_task.c
Normal file
16
controler/User/task/user_task.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include "task/user_task.h"
|
||||
|
||||
Task_Runtime_t task_runtime;
|
||||
|
||||
const osThreadAttr_t attr_init = {
|
||||
.name = "Task_Init",
|
||||
.priority = osPriorityRealtime,
|
||||
.stack_size = 256 * 4,
|
||||
};
|
||||
|
||||
/* User_task */
|
||||
const osThreadAttr_t attr_lvgl = {
|
||||
.name = "lvgl",
|
||||
.priority = osPriorityNormal,
|
||||
.stack_size = 1024 * 8,
|
||||
};
|
||||
80
controler/User/task/user_task.h
Normal file
80
controler/User/task/user_task.h
Normal file
@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include <cmsis_os2.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* USER INCLUDE BEGIN */
|
||||
|
||||
/* USER INCLUDE END */
|
||||
/* Exported constants ------------------------------------------------------- */
|
||||
/* 任务运行频率 */
|
||||
|
||||
|
||||
/* 任务初始化延时ms */
|
||||
#define TASK_INIT_DELAY (100u)
|
||||
#define LVGL_INIT_DELAY (0)
|
||||
|
||||
/* Exported defines --------------------------------------------------------- */
|
||||
/* Exported macro ----------------------------------------------------------- */
|
||||
/* Exported types ----------------------------------------------------------- */
|
||||
|
||||
/* 任务运行时结构体 */
|
||||
typedef struct {
|
||||
/* 各任务,也可以叫做线程 */
|
||||
struct {
|
||||
osThreadId_t lvgl;
|
||||
} thread;
|
||||
|
||||
/* USER MESSAGE BEGIN */
|
||||
struct {
|
||||
osMessageQueueId_t user_msg; /* 用户自定义任务消息队列 */
|
||||
} msgq;
|
||||
/* USER MESSAGE END */
|
||||
|
||||
/* 机器人状态 */
|
||||
struct {
|
||||
float battery; /* 电池电量百分比 */
|
||||
float vbat; /* 电池电压 */
|
||||
float cpu_temp; /* CPU温度 */
|
||||
} status;
|
||||
|
||||
/* USER CONFIG BEGIN */
|
||||
|
||||
/* USER CONFIG END */
|
||||
|
||||
/* 各任务的stack使用 */
|
||||
struct {
|
||||
UBaseType_t lvgl;
|
||||
} stack_water_mark;
|
||||
|
||||
/* 各任务运行频率 */
|
||||
struct {
|
||||
|
||||
} freq;
|
||||
|
||||
/* 任务最近运行时间 */
|
||||
struct {
|
||||
|
||||
} last_up_time;
|
||||
|
||||
} Task_Runtime_t;
|
||||
|
||||
/* 任务运行时结构体 */
|
||||
extern Task_Runtime_t task_runtime;
|
||||
|
||||
/* 初始化任务句柄 */
|
||||
extern const osThreadAttr_t attr_init;
|
||||
extern const osThreadAttr_t attr_lvgl;
|
||||
|
||||
/* 任务函数声明 */
|
||||
void Task_Init(void *argument);
|
||||
void Task_lvgl(void *argument);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -43,35 +43,36 @@ Mcu.Name=STM32F407V(E-G)Tx
|
||||
Mcu.Package=LQFP100
|
||||
Mcu.Pin0=PH0-OSC_IN
|
||||
Mcu.Pin1=PH1-OSC_OUT
|
||||
Mcu.Pin10=PE15
|
||||
Mcu.Pin11=PD8
|
||||
Mcu.Pin12=PD9
|
||||
Mcu.Pin13=PD10
|
||||
Mcu.Pin14=PD11
|
||||
Mcu.Pin15=PD14
|
||||
Mcu.Pin16=PD15
|
||||
Mcu.Pin17=PA9
|
||||
Mcu.Pin18=PA10
|
||||
Mcu.Pin19=PA11
|
||||
Mcu.Pin2=PE7
|
||||
Mcu.Pin20=PA12
|
||||
Mcu.Pin21=PA13
|
||||
Mcu.Pin22=PA14
|
||||
Mcu.Pin23=PD0
|
||||
Mcu.Pin24=PD1
|
||||
Mcu.Pin25=PD4
|
||||
Mcu.Pin26=PD5
|
||||
Mcu.Pin27=PD7
|
||||
Mcu.Pin28=VP_FREERTOS_VS_CMSIS_V2
|
||||
Mcu.Pin29=VP_SYS_VS_tim14
|
||||
Mcu.Pin3=PE8
|
||||
Mcu.Pin4=PE9
|
||||
Mcu.Pin5=PE10
|
||||
Mcu.Pin6=PE11
|
||||
Mcu.Pin7=PE12
|
||||
Mcu.Pin8=PE13
|
||||
Mcu.Pin9=PE14
|
||||
Mcu.PinsNb=30
|
||||
Mcu.Pin10=PE14
|
||||
Mcu.Pin11=PE15
|
||||
Mcu.Pin12=PD8
|
||||
Mcu.Pin13=PD9
|
||||
Mcu.Pin14=PD10
|
||||
Mcu.Pin15=PD11
|
||||
Mcu.Pin16=PD14
|
||||
Mcu.Pin17=PD15
|
||||
Mcu.Pin18=PA9
|
||||
Mcu.Pin19=PA10
|
||||
Mcu.Pin2=PB0
|
||||
Mcu.Pin20=PA11
|
||||
Mcu.Pin21=PA12
|
||||
Mcu.Pin22=PA13
|
||||
Mcu.Pin23=PA14
|
||||
Mcu.Pin24=PD0
|
||||
Mcu.Pin25=PD1
|
||||
Mcu.Pin26=PD4
|
||||
Mcu.Pin27=PD5
|
||||
Mcu.Pin28=PD7
|
||||
Mcu.Pin29=VP_FREERTOS_VS_CMSIS_V2
|
||||
Mcu.Pin3=PE7
|
||||
Mcu.Pin30=VP_SYS_VS_tim14
|
||||
Mcu.Pin4=PE8
|
||||
Mcu.Pin5=PE9
|
||||
Mcu.Pin6=PE10
|
||||
Mcu.Pin7=PE11
|
||||
Mcu.Pin8=PE12
|
||||
Mcu.Pin9=PE13
|
||||
Mcu.PinsNb=31
|
||||
Mcu.ThirdPartyNb=0
|
||||
Mcu.UserConstants=
|
||||
Mcu.UserName=STM32F407VGTx
|
||||
@ -80,6 +81,7 @@ MxDb.Version=DB.6.0.150
|
||||
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||
NVIC.CAN1_RX0_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
||||
NVIC.CAN1_RX1_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
||||
NVIC.DMA2_Stream0_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
||||
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||
NVIC.ForceEnableDMAVector=true
|
||||
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||
@ -109,6 +111,8 @@ PA14.Mode=Serial_Wire
|
||||
PA14.Signal=SYS_JTCK-SWCLK
|
||||
PA9.Mode=Asynchronous
|
||||
PA9.Signal=USART1_TX
|
||||
PB0.Locked=true
|
||||
PB0.Signal=GPIO_Output
|
||||
PD0.Mode=16b-d1
|
||||
PD0.Signal=FSMC_D2
|
||||
PD1.Mode=16b-d1
|
||||
@ -199,26 +203,26 @@ RCC.EthernetFreq_Value=168000000
|
||||
RCC.FCLKCortexFreq_Value=168000000
|
||||
RCC.FamilyName=M
|
||||
RCC.HCLKFreq_Value=168000000
|
||||
RCC.HSE_VALUE=25000000
|
||||
RCC.HSE_VALUE=8000000
|
||||
RCC.HSI_VALUE=16000000
|
||||
RCC.I2SClocksFreq_Value=96000000
|
||||
RCC.I2SClocksFreq_Value=192000000
|
||||
RCC.IPParameters=48MHZClocksFreq_Value,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,CortexFreq_Value,EthernetFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2SClocksFreq_Value,LSE_VALUE,LSI_VALUE,MCO2PinFreq_Value,PLLCLKFreq_Value,PLLM,PLLN,PLLQCLKFreq_Value,PLLSourceVirtual,RTCFreq_Value,RTCHSEDivFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VcooutputI2S
|
||||
RCC.LSE_VALUE=32768
|
||||
RCC.LSI_VALUE=32000
|
||||
RCC.MCO2PinFreq_Value=168000000
|
||||
RCC.PLLCLKFreq_Value=168000000
|
||||
RCC.PLLM=25
|
||||
RCC.PLLN=336
|
||||
RCC.PLLM=4
|
||||
RCC.PLLN=168
|
||||
RCC.PLLQCLKFreq_Value=84000000
|
||||
RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE
|
||||
RCC.RTCFreq_Value=32000
|
||||
RCC.RTCHSEDivFreq_Value=12500000
|
||||
RCC.RTCHSEDivFreq_Value=4000000
|
||||
RCC.SYSCLKFreq_VALUE=168000000
|
||||
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
|
||||
RCC.VCOI2SOutputFreq_Value=192000000
|
||||
RCC.VCOInputFreq_Value=1000000
|
||||
RCC.VCOI2SOutputFreq_Value=384000000
|
||||
RCC.VCOInputFreq_Value=2000000
|
||||
RCC.VCOOutputFreq_Value=336000000
|
||||
RCC.VcooutputI2S=96000000
|
||||
RCC.VcooutputI2S=192000000
|
||||
USART1.IPParameters=VirtualMode
|
||||
USART1.VirtualMode=VM_ASYNC
|
||||
VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2
|
||||
@ -226,3 +230,4 @@ VP_FREERTOS_VS_CMSIS_V2.Signal=FREERTOS_VS_CMSIS_V2
|
||||
VP_SYS_VS_tim14.Mode=TIM14
|
||||
VP_SYS_VS_tim14.Signal=SYS_VS_tim14
|
||||
board=custom
|
||||
rtos.0.ip=FREERTOS
|
||||
|
||||
@ -57,6 +57,7 @@ target_sources(${CMAKE_PROJECT_NAME} PRIVATE
|
||||
User/component/kinematics.c
|
||||
User/component/pid.c
|
||||
User/component/user_math.c
|
||||
./User/component/mixer.c
|
||||
|
||||
# User/device sources
|
||||
User/device/motor.c
|
||||
|
||||
@ -6,6 +6,10 @@ filter:
|
||||
dependencies:
|
||||
- component/ahrs
|
||||
enabled: true
|
||||
mixer:
|
||||
dependencies:
|
||||
- component/user_math.h
|
||||
enabled: true
|
||||
pid:
|
||||
dependencies:
|
||||
- component/filter
|
||||
|
||||
94
engineer/User/component/mixer.c
Normal file
94
engineer/User/component/mixer.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
混合器
|
||||
*/
|
||||
|
||||
#include "mixer.h"
|
||||
|
||||
#include "math.h"
|
||||
|
||||
/**
|
||||
* @brief 初始化混合器
|
||||
*
|
||||
* @param mixer 混合器
|
||||
* @param mode 混合器模式
|
||||
* @return int8_t 0对应没有错误
|
||||
*/
|
||||
int8_t Mixer_Init(Mixer_t *mixer, Mixer_Mode_t mode) {
|
||||
if (mixer == NULL) return -1;
|
||||
|
||||
mixer->mode = mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 计算输出
|
||||
*
|
||||
* @param mixer 混合器
|
||||
* @param move_vec 运动向量
|
||||
* @param out 输出数组
|
||||
* @param len 输出数组长短
|
||||
* @param scale 输出放大因子
|
||||
* @return int8_t 0对应没有错误
|
||||
*/
|
||||
int8_t Mixer_Apply(Mixer_t *mixer, MoveVector_t *move_vec, float *out,
|
||||
int8_t len, float scale) {
|
||||
if (mixer == NULL) return -1;
|
||||
|
||||
switch (mixer->mode) {
|
||||
case MIXER_MECANUM:
|
||||
if (len == 4) {
|
||||
out[0] = move_vec->vx - move_vec->vy + move_vec->wz;
|
||||
out[1] = move_vec->vx + move_vec->vy + move_vec->wz;
|
||||
out[2] = -move_vec->vx + move_vec->vy + move_vec->wz;
|
||||
out[3] = -move_vec->vx - move_vec->vy + move_vec->wz;
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
|
||||
case MIXER_PARLFIX4:
|
||||
if (len == 4) {
|
||||
out[0] = -move_vec->vx;
|
||||
out[1] = move_vec->vx;
|
||||
out[2] = move_vec->vx;
|
||||
out[3] = -move_vec->vx;
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
case MIXER_PARLFIX2:
|
||||
if (len == 2) {
|
||||
out[0] = -move_vec->vx;
|
||||
out[1] = move_vec->vx;
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
case MIXER_SINGLE:
|
||||
if (len == 1) {
|
||||
out[0] = move_vec->vx;
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
case MIXER_OMNICROSS:
|
||||
case MIXER_OMNIPLUS:
|
||||
goto error;
|
||||
}
|
||||
|
||||
float abs_max = 0.f;
|
||||
for (int8_t i = 0; i < len; i++) {
|
||||
const float abs_val = fabsf(out[i]);
|
||||
abs_max = (abs_val > abs_max) ? abs_val : abs_max;
|
||||
}
|
||||
if (abs_max > 1.f) {
|
||||
for (int8_t i = 0; i < len; i++) {
|
||||
out[i] /= abs_max;
|
||||
}
|
||||
}
|
||||
for (int8_t i = 0; i < len; i++) {
|
||||
out[i] *= scale;
|
||||
}
|
||||
return 0;
|
||||
|
||||
error:
|
||||
for (uint8_t i = 0; i < len; i++) out[i] = 0;
|
||||
return -1;
|
||||
}
|
||||
76
engineer/User/component/mixer.h
Normal file
76
engineer/User/component/mixer.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
混合器
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "user_math.h"
|
||||
|
||||
/* USER INCLUDE BEGIN */
|
||||
|
||||
/* USER INCLUDE END */
|
||||
|
||||
/* USER DEFINE BEGIN */
|
||||
|
||||
/* USER DEFINE END */
|
||||
|
||||
/** 四轮布局 */
|
||||
/* 前 */
|
||||
/* 2 1 */
|
||||
/* 3 4 */
|
||||
|
||||
/* 两轮布局 */
|
||||
/* 前 */
|
||||
/* 2 1 */
|
||||
|
||||
/* 混合器模式 */
|
||||
typedef enum {
|
||||
MIXER_MECANUM, /* 麦克纳姆轮 */
|
||||
MIXER_PARLFIX4, /* 平行四驱动轮 */
|
||||
MIXER_PARLFIX2, /* 平行对侧两驱动轮 */
|
||||
MIXER_OMNICROSS, /* 叉形全向轮 */
|
||||
MIXER_OMNIPLUS, /* 十字全向轮 */
|
||||
MIXER_SINGLE, /* 单个摩擦轮 */
|
||||
} Mixer_Mode_t;
|
||||
|
||||
typedef struct {
|
||||
Mixer_Mode_t mode;
|
||||
} Mixer_t; /* 混合器主结构体 */
|
||||
|
||||
/* USER STRUCT BEGIN */
|
||||
|
||||
/* USER STRUCT END */
|
||||
|
||||
/**
|
||||
* @brief 初始化混合器
|
||||
*
|
||||
* @param mixer 混合器
|
||||
* @param mode 混合器模式
|
||||
* @return int8_t 0对应没有错误
|
||||
*/
|
||||
int8_t Mixer_Init(Mixer_t *mixer, Mixer_Mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief 计算输出
|
||||
*
|
||||
* @param mixer 混合器
|
||||
* @param move_vec 运动向量
|
||||
* @param out 输出数组
|
||||
* @param len 输出数组长短
|
||||
* @param scale 输出放大因子
|
||||
* @return int8_t 0对应没有错误
|
||||
*/
|
||||
int8_t Mixer_Apply(Mixer_t *mixer, MoveVector_t *move_vec, float *out,
|
||||
int8_t len, float scale);
|
||||
|
||||
/* USER FUNCTION BEGIN */
|
||||
|
||||
/* USER FUNCTION END */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
418
engineer/User/module/chassis.c
Normal file
418
engineer/User/module/chassis.c
Normal file
@ -0,0 +1,418 @@
|
||||
/*
|
||||
* 底盘模组
|
||||
*/
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include "chassis.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bsp/mm.h"
|
||||
#include "cmsis_os2.h"
|
||||
#include "component/limiter.h"
|
||||
#include "device/can.h"
|
||||
#include "module/cap.h"
|
||||
|
||||
/* Private typedef ---------------------------------------------------------- */
|
||||
/* Private define ----------------------------------------------------------- */
|
||||
#define _CAP_PERCENTAGE_WORK 100 /* 底盘不再限制功率的电容电量 */
|
||||
#define _CAP_PERCENTAGE_CHARGE 30 /* 电容开始工作的电容电量 */
|
||||
|
||||
#define CHASSIS_MAX_CAP_POWER 100 /* 电容能够提供的最大功率 */
|
||||
|
||||
#define CHASSIS_ROTOR_WZ_MIN 0.6f /* 小陀螺旋转位移下界 */
|
||||
#define CHASSIS_ROTOR_WZ_MAX 0.8f /* 小陀螺旋转位移上界 */
|
||||
#define M_7OVER72PI (M_2PI * 7.0f / 72.0f) /* 三十五度对应弧度值 */
|
||||
// #define CHASSIS_ROTOR_OMEGA 0.15f /* 小陀螺转动频率 */
|
||||
// 随机产生小陀螺转动频率,范围0.001-0.05
|
||||
//#define CHASSIS_ROTOR_OMEGA rand() % 50 / 10000.0f + 0.001f
|
||||
#define CHASSIS_ROTOR_OMEGA 0.001
|
||||
/* Private macro ------------------------------------------------------------ */
|
||||
|
||||
/* 保证电容电量宏定义在正确范围内 */
|
||||
#if ((_CAP_PERCENTAGE_WORK < 0) || (_CAP_PERCENTAGE_WORK > 100) || \
|
||||
(_CAP_PERCENTAGE_CHARGE < 0) || (_CAP_PERCENTAGE_CHARGE > 100))
|
||||
#error "Cap percentage should be in the range from 0 to 100."
|
||||
#endif
|
||||
|
||||
/* 保证电容功率宏定义在正确范围内 */
|
||||
#if ((CHASSIS_MAX_CAP_POWER < 60) || (CHASSIS_MAX_CAP_POWER > 200))
|
||||
#error "The capacitor power should be in in the range from 60 to 200."
|
||||
#endif
|
||||
|
||||
/* Private variables -------------------------------------------------------- */
|
||||
|
||||
static const float CAP_PERCENTAGE_WORK = (float)_CAP_PERCENTAGE_WORK / 100.0f;
|
||||
static const float CAP_PERCENTAGE_CHARGE =
|
||||
(float)_CAP_PERCENTAGE_CHARGE / 100.0f;
|
||||
|
||||
/* Private function -------------------------------------------------------- */
|
||||
/**
|
||||
* \brief 设置底盘模式
|
||||
*
|
||||
* \param c 包含底盘数据的结构体
|
||||
* \param mode 要设置的模式
|
||||
*
|
||||
* \return 函数运行结果
|
||||
*/
|
||||
static int8_t Chassis_SetMode(Chassis_t *c, CMD_ChassisMode_t mode,
|
||||
uint32_t now) {
|
||||
if (c == NULL) return CHASSIS_ERR_NULL; /* 主结构体不能为空 */
|
||||
if (mode == c->mode) return CHASSIS_OK; /* 模式未改变直接返回 */
|
||||
|
||||
if (mode == CHASSIS_MODE_ROTOR && c->mode != CHASSIS_MODE_ROTOR) {
|
||||
srand(now);
|
||||
c->wz_multi = (rand() % 2) ? -1 : 1;
|
||||
}
|
||||
/* 切换模式后重置PID和滤波器 */
|
||||
for (uint8_t i = 0; i < c->num_wheel; i++) {
|
||||
PID_Reset(c->pid.motor + i);
|
||||
LowPassFilter2p_Reset(c->filter.in + i, 0.0f);
|
||||
LowPassFilter2p_Reset(c->filter.out + i, 0.0f);
|
||||
}
|
||||
c->mode = mode;
|
||||
|
||||
return CHASSIS_OK;
|
||||
}
|
||||
/**
|
||||
* @brief 产生小陀螺wz随机速度
|
||||
*
|
||||
* @param min wz产生最小速度
|
||||
* @param max wz产生最大速度
|
||||
* @param now ctrl_chassis的tick数
|
||||
* @return float
|
||||
*/
|
||||
static float Chassis_CalcWz(const float min, const float max, uint32_t now) {
|
||||
/* wz在min和max之间,上限0.6f */
|
||||
float wz_vary = fabs(0.2f * sinf(CHASSIS_ROTOR_OMEGA * (float)now)) + min;
|
||||
return wz_vary > 0.8f ? max : wz_vary;
|
||||
}
|
||||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* \brief 初始化底盘
|
||||
*
|
||||
* \param c 包含底盘数据的结构体
|
||||
* \param param 包含底盘参数的结构体指针
|
||||
* \param target_freq 任务预期的运行频率
|
||||
*
|
||||
* \return 函数运行结果
|
||||
*/
|
||||
int8_t Chassis_Init(Chassis_t *c, const Chassis_Params_t *param,
|
||||
AHRS_Eulr_t *mech_zero, float target_freq) {
|
||||
if (c == NULL) return CHASSIS_ERR_NULL;
|
||||
|
||||
c->param = param; /* 初始化参数 */
|
||||
c->mode = CHASSIS_MODE_RELAX; /* 设置上电后底盘默认模式 */
|
||||
c->mech_zero = mech_zero; /* 设置底盘机械零点 */
|
||||
|
||||
/* 如果电机反装重新计算机械零点 */
|
||||
if (param->reverse.yaw) CircleReverse(&(c->mech_zero->yaw));
|
||||
|
||||
/* 根据参数(param)中的底盘型号初始化Mixer */
|
||||
Mixer_Mode_t mixer_mode;
|
||||
switch (c->param->type) {
|
||||
case CHASSIS_TYPE_MECANUM:
|
||||
c->num_wheel = 4;
|
||||
mixer_mode = MIXER_MECANUM;
|
||||
break;
|
||||
|
||||
case CHASSIS_TYPE_PARLFIX4:
|
||||
c->num_wheel = 4;
|
||||
mixer_mode = MIXER_PARLFIX4;
|
||||
break;
|
||||
|
||||
case CHASSIS_TYPE_PARLFIX2:
|
||||
c->num_wheel = 2;
|
||||
mixer_mode = MIXER_PARLFIX2;
|
||||
break;
|
||||
|
||||
case CHASSIS_TYPE_OMNI_CROSS:
|
||||
c->num_wheel = 4;
|
||||
mixer_mode = MIXER_OMNICROSS;
|
||||
break;
|
||||
|
||||
case CHASSIS_TYPE_OMNI_PLUS:
|
||||
c->num_wheel = 4;
|
||||
mixer_mode = MIXER_OMNIPLUS;
|
||||
break;
|
||||
|
||||
case CHASSIS_TYPE_SINGLE:
|
||||
c->num_wheel = 1;
|
||||
mixer_mode = MIXER_SINGLE;
|
||||
break;
|
||||
|
||||
case CHASSIS_TYPE_DRONE:
|
||||
/* onboard sdk. */
|
||||
return CHASSIS_ERR_TYPE;
|
||||
}
|
||||
|
||||
/* 根据底盘型号动态分配控制时使用的变量 */
|
||||
c->feedback.motor_rpm =
|
||||
BSP_Malloc((size_t)c->num_wheel * sizeof(*c->feedback.motor_rpm));
|
||||
if (c->feedback.motor_rpm == NULL) goto error; /* 变量未分配,返回错误 */
|
||||
|
||||
c->feedback.motor_current =
|
||||
BSP_Malloc((size_t)c->num_wheel * sizeof(*c->feedback.motor_current));
|
||||
if (c->feedback.motor_current == NULL) goto error;
|
||||
|
||||
c->setpoint.motor_rpm =
|
||||
BSP_Malloc((size_t)c->num_wheel * sizeof(*c->setpoint.motor_rpm));
|
||||
if (c->setpoint.motor_rpm == NULL) goto error;
|
||||
|
||||
c->pid.motor = BSP_Malloc((size_t)c->num_wheel * sizeof(*c->pid.motor));
|
||||
if (c->pid.motor == NULL) goto error;
|
||||
|
||||
c->out = BSP_Malloc((size_t)c->num_wheel * sizeof(*c->out));
|
||||
if (c->out == NULL) goto error;
|
||||
|
||||
c->filter.in = BSP_Malloc((size_t)c->num_wheel * sizeof(*c->filter.in));
|
||||
if (c->filter.in == NULL) goto error;
|
||||
|
||||
c->filter.out = BSP_Malloc((size_t)c->num_wheel * sizeof(*c->filter.out));
|
||||
if (c->filter.out == NULL) goto error;
|
||||
|
||||
/* 初始化轮子电机控制PID和LPF */
|
||||
for (uint8_t i = 0; i < c->num_wheel; i++) {
|
||||
PID_Init(c->pid.motor + i, KPID_MODE_NO_D, target_freq,
|
||||
&(c->param->motor_pid_param));
|
||||
|
||||
LowPassFilter2p_Init(c->filter.in + i, target_freq,
|
||||
c->param->low_pass_cutoff_freq.in);
|
||||
LowPassFilter2p_Init(c->filter.out + i, target_freq,
|
||||
c->param->low_pass_cutoff_freq.out);
|
||||
}
|
||||
|
||||
/* 初始化跟随云台的控制PID */
|
||||
PID_Init(&(c->pid.follow), KPID_MODE_NO_D, target_freq,
|
||||
&(c->param->follow_pid_param));
|
||||
|
||||
Mixer_Init(&(c->mixer), mixer_mode); /* 初始化混合器 */
|
||||
return CHASSIS_OK;
|
||||
|
||||
error:
|
||||
/* 动态内存分配错误时,释放已经分配的内存,返回错误值 */
|
||||
BSP_Free(c->feedback.motor_rpm);
|
||||
BSP_Free(c->setpoint.motor_rpm);
|
||||
BSP_Free(c->pid.motor);
|
||||
BSP_Free(c->out);
|
||||
BSP_Free(c->filter.in);
|
||||
BSP_Free(c->filter.out);
|
||||
return CHASSIS_ERR_NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief 更新底盘的反馈信息
|
||||
*
|
||||
* \param c 包含底盘数据的结构体
|
||||
* \param can CAN设备结构体
|
||||
*
|
||||
* \return 函数运行结果
|
||||
*/
|
||||
int8_t Chassis_UpdateFeedback(Chassis_t *c, const CAN_t *can) {
|
||||
/* 底盘数据和CAN结构体不能为空 */
|
||||
if (c == NULL) return CHASSIS_ERR_NULL;
|
||||
if (can == NULL) return CHASSIS_ERR_NULL;
|
||||
|
||||
/* 如果电机反装重新计算正确的反馈值 */
|
||||
if (c->param->reverse.yaw) {
|
||||
c->feedback.gimbal_yaw_encoder =
|
||||
-can->motor.gimbal.named.yaw.rotor_angle + M_2PI;
|
||||
} else {
|
||||
c->feedback.gimbal_yaw_encoder = can->motor.gimbal.named.yaw.rotor_angle;
|
||||
}
|
||||
|
||||
/* 将CAN中的反馈数据写入到feedback中 */
|
||||
for (uint8_t i = 0; i < c->num_wheel; i++) {
|
||||
c->feedback.motor_rpm[i] = can->motor.chassis.as_array[i].rotor_speed;
|
||||
c->feedback.motor_current[i] =
|
||||
can->motor.chassis.as_array[i].torque_current;
|
||||
}
|
||||
|
||||
return CHASSIS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief 运行底盘控制逻辑
|
||||
*
|
||||
* \param c 包含底盘数据的结构体
|
||||
* \param c_cmd 底盘控制指令
|
||||
* \param dt_sec 两次调用的时间间隔
|
||||
*
|
||||
* \return 函数运行结果
|
||||
*/
|
||||
int8_t Chassis_Control(Chassis_t *c, const CMD_ChassisCmd_t *c_cmd,
|
||||
uint32_t now) {
|
||||
/* 底盘数据和控制指令结构体不能为空 */
|
||||
if (c == NULL) return CHASSIS_ERR_NULL;
|
||||
if (c_cmd == NULL) return CHASSIS_ERR_NULL;
|
||||
|
||||
c->dt = (float)(now - c->lask_wakeup) / 1000.0f;
|
||||
c->lask_wakeup = now;
|
||||
|
||||
/* 根据遥控器命令更改底盘模式 */
|
||||
Chassis_SetMode(c, c_cmd->mode, now);
|
||||
|
||||
/* ctrl_vec -> move_vec 控制向量和真实的移动向量之间有一个换算关系 */
|
||||
/* 计算vx、vy */
|
||||
switch (c->mode) {
|
||||
case CHASSIS_MODE_BREAK: /* 刹车模式电机停止 */
|
||||
c->move_vec.vx = 0.0f;
|
||||
c->move_vec.vy = 0.0f;
|
||||
break;
|
||||
|
||||
case CHASSIS_MODE_INDENPENDENT: /* 独立模式控制向量与运动向量相等 */
|
||||
c->move_vec.vx = c_cmd->ctrl_vec.vx;
|
||||
c->move_vec.vy = c_cmd->ctrl_vec.vx;
|
||||
break;
|
||||
|
||||
case CHASSIS_MODE_OPEN:
|
||||
case CHASSIS_MODE_RELAX:
|
||||
case CHASSIS_MODE_FOLLOW_GIMBAL: /* 按照云台方向换算运动向量 */
|
||||
case CHASSIS_MODE_FOLLOW_GIMBAL_35:
|
||||
case CHASSIS_MODE_ROTOR: {
|
||||
float beta = c->feedback.gimbal_yaw_encoder - c->mech_zero->yaw;
|
||||
float cos_beta = cosf(beta);
|
||||
float sin_beta = sinf(beta);
|
||||
c->move_vec.vx =
|
||||
cos_beta * c_cmd->ctrl_vec.vx - sin_beta * c_cmd->ctrl_vec.vy;
|
||||
c->move_vec.vy =
|
||||
sin_beta * c_cmd->ctrl_vec.vx + cos_beta * c_cmd->ctrl_vec.vy;
|
||||
}
|
||||
}
|
||||
|
||||
/* 计算wz */
|
||||
switch (c->mode) {
|
||||
case CHASSIS_MODE_RELAX:
|
||||
case CHASSIS_MODE_BREAK:
|
||||
case CHASSIS_MODE_INDENPENDENT: /* 独立模式wz为0 */
|
||||
c->move_vec.wz = 0.0f;
|
||||
break;
|
||||
|
||||
case CHASSIS_MODE_OPEN:
|
||||
case CHASSIS_MODE_FOLLOW_GIMBAL: /* 跟随模式通过PID控制使车头跟随云台 */
|
||||
c->move_vec.wz = PID_Calc(&(c->pid.follow), c->mech_zero->yaw,
|
||||
c->feedback.gimbal_yaw_encoder, 0.0f, c->dt);
|
||||
break;
|
||||
case CHASSIS_MODE_FOLLOW_GIMBAL_35:
|
||||
c->move_vec.wz =
|
||||
PID_Calc(&(c->pid.follow), c->mech_zero->yaw + M_7OVER72PI,
|
||||
c->feedback.gimbal_yaw_encoder, 0.0f, c->dt);
|
||||
break;
|
||||
case CHASSIS_MODE_ROTOR: { /* 小陀螺模式使底盘以一定速度旋转 */
|
||||
c->move_vec.wz = c->wz_multi * Chassis_CalcWz(CHASSIS_ROTOR_WZ_MIN,
|
||||
CHASSIS_ROTOR_WZ_MAX, now);
|
||||
}
|
||||
}
|
||||
|
||||
/* move_vec -> motor_rpm_set. 通过运动向量计算轮子转速目标值 */
|
||||
Mixer_Apply(&(c->mixer), &(c->move_vec), c->setpoint.motor_rpm, c->num_wheel,
|
||||
7000.0f);
|
||||
|
||||
/* 根据轮子转速目标值,利用PID计算电机输出值 */
|
||||
for (uint8_t i = 0; i < c->num_wheel; i++) {
|
||||
/* 输入滤波. */
|
||||
c->feedback.motor_rpm[i] =
|
||||
LowPassFilter2p_Apply(c->filter.in + i, c->feedback.motor_rpm[i]);
|
||||
|
||||
/* 根据底盘模式计算输出值 */
|
||||
switch (c->mode) {
|
||||
case CHASSIS_MODE_BREAK:
|
||||
case CHASSIS_MODE_FOLLOW_GIMBAL:
|
||||
case CHASSIS_MODE_FOLLOW_GIMBAL_35:
|
||||
case CHASSIS_MODE_ROTOR:
|
||||
case CHASSIS_MODE_INDENPENDENT: /* 独立模式,受PID控制 */
|
||||
c->out[i] = PID_Calc(c->pid.motor + i, c->setpoint.motor_rpm[i],
|
||||
c->feedback.motor_rpm[i], 0.0f, c->dt);
|
||||
break;
|
||||
|
||||
case CHASSIS_MODE_OPEN: /* 开环模式,不受PID控制 */
|
||||
c->out[i] = c->setpoint.motor_rpm[i] / 9000.0f;
|
||||
break;
|
||||
|
||||
case CHASSIS_MODE_RELAX: /* 放松模式,不输出 */
|
||||
c->out[i] = 0;
|
||||
break;
|
||||
}
|
||||
/* 输出滤波. */
|
||||
c->out[i] = LowPassFilter2p_Apply(c->filter.out + i, c->out[i]);
|
||||
}
|
||||
|
||||
return CHASSIS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 底盘功率限制
|
||||
*
|
||||
* @param c 底盘数据
|
||||
* @param cap 电容数据
|
||||
* @param ref 裁判系统数据
|
||||
* @return 函数运行结果
|
||||
*/
|
||||
int8_t Chassis_PowerLimit(Chassis_t *c, const CAN_Capacitor_t *cap,
|
||||
const Referee_ForChassis_t *ref) {
|
||||
float power_limit = 0.0f;
|
||||
if (ref->ref_status != REF_STATUS_RUNNING) {
|
||||
/* 裁判系统离线,将功率限制为固定值 */
|
||||
power_limit = CHASSIS_POWER_MAX_WITHOUT_REF;
|
||||
} else {
|
||||
if (cap->cap_status == CAN_CAP_STATUS_RUNNING &&
|
||||
cap->percentage > CAP_PERCENTAGE_CHARGE) {
|
||||
/* 电容在线且电量足够,使用电容 */
|
||||
if (cap->percentage > CAP_PERCENTAGE_WORK) {
|
||||
/* 电容接近充满时不再限制功率 */
|
||||
power_limit = -1.0f;
|
||||
} else {
|
||||
/* 按照电容能量百分比计算输出功率 */
|
||||
power_limit = ref->chassis_power_limit +
|
||||
(cap->percentage - CAP_PERCENTAGE_CHARGE) /
|
||||
(CAP_PERCENTAGE_WORK - CAP_PERCENTAGE_CHARGE) *
|
||||
(float)CHASSIS_MAX_CAP_POWER;
|
||||
}
|
||||
} else {
|
||||
/* 电容不在工作,根据缓冲能量计算输出功率限制 */
|
||||
power_limit = PowerLimit_TargetPower(ref->chassis_power_limit,
|
||||
ref->chassis_pwr_buff);
|
||||
}
|
||||
}
|
||||
/* 应用功率限制 */
|
||||
PowerLimit_ChassicOutput(power_limit, c->out, c->feedback.motor_rpm,
|
||||
c->num_wheel);
|
||||
|
||||
return CHASSIS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief 复制底盘输出值
|
||||
*
|
||||
* \param s 包含底盘数据的结构体
|
||||
* \param out CAN设备底盘输出结构体
|
||||
*/
|
||||
void Chassis_DumpOutput(Chassis_t *c, CAN_ChassisOutput_t *out) {
|
||||
for (uint8_t i = 0; i < c->num_wheel; i++) {
|
||||
out->as_array[i] = c->out[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief 清空Chassis输出数据
|
||||
*
|
||||
* \param out CAN设备底盘输出结构体
|
||||
*/
|
||||
void Chassis_ResetOutput(CAN_ChassisOutput_t *out) {
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
out->as_array[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 导出底盘数据
|
||||
*
|
||||
* @param chassis 底盘数据结构体
|
||||
* @param ui UI数据结构体
|
||||
*/
|
||||
void Chassis_DumpUI(const Chassis_t *c, Referee_ChassisUI_t *ui) {
|
||||
ui->mode = c->mode;
|
||||
ui->angle = c->feedback.gimbal_yaw_encoder - c->mech_zero->yaw;
|
||||
}
|
||||
179
engineer/User/module/chassis.h
Normal file
179
engineer/User/module/chassis.h
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* 底盘模组
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include "component/filter.h"
|
||||
#include "component/mixer.h"
|
||||
#include "component/pid.h"
|
||||
#include "bsp/can.h"
|
||||
#include "device/referee.h"
|
||||
|
||||
/* Exported constants ------------------------------------------------------- */
|
||||
#define CHASSIS_OK (0) /* 运行正常 */
|
||||
#define CHASSIS_ERR (-1) /* 运行时发现了其他错误 */
|
||||
#define CHASSIS_ERR_NULL (-2) /* 运行时发现NULL指针 */
|
||||
#define CHASSIS_ERR_MODE (-3) /* 运行时配置了错误的CMD_ChassisMode_t */
|
||||
#define CHASSIS_ERR_TYPE (-4) /* 运行时配置了错误的Chassis_Type_t */
|
||||
|
||||
/* Exported macro ----------------------------------------------------------- */
|
||||
/* Exported types ----------------------------------------------------------- */
|
||||
|
||||
/* 底盘类型(底盘的物理设计) */
|
||||
typedef enum {
|
||||
CHASSIS_TYPE_MECANUM, /* 麦克纳姆轮 */
|
||||
CHASSIS_TYPE_PARLFIX4, /* 平行摆设的四个驱动轮 */
|
||||
CHASSIS_TYPE_PARLFIX2, /* 平行摆设的两个驱动轮 */
|
||||
CHASSIS_TYPE_OMNI_CROSS, /* 叉型摆设的四个全向轮 */
|
||||
CHASSIS_TYPE_OMNI_PLUS, /* 十字型摆设的四个全向轮 */
|
||||
CHASSIS_TYPE_DRONE, /* 底盘为无人机 */
|
||||
CHASSIS_TYPE_SINGLE, /* 单个摩擦轮 */
|
||||
} Chassis_Type_t;
|
||||
|
||||
/* 底盘参数的结构体,包含所有初始化用的参数,通常是const,存好几组 */
|
||||
typedef struct {
|
||||
Chassis_Type_t type; /* 底盘类型,底盘的机械设计和轮子选型 */
|
||||
KPID_Params_t motor_pid_param; /* 轮子控制PID的参数 */
|
||||
KPID_Params_t follow_pid_param; /* 跟随云台PID的参数 */
|
||||
|
||||
/* 低通滤波器截止频率 */
|
||||
struct {
|
||||
float in; /* 输入 */
|
||||
float out; /* 输出 */
|
||||
} low_pass_cutoff_freq;
|
||||
|
||||
/* 电机反装 应该和云台设置相同*/
|
||||
struct {
|
||||
bool yaw;
|
||||
} reverse;
|
||||
|
||||
} Chassis_Params_t;
|
||||
|
||||
/*
|
||||
* 运行的主结构体,所有这个文件里的函数都在操作这个结构体
|
||||
* 包含了初始化参数,中间变量,输出变量
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t lask_wakeup;
|
||||
float dt;
|
||||
|
||||
const Chassis_Params_t *param; /* 底盘的参数,用Chassis_Init设定 */
|
||||
AHRS_Eulr_t *mech_zero;
|
||||
|
||||
/* 模块通用 */
|
||||
CMD_ChassisMode_t mode; /* 底盘模式 */
|
||||
|
||||
/* 底盘设计 */
|
||||
int8_t num_wheel; /* 底盘轮子数量 */
|
||||
Mixer_t mixer; /* 混合器,移动向量->电机目标值 */
|
||||
|
||||
MoveVector_t move_vec; /* 底盘实际的运动向量 */
|
||||
|
||||
/* 反馈信息 */
|
||||
struct {
|
||||
float gimbal_yaw_encoder; /* 云台Yaw轴编码器角度 */
|
||||
float *motor_rpm; /* 电机转速的动态数组,单位:RPM */
|
||||
float *motor_current; /* 转矩电流 单位:A */
|
||||
} feedback;
|
||||
|
||||
float wz_multi; /* 小陀螺模式旋转方向 */
|
||||
|
||||
/* PID计算的目标值 */
|
||||
struct {
|
||||
float *motor_rpm; /* 电机转速的动态数组,单位:RPM */
|
||||
} setpoint;
|
||||
|
||||
/* 反馈控制用的PID */
|
||||
struct {
|
||||
KPID_t *motor; /* 控制轮子电机用的PID的动态数组 */
|
||||
KPID_t follow; /* 跟随云台用的PID */
|
||||
} pid;
|
||||
|
||||
/* 滤波器 */
|
||||
struct {
|
||||
LowPassFilter2p_t *in; /* 反馈值滤波器 */
|
||||
LowPassFilter2p_t *out; /* 输出值滤波器 */
|
||||
} filter;
|
||||
|
||||
float *out; /* 电机最终的输出值的动态数组 */
|
||||
} Chassis_t;
|
||||
|
||||
/* Exported functions prototypes -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* \brief 初始化底盘
|
||||
*
|
||||
* \param c 包含底盘数据的结构体
|
||||
* \param param 包含底盘参数的结构体指针
|
||||
* \param target_freq 任务预期的运行频率
|
||||
*
|
||||
* \return 函数运行结果
|
||||
*/
|
||||
int8_t Chassis_Init(Chassis_t *c, const Chassis_Params_t *param,
|
||||
AHRS_Eulr_t *mech_zero, float target_freq);
|
||||
|
||||
/**
|
||||
* \brief 更新底盘的反馈信息
|
||||
*
|
||||
* \param c 包含底盘数据的结构体
|
||||
* \param can CAN设备结构体
|
||||
*
|
||||
* \return 函数运行结果
|
||||
*/
|
||||
int8_t Chassis_UpdateFeedback(Chassis_t *c, const CAN_t *can);
|
||||
|
||||
/**
|
||||
* \brief 运行底盘控制逻辑
|
||||
*
|
||||
* \param c 包含底盘数据的结构体
|
||||
* \param c_cmd 底盘控制指令
|
||||
* \param dt_sec 两次调用的时间间隔
|
||||
*
|
||||
* \return 函数运行结果
|
||||
*/
|
||||
int8_t Chassis_Control(Chassis_t *c, const CMD_ChassisCmd_t *c_cmd,
|
||||
uint32_t now);
|
||||
|
||||
/**
|
||||
* @brief 底盘功率限制
|
||||
*
|
||||
* @param c 底盘数据
|
||||
* @param cap 电容数据
|
||||
* @param ref 裁判系统数据
|
||||
* @return 函数运行结果
|
||||
*/
|
||||
int8_t Chassis_PowerLimit(Chassis_t *c, const CAN_Capacitor_t *cap,
|
||||
const Referee_ForChassis_t *ref);
|
||||
|
||||
/**
|
||||
* \brief 复制底盘输出值
|
||||
*
|
||||
* \param s 包含底盘数据的结构体
|
||||
* \param out CAN设备底盘输出结构体
|
||||
*/
|
||||
void Chassis_DumpOutput(Chassis_t *c, CAN_ChassisOutput_t *out);
|
||||
|
||||
/**
|
||||
* \brief 清空Chassis输出数据
|
||||
*
|
||||
* \param out CAN设备底盘输出结构体
|
||||
*/
|
||||
void Chassis_ResetOutput(CAN_ChassisOutput_t *out);
|
||||
|
||||
/**
|
||||
* @brief 导出底盘数据
|
||||
*
|
||||
* @param chassis 底盘数据结构体
|
||||
* @param ui UI数据结构体
|
||||
*/
|
||||
void Chassis_DumpUI(const Chassis_t *c, Referee_ChassisUI_t *ui);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -5,3 +5,9 @@
|
||||
function: Task_control
|
||||
name: control
|
||||
stack: 1024
|
||||
- delay: 0
|
||||
description: ''
|
||||
freq_control: false
|
||||
function: Task_display
|
||||
name: display
|
||||
stack: 1024
|
||||
|
||||
@ -4,9 +4,6 @@
|
||||
*/
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include "component/filter.h"
|
||||
#include "component/pid.h"
|
||||
#include "device/motor_dm.h"
|
||||
#include "task/user_task.h"
|
||||
/* USER INCLUDE BEGIN */
|
||||
#include "component/kinematics.h"
|
||||
@ -99,39 +96,20 @@ MOTOR_LZ_t* a;
|
||||
void Task_control(void *argument) {
|
||||
(void)argument; /* 未使用argument,消除警告 */
|
||||
|
||||
|
||||
/* 计算任务运行到指定频率需要等待的tick数 */
|
||||
const uint32_t delay_tick = osKernelGetTickFreq() / CONTROL_FREQ;
|
||||
|
||||
osDelay(CONTROL_INIT_DELAY); /* 延时一段时间再开启任务 */
|
||||
BSP_CAN_Init();
|
||||
|
||||
MOTOR_LZ_Init();
|
||||
MOTOR_LZ_Register(&lzmotor.param);
|
||||
MOTOR_LZ_Enable(&lzmotor.param);
|
||||
a = MOTOR_LZ_GetMotor(&lzmotor.param);
|
||||
// MOTOR_DM_Register(&motor.param);
|
||||
// MOTOR_DM_Enable(&motor.param);
|
||||
// PID_Init(&pid, KPID_MODE_SET_D, 1000, &pid_pram);
|
||||
// LowPassFilter2p_Init(&filter, 1000, 20);
|
||||
// LPF_Init(&ff, 1, 5);
|
||||
//
|
||||
// motor_out.angle = tp;
|
||||
// motor_out.velocity = 0;
|
||||
// motor_out.kp = 0;
|
||||
// motor_out.kd = 0;
|
||||
// motor_out.torque = 0;
|
||||
// float sp = 0;
|
||||
|
||||
robot_init(&hand, LINK, T_mat, mat_pdata, 5);
|
||||
fkine(&hand);
|
||||
uint32_t tick = osKernelGetTickCount(); /* 控制任务运行频率的计时 */
|
||||
/* USER CODE INIT BEGIN *
|
||||
/* USER CODE INIT BEGIN */
|
||||
|
||||
/* USER CODE INIT END */
|
||||
|
||||
while (1) {
|
||||
tick += delay_tick; /* 计算下一个唤醒时刻 */
|
||||
/* USER CODE BEGIN */
|
||||
/* USER CODE BEGIN */
|
||||
|
||||
// MOTOR_LZ_UpdateAll();
|
||||
MOTOR_LZ_Update(&lzmotor.param);
|
||||
@ -151,4 +129,5 @@ a = MOTOR_LZ_GetMotor(&lzmotor.param);
|
||||
/* USER CODE END */
|
||||
osDelayUntil(tick); /* 运行结束,等待下一次唤醒 */
|
||||
}
|
||||
|
||||
}
|
||||
38
engineer/User/task/display.c
Normal file
38
engineer/User/task/display.c
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
display Task
|
||||
|
||||
*/
|
||||
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include "task/user_task.h"
|
||||
/* USER INCLUDE BEGIN */
|
||||
|
||||
/* USER INCLUDE END */
|
||||
|
||||
/* Private typedef ---------------------------------------------------------- */
|
||||
/* Private define ----------------------------------------------------------- */
|
||||
/* Private macro ------------------------------------------------------------ */
|
||||
/* Private variables -------------------------------------------------------- */
|
||||
/* USER STRUCT BEGIN */
|
||||
|
||||
/* USER STRUCT END */
|
||||
|
||||
/* Private function --------------------------------------------------------- */
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void Task_display(void *argument) {
|
||||
(void)argument; /* 未使用argument,消除警告 */
|
||||
|
||||
|
||||
osDelay(DISPLAY_INIT_DELAY); /* 延时一段时间再开启任务 */
|
||||
|
||||
/* USER CODE INIT BEGIN */
|
||||
|
||||
/* USER CODE INIT END */
|
||||
|
||||
while (1) {
|
||||
/* USER CODE BEGIN */
|
||||
|
||||
/* USER CODE END */
|
||||
}
|
||||
|
||||
}
|
||||
@ -31,6 +31,7 @@ void Task_Init(void *argument) {
|
||||
|
||||
/* 创建任务线程 */
|
||||
task_runtime.thread.control = osThreadNew(Task_control, NULL, &attr_control);
|
||||
task_runtime.thread.display = osThreadNew(Task_display, NULL, &attr_display);
|
||||
|
||||
// 创建消息队列
|
||||
/* USER MESSAGE BEGIN */
|
||||
|
||||
@ -14,3 +14,8 @@ const osThreadAttr_t attr_control = {
|
||||
.priority = osPriorityNormal,
|
||||
.stack_size = 1024 * 4,
|
||||
};
|
||||
const osThreadAttr_t attr_display = {
|
||||
.name = "display",
|
||||
.priority = osPriorityNormal,
|
||||
.stack_size = 1024 * 4,
|
||||
};
|
||||
@ -18,6 +18,7 @@ extern "C" {
|
||||
/* 任务初始化延时ms */
|
||||
#define TASK_INIT_DELAY (100u)
|
||||
#define CONTROL_INIT_DELAY (0)
|
||||
#define DISPLAY_INIT_DELAY (0)
|
||||
|
||||
/* Exported defines --------------------------------------------------------- */
|
||||
/* Exported macro ----------------------------------------------------------- */
|
||||
@ -28,6 +29,7 @@ typedef struct {
|
||||
/* 各任务,也可以叫做线程 */
|
||||
struct {
|
||||
osThreadId_t control;
|
||||
osThreadId_t display;
|
||||
} thread;
|
||||
|
||||
/* USER MESSAGE BEGIN */
|
||||
@ -50,6 +52,7 @@ typedef struct {
|
||||
/* 各任务的stack使用 */
|
||||
struct {
|
||||
UBaseType_t control;
|
||||
UBaseType_t display;
|
||||
} stack_water_mark;
|
||||
|
||||
/* 各任务运行频率 */
|
||||
@ -70,10 +73,12 @@ extern Task_Runtime_t task_runtime;
|
||||
/* 初始化任务句柄 */
|
||||
extern const osThreadAttr_t attr_init;
|
||||
extern const osThreadAttr_t attr_control;
|
||||
extern const osThreadAttr_t attr_display;
|
||||
|
||||
/* 任务函数声明 */
|
||||
void Task_Init(void *argument);
|
||||
void Task_control(void *argument);
|
||||
void Task_display(void *argument);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user