当前位置: 首页 > news >正文

手机网页加速器优化公司排行榜

手机网页加速器,优化公司排行榜,手机wap网站用什么语言开发,独立购物网站建设KEIL开发 51 单片机程序 算法处理过程中遇到的问题 ...... by 矜辰所致前言 因为产品的更新换代, 把所有温湿度传感器都换成 SHT40 ,替换以前的 SHT21。在 STM32 系列产品上的替换都正常,但是在一块 51 内核的无线产品上面,数据…
KEIL开发 51 单片机程序 算法处理过程中遇到的问题  ...... by 矜辰所致

前言

因为产品的更新换代, 把所有温湿度传感器都换成 SHT40 ,替换以前的 SHT21。在 STM32 系列产品上的替换都正常,但是在一块 51 内核的无线产品上面,数据莫名其妙的总会遇到异常的情况,弯弯绕绕了好一阵子,最后才发现是程序在执行一个不算复杂的算法的时候会出错。

那么本文的目的就是说明这个问题,以及如何解决这个问题,同时也想向大家请教这个问题出现的原因。 因为到最后,没有花时间去过多的研究到底是怎么出的问题。

我是矜辰所致,全网同名,尽量用心写好每一系列文章,不浮夸,不将就,认真对待学知识的我们,矜辰所致,金石为开!

目录

  • 前言
  • 一、 SHT40 温湿度读取
  • 二、51 上的数据异常
    • 2.1 程序移植
    • 2.2 问题分析
    • 2.3 问题解决
  • 结语

一、 SHT40 温湿度读取

本来 SHT40 其实特别简单, 简单的 I2C 通讯,简单的计算公式,在 SHT40 数据手册上面,只要看一个地方基本就能把 SHT40 用起来了,如下图:

在这里插入图片描述

硬件电路,和算法手册都给出来了,实际上在使用 STM32 的时候确实是真简单就可以正确的读取到数据,代码如下:

/*
SHT40
地址和 SHT30 一样 0x44
*/
Readthstruct SHT40_read_result(u8 addr)
{u16 tem,hum;u16 buff[6] = {0};float Temperature=0;float Humidity=0;Readthstruct sensordata;I2C_Start();I2C_Send_Byte(addr<<1 | write);//写7位I2C设备地址加0作为写取位,1为读取位I2C_Wait_Ack();I2C_Send_Byte(0xFD);    //  SHT 40 只需要一个 0xFDI2C_Wait_Ack();// I2C_Send_Byte(0x06);// I2C_Wait_Ack();I2C_Stop();HAL_Delay(20);I2C_Start();I2C_Send_Byte(addr<<1 | read);//写7位I2C设备地址加0作为写取位,1为读取位if(I2C_Wait_Ack()==0){buff[0]=I2C_Read_Byte(1);buff[1]=I2C_Read_Byte(1);        buff[2]=I2C_Read_Byte(1);        buff[3]=I2C_Read_Byte(1);buff[4]=I2C_Read_Byte(1);buff[5]=I2C_Read_Byte(0);I2C_Stop();}tem = ((buff[0]<<8) | buff[1]);//温度拼接hum = ((buff[3]<<8) | buff[4]);//湿度拼接/*转换实际温度*/Temperature= (175.0*(float)tem/65535.0-45.0) ;// T = -45 + 175 * tem / (2^16-1)/**humi = (1.0 * 125 * (readData[3] * 256 + readData[4])) / 65535.0 - 6.0;rh_pRH = -6 + 125 * rh_ticks/65535*/Humidity= (125.0*(float)hum/65535.0-6.0); // sprintf(humiture_buff1,"%6.2f*C %6.2f%%",Temperature,Humidity);//111.01*C 100.01%(保留2位小数)// printf("温湿度:%s\n",humiture_buff1);if((Temperature>=-20)&&(Temperature<=80)&&(Humidity>=0)&&(Humidity<=100))//过滤错误数据{sensordata.tem_100 = (u16)(Temperature*100);sensordata.hum_100 = (u16)(Humidity*100);}else{//重新通讯读取一遍}// printf("温度100倍:%d\n湿度100倍:%d\n",sensordata.tem_100,sensordata.hum_100);hum=0;tem=0;if(sensordata.tem_100>4000) sensordata.tem_100=4000;              //A5-04-01 0~40du else if(sensordata.tem_100<0) sensordata.tem_100=0;if(sensordata.hum_100>10000) sensordata.hum_100=10000;              //prevent temperature over-/underflowelse if(sensordata.hum_100<0) sensordata.hum_100=0;return sensordata;
}

上面的代码是为了得到 温湿度实际数据的100倍的结果, 上面时候因为测试,中途需要打印浮点数,所以中途按照浮点数计算了结果,
其实可以在Temperature= (175.0*(float)tem/65535.0-45.0) 这地方直接得到 100 倍的数值,
而且还可以省去浮点数的计算。

反正到这里一切都是正常的,于情于理挺简单的应用当然不会有问题。

二、51 上的数据异常

2.1 程序移植

在 STM32 上替换很顺利,那么还有一款 51 内核的无线芯片也需要替换,那么其实也就是做了简单的移植,通讯逻辑基本和上面一样:

void SHT40THMeasure()
{sint16 tem,hum;uint16 buff[6] = {0};float Temperature=0;float Humidity=0;time_wait(20);i2c_start();u8Ack = i2c_write(0x94); //SHT40_SOFT_RESETi2c_stop();time_wait(10);	i2c_start();u8Ack = i2c_write(0X44<<1); //I2C_Send_Byte(0x44<<1 | 0);u8Ack = i2c_write(0xFD);i2c_stop();time_wait(20); //HAL_Delay(20);i2c_start();u8Ack = i2c_write((0X44<<1) + 1);if(u8Ack==I2C_ACK){buff[0]= i2c_read(I2C_ACK);	buff[1]= i2c_read(I2C_ACK);	buff[2]= i2c_read(I2C_ACK);	buff[3]= i2c_read(I2C_ACK);buff[4]= i2c_read(I2C_ACK);	buff[5]= i2c_read(I2C_NACK);i2c_stop();} tem = ((buff[0]<<8) | buff[1]);//温度拼接hum = ((buff[3]<<8) | buff[4]);//湿度拼接Temperature= (175.0*(float)tem/65535.0-45.0) ;// T = -45 + 175 * tem / (2^16-1)Humidity= (125.0*(float)hum/65535.0-6.0); if((Temperature>=-20)&&(Temperature<=80)&&(Humidity>=0)&&(Humidity<=100))//过滤错误数据{aTemperature.value = (u16)(Temperature*100);aHumidity.value = (u16)(Humidity*100);}else{//数据出错,再来一遍i2c_start();u8Ack = i2c_write(0x94); //SHT40_SOFT_RESETi2c_stop();// 这里就省略了,就是重复一遍}if(aTemperature.value>4000) aTemperature.value=4000;              //prevent temperature over-/underflowelse if(aTemperature.value<0) aTemperature.value=0;if(aHumidity.value>10000) aHumidity.value=10000;              //prevent temperature over-/underflowelse if(aHumidity.value<0) aHumidity.value=0;}

上面代码其实也不复杂,因为本来就很简单。 但是在测试的时候,总是会出现温湿度数据异常的情况,比如湿度为0 ,温度最最大值等等 。

2.2 问题分析

在最开始的时候,连硬件问题,然后还有因为低功耗需要给传感器断电问题都统统想到过,都先给一一排除了。

最终还是回到程序上来,也尝试过校验,软件复位,多次读取等等方式,发现依然存在问题。

各种可能的不可能的问题估计都想过,最后考虑了一下以前是 32 位的 ARM 内核,现在是 8 位 51 内核,是不是算法有点问题,然后看了下代码,主要集中在算法那两行代码 :

	Temperature= (175.0*(float)tem/65535.0-45.0) ;// T = -45 + 175 * tem / (2^16-1)Humidity= (125.0*(float)hum/65535.0-6.0); 

想着在 51 单片机上进行浮点数运算比较 “困难” 的,如果可以尽量减少浮点数的运算 。

所以为了防止因为浮点数计算导致的问题,直接把浮点数运算也去掉,因为以前 SHT21 在 51 上数据也是正常的,所以参考了一下 以前 SHT21 的算法书写:

sint16 sht21_calcRH(uint16 u16RH)
{sint16 humidityRH;              // variable for resultu16RH &= ~0x0003;          // clear bits [1..0] (status bits)//-- calculate relative humidity [%RH] --humidityRH = (sint16)(-600 + (12500*(sint32)u16RH)/65536 ); // RH = -6 + 125 * SRH/2^16return humidityRH;                                          // Return RH*100
}// -------------------------------------------------------------------
sint16 sht21_calcTemperature(uint16 u16T)
{sint16 temperature;            // variable for resultu16T &= ~0x0003;           // clear bits [1..0] (status bits)//-- calculate temperature [癈] --temperature= (sint16)(-4685 + (17572*(sint32)u16T)/65536); //T = -46.85 + 175.72 * ST/2^16return temperature;                                        //return T*100
}

把算法变成如下:

tem = ((buff[0]<<8) | buff[1]);//温度拼接hum = ((buff[3]<<8) | buff[4]);//湿度拼接aTemperature.value =   (sint16)	(17500*(sint32)tem/65535 - 4500) ;aHumidity.value = (sint16) (12500*(sint32)hum/65535 - 600); ...

上面已经没有了浮点数运算,数据类型也注意到了,感觉应该没什么问题。

但是实际测试下来,结果还是和以前一样。

期间还测试发现当湿度大于接近 40% 的时候,湿度 aHumidity.value 就会变成 0 。

为了排除不是传感器通讯的问题,期间还读取过 tem 和 hum 的值观察,然后自己通过算法计算都能得到准确的数据。

然后自己给一个合理的 tem hum 的值,如下图:

tem = ((buff[0]<<8) | buff[1]);//温度拼接hum = ((buff[3]<<8) | buff[4]);//湿度拼接tem = 0x 78;//写文章的测试例子,当时是多少来着忘记了tem = 0x 78;aTemperature.value =   (sint16)	(17500*(sint32)tem/65535 - 4500) ;aHumidity.value = (sint16) (12500*(sint32)hum/65535 - 600); ...

确实发现只要 aHumidity.value 正确计算结果在接近或者大于 4000 的时候,这个算是结果在程序中就会变成 0 。

对比了一下算法的书写,是在看不出哪里会溢出什么的。

再反复看了以前 SHT21 的算法,明明也是这样的算法,怎么就会不行了呢?

在这里插入图片描述

2.3 问题解决

最后实在是觉得还是不应该出问题,但是明明以前 SHT21 也是在同样的环境,同样的平台下,就是这么写的算式,不应该啊。

最后才看来看去,再看了下以前 SHT21 怎么处理的:

在这里插入图片描述

在文章上面其实我也给出了 SHT21 的这两个计算结果的函数,在以前 I2C 通讯完毕,是通过调用了计算结果的函数得到的数值没有问题。

于是乎,我把 SHT40 也尝试封装成了同样的函数,算法直接复制进去,如下图:

在这里插入图片描述

然后忽然就发现…… 好了…… 数据怎么样都正常了……

这真的是沙比问题,我确实有点懵了,反正最后自己也不知道是什么根本原因。

网上也没有明确的此类问题的,到处查阅了一些资料,有的说是因为编译器的代码优化问题,或者说是因为 51 编译器自己的问题导致的。

结语

其实问题虽然是解决了,但是我还是不知道是因为什么原因,如果有小伙伴知道,还望多多指教,记得留言哦 。

当然出了这个问题,也给我们提了个醒,算法最好是封装成函数,虽然说,函数调用会有一定的开销,但是这样做不仅可读性和维护性强, 在重用,调试等方面也更有优势, 最重要的可以避免编译器对我们的程序进行不理想的优化导致的一些错误 。

那么本文就到这里,谢谢大家!

http://www.ocqcb.cn/news/589.html

相关文章:

  • 百度推广太原网站建设seo页面代码优化
  • 各大网站平台发布信息软文营销广告
  • 如何做部落冲突网站windows 优化大师
  • 商城网站是怎么做的武汉网站快速排名提升
  • 无锡网站推广综合权重查询
  • 怎么做建设网站首页windows优化大师是官方的吗
  • 怎么看一个网站是哪个公司做的网站推广软件ky99
  • 电商网站支付方案南宁网络推广服务商
  • 浙江省建设厅网站资质迁移bt磁力搜索
  • vps用什么软件做网站线上营销策略都有哪些
  • 做贷款的网站有哪些网站流量统计分析工具
  • 拱墅网站建设制作热点时事新闻
  • 深圳住房和建设局官网网站十大网络营销经典案例
  • 东莞市网站建设分站58同城关键词怎么优化
  • 做网站赚钱的QQ群惠州seo排名
  • vs2010可以做动态网站吗学大教育一对一收费价格表
  • 惠州网站建设咨询重庆seo公司怎么样
  • semcms外贸网站管理系统营销型网站建设设计
  • 英迈思做网站做的怎样搜索引擎seo
  • 购物网站排名前十北京网站推广助理
  • 青岛网站建设收费哪个平台好公司网站怎么建立
  • 网站所有权网上推广怎么收费
  • 黑龙江两学一做网站中央广播电视总台
  • python 做网站教程如何去除痘痘效果好
  • 广州做网站建设的公司排名汕头seo排名收费
  • 网站建设 小知识昆明网站seo公司
  • abc公司电子商务网站建设策划书网站免费搭建平台
  • 专业做网文的网站新闻式软文范例
  • 网络网站建设电话推销福州百度开户多少钱
  • 定西网站建设天津百度网站排名优化