重构完代码结构了

This commit is contained in:
2025-07-26 01:22:52 +08:00
parent 47e0b8419f
commit 501a9ddff4
108 changed files with 224 additions and 2017 deletions

BIN
assets/User_code/.DS_Store vendored Normal file

Binary file not shown.

BIN
assets/User_code/bsp/.DS_Store vendored Normal file

Binary file not shown.

View File

View File

@@ -0,0 +1,15 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define BSP_OK (0)
#define BSP_ERR (-1)
#define BSP_ERR_NULL (-2)
#define BSP_ERR_INITED (-3)
#define BSP_ERR_NO_DEV (-4)
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,32 @@
/* Includes ----------------------------------------------------------------- */
#include <gpio.h>
#include "bsp/bsp.h"
#include "bsp/buzzer_gpio.h"
/* Private define ----------------------------------------------------------- */
#define BSP_BUZZER_GPIO GPIOA
#define BSP_BUZZER_PIN GPIO_PIN_1
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
/* Private function --------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
int8_t BSP_Buzzer_Set(BSP_Buzzer_Status_t s)
{
switch (s)
{
case BSP_BUZZER_ON:
HAL_GPIO_WritePin(BSP_BUZZER_GPIO, BSP_BUZZER_PIN, GPIO_PIN_SET); // 打开蜂鸣器
break;
case BSP_BUZZER_OFF:
HAL_GPIO_WritePin(BSP_BUZZER_GPIO, BSP_BUZZER_PIN, GPIO_PIN_RESET); // 关闭蜂鸣器
break;
case BSP_BUZZER_TAGGLE:
HAL_GPIO_TogglePin(BSP_BUZZER_GPIO, BSP_BUZZER_PIN); // 切换蜂鸣器状态
break;
default:
return BSP_ERR;
}
return BSP_OK;
}

View File

@@ -0,0 +1,20 @@
#pragma once
/* Includes ----------------------------------------------------------------- */
#include <stdint.h>
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
/* 设置BUZZER状态 */
typedef enum
{
BSP_BUZZER_ON,
BSP_BUZZER_OFF,
BSP_BUZZER_TAGGLE,
} BSP_Buzzer_Status_t;
/* Exported functions prototypes -------------------------------------------- */
int8_t BSP_Buzzer_Set(BSP_Buzzer_Status_t s);

141
assets/User_code/bsp/can.c Normal file
View File

@@ -0,0 +1,141 @@
/* Includes ----------------------------------------------------------------- */
#include "bsp\can.h"
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
static void (*CAN_Callback[BSP_CAN_NUM][BSP_CAN_CB_NUM])(void);
/* Private function -------------------------------------------------------- */
static BSP_CAN_t CAN_Get(CAN_HandleTypeDef *hcan) {
if (hcan->Instance == CAN2)
return BSP_CAN_2;
else if (hcan->Instance == CAN1)
return BSP_CAN_1;
else
return BSP_CAN_ERR;
}
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) {
BSP_CAN_t bsp_can = CAN_Get(hcan);
if (bsp_can != BSP_CAN_ERR) {
if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_CPLT_CB])
CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_CPLT_CB]();
}
}
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) {
BSP_CAN_t bsp_can = CAN_Get(hcan);
if (bsp_can != BSP_CAN_ERR) {
if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_CPLT_CB])
CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_CPLT_CB]();
}
}
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) {
BSP_CAN_t bsp_can = CAN_Get(hcan);
if (bsp_can != BSP_CAN_ERR) {
if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_CPLT_CB])
CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_CPLT_CB]();
}
}
void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan) {
BSP_CAN_t bsp_can = CAN_Get(hcan);
if (bsp_can != BSP_CAN_ERR) {
if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_ABORT_CB])
CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_ABORT_CB]();
}
}
void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan) {
BSP_CAN_t bsp_can = CAN_Get(hcan);
if (bsp_can != BSP_CAN_ERR) {
if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_ABORT_CB])
CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_ABORT_CB]();
}
}
void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan) {
BSP_CAN_t bsp_can = CAN_Get(hcan);
if (bsp_can != BSP_CAN_ERR) {
if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_ABORT_CB])
CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_ABORT_CB]();
}
}
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {
BSP_CAN_t bsp_can = CAN_Get(hcan);
if (bsp_can != BSP_CAN_ERR) {
if (CAN_Callback[bsp_can][HAL_CAN_RX_FIFO0_MSG_PENDING_CB])
CAN_Callback[bsp_can][HAL_CAN_RX_FIFO0_MSG_PENDING_CB]();
}
}
void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan) {
BSP_CAN_t bsp_can = CAN_Get(hcan);
if (bsp_can != BSP_CAN_ERR) {
if (CAN_Callback[bsp_can][HAL_CAN_RX_FIFO0_FULL_CB])
CAN_Callback[bsp_can][HAL_CAN_RX_FIFO0_FULL_CB]();
}
}
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) {
BSP_CAN_t bsp_can = CAN_Get(hcan);
if (bsp_can != BSP_CAN_ERR) {
if (CAN_Callback[bsp_can][HAL_CAN_RX_FIFO1_MSG_PENDING_CB])
CAN_Callback[bsp_can][HAL_CAN_RX_FIFO1_MSG_PENDING_CB]();
}
}
void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan) {
BSP_CAN_t bsp_can = CAN_Get(hcan);
if (bsp_can != BSP_CAN_ERR) {
if (CAN_Callback[bsp_can][HAL_CAN_RX_FIFO1_FULL_CB])
CAN_Callback[bsp_can][HAL_CAN_RX_FIFO1_FULL_CB]();
}
}
void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan) {
BSP_CAN_t bsp_can = CAN_Get(hcan);
if (bsp_can != BSP_CAN_ERR) {
if (CAN_Callback[bsp_can][HAL_CAN_SLEEP_CB])
CAN_Callback[bsp_can][HAL_CAN_SLEEP_CB]();
}
}
void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan) {
BSP_CAN_t bsp_can = CAN_Get(hcan);
if (bsp_can != BSP_CAN_ERR) {
if (CAN_Callback[bsp_can][HAL_CAN_WAKEUP_FROM_RX_MSG_CB])
CAN_Callback[bsp_can][HAL_CAN_WAKEUP_FROM_RX_MSG_CB]();
}
}
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) {
BSP_CAN_t bsp_can = CAN_Get(hcan);
if (bsp_can != BSP_CAN_ERR) {
if (CAN_Callback[bsp_can][HAL_CAN_ERROR_CB])
CAN_Callback[bsp_can][HAL_CAN_ERROR_CB]();
}
}
/* Exported functions ------------------------------------------------------- */
CAN_HandleTypeDef *BSP_CAN_GetHandle(BSP_CAN_t can) {
switch (can) {
case BSP_CAN_2:
return &hcan2;
case BSP_CAN_1:
return &hcan1;
default:
return NULL;
}
}
int8_t BSP_CAN_RegisterCallback(BSP_CAN_t can, BSP_CAN_Callback_t type,
void (*callback)(void)) {
if (callback == NULL) return BSP_ERR_NULL;
CAN_Callback[can][type] = callback;
return BSP_OK;
}

View File

@@ -0,0 +1,46 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include <can.h>
#include "bsp/bsp.h"
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
typedef enum {
BSP_CAN_1,
BSP_CAN_2,
BSP_CAN_NUM,
BSP_CAN_ERR,
} BSP_CAN_t;
typedef enum {
HAL_CAN_TX_MAILBOX0_CPLT_CB,
HAL_CAN_TX_MAILBOX1_CPLT_CB,
HAL_CAN_TX_MAILBOX2_CPLT_CB,
HAL_CAN_TX_MAILBOX0_ABORT_CB,
HAL_CAN_TX_MAILBOX1_ABORT_CB,
HAL_CAN_TX_MAILBOX2_ABORT_CB,
HAL_CAN_RX_FIFO0_MSG_PENDING_CB,
HAL_CAN_RX_FIFO0_FULL_CB,
HAL_CAN_RX_FIFO1_MSG_PENDING_CB,
HAL_CAN_RX_FIFO1_FULL_CB,
HAL_CAN_SLEEP_CB,
HAL_CAN_WAKEUP_FROM_RX_MSG_CB,
HAL_CAN_ERROR_CB,
BSP_CAN_CB_NUM
} BSP_CAN_Callback_t;
/* Exported functions prototypes -------------------------------------------- */
CAN_HandleTypeDef *BSP_CAN_GetHandle(BSP_CAN_t can);
int8_t BSP_CAN_RegisterCallback(BSP_CAN_t can, BSP_CAN_Callback_t type,
void (*callback)(void));
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,118 @@
#include "bsp_delay.h"
#include "cmsis_os.h"
#include "main.h"
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
static uint8_t fac_us = 0;
static uint32_t fac_ms = 0;
/* Private function -------------------------------------------------------- */
static void delay_ticks(uint32_t ticks)
{
uint32_t told = SysTick->VAL;
uint32_t tnow = 0;
uint32_t tcnt = 0;
uint32_t reload = SysTick->LOAD;
while (1)
{
tnow = SysTick->VAL;
if (tnow != told)
{
if (tnow < told)
{
tcnt += told - tnow;
}
else
{
tcnt += reload - tnow + told;
}
told = tnow;
if (tcnt >= ticks)
{
break;
}
}
}
}
/* Exported functions ------------------------------------------------------- */
/**
* @brief 毫秒延时函数
* @param ms
* @return
*/
int8_t BSP_Delay(uint32_t ms)
{
uint32_t tick_period = 1000u / osKernelGetTickFreq();
uint32_t ticks = ms / tick_period;
switch (osKernelGetState())
{
case osKernelError:
case osKernelReserved:
case osKernelLocked:
case osKernelSuspended:
return BSP_ERR;
case osKernelRunning:
osDelay(ticks ? ticks : 1);
break;
case osKernelInactive:
case osKernelReady:
HAL_Delay(ms);
break;
}
return BSP_OK;
}
/**
* @brief 延时初始化
* @param
* @return
*/
int8_t BSP_Delay_Init(void)
{
if (SystemCoreClock == 0)
{
return BSP_ERR;
}
fac_us = SystemCoreClock / 1000000;
fac_ms = SystemCoreClock / 1000;
return BSP_OK;
}
/**
* @brief 微秒延时,注意:此函数会阻塞当前线程,直到延时结束,并且会被中断打断
* @param us
* @return
*/
int8_t BSP_Delay_us(uint32_t us)
{
if (fac_us == 0)
{
return BSP_ERR;
}
uint32_t ticks = us * fac_us;
delay_ticks(ticks);
return BSP_OK;
}
/**
* @brief 毫秒延时,注意:此函数会阻塞当前线程,直到延时结束,并且会被中断打断
* @param ms
* @return
*/
int8_t BSP_Delay_ms(uint32_t ms)
{
if (fac_ms == 0)
{
return BSP_ERR;
}
uint32_t ticks = ms * fac_ms;
delay_ticks(ticks);
return BSP_OK;
}

View File

@@ -0,0 +1,24 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include <stdint.h>
#include "bsp/bsp.h"
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
/* Exported functions prototypes -------------------------------------------- */
int8_t BSP_Delay(uint32_t ms);
int8_t BSP_Delay_Init(void);
int8_t BSP_Delay_us(uint32_t us);
int8_t BSP_Delay_ms(uint32_t ms);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,2 @@
i2c,I2C
uart,USART,UART
1 i2c,I2C
2 uart,USART,UART

View File

@@ -0,0 +1,2 @@
uart,要求开启dma和中断
can,要求开启can的中断
1 uart 要求开启dma和中断
2 can 要求开启can的中断

View File

@@ -0,0 +1,72 @@
/* Includes ----------------------------------------------------------------- */
#include "bsp\gpio.h"
#include <gpio.h>
#include <main.h>
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
static void (*GPIO_Callback[BSP_GPIO_NUM][BSP_GPIO_CB_NUM])(void);
/* Private function -------------------------------------------------------- */
static BSP_GPIO_t GPIO_Get(uint16_t pin) {
switch (pin) {
case USER_KEY_Pin:
return BSP_GPIO_USER_KEY;
/* case XXX_Pin:
return BSP_GPIO_XXX; */
default:
return BSP_GPIO_ERR;
}
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
BSP_GPIO_t gpio = GPIO_Get(GPIO_Pin);
if (gpio != BSP_GPIO_ERR) {
if (GPIO_Callback[gpio][BSP_GPIO_EXTI_CB]) {
GPIO_Callback[gpio][BSP_GPIO_EXTI_CB]();
}
}
}
/* Exported functions ------------------------------------------------------- */
int8_t BSP_GPIO_RegisterCallback(BSP_GPIO_t gpio, BSP_GPIO_Callback_t type, void (*callback)(void)) {
if (callback == NULL || gpio >= BSP_GPIO_NUM || type >= BSP_GPIO_CB_NUM) return BSP_ERR_NULL;
GPIO_Callback[gpio][type] = callback;
return BSP_OK;
}
int8_t BSP_GPIO_EnableIRQ(BSP_GPIO_t gpio) {
switch (gpio) {
case BSP_GPIO_USER_KEY:
HAL_NVIC_EnableIRQ(USER_KEY_EXTI_IRQn);
break;
/* case BSP_GPIO_XXX:
HAL_NVIC_EnableIRQ(XXX_IRQn);
break; */
default:
return BSP_ERR;
}
return BSP_OK;
}
int8_t BSP_GPIO_DisableIRQ(BSP_GPIO_t gpio) {
switch (gpio) {
case BSP_GPIO_USER_KEY:
HAL_NVIC_DisableIRQ(USER_KEY_EXTI_IRQn);
break;
/* case BSP_GPIO_XXX:
HAL_NVIC_DisableIRQ(XXX_IRQn);
break; */
default:
return BSP_ERR;
}
return BSP_OK;
}

View File

@@ -0,0 +1,37 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include <stdint.h>
#include "bsp/bsp.h"
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
/* GPIO设备枚举与设备对应 */
typedef enum {
BSP_GPIO_USER_KEY,
/* BSP_GPIO_XXX, */
BSP_GPIO_NUM,
BSP_GPIO_ERR,
} BSP_GPIO_t;
/* GPIO支持的中断回调函数类型 */
typedef enum {
BSP_GPIO_EXTI_CB,
BSP_GPIO_CB_NUM,
} BSP_GPIO_Callback_t;
/* Exported functions prototypes -------------------------------------------- */
int8_t BSP_GPIO_RegisterCallback(BSP_GPIO_t gpio, BSP_GPIO_Callback_t type, void (*callback)(void));
int8_t BSP_GPIO_EnableIRQ(BSP_GPIO_t gpio);
int8_t BSP_GPIO_DisableIRQ(BSP_GPIO_t gpio);
#ifdef __cplusplus
}
#endif

109
assets/User_code/bsp/i2c.c Normal file
View File

@@ -0,0 +1,109 @@
/* Includes ----------------------------------------------------------------- */
#include "bsp\i2c.h"
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
static void (*I2C_Callback[BSP_I2C_NUM][BSP_I2C_CB_NUM])(void);
/* Private function -------------------------------------------------------- */
static BSP_I2C_t I2C_Get(I2C_HandleTypeDef *hi2c) {
if (hi2c->Instance == I2C1)
return BSP_I2C_EXAMPLE;
// else if (hi2c->Instance == I2CX)
// return BSP_I2C_XXX;
else
return BSP_I2C_ERR;
}
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_MASTER_TX_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_MASTER_TX_CPLT_CB]();
}
}
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_MASTER_RX_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_MASTER_RX_CPLT_CB]();
}
}
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_SLAVE_TX_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_SLAVE_TX_CPLT_CB]();
}
}
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_SLAVE_RX_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_SLAVE_RX_CPLT_CB]();
}
}
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_LISTEN_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_LISTEN_CPLT_CB]();
}
}
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_MEM_TX_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_MEM_TX_CPLT_CB]();
}
}
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_MEM_RX_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_MEM_RX_CPLT_CB]();
}
}
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_ERROR_CB])
I2C_Callback[bsp_i2c][HAL_I2C_ERROR_CB]();
}
}
void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c) {
BSP_I2C_t bsp_i2c = I2C_Get(hi2c);
if (bsp_i2c != BSP_I2C_ERR) {
if (I2C_Callback[bsp_i2c][HAL_I2C_ABORT_CPLT_CB])
I2C_Callback[bsp_i2c][HAL_I2C_ABORT_CPLT_CB]();
}
}
/* Exported functions ------------------------------------------------------- */
I2C_HandleTypeDef *BSP_I2C_GetHandle(BSP_I2C_t i2c) {
switch (i2c) {
case BSP_I2C_EXAMPLE:
return &hi2c1;
// case BSP_I2C_XXX:
// return &hi2cX;
default:
return NULL;
}
}
int8_t BSP_I2C_RegisterCallback(BSP_I2C_t i2c, BSP_I2C_Callback_t type,
void (*callback)(void)) {
if (callback == NULL) return BSP_ERR_NULL;
I2C_Callback[i2c][type] = callback;
return BSP_OK;
}

View File

@@ -0,0 +1,47 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include <i2c.h>
#include "bsp/bsp.h"
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
/* 要添加使用I2C的新设备需要先在此添加对应的枚举值 */
/* I2C实体枚举与设备对应 */
typedef enum {
BSP_I2C_EXAMPLE,
/* BSP_I2C_XXX,*/
BSP_I2C_NUM,
BSP_I2C_ERR,
} BSP_I2C_t;
/* I2C支持的中断回调函数类型*/
typedef enum {
HAL_I2C_MASTER_TX_CPLT_CB,
HAL_I2C_MASTER_RX_CPLT_CB,
HAL_I2C_SLAVE_TX_CPLT_CB,
HAL_I2C_SLAVE_RX_CPLT_CB,
HAL_I2C_LISTEN_CPLT_CB,
HAL_I2C_MEM_TX_CPLT_CB,
HAL_I2C_MEM_RX_CPLT_CB,
HAL_I2C_ERROR_CB,
HAL_I2C_ABORT_CPLT_CB,
BSP_I2C_CB_NUM,
} BSP_I2C_Callback_t;
/* Exported functions prototypes -------------------------------------------- */
I2C_HandleTypeDef *BSP_I2C_GetHandle(BSP_I2C_t i2c);
int8_t BSP_I2C_RegisterCallback(BSP_I2C_t i2c, BSP_I2C_Callback_t type,
void (*callback)(void));
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,50 @@
/* Includes ----------------------------------------------------------------- */
#include "bsp/led_gpio.h"
#include "bsp/bsp.h"
#include <gpio.h>
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
static uint32_t led_stats; // 使用位掩码记录每个通道的状态最多支持32LED
// 定义 LED 引脚和端口映射表:需要根据自己的修改,添加,或删减。
static const BSP_LED_Config_t LED_CONFIGS[] = {
{GPIOA, GPIO_PIN_2}, // BSP_LED_1
{GPIOA, GPIO_PIN_3}, // BSP_LED_2
{GPIOA, GPIO_PIN_4}, // BSP_LED_3
};
#define LED_CHANNEL_COUNT (sizeof(LED_CONFIGS) / sizeof(LED_CONFIGS[0])) // 通道数量
/* Private function --------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
int8_t BSP_LED_Set(BSP_LED_Channel_t ch, BSP_LED_Status_t s)
{
if (ch < LED_CHANNEL_COUNT)
{
GPIO_TypeDef *port = LED_CONFIGS[ch].port;
uint16_t pin = LED_CONFIGS[ch].pin;
switch (s)
{
case BSP_LED_ON:
led_stats |= (1 << ch);
HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET); // 点亮LED
break;
case BSP_LED_OFF:
led_stats &= ~(1 << ch);
HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET); // 熄灭LED
break;
case BSP_LED_TAGGLE:
led_stats ^= (1 << ch);
HAL_GPIO_TogglePin(port, pin); // 切换LED状态
break;
default:
return BSP_ERR;
}
return BSP_OK;
}
return BSP_ERR;
}

View File

@@ -0,0 +1,36 @@
#pragma once
/* Includes ----------------------------------------------------------------- */
#include <stdint.h>
#include "gpio.h"
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
/* LED灯状态设置用 */
typedef enum
{
BSP_LED_ON,
BSP_LED_OFF,
BSP_LED_TAGGLE,
} BSP_LED_Status_t;
/* LED通道 */
typedef enum
{
BSP_LED_1,
BSP_LED_2,
BSP_LED_3,
/*BSP_LED_XXX*/
} BSP_LED_Channel_t;
/* LED GPIO 配置 */
typedef struct
{
GPIO_TypeDef *port; // GPIO 端口 (如 GPIOA, GPIOB)
uint16_t pin; // GPIO 引脚
} BSP_LED_Config_t;
/* Exported functions prototypes -------------------------------------------- */
int8_t BSP_LED_Set(BSP_LED_Channel_t ch, BSP_LED_Status_t s);

View File

@@ -0,0 +1,48 @@
/* Includes ----------------------------------------------------------------- */
#include "servo_pwm.h"
#include "main.h"
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
/* Private function -------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
int8_t BSP_PWM_Start(BSP_PWM_Channel_t ch) {
TIM_HandleTypeDef* htim = pwm_channel_config[ch].htim;
uint32_t channel = pwm_channel_config[ch].channel;
if(HAL_TIM_PWM_Start(htim, channel)!=HAL_OK){
return -1;
}else return 0;
}
int8_t BSP_PWM_Set(BSP_PWM_Channel_t ch, float duty_cycle) {
if (duty_cycle > 1.0f) return -1;
uint16_t pulse = duty_cycle/CYCLE * PWM_RESOLUTION;
if(__HAL_TIM_SET_COMPARE(pwm_channel_config[ch].htim, pwm_channel_config[ch].channel, pulse)!=HAL_OK){
return -1;
}else return 0;
}
int8_t BSP_PWM_Stop(BSP_PWM_Channel_t ch){
TIM_HandleTypeDef* htim = pwm_channel_config[ch].htim;
uint32_t channel = pwm_channel_config[ch].channel;
if(HAL_TIM_PWM_Stop(htim, channel)!=HAL_OK){
return -1;
}else return 0;
};

View File

@@ -0,0 +1,45 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include <stdint.h>
#include "tim.h"
#include "bsp/bsp.h"
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
typedef struct {
TIM_HandleTypeDef* htim; // 定时器句柄
uint32_t channel; // 定时器通道
} PWM_Channel_Config_t;
#define PWM_RESOLUTION 1000 // ARR change begin
#define CYCLE 20 //ms
typedef enum {
BSP_PWM_SERVO = 0,
BSP_PWM_IMU_HEAT = 1,
} BSP_PWM_Channel_t;
const PWM_Channel_Config_t pwm_channel_config[] = {
[BSP_PWM_SERVO] = { &htim1, TIM_CHANNEL_1 }, // xxx 对应 TIMx 通道x
[BSP_PWM_IMU_HEAT] = { &htim1, TIM_CHANNEL_2 }
}; //change end
/* Exported functions prototypes -------------------------------------------- */
int8_t BSP_PWM_Start(BSP_PWM_Channel_t ch);
int8_t BSP_PWM_Set(BSP_PWM_Channel_t ch, float duty_cycle);
int8_t BSP_PWM_Stop(BSP_PWM_Channel_t ch);
#ifdef __cplusplus
}
#endif

106
assets/User_code/bsp/spi.c Normal file
View File

@@ -0,0 +1,106 @@
/* Includes ----------------------------------------------------------------- */
#include "bsp\spi.h"
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
static void (*SPI_Callback[BSP_SPI_NUM][BSP_SPI_CB_NUM])(void);
/* Private function -------------------------------------------------------- */
static BSP_SPI_t SPI_Get(SPI_HandleTypeDef *hspi) {
if (hspi->Instance == SPI1)
return BSP_SPI_EXAMPLE;
/*
else if (hspi->Instance == SPIX)
return BSP_SPI_XXX;
*/
else
return BSP_SPI_ERR;
}
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) {
BSP_SPI_t bsp_spi = SPI_Get(hspi);
if (bsp_spi != BSP_SPI_ERR) {
if (SPI_Callback[bsp_spi][BSP_SPI_TX_CPLT_CB]) {
SPI_Callback[bsp_spi][BSP_SPI_TX_CPLT_CB]();
}
}
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) {
BSP_SPI_t bsp_spi = SPI_Get(hspi);
if (bsp_spi != BSP_SPI_ERR) {
if (SPI_Callback[SPI_Get(hspi)][BSP_SPI_RX_CPLT_CB])
SPI_Callback[SPI_Get(hspi)][BSP_SPI_RX_CPLT_CB]();
}
}
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) {
BSP_SPI_t bsp_spi = SPI_Get(hspi);
if (bsp_spi != BSP_SPI_ERR) {
if (SPI_Callback[SPI_Get(hspi)][BSP_SPI_TX_RX_CPLT_CB])
SPI_Callback[SPI_Get(hspi)][BSP_SPI_TX_RX_CPLT_CB]();
}
}
void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi) {
BSP_SPI_t bsp_spi = SPI_Get(hspi);
if (bsp_spi != BSP_SPI_ERR) {
if (SPI_Callback[SPI_Get(hspi)][BSP_SPI_TX_HALF_CPLT_CB])
SPI_Callback[SPI_Get(hspi)][BSP_SPI_TX_HALF_CPLT_CB]();
}
}
void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi) {
BSP_SPI_t bsp_spi = SPI_Get(hspi);
if (bsp_spi != BSP_SPI_ERR) {
if (SPI_Callback[SPI_Get(hspi)][BSP_SPI_RX_HALF_CPLT_CB])
SPI_Callback[SPI_Get(hspi)][BSP_SPI_RX_HALF_CPLT_CB]();
}
}
void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi) {
BSP_SPI_t bsp_spi = SPI_Get(hspi);
if (bsp_spi != BSP_SPI_ERR) {
if (SPI_Callback[SPI_Get(hspi)][BSP_SPI_TX_RX_HALF_CPLT_CB])
SPI_Callback[SPI_Get(hspi)][BSP_SPI_TX_RX_HALF_CPLT_CB]();
}
}
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) {
BSP_SPI_t bsp_spi = SPI_Get(hspi);
if (bsp_spi != BSP_SPI_ERR) {
if (SPI_Callback[SPI_Get(hspi)][BSP_SPI_ERROR_CB])
SPI_Callback[SPI_Get(hspi)][BSP_SPI_ERROR_CB]();
}
}
void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *hspi) {
BSP_SPI_t bsp_spi = SPI_Get(hspi);
if (bsp_spi != BSP_SPI_ERR) {
if (SPI_Callback[SPI_Get(hspi)][BSP_SPI_ABORT_CPLT_CB])
SPI_Callback[SPI_Get(hspi)][BSP_SPI_ABORT_CPLT_CB]();
}
}
/* Exported functions ------------------------------------------------------- */
SPI_HandleTypeDef *BSP_SPI_GetHandle(BSP_SPI_t spi) {
switch (spi) {
case BSP_SPI_EXAMPLE:
return &hspi1;
/*
case BSP_SPI_XXX:
return &hspiX;
*/
default:
return NULL;
}
}
int8_t BSP_SPI_RegisterCallback(BSP_SPI_t spi, BSP_SPI_Callback_t type,
void (*callback)(void)) {
if (callback == NULL) return BSP_ERR_NULL;
SPI_Callback[spi][type] = callback;
return BSP_OK;
}

View File

@@ -0,0 +1,46 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include <spi.h>
#include "bsp/bsp.h"
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
/* 要添加使用SPI的新设备需要先在此添加对应的枚举值 */
/* SPI实体枚举与设备对应 */
typedef enum {
BSP_SPI_EXAMPLE,
/* BSP_SPI_XXX,*/
BSP_SPI_NUM,
BSP_SPI_ERR,
} BSP_SPI_t;
/* SPI支持的中断回调函数类型具体参考HAL中定义 */
typedef enum {
BSP_SPI_TX_CPLT_CB,
BSP_SPI_RX_CPLT_CB,
BSP_SPI_TX_RX_CPLT_CB,
BSP_SPI_TX_HALF_CPLT_CB,
BSP_SPI_RX_HALF_CPLT_CB,
BSP_SPI_TX_RX_HALF_CPLT_CB,
BSP_SPI_ERROR_CB,
BSP_SPI_ABORT_CPLT_CB,
BSP_SPI_CB_NUM,
} BSP_SPI_Callback_t;
/* Exported functions prototypes -------------------------------------------- */
SPI_HandleTypeDef *BSP_SPI_GetHandle(BSP_SPI_t spi);
int8_t BSP_SPI_RegisterCallback(BSP_SPI_t spi, BSP_SPI_Callback_t type,
void (*callback)(void));
#ifdef __cplusplus
}
#endif

118
assets/User_code/bsp/uart.c Normal file
View File

@@ -0,0 +1,118 @@
/* Includes ----------------------------------------------------------------- */
#include "bsp\uart.h"
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
static void (*UART_Callback[BSP_UART_NUM][BSP_UART_CB_NUM])(void);
/* Private function -------------------------------------------------------- */
static BSP_UART_t UART_Get(UART_HandleTypeDef *huart) {
if (huart->Instance == USART1)
return BSP_UART_EXAMPLE;
// else if (huart->Instance == USARTX)
// return BSP_UART_XXX;
else
return BSP_UART_ERR;
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_TX_CPLT_CB]) {
UART_Callback[bsp_uart][BSP_UART_TX_CPLT_CB]();
}
}
}
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_TX_HALF_CPLT_CB]) {
UART_Callback[bsp_uart][BSP_UART_TX_HALF_CPLT_CB]();
}
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_RX_CPLT_CB]) {
UART_Callback[bsp_uart][BSP_UART_RX_CPLT_CB]();
}
}
}
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_RX_HALF_CPLT_CB]) {
UART_Callback[bsp_uart][BSP_UART_RX_HALF_CPLT_CB]();
}
}
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_ERROR_CB]) {
UART_Callback[bsp_uart][BSP_UART_ERROR_CB]();
}
}
}
void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_ABORT_CPLT_CB]) {
UART_Callback[bsp_uart][BSP_UART_ABORT_CPLT_CB]();
}
}
}
void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_ABORT_TX_CPLT_CB]) {
UART_Callback[bsp_uart][BSP_UART_ABORT_TX_CPLT_CB]();
}
}
}
void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart) {
BSP_UART_t bsp_uart = UART_Get(huart);
if (bsp_uart != BSP_UART_ERR) {
if (UART_Callback[bsp_uart][BSP_UART_ABORT_RX_CPLT_CB]) {
UART_Callback[bsp_uart][BSP_UART_ABORT_RX_CPLT_CB]();
}
}
}
/* Exported functions ------------------------------------------------------- */
void BSP_UART_IRQHandler(UART_HandleTypeDef *huart) {
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE)) {
__HAL_UART_CLEAR_IDLEFLAG(huart);
if (UART_Callback[UART_Get(huart)][BSP_UART_IDLE_LINE_CB]) {
UART_Callback[UART_Get(huart)][BSP_UART_IDLE_LINE_CB]();
}
}
}
UART_HandleTypeDef *BSP_UART_GetHandle(BSP_UART_t uart) {
switch (uart) {
case BSP_UART_EXAMPLE:
return &huart1;
// case BSP_UART_XXX:
// return &huartX;
default:
return NULL;
}
}
int8_t BSP_UART_RegisterCallback(BSP_UART_t uart, BSP_UART_Callback_t type,
void (*callback)(void)) {
if (callback == NULL) return BSP_ERR_NULL;
UART_Callback[uart][type] = callback;
return BSP_OK;
}

View File

@@ -0,0 +1,48 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include <usart.h>
#include "bsp/bsp.h"
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
/* 要添加使用UART的新设备需要先在此添加对应的枚举值 */
/* UART实体枚举与设备对应 */
typedef enum {
BSP_UART_EXAMPLE,
/*BSP_UART_XXX*/
BSP_UART_NUM,
BSP_UART_ERR,
} BSP_UART_t;
/* UART支持的中断回调函数类型具体参考HAL中定义 */
typedef enum {
BSP_UART_TX_HALF_CPLT_CB,
BSP_UART_TX_CPLT_CB,
BSP_UART_RX_HALF_CPLT_CB,
BSP_UART_RX_CPLT_CB,
BSP_UART_ERROR_CB,
BSP_UART_ABORT_CPLT_CB,
BSP_UART_ABORT_TX_CPLT_CB,
BSP_UART_ABORT_RX_CPLT_CB,
BSP_UART_IDLE_LINE_CB,
BSP_UART_CB_NUM,
} BSP_UART_Callback_t;
/* Exported functions prototypes -------------------------------------------- */
UART_HandleTypeDef *BSP_UART_GetHandle(BSP_UART_t uart);
int8_t BSP_UART_RegisterCallback(BSP_UART_t uart, BSP_UART_Callback_t type,
void (*callback)(void));
#ifdef __cplusplus
}
#endif

View File

View File

@@ -0,0 +1,50 @@
#include "crc16_rm.h"
static const uint16_t crc16_tab[256] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48,
0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108,
0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb,
0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399,
0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e,
0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e,
0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd,
0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285,
0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44,
0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014,
0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5,
0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3,
0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862,
0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e,
0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1,
0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483,
0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50,
0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710,
0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7,
0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1,
0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72,
0x3efb, 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e,
0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf,
0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d,
0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c,
0x3de3, 0x2c6a, 0x1ef1, 0x0f78};
static inline uint16_t CRC16_Byte(uint16_t crc, const uint8_t data) {
return (crc >> 8) ^ crc16_tab[(crc ^ data) & 0xff];
}
uint16_t CRC16_Calc(const uint8_t *buf, size_t len, uint16_t crc) {
while (len--) crc = CRC16_Byte(crc, *buf++);
return crc;
}
bool CRC16_Verify(const uint8_t *buf, size_t len) {
if (len < 2) return false;
uint16_t expected = CRC16_Calc(buf, len - sizeof(uint16_t), CRC16_INIT);
return expected ==
((const uint16_t *)((const uint8_t *)buf +
(len % 2)))[len / sizeof(uint16_t) - 1];
}

View File

@@ -0,0 +1,16 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#define CRC16_INIT 0XFFFF
uint16_t CRC16_Calc(const uint8_t *buf, size_t len, uint16_t crc);
bool CRC16_Verify(const uint8_t *buf, size_t len);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,44 @@
/*
参考了Linux
*/
#include "crc8_rm.h"
static const uint8_t crc8_tab[256] = {
0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83, 0xc2, 0x9c, 0x7e, 0x20,
0xa3, 0xfd, 0x1f, 0x41, 0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e,
0x5f, 0x01, 0xe3, 0xbd, 0x3e, 0x60, 0x82, 0xdc, 0x23, 0x7d, 0x9f, 0xc1,
0x42, 0x1c, 0xfe, 0xa0, 0xe1, 0xbf, 0x5d, 0x03, 0x80, 0xde, 0x3c, 0x62,
0xbe, 0xe0, 0x02, 0x5c, 0xdf, 0x81, 0x63, 0x3d, 0x7c, 0x22, 0xc0, 0x9e,
0x1d, 0x43, 0xa1, 0xff, 0x46, 0x18, 0xfa, 0xa4, 0x27, 0x79, 0x9b, 0xc5,
0x84, 0xda, 0x38, 0x66, 0xe5, 0xbb, 0x59, 0x07, 0xdb, 0x85, 0x67, 0x39,
0xba, 0xe4, 0x06, 0x58, 0x19, 0x47, 0xa5, 0xfb, 0x78, 0x26, 0xc4, 0x9a,
0x65, 0x3b, 0xd9, 0x87, 0x04, 0x5a, 0xb8, 0xe6, 0xa7, 0xf9, 0x1b, 0x45,
0xc6, 0x98, 0x7a, 0x24, 0xf8, 0xa6, 0x44, 0x1a, 0x99, 0xc7, 0x25, 0x7b,
0x3a, 0x64, 0x86, 0xd8, 0x5b, 0x05, 0xe7, 0xb9, 0x8c, 0xd2, 0x30, 0x6e,
0xed, 0xb3, 0x51, 0x0f, 0x4e, 0x10, 0xf2, 0xac, 0x2f, 0x71, 0x93, 0xcd,
0x11, 0x4f, 0xad, 0xf3, 0x70, 0x2e, 0xcc, 0x92, 0xd3, 0x8d, 0x6f, 0x31,
0xb2, 0xec, 0x0e, 0x50, 0xaf, 0xf1, 0x13, 0x4d, 0xce, 0x90, 0x72, 0x2c,
0x6d, 0x33, 0xd1, 0x8f, 0x0c, 0x52, 0xb0, 0xee, 0x32, 0x6c, 0x8e, 0xd0,
0x53, 0x0d, 0xef, 0xb1, 0xf0, 0xae, 0x4c, 0x12, 0x91, 0xcf, 0x2d, 0x73,
0xca, 0x94, 0x76, 0x28, 0xab, 0xf5, 0x17, 0x49, 0x08, 0x56, 0xb4, 0xea,
0x69, 0x37, 0xd5, 0x8b, 0x57, 0x09, 0xeb, 0xb5, 0x36, 0x68, 0x8a, 0xd4,
0x95, 0xcb, 0x29, 0x77, 0xf4, 0xaa, 0x48, 0x16, 0xe9, 0xb7, 0x55, 0x0b,
0x88, 0xd6, 0x34, 0x6a, 0x2b, 0x75, 0x97, 0xc9, 0x4a, 0x14, 0xf6, 0xa8,
0x74, 0x2a, 0xc8, 0x96, 0x15, 0x4b, 0xa9, 0xf7, 0xb6, 0xe8, 0x0a, 0x54,
0xd7, 0x89, 0x6b, 0x35,
};
uint8_t CRC8_Calc(const uint8_t *buf, size_t len, uint8_t crc) {
/* loop over the buffer data */
while (len-- > 0) crc = crc8_tab[(crc ^ *buf++) & 0xff];
return crc;
}
bool CRC8_Verify(const uint8_t *buf, size_t len) {
if (len < 2) return false;
uint8_t expected = CRC8_Calc(buf, len - sizeof(uint8_t), CRC8_INIT);
return expected == buf[len - sizeof(uint8_t)];
}

View File

@@ -0,0 +1,22 @@
/*
参考了Linux
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#define CRC8_INIT 0xFF
uint8_t CRC8_Calc(const uint8_t *buf, size_t len, uint8_t crc);
bool CRC8_Verify(const uint8_t *buf, size_t len);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,3 @@
pid,component/filter
pid,component/user_math
filter,component/user_math
1 pid component/filter
2 pid component/user_math
3 filter component/user_math

View File

@@ -0,0 +1 @@
pid,好用的
1 pid 好用的

View File

@@ -0,0 +1,186 @@
/*
各类滤波器。
*/
#include "filter.h"
#include <stddef.h>
#include "user_math.h"
/**
* @brief 初始化滤波器
*
* @param f 滤波器
* @param sample_freq 采样频率
* @param cutoff_freq 截止频率
*/
void LowPassFilter2p_Init(LowPassFilter2p_t *f, float sample_freq,
float cutoff_freq) {
if (f == NULL) return;
f->cutoff_freq = cutoff_freq;
f->delay_element_1 = 0.0f;
f->delay_element_2 = 0.0f;
if (f->cutoff_freq <= 0.0f) {
/* no filtering */
f->b0 = 1.0f;
f->b1 = 0.0f;
f->b2 = 0.0f;
f->a1 = 0.0f;
f->a2 = 0.0f;
return;
}
const float fr = sample_freq / f->cutoff_freq;
const float ohm = tanf(M_PI / fr);
const float c = 1.0f + 2.0f * cosf(M_PI / 4.0f) * ohm + ohm * ohm;
f->b0 = ohm * ohm / c;
f->b1 = 2.0f * f->b0;
f->b2 = f->b0;
f->a1 = 2.0f * (ohm * ohm - 1.0f) / c;
f->a2 = (1.0f - 2.0f * cosf(M_PI / 4.0f) * ohm + ohm * ohm) / c;
}
/**
* @brief 施加一次滤波计算
*
* @param f 滤波器
* @param sample 采样的值
* @return float 滤波后的值
*/
float LowPassFilter2p_Apply(LowPassFilter2p_t *f, float sample) {
if (f == NULL) return 0.0f;
/* do the filtering */
float delay_element_0 =
sample - f->delay_element_1 * f->a1 - f->delay_element_2 * f->a2;
if (isinf(delay_element_0)) {
/* don't allow bad values to propagate via the filter */
delay_element_0 = sample;
}
const float output = delay_element_0 * f->b0 + f->delay_element_1 * f->b1 +
f->delay_element_2 * f->b2;
f->delay_element_2 = f->delay_element_1;
f->delay_element_1 = delay_element_0;
/* return the value. Should be no need to check limits */
return output;
}
/**
* @brief 重置滤波器
*
* @param f 滤波器
* @param sample 采样的值
* @return float 滤波后的值
*/
float LowPassFilter2p_Reset(LowPassFilter2p_t *f, float sample) {
if (f == NULL) return 0.0f;
const float dval = sample / (f->b0 + f->b1 + f->b2);
if (isfinite(dval)) {
f->delay_element_1 = dval;
f->delay_element_2 = dval;
} else {
f->delay_element_1 = sample;
f->delay_element_2 = sample;
}
return LowPassFilter2p_Apply(f, sample);
}
/**
* @brief 初始化滤波器
*
* @param f 滤波器
* @param sample_freq 采样频率
* @param notch_freq 中心频率
* @param bandwidth 带宽
*/
void NotchFilter_Init(NotchFilter_t *f, float sample_freq, float notch_freq,
float bandwidth) {
if (f == NULL) return;
f->notch_freq = notch_freq;
f->bandwidth = bandwidth;
f->delay_element_1 = 0.0f;
f->delay_element_2 = 0.0f;
if (notch_freq <= 0.0f) {
/* no filtering */
f->b0 = 1.0f;
f->b1 = 0.0f;
f->b2 = 0.0f;
f->a1 = 0.0f;
f->a2 = 0.0f;
return;
}
const float alpha = tanf(M_PI * bandwidth / sample_freq);
const float beta = -cosf(M_2PI * notch_freq / sample_freq);
const float a0_inv = 1.0f / (alpha + 1.0f);
f->b0 = a0_inv;
f->b1 = 2.0f * beta * a0_inv;
f->b2 = a0_inv;
f->a1 = f->b1;
f->a2 = (1.0f - alpha) * a0_inv;
}
/**
* @brief 施加一次滤波计算
*
* @param f 滤波器
* @param sample 采样的值
* @return float 滤波后的值
*/
inline float NotchFilter_Apply(NotchFilter_t *f, float sample) {
if (f == NULL) return 0.0f;
/* Direct Form II implementation */
const float delay_element_0 =
sample - f->delay_element_1 * f->a1 - f->delay_element_2 * f->a2;
const float output = delay_element_0 * f->b0 + f->delay_element_1 * f->b1 +
f->delay_element_2 * f->b2;
f->delay_element_2 = f->delay_element_1;
f->delay_element_1 = delay_element_0;
return output;
}
/**
* @brief 重置滤波器
*
* @param f 滤波器
* @param sample 采样的值
* @return float 滤波后的值
*/
float NotchFilter_Reset(NotchFilter_t *f, float sample) {
if (f == NULL) return 0.0f;
float dval = sample;
if (fabsf(f->b0 + f->b1 + f->b2) > FLT_EPSILON) {
dval = dval / (f->b0 + f->b1 + f->b2);
}
f->delay_element_1 = dval;
f->delay_element_2 = dval;
return NotchFilter_Apply(f, sample);
}

View File

@@ -0,0 +1,102 @@
/*
各类滤波器。
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* 二阶低通滤波器 */
typedef struct {
float cutoff_freq; /* 截止频率 */
float a1;
float a2;
float b0;
float b1;
float b2;
float delay_element_1;
float delay_element_2;
} LowPassFilter2p_t;
/* 带阻滤波器 */
typedef struct {
float notch_freq; /* 阻止频率 */
float bandwidth; /* 带宽 */
float a1;
float a2;
float b0;
float b1;
float b2;
float delay_element_1;
float delay_element_2;
} NotchFilter_t;
/**
* @brief 初始化滤波器
*
* @param f 滤波器
* @param sample_freq 采样频率
* @param cutoff_freq 截止频率
*/
void LowPassFilter2p_Init(LowPassFilter2p_t *f, float sample_freq,
float cutoff_freq);
/**
* @brief 施加一次滤波计算
*
* @param f 滤波器
* @param sample 采样的值
* @return float 滤波后的值
*/
float LowPassFilter2p_Apply(LowPassFilter2p_t *f, float sample);
/**
* @brief 重置滤波器
*
* @param f 滤波器
* @param sample 采样的值
* @return float 滤波后的值
*/
float LowPassFilter2p_Reset(LowPassFilter2p_t *f, float sample);
/**
* @brief 初始化滤波器
*
* @param f 滤波器
* @param sample_freq 采样频率
* @param notch_freq 中心频率
* @param bandwidth 带宽
*/
void NotchFilter_Init(NotchFilter_t *f, float sample_freq, float notch_freq,
float bandwidth);
/**
* @brief 施加一次滤波计算
*
* @param f 滤波器
* @param sample 采样的值
* @return float 滤波后的值
*/
float NotchFilter_Apply(NotchFilter_t *f, float sample);
/**
* @brief 重置滤波器
*
* @param f 滤波器
* @param sample 采样的值
* @return float 滤波后的值
*/
float NotchFilter_Reset(NotchFilter_t *f, float sample);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,161 @@
/*
Modified from
https://github.com/PX4/Firmware/blob/master/src/lib/pid/pid.cpp
参考资料:
https://github.com/PX4/Firmware/issues/12362
https://dev.px4.io/master/en/flight_stack/controller_diagrams.html
https://docs.px4.io/master/en/config_mc/pid_tuning_guide_multicopter.html#standard_form
https://www.controleng.com/articles/not-all-pid-controllers-are-the-same/
https://en.wikipedia.org/wiki/PID_controller
http://brettbeauregard.com/blog/2011/04/improving-the-beginner%E2%80%99s-pid-derivative-kick/
*/
#include "pid.h"
#include <stddef.h>
#include "user_math.h"
#define SIGMA 0.000001f
/**
* @brief 初始化PID
*
* @param pid PID结构体
* @param mode PID模式
* @param sample_freq 采样频率
* @param param PID参数
* @return int8_t 0对应没有错误
*/
int8_t PID_Init(KPID_t *pid, KPID_Mode_t mode, float sample_freq,
const KPID_Params_t *param) {
if (pid == NULL) return -1;
if (!isfinite(param->p)) return -1;
if (!isfinite(param->i)) return -1;
if (!isfinite(param->d)) return -1;
if (!isfinite(param->i_limit)) return -1;
if (!isfinite(param->out_limit)) return -1;
pid->param = param;
float dt_min = 1.0f / sample_freq;
if (isfinite(dt_min))
pid->dt_min = dt_min;
else
return -1;
LowPassFilter2p_Init(&(pid->dfilter), sample_freq, pid->param->d_cutoff_freq);
pid->mode = mode;
PID_Reset(pid);
return 0;
}
/**
* @brief PID计算
*
* @param pid PID结构体
* @param sp 设定值
* @param fb 反馈值
* @param fb_dot 反馈值微分
* @param dt 间隔时间
* @return float 计算的输出
*/
float PID_Calc(KPID_t *pid, float sp, float fb, float fb_dot, float dt) {
if (!isfinite(sp) || !isfinite(fb) || !isfinite(fb_dot) || !isfinite(dt)) {
return pid->last.out;
}
/* 计算误差值 */
const float err = CircleError(sp, fb, pid->param->range);
/* 计算P项 */
const float k_err = err * pid->param->k;
/* 计算D项 */
const float k_fb = pid->param->k * fb;
const float filtered_k_fb = LowPassFilter2p_Apply(&(pid->dfilter), k_fb);
float d;
switch (pid->mode) {
case KPID_MODE_CALC_D:
/* 通过fb计算D避免了由于sp变化导致err突变的问题 */
/* 当sp不变时err的微分等于负的fb的微分 */
d = (filtered_k_fb - pid->last.k_fb) / fmaxf(dt, pid->dt_min);
break;
case KPID_MODE_SET_D:
d = fb_dot;
break;
case KPID_MODE_NO_D:
d = 0.0f;
break;
}
pid->last.err = err;
pid->last.k_fb = filtered_k_fb;
if (!isfinite(d)) d = 0.0f;
/* 计算PD输出 */
float output = (k_err * pid->param->p) - (d * pid->param->d);
/* 计算I项 */
const float i = pid->i + (k_err * dt);
const float i_out = i * pid->param->i;
if (pid->param->i > SIGMA) {
/* 检查是否饱和 */
if (isfinite(i)) {
if ((fabsf(output + i_out) <= pid->param->out_limit) &&
(fabsf(i) <= pid->param->i_limit)) {
/* 未饱和,使用新积分 */
pid->i = i;
}
}
}
/* 计算PID输出 */
output += i_out;
/* 限制输出 */
if (isfinite(output)) {
if (pid->param->out_limit > SIGMA) {
output = AbsClip(output, pid->param->out_limit);
}
pid->last.out = output;
}
return pid->last.out;
}
/**
* @brief 重置微分项
*
* @param pid PID结构体
* @return int8_t 0对应没有错误
*/
int8_t PID_ResetIntegral(KPID_t *pid) {
if (pid == NULL) return -1;
pid->i = 0.0f;
return 0;
}
/**
* @brief 重置PID
*
* @param pid PID结构体
* @return int8_t 0对应没有错误
*/
int8_t PID_Reset(KPID_t *pid) {
if (pid == NULL) return -1;
pid->i = 0.0f;
pid->last.err = 0.0f;
pid->last.k_fb = 0.0f;
pid->last.out = 0.0f;
LowPassFilter2p_Reset(&(pid->dfilter), 0.0f);
return 0;
}

View File

@@ -0,0 +1,94 @@
/*
Modified from
https://github.com/PX4/Firmware/blob/master/src/lib/pid/pid.h
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "filter.h"
/* PID模式 */
typedef enum {
KPID_MODE_NO_D = 0, /* 不使用微分项PI控制器 */
KPID_MODE_CALC_D, /* 根据反馈的值计算离散微分忽略PID_Calc中的fb_dot */
KPID_MODE_SET_D /* 直接提供微分值PID_Calc中的fb_dot将被使用(Gyros) */
} KPID_Mode_t;
/* PID参数 */
typedef struct {
float k; /* 控制器增益设置为1用于并行模式 */
float p; /* 比例项增益设置为1用于标准形式 */
float i; /* 积分项增益 */
float d; /* 微分项增益 */
float i_limit; /* 积分项上限 */
float out_limit; /* 输出绝对值限制 */
float d_cutoff_freq; /* D项低通截止频率 */
float range; /* 计算循环误差时使用大于0时启用 */
} KPID_Params_t;
/* PID主结构体 */
typedef struct {
KPID_Mode_t mode;
const KPID_Params_t *param;
float dt_min; /* 最小PID_Calc调用间隔 */
float i; /* 积分 */
struct {
float err; /* 上次误差 */
float k_fb; /* 上次反馈值 */
float out; /* 上次输出 */
} last;
LowPassFilter2p_t dfilter; /* D项低通滤波器 */
} KPID_t;
/**
* @brief 初始化PID
*
* @param pid PID结构体
* @param mode PID模式
* @param sample_freq 采样频率
* @param param PID参数
* @return int8_t 0对应没有错误
*/
int8_t PID_Init(KPID_t *pid, KPID_Mode_t mode, float sample_freq,
const KPID_Params_t *param);
/**
* @brief PID计算
*
* @param pid PID结构体
* @param sp 设定值
* @param fb 反馈值
* @param fb_dot 反馈值微分
* @param dt 间隔时间
* @return float 计算的输出
*/
float PID_Calc(KPID_t *pid, float sp, float fb, float fb_dot, float dt);
/**
* @brief 重置微分项
*
* @param pid PID结构体
* @return int8_t 0对应没有错误
*/
int8_t PID_ResetIntegral(KPID_t *pid);
/**
* @brief 重置PID
*
* @param pid PID结构体
* @return int8_t 0对应没有错误
*/
int8_t PID_Reset(KPID_t *pid);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,88 @@
/*
自定义的数学运算。
*/
#include "user_math.h"
#include <string.h>
#include <stdint.h>
inline float InvSqrt(float x) {
//#if 0
/* Fast inverse square-root */
/* See: http://en.wikipedia.org/wiki/Fast_inverse_square_root */
float halfx = 0.5f * x;
float y = x;
long i = *(long*)&y;
i = 0x5f3759df - (i>>1);
y = *(float*)&i;
y = y * (1.5f - (halfx * y * y));
y = y * (1.5f - (halfx * y * y));
return y;
//#else
// return 1.0f / sqrtf(x);
//#endif
}
inline float AbsClip(float in, float limit) {
return (in < -limit) ? -limit : ((in > limit) ? limit : in);
}
float fAbs(float in){
return (in > 0) ? in : -in;
}
inline void Clip(float *origin, float min, float max) {
if (*origin > max) *origin = max;
if (*origin < min) *origin = min;
}
inline float Sign(float in) { return (in > 0) ? 1.0f : 0.0f; }
/**
* \brief 计算循环值的误差,用于没有负数值,并在一定范围内变化的值
* 例如编码器相差1.5PI其实等于相差-0.5PI
*
* \param sp 被操作的值
* \param fb 变化量
* \param range 被操作的值变化范围,正数时起效
*
* \return 函数运行结果
*/
inline float CircleError(float sp, float fb, float range) {
float error = sp - fb;
if (range > 0.0f) {
float half_range = range / 2.0f;
if (error > half_range)
error -= range;
else if (error < -half_range)
error += range;
}
return error;
}
/**
* \brief 循环加法,用于没有负数值,并在一定范围内变化的值
* 例如编码器在0-2PI内变化1.5PI + 1.5PI = 1PI
*
* \param origin 被操作的值
* \param delta 变化量
* \param range 被操作的值变化范围,正数时起效
*/
inline void CircleAdd(float *origin, float delta, float range) {
float out = *origin + delta;
if (range > 0.0f) {
if (out >= range)
out -= range;
else if (out < 0.0f)
out += range;
}
*origin = out;
}
/**
* @brief 循环值取反
*
* @param origin 被操作的值
*/
inline void CircleReverse(float *origin) { *origin = -(*origin) + M_2PI; }

View File

@@ -0,0 +1,130 @@
/*
自定义的数学运算。
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <float.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#define M_DEG2RAD_MULT (0.01745329251f)
#define M_RAD2DEG_MULT (57.2957795131f)
#ifndef M_PI
#define M_PI 3.14159265358979323846f
#endif
#ifndef M_2PI
#define M_2PI 6.28318530717958647692f
#endif
#define max(a, b) \
({ \
__typeof__(a) _a = (a); \
__typeof__(b) _b = (b); \
_a > _b ? _a : _b; \
})
#define min(a, b) \
({ \
__typeof__(a) _a = (a); \
__typeof__(b) _b = (b); \
_a < _b ? _a : _b; \
})
/* 移动向量 */
typedef struct {
float vx; /* 前后平移 */
float vy; /* 左右平移 */
float wz; /* 转动 */
} MoveVector_t;
float InvSqrt(float x);
float AbsClip(float in, float limit);
float fAbs(float in);
void Clip(float *origin, float min, float max);
float Sign(float in);
/**
* \brief 计算循环值的误差,用于没有负数值,并在一定范围内变化的值
* 例如编码器相差1.5PI其实等于相差-0.5PI
*
* \param sp 被操作的值
* \param fb 变化量
* \param range 被操作的值变化范围,正数时起效
*
* \return 函数运行结果
*/
float CircleError(float sp, float fb, float range);
/**
* \brief 循环加法,用于没有负数值,并在一定范围内变化的值
* 例如编码器在0-2PI内变化1.5PI + 1.5PI = 1PI
*
* \param origin 被操作的值
* \param delta 变化量
* \param range 被操作的值变化范围,正数时起效
*/
void CircleAdd(float *origin, float delta, float range);
/**
* @brief 循环值取反
*
* @param origin 被操作的值
*/
void CircleReverse(float *origin);
#ifdef __cplusplus
}
#endif
#ifdef DEBUG
/**
* @brief 如果表达式的值为假则运行处理函数
*
*/
#define ASSERT(expr) \
do { \
if (!(expr)) { \
VerifyFailed(__FILE__, __LINE__); \
} \
} while (0)
#else
/**
* @brief 未定DEBUG表达式不会运行断言被忽略
*
*/
#define ASSERT(expr) ((void)(0))
#endif
#ifdef DEBUG
/**
* @brief 如果表达式的值为假则运行处理函数
*
*/
#define VERIFY(expr) \
do { \
if (!(expr)) { \
VerifyFailed(__FILE__, __LINE__); \
} \
} while (0)
#else
/**
* @brief 表达式会运行,忽略表达式结果
*
*/
#define VERIFY(expr) ((void)(expr))
#endif

BIN
assets/User_code/device/.DS_Store vendored Normal file

Binary file not shown.

View File

View File

@@ -0,0 +1,301 @@
#include "bmp280_i2c.h"
#include "bsp/i2c.h"
#define I2C_Handle BSP_I2C_GetHandle(BSP_I2C_BMP280)
/**
* @brief 读寄存器
* @param regAdd 寄存器开始地址
* @param pdata 存储数据的指针
* @param size 寄存器个数
* @retval 无
*/
void bmp280_readReg(uint8_t regAdd, uint8_t *pdata, uint8_t size) {
HAL_I2C_Mem_Read(I2C_Handle, BMP280_I2C_ADDR << 1, regAdd, I2C_MEMADD_SIZE_8BIT, pdata, size, 1000);
}
/**
* @brief 写1个寄存器
* @param regAdd 寄存器开始地址
* @param pdata 存储数据的指针
* @retval 0 写入成功
* 1 写入失败
*/
uint8_t bmp280_writeReg(uint8_t regAdd, uint8_t *pdata) {
if (HAL_I2C_Mem_Write(I2C_Handle, BMP280_I2C_ADDR << 1, regAdd, I2C_MEMADD_SIZE_8BIT, pdata, 1, 1000) == HAL_OK) {
return 0;
}
return 1;
}
/**
* @brief 读取设备物理id用于调试
* @param 无
* @retval 设备id
*/
uint8_t bmp280_get_id(void) {
uint8_t temp = 0;
bmp280_readReg(BMP280_ID, &temp, 1);
return temp;
}
/**
* @brief 重启设备
* @param 无
* @retval 0 重启成功
* 1 重启失败
*/
uint8_t bmp280_reset(void) {
uint8_t temp = 0xB6;
return bmp280_writeReg(BMP280_RESET, &temp);
}
/**
* @brief 获取设备状态
* @param 无
* @retval 0 空闲
* 1 正在测量或者正在复制
*/
uint8_t bmp280_getStatus(void) {
uint8_t temp = 0;
bmp280_readReg(BMP280_STATUS, &temp, 1);
return (temp & 0x09) ? 1 : 0;
}
/**
* @brief 工作模式设置推荐
* @param mode 0 睡眠模式
* 1 单次测量模式,测量完成后回到休眠模式
* 2 连续测量模式
* @retval 0 设置成功
* 1 设置失败
*/
uint8_t bmp280_setMode(uint8_t mode)
{
uint8_t temp=0;
bmp280_readReg(BMP280_CTRL_MEAS,&temp,1);
switch(mode)
{
case 0:
temp&=0xFC;
break;
case 1:
temp&=0xFC;
temp|=0x01;
break;
case 2:
temp&=0xFC;
temp|=0x03;
break;
default:
return 1;
}
return bmp280_writeReg(BMP280_CTRL_MEAS,&temp);
}
/**
* @brief 过采样设置
* @param mode temp&press 0 禁用
* 1 过采样×1
* 2 过采样×2
* 3 过采样×4
* .. .....
* 5 过采样×16
* @retval 0 设置成功
* 1 设置失败
*/
uint8_t bmp280_setOversampling(uint8_t osrs_p,uint8_t osrs_t)
{
uint8_t temp=0;
bmp280_readReg(BMP280_CTRL_MEAS,&temp,1);
temp&=0xE3;
osrs_p = osrs_p<<2;
osrs_p&= 0x1C;
temp|=osrs_p;
temp&=0x1F;
osrs_t = osrs_t<<5;
osrs_t&= 0xE0;
temp|=osrs_t;
return bmp280_writeReg(BMP280_CTRL_MEAS,&temp);
}
/**
* @brief 滤波器系数和采样间隔时间设置
* @param Standbyt 0 0.5ms filter 0 关闭滤波器
* 1 62.5ms 1 2
* 2 125ms 2 4
* 3 250ms 3 8
* 4 500ms 4 16
* 5 1000ms
* 6 2000ms
* 7 4000ms
* @retval 0 设置成功
* 1 设置失败
*/
uint8_t bmp280_setConfig(uint8_t Standbyt,uint8_t filter)
{
uint8_t temp=0;
temp = Standbyt<<5;
filter&=0x07;
filter=filter<<2;
temp|=filter;
return bmp280_writeReg(BMP280_CONFIG,&temp);
}
/**
* @brief 获取校准系数
* @param calib 储存系数的结构体
* @retval 无
*/
void bmp280_getCalibration(bmp280_calib *calib)
{
uint8_t buf[20];
bmp280_readReg(BMP280_DIGT,buf,6);
calib->dig_t1 =(uint16_t)(bmp280_msblsb_to_u16(buf[1], buf[0]));
calib->dig_t2 =(int16_t)(bmp280_msblsb_to_u16(buf[3], buf[2]));
calib->dig_t3 =(int16_t)(bmp280_msblsb_to_u16(buf[5], buf[4]));
bmp280_readReg(BMP280_DIGP,buf,18);
calib->dig_p1 = (uint16_t)(bmp280_msblsb_to_u16(buf[1], buf[0]));
calib->dig_p2 =(int16_t)(bmp280_msblsb_to_u16(buf[3], buf[2]));
calib->dig_p3 =(int16_t)(bmp280_msblsb_to_u16(buf[5], buf[4]));
calib->dig_p4 =(int16_t)(bmp280_msblsb_to_u16(buf[7], buf[6]));
calib->dig_p5 =(int16_t)(bmp280_msblsb_to_u16(buf[9], buf[8]));
calib->dig_p6 =(int16_t)(bmp280_msblsb_to_u16(buf[11], buf[10]));
calib->dig_p7 =(int16_t)(bmp280_msblsb_to_u16(buf[13], buf[12]));
calib->dig_p8 =(int16_t)(bmp280_msblsb_to_u16(buf[15], buf[14]));
calib->dig_p9 =(int16_t)(bmp280_msblsb_to_u16(buf[17], buf[16]));
}
/**
* @brief 获取温度
* @param calib 系数的结构体
* *temperature 温度值指针
* *t_fine 精细分辨率温度值指针
* @retval 无
*/
void bmp280_getTemperature(bmp280_calib *calib,double *temperature,int32_t *t_fine)
{
uint8_t buf[3];
uint32_t data_xlsb;
uint32_t data_lsb;
uint32_t data_msb;
int32_t uncomp_temperature;
double var1, var2;
bmp280_readReg(BMP280_TEMP,buf,3);
data_msb = (int32_t)buf[0] << 12;
data_lsb = (int32_t)buf[1] << 4;
data_xlsb = (int32_t)buf[2] >> 4;
uncomp_temperature = (int32_t)(data_msb | data_lsb | data_xlsb);
var1 = (((double) uncomp_temperature) / 16384.0 - ((double) calib->dig_t1) / 1024.0) *
((double) calib->dig_t2);
var2 =
((((double) uncomp_temperature) / 131072.0 - ((double) calib->dig_t1) / 8192.0) *
(((double) uncomp_temperature) / 131072.0 - ((double) calib->dig_t1) / 8192.0)) *
((double) calib->dig_t3);
*t_fine = (int32_t) (var1 + var2);
*temperature = (var1 + var2) / 5120.0;
}
/**
* @brief 获取气压
* @param calib 系数的结构体
* *pressure 气压值指针
* *t_fine 精细分辨率温度值指针
* @retval 无
*/
void bmp280_getPressure(bmp280_calib *calib,double *pressure,int32_t *t_fine)
{
uint8_t buf[3];
uint32_t data_xlsb;
uint32_t data_lsb;
uint32_t data_msb;
int32_t uncomp_pressure;
double var1, var2;
bmp280_readReg(BMP280_PRES,buf,3);
data_msb = (uint32_t)buf[0] << 12;
data_lsb = (uint32_t)buf[1] << 4;
data_xlsb = (uint32_t)buf[2] >> 4;
uncomp_pressure = (data_msb | data_lsb | data_xlsb);
var1 = ((double) *t_fine / 2.0) - 64000.0;
var2 = var1 * var1 * ((double) calib->dig_p6) / 32768.0;
var2 = var2 + var1 * ((double) calib->dig_p5) * 2.0;
var2 = (var2 / 4.0) + (((double) calib->dig_p4) * 65536.0);
var1 = (((double)calib->dig_p3) * var1 * var1 / 524288.0 + ((double)calib->dig_p2) * var1) /
524288.0;
var1 = (1.0 + var1 / 32768.0) * ((double) calib->dig_p1);
*pressure = 1048576.0 - (double)uncomp_pressure;
*pressure = (*pressure - (var2 / 4096.0)) * 6250.0 / var1;
var1 = ((double)calib->dig_p9) * *pressure * *pressure / 2147483648.0;
var2 = *pressure * ((double)calib->dig_p8) / 32768.0;
*pressure = *pressure + (var1 + var2 + ((double)calib->dig_p7)) / 16.0;
}
/**
* @brief 初始化
* @param *calib 系数的结构体指针
* @retval 0 设置成功
* 1 设置失败
*/
uint8_t bmp280_init(bmp280_calib *calib)
{
uint8_t rslt;
rslt = bmp280_get_id();
if(rslt == BMP2_CHIP_ID)
{
bmp280_getCalibration(calib);
rslt = bmp280_setOversampling(5,2);
if(rslt)
{
return 1;
}
rslt = bmp280_setConfig(0,4);
if(rslt)
{
return 1;
}
rslt = bmp280_setMode(2);
if(rslt)
{
return 1;
}
}
else
{
return 1;
}
return 0;
}
/**
* @brief 获取最终数据
* @param *calib 系数的结构体指针
* @retval 无
*/
void bmp280_getdata(bmp280_calib *calib,float *temperature,float *pressure)
{
double temp_T,temp_P;
int32_t t_fine;
bmp280_getTemperature(calib,&temp_T,&t_fine);
bmp280_getPressure(calib,&temp_P,&t_fine);
*temperature = (float)temp_T;
*pressure = (float)temp_P;
}

View File

@@ -0,0 +1,49 @@
#pragma once
/*底层接口定义*/
#include "bsp/i2c.h"
#include "stdint.h"
#define BMP280_I2C_ADDR 0x76 // BMP280 默认 I2C 地址
/*寄存器地址*/
#define BMP280_ID 0xD0 // 设备ID地址
#define BMP280_RESET 0xE0 // 设备重启
#define BMP280_STATUS 0xF3 // 设备状态
#define BMP280_CTRL_MEAS 0xF4 // 数据采集和模式设置
#define BMP280_CONFIG 0xF5 // 采样速率,滤波器和接口设置
#define BMP280_DIGT 0x88 // 温度校准系数起始位置
#define BMP280_DIGP 0x8E // 气压校准系数起始位置
#define BMP280_TEMP 0xFA // 温度储存起始位置
#define BMP280_PRES 0xF7 // 气压储存起始位置
#define BMP2_CHIP_ID 0x58 // 设备ID地址
#define bmp280_msblsb_to_u16(msb, lsb) (((uint16_t)msb << 8) | ((uint16_t)lsb))
typedef struct {
unsigned short dig_t1;
signed short dig_t2;
signed short dig_t3;
unsigned short dig_p1;
signed short dig_p2;
signed short dig_p3;
signed short dig_p4;
signed short dig_p5;
signed short dig_p6;
signed short dig_p7;
signed short dig_p8;
signed short dig_p9;
} bmp280_calib;
uint8_t bmp280_get_id(void);
uint8_t bmp280_reset(void);
uint8_t bmp280_getStatus(void);
uint8_t bmp280_setMode(uint8_t mode);
uint8_t bmp280_setOversampling(uint8_t osrs_p, uint8_t osrs_t);
uint8_t bmp280_setConfig(uint8_t Standbyt, uint8_t filter);
void bmp280_getCalibration(bmp280_calib *calib);
void bmp280_getTemperature(bmp280_calib *calib, double *temperature, int32_t *t_fine);
void bmp280_getPressure(bmp280_calib *calib, double *pressure, int32_t *t_fine);
uint8_t bmp280_init(bmp280_calib *calib);
void bmp280_getdata(bmp280_calib *calib, float *temperature, float *pressure);

View File

@@ -0,0 +1,5 @@
oled_i2c,bsp/i2c
bmp280_i2c,bsp/i2c
pc_uart,bsp/uart
key_gpio,bsp/gpio_exti
servo,bsp/servo_pwm
1 oled_i2c bsp/i2c
2 bmp280_i2c bsp/i2c
3 pc_uart bsp/uart
4 key_gpio bsp/gpio_exti
5 servo bsp/servo_pwm

View File

@@ -0,0 +1 @@
servo,测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息
1 servo 测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息测试消息

View File

@@ -0,0 +1,15 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define DEVICE_OK (0)
#define DEVICE_ERR (-1)
#define DEVICE_ERR_NULL (-2)
#define DEVICE_ERR_INITED (-3)
#define DEVICE_ERR_NO_DEV (-4)
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,65 @@
/* Includes ----------------------------------------------------------------- */
#include "key_gpio.h"
#include "device.h"
#include "bsp/gpio_exti.h"
#include "gpio.h"
/* Private define ----------------------------------------------------------- */
#define DEBOUNCE_TIME_MS 20
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
/* Private function -------------------------------------------------------- */
/* 外部声明标志位(标志位) */
volatile uint8_t key_flag = 0; // 1=按下0=松开
volatile uint8_t key_exti = 0;
volatile uint8_t key_pressed = 0; // 全局标志位
static uint32_t last_debounce_time = 0; // 消抖
/* Private function -------------------------------------------------------- */
static void KEY_Interrupt_Callback(void) {
// 切换标志位状态
key_flag = !key_flag;
key_exti = 1;
}
/* Exported functions ------------------------------------------------------- */
void KEY_Process(void)
{
BSP_GPIO_RegisterCallback(BSP_GPIO_USER_KEY, BSP_GPIO_EXTI_CB, KEY_Interrupt_Callback);
if(key_exti == 1)
{
uint32_t now = HAL_GetTick();
// 检查是否超过消抖时间
if ((now - last_debounce_time) > DEBOUNCE_TIME_MS) {
// 更新有效状态(假设按下为低电平)
if(key_flag == 0)
{
key_pressed = DEVICE_KEY_RELEASED;
}
if(key_flag == 1)
{
key_pressed = DEVICE_KEY_PRESSED;
}
}
else
{
HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6);
}
last_debounce_time = now; // 重置消抖计时器
key_exti = 0;
}
else
{
}
}
uint8_t KEY_Get_State(void) {
return key_pressed;
}

View File

@@ -0,0 +1,21 @@
#ifndef KEY_GPIO_H
#define KEY_GPIO_H
/* Includes ----------------------------------------------------------------- */
#include <stdint.h>
#include "main.h"
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
///* KEY按键状态设置用 */
typedef enum
{
DEVICE_KEY_RELEASED, //按键释放
DEVICE_KEY_PRESSED, //按键按下
} DEVICE_KEY_Status_t;
void KEY_Process(void);
uint8_t KEY_Get_State(void);
#endif

View File

@@ -0,0 +1,267 @@
/* Includes ----------------------------------------------------------------- */
#include "device/oled_i2c.h"
#include "bsp/i2c.h"
#include <string.h>
#include <stdint.h>
/* Private define ----------------------------------------------------------- */
#define OLED_I2C_ADDR 0x78 // OLED I2C 地址
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
/* Private variables -------------------------------------------------------- */
static uint8_t oled_buffer[OLED_WIDTH * OLED_HEIGHT / 8];
static struct {
uint8_t x_min;
uint8_t x_max;
uint8_t y_min;
uint8_t y_max;
uint8_t dirty; // 标志是否有脏区域
} dirty_rect = {0, 0, 0, 0, 0};
/* Private function prototypes ---------------------------------------------- */
static void OLED_WriteCommand(uint8_t cmd) {
uint8_t data[2] = {0x00, cmd};
HAL_I2C_Master_Transmit(BSP_I2C_GetHandle(BSP_I2C_OLED), OLED_I2C_ADDR, data, 2, HAL_MAX_DELAY);
}
static void OLED_WriteData(uint8_t *data, uint16_t size) {
uint8_t buffer[size + 1];
buffer[0] = 0x40;
memcpy(&buffer[1], data, size);
HAL_I2C_Master_Transmit(BSP_I2C_GetHandle(BSP_I2C_OLED), OLED_I2C_ADDR, buffer, size + 1, HAL_MAX_DELAY);
}
static void OLED_MarkDirty(uint8_t x, uint8_t y);
static void OLED_UpdateDirtyScreen(void);
static const uint8_t oled_font[95][8] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}, /* " ", 0 */
{0x00,0x00,0x00,0xcf,0xcf,0x00,0x00,0x00,}, /* "!", 1 */
{0x00,0x0c,0x06,0x00,0x0c,0x06,0x00,0x00,}, /* """, 2 */
{0x24,0xe4,0x3c,0x27,0xe4,0x3c,0x27,0x24,}, /* "#", 3 */
{0x00,0x20,0x46,0xf9,0x9f,0x62,0x04,0x00,}, /* "$", 4 */
{0x06,0x09,0xc6,0x30,0x0c,0x63,0x90,0x60,}, /* "%", 5 */
{0x00,0x00,0x6e,0x91,0xa9,0x46,0xa0,0x00,}, /* "&", 6 */
{0x00,0x00,0x00,0x1c,0x0e,0x00,0x00,0x00,}, /* "'", 7 */
{0x00,0x00,0x3c,0x42,0x81,0x00,0x00,0x00,}, /* "(", 8 */
{0x00,0x00,0x00,0x81,0x42,0x3c,0x00,0x00,}, /* ")", 9 */
{0x00,0x10,0x54,0x38,0x38,0x54,0x10,0x00,}, /* "*", 10 */
{0x00,0x10,0x10,0xfc,0x10,0x10,0x00,0x00,}, /* "+", 11 */
{0x00,0x00,0x00,0xc0,0x60,0x00,0x00,0x00,}, /* ",", 12 */
{0x00,0x00,0x10,0x10,0x10,0x10,0x00,0x00,}, /* "-", 13 */
{0x00,0x00,0x00,0x00,0xc0,0xc0,0x00,0x00,}, /* ".", 14 */
{0x00,0x00,0x00,0xc0,0x38,0x07,0x00,0x00,}, /* "/", 15 */
{0x00,0x00,0x7c,0x92,0x8a,0x7c,0x00,0x00,}, /* "0", 16 */
{0x00,0x00,0x00,0x84,0xfe,0x80,0x00,0x00,}, /* "1", 17 */
{0x00,0x00,0x8c,0xc2,0xa2,0x9c,0x00,0x00,}, /* "2", 18 */
{0x00,0x00,0x44,0x92,0x92,0x6c,0x00,0x00,}, /* "3", 19 */
{0x00,0x20,0x38,0x24,0xfe,0x20,0x00,0x00,}, /* "4", 20 */
{0x00,0x00,0x5e,0x92,0x92,0x62,0x00,0x00,}, /* "5", 21 */
{0x00,0x00,0x78,0x94,0x92,0x62,0x00,0x00,}, /* "6", 22 */
{0x00,0x00,0x82,0x62,0x1a,0x06,0x00,0x00,}, /* "7", 23 */
{0x00,0x00,0x6c,0x92,0x92,0x6c,0x00,0x00,}, /* "8", 24 */
{0x00,0x00,0x8c,0x52,0x32,0x1c,0x00,0x00,}, /* "9", 25 */
{0x00,0x00,0x00,0x6c,0x6c,0x00,0x00,0x00,}, /* ":", 26 */
{0x00,0x00,0x80,0xec,0x6c,0x00,0x00,0x00,}, /* ";", 27 */
{0x00,0x00,0x10,0x28,0x44,0x00,0x00,0x00,}, /* "<", 28 */
{0x00,0x00,0x24,0x24,0x24,0x24,0x00,0x00,}, /* "=", 29 */
{0x00,0x00,0x00,0x44,0x28,0x10,0x00,0x00,}, /* ">", 30 */
{0x00,0x00,0x0c,0xa2,0x92,0x1c,0x00,0x00,}, /* "?", 31 */
{0x00,0x3c,0x42,0x99,0xa5,0xa2,0x3c,0x00,}, /* "@", 32 */
{0x00,0xe0,0x1c,0x12,0x12,0x1c,0xe0,0x00,}, /* "A", 33 */
{0x00,0xfe,0x92,0x92,0x9c,0x90,0x60,0x00,}, /* "B", 34 */
{0x00,0x38,0x44,0x82,0x82,0x82,0x44,0x00,}, /* "C", 35 */
{0x00,0xfe,0x82,0x82,0x82,0x82,0x7c,0x00,}, /* "D", 36 */
{0x00,0xfe,0x92,0x92,0x92,0x92,0x92,0x00,}, /* "E", 37 */
{0x00,0xfe,0x12,0x12,0x12,0x12,0x02,0x00,}, /* "F", 38 */
{0x00,0x7c,0x82,0x92,0x92,0x72,0x00,0x00,}, /* "G", 39 */
{0x00,0xfe,0x10,0x10,0x10,0x10,0xfe,0x00,}, /* "H", 40 */
{0x00,0x82,0x82,0xfe,0x82,0x82,0x00,0x00,}, /* "I", 41 */
{0x00,0x82,0x82,0x7e,0x02,0x02,0x00,0x00,}, /* "J", 42 */
{0x00,0xfe,0x10,0x28,0x44,0x82,0x00,0x00,}, /* "K", 43 */
{0x00,0xfe,0x80,0x80,0x80,0x80,0x00,0x00,}, /* "L", 44 */
{0xfc,0x02,0x04,0xf8,0x04,0x02,0xfc,0x00,}, /* "M", 45 */
{0x00,0xfe,0x04,0x18,0x30,0x40,0xfe,0x00,}, /* "N", 46 */
{0x00,0x7c,0x82,0x82,0x82,0x82,0x7c,0x00,}, /* "O", 47 */
{0x00,0x00,0xfe,0x12,0x12,0x0c,0x00,0x00,}, /* "P", 48 */
{0x00,0x00,0x3c,0x42,0xc2,0xbc,0x00,0x00,}, /* "Q", 49 */
{0x00,0x00,0xfe,0x32,0x52,0x8c,0x00,0x00,}, /* "R", 50 */
{0x00,0x00,0x4c,0x92,0x92,0x64,0x00,0x00,}, /* "S", 51 */
{0x00,0x02,0x02,0xfe,0x02,0x02,0x00,0x00,}, /* "T", 52 */
{0x00,0x7e,0x80,0x80,0x80,0x80,0x7e,0x00,}, /* "U", 53 */
{0x00,0x0c,0x30,0xc0,0x30,0x0c,0x00,0x00,}, /* "V", 54 */
{0x7c,0x80,0x80,0x78,0x80,0x80,0x7c,0x00,}, /* "W", 55 */
{0x00,0x84,0x48,0x30,0x30,0x48,0x84,0x00,}, /* "X", 56 */
{0x00,0x06,0x08,0xf0,0x08,0x06,0x00,0x00,}, /* "Y", 57 */
{0x00,0x00,0xc2,0xa2,0x92,0x8e,0x00,0x00,}, /* "Z", 58 */
{0x00,0x00,0xfe,0x82,0x82,0x82,0x00,0x00,}, /* "[", 59 */
{0x00,0x00,0x06,0x18,0x60,0x80,0x00,0x00,}, /* "\", 60 */
{0x00,0x00,0x82,0x82,0x82,0xfe,0x00,0x00,}, /* "]", 61 */
{0x00,0x30,0x0c,0x02,0x0c,0x30,0x00,0x00,}, /* "^", 62 */
{0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,}, /* "_", 63 */
{0x00,0x00,0x04,0x0c,0x18,0x00,0x00,0x00,}, /* "`", 64 */
{0x00,0x00,0x60,0x90,0x90,0xe0,0x00,0x00,}, /* "a", 65 */
{0x00,0x00,0xf8,0xa0,0xe0,0x00,0x00,0x00,}, /* "b", 66 */
{0x00,0x00,0x60,0x90,0x90,0x00,0x00,0x00,}, /* "c", 67 */
{0x00,0x00,0xe0,0xa0,0xf8,0x00,0x00,0x00,}, /* "d", 68 */
{0x00,0x00,0x70,0xa8,0xa8,0x90,0x00,0x00,}, /* "e", 69 */
{0x00,0x00,0x10,0xf8,0x14,0x00,0x00,0x00,}, /* "f", 70 */
{0x00,0x00,0xd8,0xa4,0x7c,0x00,0x00,0x00,}, /* "g", 71 */
{0x00,0x00,0xf8,0x20,0xe0,0x00,0x00,0x00,}, /* "h", 72 */
{0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x00,}, /* "i", 73 */
{0x00,0x00,0x40,0x90,0x74,0x00,0x00,0x00,}, /* "j", 74 */
{0x00,0x00,0xf8,0x60,0x90,0x00,0x00,0x00,}, /* "k", 75 */
{0x00,0x00,0x78,0x80,0x80,0x00,0x00,0x00,}, /* "l", 76 */
{0x00,0xe0,0x10,0xe0,0x10,0xe0,0x00,0x00,}, /* "m", 77 */
{0x00,0x00,0xf0,0x10,0x10,0xe0,0x00,0x00,}, /* "n", 78 */
{0x00,0x00,0x60,0x90,0x90,0x60,0x00,0x00,}, /* "o", 79 */
{0x00,0x00,0xf0,0x48,0x48,0x30,0x00,0x00,}, /* "p", 80 */
{0x00,0x00,0x30,0x48,0x48,0xf0,0x00,0x00,}, /* "q", 81 */
{0x00,0x00,0x00,0xf0,0x20,0x10,0x00,0x00,}, /* "r", 82 */
{0x00,0x00,0x90,0xa8,0xa8,0x48,0x00,0x00,}, /* "s", 83 */
{0x00,0x10,0x10,0xf8,0x90,0x90,0x00,0x00,}, /* "t", 84 */
{0x00,0x00,0x78,0x80,0x80,0xf8,0x00,0x00,}, /* "u", 85 */
{0x00,0x18,0x60,0x80,0x60,0x18,0x00,0x00,}, /* "v", 86 */
{0x00,0x38,0xc0,0x38,0xc0,0x38,0x00,0x00,}, /* "w", 87 */
{0x00,0x88,0x50,0x20,0x50,0x88,0x00,0x00,}, /* "x", 88 */
{0x00,0x8c,0x50,0x20,0x10,0x0c,0x00,0x00,}, /* "y", 89 */
{0x00,0x88,0xc8,0xa8,0x98,0x88,0x00,0x00,}, /* "z", 90 */
{0x00,0x00,0x10,0x7c,0x82,0x00,0x00,0x00,}, /* "{", 91 */
{0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,}, /* "|", 92 */
{0x00,0x00,0x00,0x82,0x7c,0x10,0x00,0x00,}, /* "}", 93 */
{0x00,0x08,0x04,0x04,0x08,0x10,0x10,0x08,}, /* "~", 94 */
};
/* Exported functions ------------------------------------------------------- */
void OLED_Init(void) {
OLED_WriteCommand(0xAE); // 关闭显示
OLED_WriteCommand(0x20); // 设置内存寻址模式
OLED_WriteCommand(0x10); // 页寻址模式
OLED_WriteCommand(0xB0); // 设置页起始地址
OLED_WriteCommand(0xC8); // 设置COM扫描方向
OLED_WriteCommand(0x00); // 设置低列地址
OLED_WriteCommand(0x10); // 设置高列地址
OLED_WriteCommand(0x40); // 设置显示起始行
OLED_WriteCommand(0x81); // 设置对比度
OLED_WriteCommand(0xFF); // 最大对比度
OLED_WriteCommand(0xA1); // 设置段重映射
OLED_WriteCommand(0xA6); // 正常显示
OLED_WriteCommand(0xA8); // 设置多路复用比率
OLED_WriteCommand(0x3F); // 1/64
OLED_WriteCommand(0xA4); // 输出跟随 RAM 内容
OLED_WriteCommand(0xD3); // 设置显示偏移
OLED_WriteCommand(0x00); // 无偏移
OLED_WriteCommand(0xD5); // 设置显示时钟分频比/振荡频率
OLED_WriteCommand(0xF0); // 高频
OLED_WriteCommand(0xD9); // 设置预充电周期
OLED_WriteCommand(0x22); // 修复缺少分号
OLED_WriteCommand(0xDA); // 设置COM引脚硬件配置
OLED_WriteCommand(0x12); // 修复缺少分号
OLED_WriteCommand(0xDB); // 设置VCOMH电压
OLED_WriteCommand(0x20); // 修复缺少分号
OLED_WriteCommand(0x8D); // 设置充电泵
OLED_WriteCommand(0x14); // 修复缺少分号
OLED_WriteCommand(0xAF); // 打开显示
}
void OLED_Clear(void) {
memset(oled_buffer, 0, sizeof(oled_buffer));
dirty_rect.x_min = 0;
dirty_rect.x_max = OLED_WIDTH - 1;
dirty_rect.y_min = 0;
dirty_rect.y_max = OLED_HEIGHT - 1;
dirty_rect.dirty = 1;
OLED_UpdateScreen();
}
void OLED_UpdateScreen(void) {
OLED_UpdateDirtyScreen();
}
void OLED_DrawPixel(uint8_t x, uint8_t y, uint8_t color) {
if (x >= OLED_WIDTH || y >= OLED_HEIGHT) return;
if (color) {
if (!(oled_buffer[x + (y / 8) * OLED_WIDTH] & (1 << (y % 8)))) {
oled_buffer[x + (y / 8) * OLED_WIDTH] |= (1 << (y % 8));
OLED_MarkDirty(x, y);
}
} else {
if (oled_buffer[x + (y / 8) * OLED_WIDTH] & (1 << (y % 8))) {
oled_buffer[x + (y / 8) * OLED_WIDTH] &= ~(1 << (y % 8));
OLED_MarkDirty(x, y);
}
}
}
void OLED_DrawChar(uint8_t x, uint8_t y, char ch, uint8_t color) {
if (ch < ' ' || ch > '~') return;
if (x >= OLED_WIDTH || y >= OLED_HEIGHT || x + 8 > OLED_WIDTH || y + 8 > OLED_HEIGHT) {
return;
}
const uint8_t *font_data = oled_font[ch - ' '];
for (uint8_t i = 0; i < 8; i++) {
uint8_t column_data = font_data[i];
for (uint8_t j = 0; j < 8; j++) {
if (column_data & (1 << j)) {
OLED_DrawPixel(x + i, y + j, color);
} else {
OLED_DrawPixel(x + i, y + j, !color);
}
}
}
}
void OLED_DrawString(uint8_t x, uint8_t y, const char *str, uint8_t color) {
while (*str) {
OLED_DrawChar(x, y, *str, color);
x += 8;
if (x + 8 > OLED_WIDTH) {
x = 0;
y += 8;
}
if (y + 8 > OLED_HEIGHT) {
break;
}
str++;
}
}
/* Private functions -------------------------------------------------------- */
static void OLED_MarkDirty(uint8_t x, uint8_t y) {
if (!dirty_rect.dirty) {
dirty_rect.x_min = x;
dirty_rect.x_max = x;
dirty_rect.y_min = y;
dirty_rect.y_max = y;
dirty_rect.dirty = 1;
} else {
if (x < dirty_rect.x_min) dirty_rect.x_min = x;
if (x > dirty_rect.x_max) dirty_rect.x_max = x;
if (y < dirty_rect.y_min) dirty_rect.y_min = y;
if (y > dirty_rect.y_max) dirty_rect.y_max = y;
}
}
static void OLED_UpdateDirtyScreen(void) {
if (!dirty_rect.dirty) return;
uint8_t y_start = dirty_rect.y_min / 8;
uint8_t y_end = dirty_rect.y_max / 8;
for (uint8_t i = y_start; i <= y_end; i++) {
OLED_WriteCommand(0xB0 + i);
OLED_WriteCommand(dirty_rect.x_min & 0x0F);
OLED_WriteCommand(0x10 | (dirty_rect.x_min >> 4));
uint8_t width = dirty_rect.x_max - dirty_rect.x_min + 1;
OLED_WriteData(&oled_buffer[dirty_rect.x_min + i * OLED_WIDTH], width);
}
dirty_rect.dirty = 0;
}

View File

@@ -0,0 +1,26 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include <stdint.h>
/* Exported constants ------------------------------------------------------- */
#define OLED_COLOR_BLACK 0
#define OLED_COLOR_WHITE 1
/* Exported functions prototypes -------------------------------------------- */
void OLED_Init(void);
void OLED_Clear(void);
void OLED_UpdateScreen(void);
void OLED_DrawPixel(uint8_t x, uint8_t y, uint8_t color);
void OLED_DrawString(uint8_t x, uint8_t y, const char *str, uint8_t color);
void OLED_DrawChar(uint8_t x, uint8_t y, char ch, uint8_t color);
void OLED_ShowChinese(uint8_t x, uint8_t y, uint8_t index);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,57 @@
/* Includes ----------------------------------------------------------------- */
#include "pc_uart.h"
#include <string.h>
#include "bsp\uart.h"
#include "device.h"
#define UART_HANDLE BSP_UART_GetHandle(BSP_UART_PC)
#define AI_LEN_RX_BUFF (sizeof(UART_RxData_t))
static bool rx_flag = false;
static uint8_t rxbuf[AI_LEN_RX_BUFF];
static void UART_RxCpltCallback(void) { rx_flag = true; }
int UART_Init(UART_t *huart)
{
UNUSED(huart);
//注册回调函数
HAL_UART_RegisterCallback(UART_HANDLE, BSP_UART_RX_CPLT_CB, UART_RxCpltCallback);
return DEVICE_OK
}
int UART_StartReceive(UART_t *huart)
{
UNUSED(huart);
HAL_UART_Receive_DMA(UART_HANDLE, rxbuf, AI_LEN_RX_BUFF);
return DEVICE_OK;
}
bool UART_IsReceiveComplete(void)
{
return rx_flag;
}
int8_t UART_ParseData(UART_t *huart)
{
memcpy(&huart->rx_data, rxbuf, sizeof(UART_RxData_t));
}
void UART_PackTx(UART_t *huart, UART_TxData_t *tx_data)
{
memcpy(tx_data, huart->tx_data, sizeof(UART_TxData_t));
}
int8_t UART_StartSend(UART_t *huart)
{
if (HAL_UART_Transmit_DMA(UART_HANDLE, huart->tx_data, sizeof(UART_TxData_t)) == HAL_OK)
{
return DEVICE_OK
}
return DEVICE_ERR;
}

View File

@@ -0,0 +1,50 @@
/*
UART通讯模板
*/
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
/* Includes ----------------------------------------------------------------- */
#include <stdbool.h>
#include <stdint.h>
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
typedef struct
{
uint8_t head;
uint8_t data;
uint8_t crc;
} UART_RxData_t;
typedef struct
{
uint8_t head;
uint8_t data;
uint8_t crc;
} UART_TxData_t;
typedef struct
{
UART_RxData_t rx_data; // Received data buffer
UART_TxData_t tx_data; // Transmit data buffer
} UART_t;
/* Exported functions prototypes -------------------------------------------- */
int UART_Init(UART_t *huart);
int UART_StartReceive(UART_t *huart);
bool UART_IsReceiveComplete(void);
int8_t UART_ParseData(UART_t *huart);
void UART_PackTx(UART_t *huart, UART_TxData_t *tx_data);
int8_t UART_StartSend(UART_t *huart);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,36 @@
/* Includes ----------------------------------------------------------------- */
#include "main.h"
#include "servo.h"
#include "bsp/servo_pwm.h"
/* Private define ----------------------------------------------------------- */
#define MIN_CYCLE 0.5f //change begin
#define MAX_CYCLE 2.5f
#define ANGLE_LIMIT 180 //change end
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
/* Private function -------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
int serve_Init(BSP_PWM_Channel_t ch)
{
if(BSP_PWM_Start(ch)!=0){
return -1;
}else return 0;
}
int set_servo_angle(BSP_PWM_Channel_t ch,float angle)
{
if (angle < 0.0f || angle > ANGLE_LIMIT) {
return -1; // ÎÞЧµÄ½Ç¶È
}
float duty_cycle=MIN_CYCLE+(MAX_CYCLE-MIN_CYCLE)*(angle/ANGLE_LIMIT);
if(BSP_PWM_Set(ch,duty_cycle)!=0){
return -1;
}else return 0;
}

View File

@@ -0,0 +1,41 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include <stdint.h>
#include "tim.h"
#include "bsp/bsp.h"
#include "bsp/servo_pwm.h"
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
extern int serve_Init(BSP_PWM_Channel_t ch);
extern int set_servo_angle(BSP_PWM_Channel_t ch,float angle);
#ifdef __cplusplus
}
#endif

View File

View File

View File

View File

@@ -0,0 +1,5 @@
oled_i2c,bsp/i2c
bmp280_i2c,bsp/i2c
pc_uart,bsp/uart
key_gpio,bsp/gpio_exti
servo,bsp/servo_pwm
1 oled_i2c bsp/i2c
2 bmp280_i2c bsp/i2c
3 pc_uart bsp/uart
4 key_gpio bsp/gpio_exti
5 servo bsp/servo_pwm

View File

View File

View File

@@ -0,0 +1,42 @@
/*
Init Task
任务初始化,创建各个线程任务和消息队列
*/
/* Includes ----------------------------------------------------------------- */
#include "task/user_task.h"
/* USER INCLUDE BEGIN */
/* USER INCLUDE BEGIN */
/* 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(); /* 锁定内核,防止任务切换 */
/* 创建任务线程 */
{{thread_creation_code}}
// 创建消息队列
/* USER MESSAGE BEGIN */
task_runtime.msgq.user_msg= osMessageQueueNew(2u, 10, NULL);
/* USER MESSAGE END */
osKernelUnlock(); // 解锁内核
osThreadTerminate(osThreadGetId()); // 任务完成后结束自身
}

View File

@@ -0,0 +1,56 @@
/*
{{task_name}} Task
{{task_description}}
*/
/* 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_function}}(void *argument) {
(void)argument; /* 未使用argument消除警告 */
{% if freq_control %}
/* 计算任务运行到指定频率需要等待的tick数 */
const uint32_t delay_tick = osKernelGetTickFreq() / {{task_frequency}};
osDelay({{task_delay}}); /* 延时一段时间再开启任务 */
/* USER CODE INIT BEGIN*/
/* USER CODE INIT END*/
uint32_t tick = osKernelGetTickCount(); /* 控制任务运行频率的计时 */
while (1) {
tick += delay_tick; /* 计算下一个唤醒时刻 */
/* USER CODE BEGIN */
/* USER CODE END */
osDelayUntil(tick); /* 运行结束,等待下一次唤醒 */
}
{% else %}
osDelay({{task_delay}}); /* 延时一段时间再开启任务 */
/* USER CODE INIT BEGIN*/
/* USER CODE INIT END*/
while (1) {
/* USER CODE BEGIN */
/* USER CODE END */
}
{% endif %}
}

View File

@@ -0,0 +1,12 @@
#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 */
{{task_attr_definitions}}

View 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 ------------------------------------------------------- */
/* 任务运行频率 */
{{task_frequency_definitions}}
/* 任务初始化延时ms */
#define TASK_INIT_DELAY (100u)
{{task_init_delay_definitions}}
/* Exported defines --------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
/* 任务运行时结构体 */
typedef struct {
/* 各任务,也可以叫做线程 */
struct {
{{thread_definitions}}
} 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 {
{{stack_definitions}}
} stack_water_mark;
/* 各任务运行频率 */
struct {
{{freq_definitions}}
} freq;
/* 任务最近运行时间 */
struct {
{{last_up_time_definitions}}
} last_up_time;
} Task_Runtime_t;
/* 任务运行时结构体 */
extern Task_Runtime_t task_runtime;
/* 初始化任务句柄 */
extern const osThreadAttr_t attr_init;
{{task_attr_declarations}}
/* 任务函数声明 */
void Task_Init(void *argument);
{{task_function_declarations}}
#ifdef __cplusplus
}
#endif

BIN
assets/mech_lib/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1 @@
# 机械常用零件库