C/C# float与byte/u8 数组的转化

如有问题,请加扣扣群:460189483

编程语言主要采用IEEE754来存储浮点数,这里有IEEE标准的介(百度百科),或者这里 (知乎:IEEE 754格式是什么?)

在C语言中对于float,用4字节存储,

比如

1.618000  ,在内存中为 160  26 207    63

1.000000,  在内存中为  0      0    128    63

那么我有4个字节数据,比如{160  26 207    63},怎么转成float呢?

在嵌入式开发中经常要用到通讯,将float类型数据上传到Windows等监控上位机,在这里只能将float数据转化为unsigned char 类型数组,那怎么转化呢,这里提供了几种方法:

1. 下位机定义float数值

  使用union联合体进行转化,例如

typedef union 
{
    float a;
    u8 b[4];
}float_t;   

程序中定义数据类型:float_t  test;

test.a=3.14f; 则可以获得对应的U8类型数组b[]={0XC3,0XF5,0X48,0X40};将这个数组传给上位机即可

2. 上位机Windows接收到数值处理

使用C#开发的桌面程序接收到数值之后怎么处理呢?可以采用

float f = BitConverter.ToSingle(b, 0);

将接收的数值转化为float类型的数值

3. Windows上位机发送float类型数值

float f=3.14f;

byte[] b = BitConverter.GetBytes(f);

这样就可以将float类型数值转化为byte类型,通过串口下发下位机即可        

4. 下位机接收到float类型

此处有2种方法,一种是使用联合体的方法

test.b[0] = 接收[0]

test.b[1] = 接收[1]

test.b[2] = 接收[2]

test.b[3] = 接收[3]

此处注意大小端对齐,上位机下位机大小端要注意一下

第二种方法是使用指针的方法

 

float temp;    
unsigned char *p = (unsigned char*)&temp;

   p[0]=接收[0]; 
   p[1]=接收[1]; 
   p[2]=接收[2];
   p[3]=接收[3];

这样也可以将内存中的数据转化为float类型的数值

这样就完成了下位机与上位机之间float类型数据互传的问题

下面加一些常用的API供参考

在c#中可以使用BitConverter类中的函数进行转换,如下:

名称

说明

GetBytes(Double)

以字节数组的形式返回指定的双精度浮点值。

GetBytes(Single)

以字节数组的形式返回指定的单精度浮点值。

ToDouble

返回由字节数组中指定位置的八个字节转换来的双精度浮点数。

ToSingle

返回由字节数组中指定位置的四个字节转换来的单精度浮点数。

BitConverter类进行基础数据类型与字节数组之间的相互转换,此类便于操作基本形式的类型。一个字节定义为一个 8位无符号整数。包含的方法如下:

名称

说明

DoubleToInt64Bits

将指定的双精度浮点数转换为 64 位有符号整数。

GetBytes(Boolean)

以字节数组的形式返回指定的布尔值。

GetBytes(Char)

以字节数组的形式返回指定的 Unicode 字符值。

GetBytes(Double)

以字节数组的形式返回指定的双精度浮点值。

GetBytes(Int16)

以字节数组的形式返回指定的 16 位有符号整数值。

GetBytes(Int32)

以字节数组的形式返回指定的 32 位有符号整数值。

GetBytes(Int64)

以字节数组的形式返回指定的 64 位有符号整数值。

GetBytes(Single)

以字节数组的形式返回指定的单精度浮点值。

GetBytes(UInt16)

以字节数组的形式返回指定的 16 位无符号整数值。

GetBytes(UInt32)

以字节数组的形式返回指定的 32 位无符号整数值。

GetBytes(UInt64)

以字节数组的形式返回指定的 64 位无符号整数值。

Int64BitsToDouble

将指定的 64 位有符号整数转换成双精度浮点数。

ToBoolean

返回由字节数组中指定位置的一个字节转换来的布尔值。

ToChar

返回由字节数组中指定位置的两个字节转换来的 Unicode 字符。

ToDouble

返回由字节数组中指定位置的八个字节转换来的双精度浮点数。

ToInt16

返回由字节数组中指定位置的两个字节转换来的 16 位有符号整数。

ToInt32

返回由字节数组中指定位置的四个字节转换来的 32 位有符号整数。

ToInt64

返回由字节数组中指定位置的八个字节转换来的 64 位有符号整数。

ToSingle

返回由字节数组中指定位置的四个字节转换来的单精度浮点数。

ToString( array<Byte []()>[])

将指定的字节数组的每个元素的数值转换为它的等效十六进制字符串表示形式。

ToString( array<Byte []()>[], Int32)

将指定的字节子数组的每个元素的数值转换为它的等效十六进制字符串表示形式。

ToString( array<Byte []()>[], Int32, Int32)

将指定的字节子数组的每个元素的数值转换为它的等效十六进制字符串表示形式。

ToUInt16

返回由字节数组中指定位置的两个字节转换来的 16 位无符号整数。

ToUInt32

返回由字节数组中指定位置的四个字节转换来的 32 位无符号整数。

ToUInt64

返回由字节数组中指定位置的八个字节转换来的 64 位无符号整数。

#include <reg52.h> #include <intrins.h> typedef unsigned int u16; typedef unsigned char u8; // 定义DS18B20温度传感器控制管脚 sbit DS18B20_PORT = P3^7; // 定义直流电机控制管脚 sbit DC_Motor = P1^0; // 修改蜂鸣器控制引脚为 P2.5 sbit Buzzer = P2^5; // 使用 P2.5 控制蜂鸣器 // 定义数码管控制引脚 sbit LSA = P2^2; sbit LSB = P2^3; sbit LSC = P2^4; #define SMG_A_DP_PORT P0 // 共阴极数码管段码表(0-F) u8 gsmg_code[17] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; /******************************************************************************* * 函 数 名 : delay_10us * 函数功能 : 延时函数,ten_us=1时约延时10us * 输 入 : ten_us - 延时参数 * 输 出 : 无 *******************************************************************************/ void delay_10us(u16 ten_us) { while (ten_us--); } /******************************************************************************* * 函 数 名 : delay_ms * 函数功能 : 毫秒级延时函数 * 输 入 : ms - 延时毫秒数 * 输 出 : 无 *******************************************************************************/ void delay_ms(u16 ms) { u16 i, j; for (i = ms; i > 0; i--) for (j = 110; j > 0; j--); } /******************************************************************************* * 函 数 名 : ds18b20_reset * 函数功能 : 复位DS18B20传感器 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void ds18b20_reset(void) { DS18B20_PORT = 0; delay_10us(75); DS18B20_PORT = 1; delay_10us(2); } /******************************************************************************* * 函 数 名 : ds18b20_check * 函数功能 : 检测DS18B20是否存在 * 输 入 : 无 * 输 出 : 1-未检测到,0-存在 *******************************************************************************/ u8 ds18b20_check(void) { u8 time_temp = 0; while (DS18B20_PORT && time_temp < 20) { time_temp++; delay_10us(1); } if (time_temp >= 20) return 1; time_temp = 0; while ((!DS18B20_PORT) && time_temp < 20) { time_temp++; delay_10us(1); } if (time_temp >= 20) return 1; return 0; } /******************************************************************************* * 函 数 名 : ds18b20_read_bit * 函数功能 : 从DS18B20读取一个位 * 输 入 : 无 * 输 出 : 读取的位数据(1/0) *******************************************************************************/ u8 ds18b20_read_bit(void) { u8 dat = 0; DS18B20_PORT = 0; _nop_(); _nop_(); DS18B20_PORT = 1; _nop_(); _nop_(); if (DS18B20_PORT) dat = 1; else dat = 0; delay_10us(5); return dat; } /******************************************************************************* * 函 数 名 : ds18b20_read_byte * 函数功能 : 从DS18B20读取一个字节 * 输 入 : 无 * 输 出 : 读取的字节数据 *******************************************************************************/ u8 ds18b20_read_byte(void) { u8 i = 0, dat = 0, temp = 0; for (i = 0; i < 8; i++) { temp = ds18b20_read_bit(); dat = (temp << 7) | (dat >> 1); } return dat; } /******************************************************************************* * 函 数 名 : ds18b20_write_byte * 函数功能 : 向DS18B20写入一个字节 * 输 入 : dat - 要写入的字节 * 输 出 : 无 *******************************************************************************/ void ds18b20_write_byte(u8 dat) { u8 i = 0, temp = 0; for (i = 0; i < 8; i++) { temp = dat & 0x01; dat >>= 1; if (temp) { DS18B20_PORT = 0; _nop_(); _nop_(); DS18B20_PORT = 1; delay_10us(6); } else { DS18B20_PORT = 0; delay_10us(6); DS18B20_PORT = 1; _nop_(); _nop_(); } } } /******************************************************************************* * 函 数 名 : ds18b20_start * 函数功能 : 启动DS18B20温度转换 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void ds18b20_start(void) { ds18b20_reset(); ds18b20_check(); ds18b20_write_byte(0xCC); ds18b20_write_byte(0x44); } /******************************************************************************* * 函 数 名 : ds18b20_init * 函数功能 : 初始化DS18B20 * 输 入 : 无 * 输 出 : 1-初始化失败,0-初始化成功 *******************************************************************************/ u8 ds18b20_init(void) { ds18b20_reset(); return ds18b20_check(); } /******************************************************************************* * 函 数 名 : ds18b20_read_temperture * 函数功能 : 读取DS18B20温度值 * 输 入 : 无 * 输 出 : 温度值(单位:0.1℃) *******************************************************************************/ float ds18b20_read_temperture(void) { float temp; u8 dath = 0, datl = 0; u16 value = 0; ds18b20_start(); ds18b20_reset(); ds18b20_check(); ds18b20_write_byte(0xCC); ds18b20_write_byte(0xBE); datl = ds18b20_read_byte(); dath = ds18b20_read_byte(); value = (dath << 8) | datl; if ((value & 0xF800) == 0xF800) { value = (~value) + 1; temp = value * (-0.0625); } else { temp = value * 0.0625; } return temp; } /******************************************************************************* * 函 数 名 : smg_display * 函数功能 : 动态数码管显示 * 输 入 : dat - 显示数据数组, pos - 起始显示位置 * 输 出 : 无 *******************************************************************************/ void smg_display(u8 dat[], u8 pos) { u8 i = 0, pos_temp = pos - 1; for (i = pos_temp; i < 8; i++) { switch (i) { case 0: LSC = 1; LSB = 1; LSA = 1; break; case 1: LSC = 1; LSB = 1; LSA = 0; break; case 2: LSC = 1; LSB = 0; LSA = 1; break; case 3: LSC = 1; LSB = 0; LSA = 0; break; case 4: LSC = 0; LSB = 1; LSA = 1; break; case 5: LSC = 0; LSB = 1; LSA = 0; break; case 6: LSC = 0; LSB = 0; LSA = 1; break; case 7: LSC = 0; LSB = 0; LSA = 0; break; } SMG_A_DP_PORT = dat[i - pos_temp]; delay_10us(100); SMG_A_DP_PORT = 0x00; } } /******************************************************************************* * 函 数 名 : buzzer_alarm * 函数功能 : 蜂鸣器报警控制(使用P2.5引脚) * 输 入 : temp - 当前温度值 * 输 出 : 无 *******************************************************************************/ void buzzer_alarm(float temp) { static u16 alarm_counter = 0; // 报警计数器 if (temp > 29.0) { // 产生间歇性报警声 (500ms周期) alarm_counter++; if (alarm_counter < 250) { Buzzer = 1; // 蜂鸣器开启(P2.5高电平) } else if (alarm_counter < 500) { Buzzer = 0; // 蜂鸣器关闭(P2.5低电平) } else { alarm_counter = 0; // 重置计数器 } } else { Buzzer = 0; // 关闭蜂鸣器(P2.5低电平) alarm_counter = 0; } } /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数,温度高于29℃启动电机和蜂鸣器,低于29℃停止 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void main() { u8 i = 0; float temp = 0; u8 temp_buf[5] = {0}; // 初始化引脚 DC_Motor = 0; // 关闭电机 Buzzer = 0; // 关闭蜂鸣器(P2.5低电平) ds18b20_init(); // 初始化DS18B20温度传感器 while (1) { i++; if (i % 50 == 0) { // 每50次循环读取一次温度 temp = ds18b20_read_temperture(); // 读取温度 } // 根据温度控制电机启停 if (temp > 29.0) { // 温度高于29℃,启动电机 DC_Motor = 1; } else { // 温度低于29℃,停止电机 DC_Motor = 0; } // 控制蜂鸣器报警(使用P2.5引脚) buzzer_alarm(temp); // 处理温度显示 if (temp < 0) { temp_buf[0] = 0x40; // 显示负号 temp = -temp; } else { temp_buf[0] = 0x00; // 不显示符号 } // 分解温度数据到显示缓冲区 temp_buf[1] = gsmg_code[(int)temp / 100]; // 百位 temp_buf[2] = gsmg_code[(int)temp % 100 / 10]; // 十位 temp_buf[3] = gsmg_code[(int)temp % 10] | 0x80; // 个位,带小数点 temp_buf[4] = gsmg_code[(int)(temp * 10) % 10]; // 小数位 smg_display(temp_buf, 4); // 从第4位开始显示 } } 修改这段代码使蜂鸣器声音一直响
最新发布
06-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值