河南专业网站建设公司,深圳昨天下午出大事,阅读推广联盟,seo指的是什么意思【嵌入式模块芯片开发】LP87524电源PMIC芯片配置流程#xff0c;给雷达供电的延时上电时序及API函数 文章目录 LP87524LP87524初始化雷达供电时需要的上电时序LP87524电源PMIC芯片的BUCK供电时序LP87524电源PMIC芯片的BUCK默认供电输出LP87524相关API函数附录#xff1a;压缩…【嵌入式模块芯片开发】LP87524电源PMIC芯片配置流程给雷达供电的延时上电时序及API函数文章目录LP87524LP87524初始化雷达供电时需要的上电时序LP87524电源PMIC芯片的BUCK供电时序LP87524电源PMIC芯片的BUCK默认供电输出LP87524相关API函数附录压缩字符串、大小端格式转换压缩字符串浮点数压缩Packed-ASCII字符串大小端转换什么是大端和小端数据传输中的大小端总结大小端转换函数LP87524LP8752x-Q1 10-A Buck Converter With Integrated Switche具有诊断功能的 LP87702-Q1 双路降压转换器和 5V 升压转换器通过I2C来通信从机地址为0x60支持随机地址读取和顺序写入支持硬件寄存器延时启动的BUCK输出另外 有两种寄存器配置输出一个是BUCK VOUT 一个是BUCK FLOOR VOUT前者是BUCK输出后者是保障最低输出比如BUCK输出3.3V 保障输出3.0V 那么电压就会在可负载的3.0-3.3之间一般FLOOR不用刻意去配置 负载不高的话 都能保得住LP87524初始化将0x40写入LP87524_CONFIGCLKIN下拉其他不选择下拉此寄存器也可配置信号延时将0x00写入PIN_FUNCTION寄存器使其不使用GPIO功能依次配置以下寄存器使B0输出3.3VB1输出1.8VB2输出1.2VB3输出1.0V#define LP87524_BUCK0_CTRL1 0x02 写入0x34bit7控制开启#define LP87524_BUCK1_CTRL1 0x04 写入0x44bit7和EN1控制开启#define LP87524_BUCK2_CTRL1 0x06 写入0x54bit7和EN2控制开启#define LP87524_BUCK3_CTRL1 0x08 写入0x64bit7和EN3控制开启#define LP87524_BUCK0_VOUT 0x0A 写入0xFC#define LP87524_BUCK0_FLOOR_VOUT 0x0B 写入0xFC#define LP87524_BUCK1_VOUT 0x0C 写入0xB1#define LP87524_BUCK1_FLOOR_VOUT 0x0D 写入0xB1#define LP87524_BUCK2_VOUT 0x0E 写入0x75#define LP87524_BUCK2_FLOOR_VOUT 0x0F 写入0x75#define LP87524_BUCK3_VOUT 0x10 写入0x4D#define LP87524_BUCK3_FLOOR_VOUT 0x11 写入0x4D若需要延迟开启或关闭则配置DEALY寄存器若需启用电压监测则配置PGOOD寄存器最后一步再开启电压输出BUCK0_CTRL1 先读取再写入使bit7置1BUCK1_CTRL1 先读取再写入使bit7置1EN1输出高电平BUCK2_CTRL1 先读取再写入使bit7置1EN2输出高电平BUCK3_CTRL1 先读取再写入使bit7置1EN3输出高电平4. 若有需要可使能EN的GPIO复用功能编程引脚可以通过配置寄存器来输出高低电平。中断及状态在INT和STAT寄存器内中断屏蔽配置在MASK寄存器内。SEL_I_LOAD寄存器可开启电流测量。雷达供电时需要的上电时序由IWR6843硬件手册可以看到几路供电的上电时序以及AWR1843的手册除了上电时序为1.2 1.8 1.0 3.3之外还要求电压稳定如果电压不稳定 则可能跑不进用户代码现象就是明明没有配置串口回环却实现串口回环看这个时序 之前的串口回环可能就是SOP的问题 因为上电不稳定 导致进入了错误的SOP模式按这个上电时序上电以后 3.3V充满电的时候 就是DC power OK 然后就是SOP setup time然后这个DC power要稳定一段时间 在nRESET之前 NRESET充满电以后 才是SOP Hold time to nRESET在nRESET这个上升沿时间中 要保持电压稳定 SOP稳定才行不稳定或不按时序上电 就会导致SOP不稳定 从而进入到了不同的BOOT模式而且烧录代码就是串口回环延迟上电不能过慢 也不能过快100us左右的间隔我测试是可以正常工作的波形图LP87524电源PMIC芯片的BUCK供电时序LP87524配置见【TI毫米波雷达】LP87702/LP87524电源PMIC芯片的BUCK供电配置我们现在的原理图是这样 BUCK0-BUCK3分别输出3.3 1.2 1.0 1.8的电压BUCK1 2 3由寄存器开关和EN1 2 3引脚共同决定 BUCK0由寄存器开关控制按这个原理图的话 时序控制为//按1.2 1.8 1.0 3.3的顺序上电//预准备delay_ms(10);datI2C_Read_y(LP87524_I2C_Handle,LP87524_Slave_Add,LP87524_BUCK2_CTRL1,1,1,true);dat|(17);I2C_Write_x(LP87524_I2C_Handle,LP87524_Slave_Add,LP87524_BUCK2_CTRL1,1,dat,1,true);delay_ms(10);Enable_LP87524_BUCK(1,true);delay_us(4400);Enable_LP87524_BUCK(3,true);delay_us(150);//Enable_LP87524_BUCK(2,true);Enable_LP87524_EN2;delay_us(4450);Enable_LP87524_BUCK(0,true);波形延迟上电间隔约100us这个是可以使用的如果加上雷达板负载 可能3.3V这一路会延后 所以还是带上雷达板测试比较好如果不进行预准备和延时间隔 则波形如图这是由于每个buck的硬件延时都不一样导致的 所以必须一个一个来调整另外 我的延时函数也有误差 不一定完全是这个延时 要根据自己的板子来调整上电稳定后的波形LP87524电源PMIC芯片的BUCK默认供电输出这一项是在芯片手册中没写的现象就是关闭VCC_5V以后 如果没有负载 几路buck会缓慢掉电 掉电到基本没电的时候 重新打开VCC_5V 立马就会进行默认输出也就是说 开启5V开关以后 87524上电 但不进行配置 也不进行复位时 BUCK0-3的输出分别是0.88 3.36 1.55 1.87这个就是87524的默认BUCK输出值 如果运用在产品中 假设要进行功耗控制 只让雷达工作一段时间 就需要频繁开关VCC_5V电源 所以我建议是把BUCK0-3按照1.0 3.3 1.2 1.8的顺序设计输出 这样的话 与默认BUCK输出的电压相近注这里的VCC_5V指的是除控制用的MCU外的其他器件总电源波形但其实是关闭电源的操作不对现在我加了一个 就是在关闭VCC_5V后 把EN1 EN2 EN3都关闭 然后重新打开VCC_5V 现在就不会有默认输出了严格按照这个顺序来操作 就不会出现buck默认输出的问题 也不会有电压跳变也就是说 在关闭LP87524的BUCK输出前 要将EN1 EN2 EN3关闭 最好是先进行关闭函数再关闭总电源LP87524相关API函数#includeLP87524_CMD.h#includemain.h#defineUSE_LP87524_EN1#ifUSE_LP87524_EN#defineEnable_LP87524_EN1HAL_GPIO_WritePin(LP87524_EN1_GPIO_Port,LP87524_EN1_Pin,GPIO_PIN_SET);#defineDisable_LP87524_EN1HAL_GPIO_WritePin(LP87524_EN1_GPIO_Port,LP87524_EN1_Pin,GPIO_PIN_RESET);#defineEnable_LP87524_EN2HAL_GPIO_WritePin(LP87524_EN2_GPIO_Port,LP87524_EN2_Pin,GPIO_PIN_SET);#defineDisable_LP87524_EN2HAL_GPIO_WritePin(LP87524_EN2_GPIO_Port,LP87524_EN2_Pin,GPIO_PIN_RESET);#defineEnable_LP87524_EN3HAL_GPIO_WritePin(LP87524_EN3_GPIO_Port,LP87524_EN3_Pin,GPIO_PIN_SET);#defineDisable_LP87524_EN3HAL_GPIO_WritePin(LP87524_EN3_GPIO_Port,LP87524_EN3_Pin,GPIO_PIN_RESET);#else#defineEnable_LP87524_EN1#defineDisable_LP87524_EN1#defineEnable_LP87524_EN2#defineDisable_LP87524_EN2#defineEnable_LP87524_EN3#defineDisable_LP87524_EN3#endif#ifdefHAL_I2C_MODULE_ENABLED/*! * brief 判断I2C设备是否可以响应 * * param [in] hi2c: I2C_HandleTypeDef 变量地址 * [in] DevAddress: 从机地址7位从机地址向右对齐 * * return 返回bool类型为true表示可以响应 */boolI2C_Judge(I2C_HandleTypeDef*hi2c,uint16_tDevAddress){DevAddress(DevAddress1)0xFF;if(HAL_I2C_IsDeviceReady(hi2c,DevAddress,5,0x00ff)HAL_OK){returntrue;}else{returnfalse;}}/*! * brief 对I2C设备进行写入 * * param [in] hi2c: I2C_HandleTypeDef 变量地址 * [in] DevAddress: 从机地址7位从机地址向右对齐 * [in] add: 从机寄存器地址8位地址 * [in] add_length: 为1表示1Byte8位为2表示2Byte16位 * [in] pData: 数据变量地址 * [in] x: 写入数据个数 * [in] prologue_flag: 序言标志 * 当prologue_flag为true时先发送从机地址再写入寄存器地址再发一次从机地址后再写入数据随机地址写入 * 当prologue_flag为false时直接发送从机地址后就写入数据当前地址写入此时不会发送从机寄存器地址 * * return true/false 发送是否成功 */boolI2C_Write_x(I2C_HandleTypeDef*hi2c,uint16_tDevAddress,uint16_tadd,uint16_tadd_length,uint8_t*pData,uint8_tx,bool prologue_flag){DevAddress(DevAddress1)0xFF;uint16_tMemAddSize1;if(pDataNULL||x0){returnfalse;}if(prologue_flag){switch(add_length){case1:MemAddSizeI2C_MEMADD_SIZE_8BIT;break;case2:MemAddSizeI2C_MEMADD_SIZE_16BIT;break;default:MemAddSizeI2C_MEMADD_SIZE_8BIT;break;}if(HAL_I2C_Mem_Write(hi2c,DevAddress,add,MemAddSize,pData,x,0xFFFF)HAL_OK){returntrue;}else{returnfalse;}}else{if(HAL_I2C_Master_Transmit(hi2c,DevAddress,pData,x,0xFFFF)HAL_OK){returntrue;}else{returnfalse;}}}/*! * brief 对I2C设备进行读取 * * param [in] hi2c: I2C_HandleTypeDef 变量地址 * [in] DevAddress: 从机地址7位从机地址向右对齐 * [in] add: 从机寄存器地址8/16位地址 * [in] add_length: 为1表示1Byte8位为2表示2Byte16位 * [in] y: 读取数据个数最大为4若大于4则返回0 * [in] prologue_flag: 序言标志 * 当prologue_flag为true时随机地址读取 * 当prologue_flag为false时当前地址读取此时从机寄存器地址无效 * * return dat: I2C读取数据返回 */uint32_tI2C_Read_y(I2C_HandleTypeDef*hi2c,uint16_tDevAddress,uint16_tadd,uint16_tadd_length,uint8_ty,bool prologue_flag){DevAddress(DevAddress1)0xFF;uint8_tpData[y];memset(pData,0,sizeof(pData));uint32_tdat0;uint16_tMemAddSize0;if(y4||y0){return0;}if(prologue_flag){switch(add_length){case1:MemAddSizeI2C_MEMADD_SIZE_8BIT;break;case2:MemAddSizeI2C_MEMADD_SIZE_16BIT;break;default:MemAddSizeI2C_MEMADD_SIZE_8BIT;break;}HAL_I2C_Mem_Read(hi2c,DevAddress,add,MemAddSize,pData,y,0xFFFF);}else{HAL_I2C_Master_Receive(hi2c,DevAddress,pData,y,0xFFFF);}for(uint8_ti0;iy;i){dat|pData[i](8*(y-1-i));}returndat;}#endif/*! * brief 复位LP87524 * * param None * * return false/true: 错误/正确标志 */boolReset_LP87524(void){uint8_tdat0;dat0x01;if(I2C_Write_x(LP87524_I2C_Handle,LP87524_Slave_Add,LP87524_RESET,1,dat,1,true)!true){returnfalse;}delay_ms(10);returntrue;}/*! * brief 控制LP87524的BUCK输出值这里只控制VOUT不控制FLOOR_VOUT * * param [in] buck_flag: BUCK序号为4时控制所有 * [in] voltage: 要输出的电压值 * [in] WriteNotRead: 写入或读取 * * return voltage_v: 写入或读取的电压值控制所有时写入的都为3.3V读取的为四个电压值之和 */floatCtrl_LP87524_BUCK_VOUT(uint8_tbuck_flag,floatvoltage_v,bool WriteNotRead){uint8_tdat0;uint8_tadd0;if(buck_flag4){voltage_vCtrl_LP87524_BUCK_VOUT(0,3.3,WriteNotRead)Ctrl_LP87524_BUCK_VOUT(1,3.3,WriteNotRead)Ctrl_LP87524_BUCK_VOUT(2,3.3,WriteNotRead)Ctrl_LP87524_BUCK_VOUT(3,3.3,WriteNotRead);}else{addLP87524_BUCK0_VOUT2*buck_flag;if(WriteNotRead){if(voltage_v0.6fvoltage_v0.73f){dat0x0A(voltage_v-0.6f)/0.01f;}elseif(voltage_v0.73fvoltage_v1.4f){dat0x17(voltage_v-0.73f)/0.005f;}elseif(voltage_v1.4fvoltage_v3.36f){dat0x9D(voltage_v-1.4f)/0.02f;}else{dat0;}I2C_Write_x(LP87524_I2C_Handle,LP87524_Slave_Add,add,1,dat,1,true);}else{datI2C_Read_y(LP87524_I2C_Handle,LP87524_Slave_Add,add,1,1,true);if(dat0x0Adat0x17){voltage_v(dat-0x0A)*0.01f0.6f;}elseif(dat0x17dat0x9D){voltage_v(dat-0x17)*0.005f0.73f;}elseif(dat0x9Ddat0xFF){voltage_v(dat-0x9D)*0.02f1.4f;}else{voltage_v0;}}}returnvoltage_v;}/*! * brief 控制LP87524的BUCK FLOOR输出值这里只控制VOUT不控制FLOOR_VOUT * * param [in] buck_flag: BUCK序号为4时控制所有 * [in] voltage: 要输出的电压值 * [in] WriteNotRead: 写入或读取 * * return voltage_v: 写入或读取的电压值控制所有时写入的都为3.3V读取的为四个电压值之和 */floatCtrl_LP87524_BUCK_FLOOR_VOUT(uint8_tbuck_flag,floatvoltage_v,bool WriteNotRead){uint8_tdat0;uint8_tadd0;if(buck_flag4){voltage_vCtrl_LP87524_BUCK_VOUT(0,3.3,WriteNotRead)Ctrl_LP87524_BUCK_VOUT(1,3.3,WriteNotRead)Ctrl_LP87524_BUCK_VOUT(2,3.3,WriteNotRead)Ctrl_LP87524_BUCK_VOUT(3,3.3,WriteNotRead);}else{addLP87524_BUCK0_FLOOR_VOUT2*buck_flag;if(WriteNotRead){if(voltage_v0.6fvoltage_v0.73f){dat0x0A(voltage_v-0.6f)/0.01f;}elseif(voltage_v0.73fvoltage_v1.4f){dat0x17(voltage_v-0.73f)/0.005f;}elseif(voltage_v1.4fvoltage_v3.36f){dat0x9D(voltage_v-1.4f)/0.02f;}else{dat0;}I2C_Write_x(LP87524_I2C_Handle,LP87524_Slave_Add,add,1,dat,1,true);}else{datI2C_Read_y(LP87524_I2C_Handle,LP87524_Slave_Add,add,1,1,true);if(dat0x0Adat0x17){voltage_v(dat-0x0A)*0.01f0.6f;}elseif(dat0x17dat0x9D){voltage_v(dat-0x17)*0.005f0.73f;}elseif(dat0x9Ddat0xFF){voltage_v(dat-0x9D)*0.02f1.4f;}else{voltage_v0;}}}returnvoltage_v;}/*! * brief 开启LP87524的BUCK输出这里是使能BUCK的输出同时对应引脚置高电平 * 初始化配置的是打开VOUT输出如果要控制打开/关闭 VOUT/FLOOR_VOUT则需要另外配置 * * param [in] buck_flag: BUCK序号为4时控制所有 * [in] EnableNotDisable: 使能或者关闭 * * return None */voidEnable_LP87524_BUCK(uint8_tbuck_flag,bool EnableNotDisable){uint8_tdat0;uint8_tadd0;if(buck_flag4){Enable_LP87524_BUCK(0,EnableNotDisable);Enable_LP87524_BUCK(1,EnableNotDisable);Enable_LP87524_BUCK(2,EnableNotDisable);Enable_LP87524_BUCK(3,EnableNotDisable);}else{addLP87524_BUCK0_CTRL12*buck_flag;datI2C_Read_y(LP87524_I2C_Handle,LP87524_Slave_Add,add,1,1,true);if(EnableNotDisable){dat|(17);}else{dat~(17);}I2C_Write_x(LP87524_I2C_Handle,LP87524_Slave_Add,add,1,dat,1,true);switch(buck_flag){case1:{if(EnableNotDisable){Enable_LP87524_EN1;}else{Disable_LP87524_EN1;}break;}case2:{if(EnableNotDisable){Enable_LP87524_EN2;}else{Disable_LP87524_EN2;}break;}case3:{if(EnableNotDisable){Enable_LP87524_EN3;}else{Disable_LP87524_EN3;}break;}default:break;}}}/*! * brief 初始化LP87524 * * param None * * return 0/1: 错误/正确标志 */uint8_tInit_LP87524(void){//原本这里是LP87524_I2C_Handle 由于原理图出错 现全部换成hi2c2uint8_tdat0;Enable_VCC_5V;delay_ms(5);Disable_LP87524_EN1;Disable_LP87524_EN2;Disable_LP87524_EN3;delay_ms(5);if(!I2C_Judge(LP87524_I2C_Handle,LP87524_Slave_Add)){return0;}if(!Reset_LP87524()){return0;}delay_ms(100);dat0x40;I2C_Write_x(LP87524_I2C_Handle,LP87524_Slave_Add,LP87524_CONFIG,1,dat,1,true);dat0x00;I2C_Write_x(LP87524_I2C_Handle,LP87524_Slave_Add,LP87524_PIN_FUNCTION,1,dat,1,true);dat0x34;I2C_Write_x(LP87524_I2C_Handle,LP87524_Slave_Add,LP87524_BUCK0_CTRL1,1,dat,1,true);dat0x44;I2C_Write_x(LP87524_I2C_Handle,LP87524_Slave_Add,LP87524_BUCK1_CTRL1,1,dat,1,true);dat0x54;I2C_Write_x(LP87524_I2C_Handle,LP87524_Slave_Add,LP87524_BUCK2_CTRL1,1,dat,1,true);dat0x64;I2C_Write_x(LP87524_I2C_Handle,LP87524_Slave_Add,LP87524_BUCK3_CTRL1,1,dat,1,true);Ctrl_LP87524_BUCK_VOUT(0,3.3,true);Ctrl_LP87524_BUCK_VOUT(1,1.2,true);Ctrl_LP87524_BUCK_VOUT(2,1.0,true);Ctrl_LP87524_BUCK_VOUT(3,1.8,true);if(Ctrl_LP87524_BUCK_VOUT(0,0,false)!3.3f){printf([INFO] LP87524: BUCK0 Error);}if(Ctrl_LP87524_BUCK_VOUT(1,0,false)!1.2f){printf([INFO] LP87524: BUCK1 Error);}if(Ctrl_LP87524_BUCK_VOUT(2,0,false)!1.0f){printf([INFO] LP87524: BUCK2 Error);}if(Ctrl_LP87524_BUCK_VOUT(3,0,false)!1.8f){printf([INFO] LP87524: BUCK3 Error);}//按1.2 1.8 1.0 3.3的顺序上电//预准备delay_ms(10);datI2C_Read_y(LP87524_I2C_Handle,LP87524_Slave_Add,LP87524_BUCK2_CTRL1,1,1,true);dat|(17);I2C_Write_x(LP87524_I2C_Handle,LP87524_Slave_Add,LP87524_BUCK2_CTRL1,1,dat,1,true);delay_ms(10);Enable_LP87524_BUCK(1,true);delay_us(4400);Enable_LP87524_BUCK(3,true);delay_us(150);//Enable_LP87524_BUCK(2,true);Enable_LP87524_EN2;delay_us(4450);Enable_LP87524_BUCK(0,true);return1;}#ifndef__LP87524_CMD_H__#define__LP87524_CMD_H__#includestdint.h#includestdbool.h#defineLP87524_OTP_REV0x01#defineLP87524_BUCK0_CTRL10x02#defineLP87524_BUCK1_CTRL10x04#defineLP87524_BUCK2_CTRL10x06#defineLP87524_BUCK3_CTRL10x08#defineLP87524_BUCK0_VOUT0x0A#defineLP87524_BUCK0_FLOOR_VOUT0x0B#defineLP87524_BUCK1_VOUT0x0C#defineLP87524_BUCK1_FLOOR_VOUT0x0D#defineLP87524_BUCK2_VOUT0x0E#defineLP87524_BUCK2_FLOOR_VOUT0x0F#defineLP87524_BUCK3_VOUT0x10#defineLP87524_BUCK3_FLOOR_VOUT0x11#defineLP87524_BUCK0_DELAY0x12#defineLP87524_BUCK1_DELAY0x13#defineLP87524_BUCK2_DELAY0x14#defineLP87524_BUCK3_DELAY0x15#defineLP87524_GPIO2_DELAY0x16#defineLP87524_GPIO3_DELAY0x17#defineLP87524_RESET0x18#defineLP87524_CONFIG0x19#defineLP87524_INT_TOP10x1A#defineLP87524_INT_TOP20x1B#defineLP87524_INT_BUCK_0_10x1C#defineLP87524_INT_BUCK_2_30x1D#defineLP87524_TOP_STAT0x1E#defineLP87524_BUCK_0_1_STAT0x1F#defineLP87524_BUCK_2_3_STAT0x20#defineLP87524_TOP_MASK10x21#defineLP87524_TOP_MASK20x22#defineLP87524_BUCK_0_1_MASK0x23#defineLP87524_BUCK_2_3_MASK0x24#defineLP87524_SEL_I_LOAD0x25#defineLP87524_I_LOAD_20x26#defineLP87524_I_LOAD_10x27#defineLP87524_PGOOD_CTRL10x28#defineLP87524_PGOOD_CTRL20x29#defineLP87524_PGOOD_FLT0x2A#defineLP87524_PLL_CTRL0x2B#defineLP87524_PIN_FUNCTION0x2C#defineLP87524_GPIO_CONFIG0x2D#defineLP87524_GPIO_IN0x2E#defineLP87524_GPIO_OUT0x2FfloatCtrl_LP87524_BUCK_VOUT(uint8_tbuck_flag,floatvoltage_v,bool WriteNotRead);floatCtrl_LP87524_BUCK_FLOOR_VOUT(uint8_tbuck_flag,floatvoltage_v,bool WriteNotRead);voidEnable_LP87524_BUCK(uint8_tbuck_flag,bool EnableNotDisable);uint8_tInit_LP87524(void);#endif附录压缩字符串、大小端格式转换压缩字符串首先HART数据格式如下重点就是浮点数和字符串类型Latin-1就不说了 基本用不到浮点数浮点数里面 如 0x40 80 00 00表示4.0f在HART协议里面 浮点数是按大端格式发送的 就是高位先发送 低位后发送发送出来的数组为40,80,00,00但在C语言对浮点数的存储中 是按小端格式来存储的 也就是40在高位 00在低位浮点数4.0f地址0x1000对应00地址0x1001对应00地址0x1002对应80地址0x1003对应40若直接使用memcpy函数 则需要进行大小端转换 否则会存储为地址0x1000对应40地址0x1001对应80地址0x1002对应00地址0x1003对应00大小端转换voidswap32(void*p){uint32_t*ptrp;uint32_tx*ptr;x(x16)|(x16);x((x0x00FF00FF)8)|((x8)0x00FF00FF);*ptrx;}压缩Packed-ASCII字符串本质上是将原本的ASCII的最高2位去掉 然后拼接起来 比如空格(0x20)四个空格拼接后就成了1000 0010 0000 1000 0010 0000十六进制82 08 20对了一下表 0x20之前的识别不了也就是只能识别0x20-0x5F的ASCII表压缩/解压函数后面再写//传入的字符串和数字必须提前声明 且字符串大小至少为str_len 数组大小至少为str_len%4*3 str_len必须为4的倍数uint8_tTrans_ASCII_to_Pack(uint8_t*str,uint8_t*buf,constuint8_tstr_len){if(str_len%4){return0;}uint8_ti0;memset(buf,0,str_len/4*3);for(i0;istr_len;i){if(str[i]0x00){str[i]0x20;}}for(i0;istr_len/4;i){buf[3*i](str[4*i]2)|((str[4*i1]4)0x03);buf[3*i1](str[4*i1]4)|((str[4*i2]2)0x0F);buf[3*i2](str[4*i2]6)|(str[4*i3]0x3F);}return1;}//传入的字符串和数字必须提前声明 且字符串大小至少为str_len 数组大小至少为str_len%4*3 str_len必须为4的倍数uint8_tTrans_Pack_to_ASCII(uint8_t*str,uint8_t*buf,constuint8_tstr_len){if(str_len%4){return0;}uint8_ti0;memset(str,0,str_len);for(i0;istr_len/4;i){str[4*i](buf[3*i]2)0x3F;str[4*i1]((buf[3*i]4)0x30)|(buf[3*i1]4);str[4*i2]((buf[3*i1]2)0x3C)|(buf[3*i2]6);str[4*i3]buf[3*i2]0x3F;}return1;}大小端转换在串口等数据解析中 难免遇到大小端格式问题什么是大端和小端所谓的大端模式就是高位字节排放在内存的低地址端低位字节排放在内存的高地址端。所谓的小端模式就是低位字节排放在内存的低地址端高位字节排放在内存的高地址端。简单来说大端——高尾端小端——低尾端举个例子比如数字 0x12 34 56 78在内存中的表示形式为1)大端模式低地址 ----------------- 高地址0x12 | 0x34 | 0x56 | 0x782)小端模式低地址 ------------------ 高地址0x78 | 0x56 | 0x34 | 0x12可见大端模式和字符串的存储模式类似。数据传输中的大小端比如地址位、起止位一般都是大端格式如起始位0x520A则发送的buf应为{0x52,0x0A}而数据位一般是小端格式单字节无大小端之分如一个16位的数据发送出来为{0x52,0x0A}则对应的uint16_t类型数为 0x0A52而对于浮点数4.0f 转为32位应是40 80 00 00以大端存储来说 发送出来的buf就是依次发送 40 80 00 00以小端存储来说 则发送 00 00 80 40由于memcpy等函数 是按字节地址进行复制 其复制的格式为小端格式 所以当数据为小端存储时 不用进行大小端转换如uint32_tdat0;uint8_tbuf[]{0x00,0x00,0x80,0x40};memcpy(dat,buf,4);floatf0.0f;f*((float*)dat);//地址强转printf(%f,f);或更优解uint8_tbuf[]{0x00,0x00,0x80,0x40};floatf0.0f;memcpy(f,buf,4);而对于大端存储的数据如HART协议数据 全为大端格式 其复制的格式仍然为小端格式 所以当数据为小端存储时 要进行大小端转换如uint32_tdat0;uint8_tbuf[]{0x40,0x80,0x00,0x00};memcpy(dat,buf,4);floatf0.0f;swap32(dat);//大小端转换f*((float*)dat);//地址强转printf(%f,f);或uint8_tbuf[]{0x40,0x80,0x00,0x00};memcpy(dat,buf,4);floatf0.0f;swap32(f);//大小端转换printf(%f,f);或更优解uint32_tdat0;uint8_tbuf[]{0x40,0x80,0x00,0x00};floatf0.0f;dat(buf[0]24)|(buf[0]16)|(buf[0]8)|(buf[0]0)f*((float*)dat);总结固 若数据为小端格式 则可以直接用memcpy函数进行转换 否则通过移位的方式再进行地址强转对于多位数据 比如同时传两个浮点数 则可以定义结构体之后进行memcpy复制数据为小端格式对于小端数据 直接用memcpy写入即可 若是浮点数 也不用再进行强转对于大端数据 如果不嫌麻烦 或想使代码更加简洁但执行效率会降低 也可以先用memcpy写入结构体之后再调用大小端转换函数 但这里需要注意的是 结构体必须全为无符号整型 浮点型只能在大小端转换写入之后再次强转 若结构体内采用浮点型 则需要强转两次所以对于大端数据 推荐通过移位的方式来进行赋值 然后再进行个别数的强转 再往通用结构体进行写入多个不同变量大小的结构体 要主要字节对齐的问题可以用#pragma pack(1) 使其对齐为1但会影响效率大小端转换函数直接通过对地址的操作来实现 传入的变量为32位的变量中间变量ptr是传入变量的地址voidswap16(void*p){uint16_t*ptrp;uint16_tx*ptr;x(x8)|(x8);*ptrx;}voidswap32(void*p){uint32_t*ptrp;uint32_tx*ptr;x(x16)|(x16);x((x0x00FF00FF)8)|((x8)0x00FF00FF);*ptrx;}voidswap64(void*p){uint64_t*ptrp;uint64_tx*ptr;x(x32)|(x32);x((x0x0000FFFF0000FFFF)16)|((x16)0x0000FFFF0000FFFF);x((x0x00FF00FF00FF00FF)8)|((x8)0x00FF00FF00FF00FF);*ptrx;}