diff --git a/application/robot_def.h b/application/robot_def.h index a4fe70d..b27181b 100644 --- a/application/robot_def.h +++ b/application/robot_def.h @@ -8,7 +8,7 @@ * @copyright Copyright (c) HNU YueLu EC 2022 all rights reserved * */ - +#pragma once #ifndef ROBOT_DEF_H #define ROBOT_DEF_H @@ -16,6 +16,11 @@ #include "master_process.h" #include "stdint.h" +#ifndef ROBOT_DEF_PARAM_WARNING +#define ROBOT_DEF_PARAM_WARNING +#warning BE SURED THAT YOU HAVE ALREADY MODIFIED THESE PARAMETER TO FIT THE ROBOT +#endif // !ROBOT_DEF_PARAM_WARNING + /* 开发板类型定义,烧录时注意不要弄错对应功能;修改定义后需要重新编译,只能存在一个定义! */ #define ONE_BOARD // 单板控制整车 // #define CHASSIS_BOARD //底盘板 @@ -54,8 +59,7 @@ #error Conflict board definition! You can only define one board type. #endif -#pragma pack(1) // 压缩结构体,取消字节对齐 - +#pragma pack(1) // 压缩结构体,取消字节对齐,下面的数据都可能被传输 /* -------------------------基本控制模式和数据类型定义-------------------------*/ /** * @brief 这些枚举类型和结构体会作为CMD控制数据和各应用的反馈数据的一部分 diff --git a/bsp/dwt/bsp_dwt.c b/bsp/dwt/bsp_dwt.c index ea4a4f0..7dc30ce 100644 --- a/bsp/dwt/bsp_dwt.c +++ b/bsp/dwt/bsp_dwt.c @@ -2,6 +2,7 @@ ****************************************************************************** * @file bsp_dwt.c * @author Wang Hongxi + * @author modified by Neo with annotation * @version V1.1.0 * @date 2022/3/8 * @brief @@ -17,7 +18,21 @@ static uint32_t CPU_FREQ_Hz, CPU_FREQ_Hz_ms, CPU_FREQ_Hz_us; static uint32_t CYCCNT_RountCount; static uint32_t CYCCNT_LAST; uint64_t CYCCNT64; -static void DWT_CNT_Update(void); + +/** + * @brief 私有函数,用于检查DWT CYCCNT寄存器是否溢出,并更新CYCCNT_RountCount + * @attention 此函数假设两次调用之间的时间间隔不超过一次溢出 + * + */ +static void DWT_CNT_Update(void) +{ + volatile uint32_t cnt_now = DWT->CYCCNT; + + if (cnt_now < CYCCNT_LAST) + CYCCNT_RountCount++; + + CYCCNT_LAST = cnt_now; +} void DWT_Init(uint32_t CPU_Freq_mHz) { @@ -101,15 +116,6 @@ uint64_t DWT_GetTimeline_us(void) return DWT_Timelinef32; } -static void DWT_CNT_Update(void) -{ - volatile uint32_t cnt_now = DWT->CYCCNT; - - if (cnt_now < CYCCNT_LAST) - CYCCNT_RountCount++; - - CYCCNT_LAST = cnt_now; -} void DWT_Delay(float Delay) { diff --git a/bsp/dwt/bsp_dwt.h b/bsp/dwt/bsp_dwt.h index 95e24ad..d81bb64 100644 --- a/bsp/dwt/bsp_dwt.h +++ b/bsp/dwt/bsp_dwt.h @@ -25,13 +25,63 @@ typedef struct extern DWT_Time_t SysTime; +/** + * @brief 初始化DWT,传入参数为CPU频率,单位MHz + * + * @param CPU_Freq_mHz c板为168MHz,A板为180MHz + */ void DWT_Init(uint32_t CPU_Freq_mHz); + +/** + * @brief 获取两次调用之间的时间间隔,单位为秒/s + * + * @param cnt_last 上一次调用的时间戳 + * @return float 时间间隔,单位为秒/s + */ float DWT_GetDeltaT(uint32_t *cnt_last); + +/** + * @brief 获取两次调用之间的时间间隔,单位为秒/s,高精度 + * + * @param cnt_last 上一次调用的时间戳 + * @return double 时间间隔,单位为秒/s + */ double DWT_GetDeltaT64(uint32_t *cnt_last); + +/** + * @brief 获取当前时间,单位为秒/s,即初始化后的时间 + * + * @return float 时间轴 + */ float DWT_GetTimeline_s(void); + +/** + * @brief 获取当前时间,单位为毫秒/ms,即初始化后的时间 + * + * @return float + */ float DWT_GetTimeline_ms(void); + +/** + * @brief 获取当前时间,单位为微秒/us,即初始化后的时间 + * + * @return uint64_t + */ uint64_t DWT_GetTimeline_us(void); + +/** + * @brief DWT延时函数,单位为秒/s + * @attention 该函数不受中断是否开启的影响,可以在临界区和关闭中断时使用 + * @note 禁止在__disable_irq()和__enable_irq()之间使用HAL_Delay()函数,应使用本函数 + * + * @param Delay 延时时间,单位为秒/s + */ void DWT_Delay(float Delay); + +/** + * @brief DWT更新时间轴函数,会被三个timeline函数调用 + * @attention 如果长时间不调用timeline函数,则需要手动调用该函数更新时间轴,否则CYCCNT溢出后定时和时间轴不准确 + */ void DWT_SysTimeUpdate(void); diff --git a/modules/BMI088/bmi088.c b/modules/BMI088/bmi088.c index 7ba8639..bf096fa 100644 --- a/modules/BMI088/bmi088.c +++ b/modules/BMI088/bmi088.c @@ -1,32 +1,8 @@ #include "bmi088_regNdef.h" #include "bmi088.h" -#include "stdlib.h" -#include "memory.h" +#include "user_lib.h" -#define REG 0 -#define DATA 1 -#define ERROR 2 -// BMI088初始化配置数组for accel,第一列为reg地址,第二列为写入的配置值,第三列为错误码(如果出错) -static uint8_t BMI088_Accel_Init_Table[BMI088_WRITE_ACCEL_REG_NUM][3] = - { - {BMI088_ACC_PWR_CTRL, BMI088_ACC_ENABLE_ACC_ON, BMI088_ACC_PWR_CTRL_ERROR}, - {BMI088_ACC_PWR_CONF, BMI088_ACC_PWR_ACTIVE_MODE, BMI088_ACC_PWR_CONF_ERROR}, - {BMI088_ACC_CONF, BMI088_ACC_NORMAL | BMI088_ACC_800_HZ | BMI088_ACC_CONF_MUST_Set, BMI088_ACC_CONF_ERROR}, - {BMI088_ACC_RANGE, BMI088_ACC_RANGE_6G, BMI088_ACC_RANGE_ERROR}, - {BMI088_INT1_IO_CTRL, BMI088_ACC_INT1_IO_ENABLE | BMI088_ACC_INT1_GPIO_PP | BMI088_ACC_INT1_GPIO_LOW, BMI088_INT1_IO_CTRL_ERROR}, - {BMI088_INT_MAP_DATA, BMI088_ACC_INT1_DRDY_INTERRUPT, BMI088_INT_MAP_DATA_ERROR}}; -// BMI088初始化配置数组for gyro,第一列为reg地址,第二列为写入的配置值,第三列为错误码(如果出错) -static uint8_t BMI088_Gyro_Init_Table[BMI088_WRITE_GYRO_REG_NUM][3] = - { - {BMI088_GYRO_RANGE, BMI088_GYRO_2000, BMI088_GYRO_RANGE_ERROR}, - {BMI088_GYRO_BANDWIDTH, BMI088_GYRO_2000_230_HZ | BMI088_GYRO_BANDWIDTH_MUST_Set, BMI088_GYRO_BANDWIDTH_ERROR}, - {BMI088_GYRO_LPM1, BMI088_GYRO_NORMAL_MODE, BMI088_GYRO_LPM1_ERROR}, - {BMI088_GYRO_CTRL, BMI088_DRDY_ON, BMI088_GYRO_CTRL_ERROR}, - {BMI088_GYRO_INT3_INT4_IO_CONF, BMI088_GYRO_INT3_GPIO_PP | BMI088_GYRO_INT3_GPIO_LOW, BMI088_GYRO_INT3_INT4_IO_CONF_ERROR}, - {BMI088_GYRO_INT3_INT4_IO_MAP, BMI088_GYRO_DRDY_IO_INT3, BMI088_GYRO_INT3_INT4_IO_MAP_ERROR}}; -// @attention : 以上两个数组配合各自的初始化函数使用. 若要修改请参照BMI088 datasheet - -// ---------------------------以下私有函数,用于读写BMI088寄存器--------------------------------// +// ---------------------------以下私有函数,用于读写BMI088寄存器封装,blocking--------------------------------// /** * @brief 读取BMI088寄存器Accel * @@ -40,7 +16,7 @@ static void BMI088AccelRead(BMI088Instance *bmi088, uint8_t reg, uint8_t *datapt static uint8_t tx[8] = {0x80, 0}; // 读取,第一个字节为0x80 | reg,第二个是dummy data tx[0] |= reg; SPITransRecv(bmi088->spi_acc, dataptr, tx, 2); // 第一个先发送reg地址,第二个发送dummy data - SPIRecv(bmi088->spi_acc, dataptr, len); // 第三个开始发送数据,别担心,会覆盖掉前面的数据(2个字节) + SPIRecv(bmi088->spi_acc, dataptr, len); // 第三个开始发送数据,别担心,会覆盖掉前面的数据(2个字节) } /** @@ -84,10 +60,31 @@ static void BMI088GyroWrite(BMI088Instance *bmi088, uint8_t reg, uint8_t data) { SPITransmit(bmi088->spi_gyro, &data, 1); } +// -------------------------以上为私有函数,封装了BMI088寄存器读写函数,blocking--------------------------------// -// -------------------------以上为私有函数,用于读写BMI088寄存器--------------------------------// - -// -------------------------以下为私有函数,用于初始化BMI088acc和gyro--------------------------------// +// -------------------------以下为私有函数,用于初始化BMI088acc和gyro的硬件和配置--------------------------------// +#define REG 0 +#define DATA 1 +#define ERROR 2 +// BMI088初始化配置数组for accel,第一列为reg地址,第二列为写入的配置值,第三列为错误码(如果出错) +static uint8_t BMI088_Accel_Init_Table[BMI088_WRITE_ACCEL_REG_NUM][3] = + { + {BMI088_ACC_PWR_CTRL, BMI088_ACC_ENABLE_ACC_ON, BMI088_ACC_PWR_CTRL_ERROR}, + {BMI088_ACC_PWR_CONF, BMI088_ACC_PWR_ACTIVE_MODE, BMI088_ACC_PWR_CONF_ERROR}, + {BMI088_ACC_CONF, BMI088_ACC_NORMAL | BMI088_ACC_800_HZ | BMI088_ACC_CONF_MUST_Set, BMI088_ACC_CONF_ERROR}, + {BMI088_ACC_RANGE, BMI088_ACC_RANGE_6G, BMI088_ACC_RANGE_ERROR}, + {BMI088_INT1_IO_CTRL, BMI088_ACC_INT1_IO_ENABLE | BMI088_ACC_INT1_GPIO_PP | BMI088_ACC_INT1_GPIO_LOW, BMI088_INT1_IO_CTRL_ERROR}, + {BMI088_INT_MAP_DATA, BMI088_ACC_INT1_DRDY_INTERRUPT, BMI088_INT_MAP_DATA_ERROR}}; +// BMI088初始化配置数组for gyro,第一列为reg地址,第二列为写入的配置值,第三列为错误码(如果出错) +static uint8_t BMI088_Gyro_Init_Table[BMI088_WRITE_GYRO_REG_NUM][3] = + { + {BMI088_GYRO_RANGE, BMI088_GYRO_2000, BMI088_GYRO_RANGE_ERROR}, + {BMI088_GYRO_BANDWIDTH, BMI088_GYRO_2000_230_HZ | BMI088_GYRO_BANDWIDTH_MUST_Set, BMI088_GYRO_BANDWIDTH_ERROR}, + {BMI088_GYRO_LPM1, BMI088_GYRO_NORMAL_MODE, BMI088_GYRO_LPM1_ERROR}, + {BMI088_GYRO_CTRL, BMI088_DRDY_ON, BMI088_GYRO_CTRL_ERROR}, + {BMI088_GYRO_INT3_INT4_IO_CONF, BMI088_GYRO_INT3_GPIO_PP | BMI088_GYRO_INT3_GPIO_LOW, BMI088_GYRO_INT3_INT4_IO_CONF_ERROR}, + {BMI088_GYRO_INT3_INT4_IO_MAP, BMI088_GYRO_DRDY_IO_INT3, BMI088_GYRO_INT3_INT4_IO_MAP_ERROR}}; +// @attention : 以上两个数组配合各自的初始化函数使用. 若要修改请参照BMI088 datasheet /** * @brief 初始化BMI088加速度计,提高可读性分拆功能 @@ -156,9 +153,94 @@ static uint8_t BMI088GyroInit(BMI088Instance *bmi088) error |= BMI088_Gyro_Init_Table[i][ERROR]; //{i--;} 可以设置retry次数,如果retry次数用完了,则返回error } + + bmi088->acc_coef = 1.0; // 尚未初始化时设定为1,使得BMI088Acquire可以正常使用 + bmi088->BMI088_GYRO_SEN = BMI088_GYRO_2000_SEN; // 后续改为从initTable中获取 + bmi088->BMI088_ACCELL_SEN = BMI088_ACCEL_6G_SEN; // 用宏字符串拼接 + return error; } -// -------------------------以上为私有函数,用于初始化BMI088acc和gyro--------------------------------// +// -------------------------以上为私有函数,用于初始化BMI088acc和gyro的硬件和配置--------------------------------// + +// -------------------------以下为公有函数,用于注册BMI088,标定和数据读取--------------------------------// + +BMI088_Data_t BMI088Acquire(BMI088Instance *bmi088) +{ + // 分配空间保存返回的数据,指针传递 + static BMI088_Data_t data_store; + static float dt_imu = 1.0; // 初始化为1,这样也可以不用first_read_flag,各有优劣 + // 如果是blocking模式,则主动触发一次读取并返回数据 + static uint8_t buf[6] = {0}; // 最多读取6个byte(gyro) + static uint8_t first_read_flag; // 判断是否时第一次进入此函数(第一次读取) + // 用于初始化DWT的计数,暂时没想到更好的方法 + if (!first_read_flag) + DWT_GetDeltaT(& bmi088->bias_dwt_cnt); // 初始化delta + else + dt_imu = DWT_GetDeltaT(&bmi088->bias_dwt_cnt); + + // 读取accel的x轴数据首地址,bmi088内部自增读取地址 + BMI088AccelRead(bmi088, BMI088_ACCEL_XOUT_L, buf, 6); // 3* sizeof(int16_t) + static float calc_coef_acc; // 防止重复计算 + if (!first_read_flag) // 初始化的时候赋值 + calc_coef_acc = bmi088->BMI088_ACCELL_SEN * bmi088->acc_coef; + bmi088->acc[0] = calc_coef_acc * (float)(int16_t)(((buf[1]) << 8) | buf[0]); + bmi088->acc[1] = calc_coef_acc * (float)(int16_t)(((buf[3]) << 8) | buf[2]); + bmi088->acc[3] = calc_coef_acc * (float)(int16_t)(((buf[5]) << 8) | buf[4]); + + BMI088GyroRead(bmi088, BMI088_GYRO_X_L, buf, 6); // 连续读取3个(3*2=6)轴的角速度 + static float gyrosen, bias1, bias2, bias3; + if (!first_read_flag) + { // 先保存,减少访问内存的开销,直接访问栈上变量 + gyrosen = bmi088->BMI088_GYRO_SEN; + bias1 = bmi088->gyro_offset[0]; + bias2 = bmi088->gyro_offset[1]; + bias3 = bmi088->gyro_offset[2]; + + first_read_flag = 1; // 最后在这里,完成一次读取,标志第一次读取完成 + } // 别担心,初始化调用的时候offset(即零飘bias)是0 + bmi088->gyro[0] = (float)(int16_t)(((buf[1]) << 8) | buf[0]) * gyrosen - bias1 * dt_imu; + bmi088->gyro[0] = (float)(int16_t)(((buf[3]) << 8) | buf[2]) * gyrosen - bias2 * dt_imu; + bmi088->gyro[0] = (float)(int16_t)(((buf[5]) << 8) | buf[4]) * gyrosen - bias3 * dt_imu; + + BMI088AccelRead(bmi088,BMI088_TEMP_M,buf,2); // 读温度,温度传感器在accel上 + bmi088->temperature= (float)(int16_t)(((buf[0] << 3) | (buf[1] >> 5))) * BMI088_TEMP_FACTOR + BMI088_TEMP_OFFSET; + + return data_store; + + // 如果是IT模式,则检查标志位.当传感器数据准备好会触发外部中断,中断服务函数会将标志位置1 + if (bmi088->work_mode == BMI088_BLOCK_TRIGGER_MODE && bmi088->update_flag.imu_ready == 1) + return data_store; + + // 如果数据还没准备好,则返回空数据?或者返回上一次的数据?或者返回错误码? @todo + if (bmi088->update_flag.imu_ready == 0) + return data_store; +} + +/* pre calibrate parameter to go here */ +#warning REMEMBER TO SET PRE CALIBRATE PARAMETER IF YOU CHOOSE NOT TO CALIBRATE +#define BMI088_PRE_CALI_ACC_X_OFFSET 0.0f +#define BMI088_PRE_CALI_ACC_Y_OFFSET 0.0f +// macro to go here... 预设标定参数 + +/** + * @brief BMI088 acc gyro 标定 + * @note 标定后的数据存储在bmi088->bias和gNorm中,用于后续数据消噪和单位转换归一化 + * @attention 不管工作模式是blocking还是IT,标定时都是blocking模式,所以不用担心中断关闭后无法标定(RobotInit关闭了全局中断) + * @attention 标定精度和等待时间有关,目前使用线性回归.后续考虑引入非线性回归 + * + * @param _bmi088 待标定的BMI088实例 + */ +void BMI088CalibrateIMU(BMI088Instance *_bmi088) +{ + if (_bmi088->cali_mode == BMI088_CALIBRATE_ONLINE_MODE) + { + } + else + { + // 读取标定数据 + // code to go here ... + } +} // 考虑阻塞模式和非阻塞模式的兼容性,通过条件编译(则需要在编译前修改宏定义)或runtime参数判断 // runtime的开销不大(一次性判断),但是需要修改函数原型,增加参数,代码长度增加(但不多) @@ -168,5 +250,43 @@ static uint8_t BMI088GyroInit(BMI088Instance *bmi088) BMI088Instance *BMI088Register(BMI088_Init_Config_s *config) { - + uint8_t error = BMI088_NO_ERROR; + // 申请内存 + BMI088Instance *bmi088_instance = (BMI088Instance *)zero_malloc(sizeof(BMI088Instance)); + + // 从右向左赋值,让bsp instance保存指向bmi088_instance的指针(父指针),便于在底层中断中访问bmi088_instance + config->acc_int_config.id = + config->gyro_int_config.id = + config->spi_acc_config.id = + config->spi_gyro_config.id = + config->heat_pwm_config.id = bmi088_instance; + + // 目前只实现了!!!阻塞读取模式!!!.如果需要使用IT模式,则需要修改这里的代码,为spi和gpio注册callback(默认为NULL) + // 还需要设置SPI的传输模式为DMA模式或IT模式(默认为blocking) + // 可以通过conditional compilation或者runtime参数判断 + // code to go here ... + + // INT_ACC EXTI CALLBACK: 检查是否有传输正在进行,如果没有则开启SPI DMA传输,有则置位wait标志位; + // 第一次是加速度计,第二次是温度. + + // INT_GYRO EXTI CALLBACK: 开启SPI DMA传输,不会出现等待传输的情况 + // SPI_GYRO DMA CALLBACK: 解算陀螺仪数据, + // SPI_ACC DMA CALLBACK: 解算加速度计数据,清除温度wait标志位并启动温度传输,第二次进入中断时解算温度数据 + + // 还有其他方案可用,比如阻塞等待传输完成,但是比较笨. + + bmi088_instance->spi_acc = SPIRegister(&config->spi_acc_config); + bmi088_instance->spi_gyro = SPIRegister(&config->spi_gyro_config); + bmi088_instance->acc_int = GPIORegister(&config->acc_int_config); + bmi088_instance->gyro_int = GPIORegister(&config->gyro_int_config); + bmi088_instance->heat_pwm = PWMRegister(&config->heat_pwm_config); + + // 初始化acc和gyro + error |= BMI088AccelInit(bmi088_instance); + error |= BMI088GyroInit(bmi088_instance); + + // 标定acc和gyro + BMI088CalibrateIMU(bmi088_instance); + + return 0; } diff --git a/modules/BMI088/bmi088.h b/modules/BMI088/bmi088.h index 7425f61..58a4ef5 100644 --- a/modules/BMI088/bmi088.h +++ b/modules/BMI088/bmi088.h @@ -7,10 +7,6 @@ #include "bsp_pwm.h" #include "stdint.h" -#define BMI088_PRE_CALI_ACC_X_OFFSET 0.0f -#define BMI088_PRE_CALI_ACC_Y_OFFSET 0.0f -// macro to go here... 预设标定参数 - // bmi088工作模式枚举 typedef enum { @@ -21,10 +17,23 @@ typedef enum // bmi088标定方式枚举,若使用预设标定参数,注意修改预设参数 typedef enum { - BMI088_CALIBRATE_MODE = 0, // 初始化时进行标定 - BMI088_LOAD_PRE_CALI_MODE, // 使用预设标定参数, + BMI088_CALIBRATE_ONLINE_MODE = 0, // 初始化时进行标定 + BMI088_LOAD_PRE_CALI_MODE, // 使用预设标定参数, } BMI088_Calibrate_Mode_e; +#pragma pack(1) // 1字节对齐 +/* BMI088数据*/ +typedef struct +{ + float gyro[3]; // 陀螺仪数据,xyz + float acc[3]; // 加速度计数据,xyz + float temperature; // 温度 + + // uint32_t timestamp; // 时间戳 + // uint32_t count; +} BMI088_Data_t; +#pragma pack() // 恢复默认对齐,需要传输的结构体务必开启1字节对齐 + /* BMI088实例结构体定义 */ typedef struct { @@ -53,6 +62,18 @@ typedef struct float BMI088_GYRO_SEN; // 用于计算两次采样的时间间隔 uint32_t bias_dwt_cnt; + // 数据更新标志位 + struct // 位域,节省空间提高可读性 + { + uint8_t gyro : 1; // 1:有新数据,0:无新数据 + uint8_t acc : 1; + uint8_t temp : 1; + uint8_t gyro_overrun : 1; // 1:数据溢出,0:无溢出 + uint8_t acc_overrun : 1; + uint8_t temp_overrun : 1; + uint8_t imu_ready : 1; // 1:IMU数据准备好,0:IMU数据未准备好(gyro+acc) + // 后续可添加其他标志位 + } update_flag; } BMI088Instance; /* BMI088初始化配置 */ @@ -68,7 +89,6 @@ typedef struct PWM_Init_Config_s heat_pwm_config; } BMI088_Init_Config_s; - /** * @brief 初始化BMI088,返回BMI088实例指针 * @note 一般一个开发板只有一个BMI088,所以这里就叫BMI088Init而不是Register @@ -78,4 +98,11 @@ typedef struct */ BMI088Instance *BMI088Register(BMI088_Init_Config_s *config); +/** + * @brief 读取BMI088数据 + * @todo 7个float数据开销较大,后续考虑使用DMA或双缓冲区直接传递指针 + * @param bmi088 BMI088实例指针 + * @return BMI088_Data_t 读取到的数据 + */ +BMI088_Data_t BMI088Acquire(BMI088Instance *bmi088); #endif // !__BMI088_H__ \ No newline at end of file diff --git a/modules/BMI088/bmi088.md b/modules/BMI088/bmi088.md index bcfb641..a877b29 100644 --- a/modules/BMI088/bmi088.md +++ b/modules/BMI088/bmi088.md @@ -39,7 +39,7 @@ write写入: 1. 当accel int中断发生,开启DMA SPI传输,完成后将acc ready置位 2. 当gyro int中断发生,开启DMA SPI传输,完成后将gyro ready置位 -3. 当温度数据中断发生,开启DMA传输,完成后将温度标志位置位 +3. 当温度数据中断(温度传感器在accel内部,也是accel int)发生,开启DMA传输,完成后将温度标志位置位 > 由于DMA传输非阻塞,启动传输后只有到传输完成时才会拉高片选结束SPI transfer,因此需要在callback中加入标志位置位的操作. 这可以通过条件编译完成. diff --git a/modules/algorithm/user_lib.c b/modules/algorithm/user_lib.c index 41db340..94d4e37 100644 --- a/modules/algorithm/user_lib.c +++ b/modules/algorithm/user_lib.c @@ -25,6 +25,13 @@ uint8_t GlobalDebugMode = 7; +void* zero_malloc(size_t size) +{ + void* ptr=malloc(size); + memset(ptr,0,size); + return ptr; +} + // 快速开方 float Sqrt(float x) { diff --git a/modules/algorithm/user_lib.h b/modules/algorithm/user_lib.h index ca46584..6e76eac 100644 --- a/modules/algorithm/user_lib.h +++ b/modules/algorithm/user_lib.h @@ -87,6 +87,13 @@ extern uint8_t GlobalDebugMode; #define VAL_MIN(a, b) ((a) < (b) ? (a) : (b)) #define VAL_MAX(a, b) ((a) > (b) ? (a) : (b)) +/** + * @brief 返回一块干净的内存,不过仍然需要强制转换为你需要的类型 + * + * @param size 分配大小 + * @return void* + */ +void* zero_malloc(size_t size); //���ٿ��� float Sqrt(float x);