本帖最后由 jinglixixi 于 2022-12-21 22:39 编辑
#申请原创#
以MM32L0136开发板为核心,实现环境状态检测记录器的整体构成如图1所示,其中传感器BH1750用于光照强度的接触,传感器BMP085用于温度和大气压的检测,OLED屏用于数据显示,串行数据记录模块用于数据记录。 在4个外设中,除数据记录模块是串行设备外,其它3个均为I2C接口的外设。 图1 整体构成
对于这4个外设,其引脚连接情况如下: OLED: SCL---B9 SDA---B10
BH1750: SCL---B11 SDA---B12
记录仪: RX---PA2_TX BMP085: SCL---D5 SDA---A8
1. 传感器BMP085 BMP085在检测过程中,主要依赖的是字节收发函数,其具体的内容如下: void BMP085_Send_Byte(char txd)
{
char t;
OUTPUT_MODE_SET();
SCL_Clr1();
for(t=0;t<8;t++)
{
if((txd&0x80)>>7)
{
SDA_Set1();
}
else
{
SDA_Clr1();
}
txd<<=1;
del_t(20);
SCL_Set1();
del_t(20);
SCL_Clr1();
del_t(20);
}
}
char BMP085_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
INPUT_MODE_SET();
for(i=0;i<8;i++)
{
SCL_Clr1();
del_t(20);
SCL_Set1();
receive<<=1;
if(SDA_IN) receive++;
del_t(20);
}
if(!ack)
BMP085_NAck();
else
BMP085_Ack();
return receive;
}
通过以上2个函数的支持,读取温度和大气压的函数分别为: long bmp085ReadTemp(void)
{
BMP085_Start();
BMP085_Send_Byte(BMP085_SlaveAddress);
while(BMP085_Wait_Ack());
BMP085_Send_Byte(0xF4);
while(BMP085_Wait_Ack());
BMP085_Send_Byte(0x2E);
while(BMP085_Wait_Ack());
BMP085_Stop();
del_t(10000); ;
return (long) Multiple_read(0xF6);
}
long bmp085ReadPressure(void)
{
long pressure = 0;
BMP085_Start();
BMP085_Send_Byte(BMP085_SlaveAddress);
while(BMP085_Wait_Ack()){}
BMP085_Send_Byte(0xF4);
while(BMP085_Wait_Ack()){}
BMP085_Send_Byte(0x34);
while(BMP085_Wait_Ack()){}
BMP085_Stop();
del_t(10000); ;
pressure = Multiple_read(0xF6);
pressure &= 0x0000FFFF;
return pressure;
}
最终实现温度与气压值转换的函数为: void bmp085Convert()
{
unsigned int ut;
unsigned long up;
long x1, x2, b5, b6, x3, b3, p;
unsigned long b4, b7;
ut = bmp085ReadTemp();
up = bmp085ReadPressure();
x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
x2 = ((long) mc << 11) / (x1 + md);
b5 = x1 + x2;
temperature1 = ((b5 + 8) >> 4);
b6 = b5 - 4000;
x1 = (b2 * (b6 * b6)>>12)>>11;
x2 = (ac2 * b6)>>11;
x3 = x1 + x2;
b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
x1 = (ac3 * b6)>>13;
x2 = (b1 * ((b6 * b6)>>12))>>16;
x3 = ((x1 + x2) + 2)>>2;
b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
b7 = ((unsigned long)(up - b3) * (50000>>OSS));
if (b7 < 0x80000000)
p = (b7<<1)/b4;
else
p = (b7/b4)<<1;
x1 = (p>>8) * (p>>8);
x1 = (x1 * 3038)>>16;
x2 = (-7357 * p)>>16;
pressure = p+((x1 + x2 + 3791)>>4);
}
这样在使用温度和大气压检测值时,通过读取变量temperature1和pressure就可以了。
2. 数据记录模块 对于数据记录模块它是一种串口设备,在使用时主要符合其波特率9600bps的要求即可,向其发送的数据即被其完整地记录到TF卡的文件中。为进行测试,通过串口可查看到其记录的数据内容,见图2所示。
图2 记录数据测试
在接入数据记录模块后,其存入文件的内容如图3所示,说明其完全符合设计的要求。 图3 记录文件格式及内容
3. 其它外设
除传感器BMP085和数据记录模块的内容之外,其它外设的使用可参见:
(1)RTC电子时钟 https://bbs.21ic.com/icview-3269248-1-1.html
(2)GPIO口使用及OLED https://bbs.21ic.com/icview-3269538-1-1.html
(3) 光照强度检测与显示 https://bbs.21ic.com/icview-3269724-1-1.html
4. 主程序
实现环境状态检测记录功能的主程序为: int main(void)
{
uint8_t ch,tt,p;
uint16_t u;
BOARD_Init();
Init_oled();
OLED_Init();
OLED_Clear();
OLED_ShowCHinese(8,0,0);
OLED_ShowCHinese(24,0,1);
OLED_ShowCHinese(40,0,2);
OLED_ShowCHinese(56,0,3);
OLED_ShowCHinese(72,0,4);
OLED_ShowCHinese(90,0,5);
OLED_ShowCHinese(106,0,8);
app_rtc_init();
OLED_ShowString(0,2," : : - ",16);
app_rtc_get_current_time();
tt=rtc_time.Months/16*10+rtc_time.Months%16;
OLED_ShowNum(72,2,tt,2,16);
tt=rtc_time.Days/16*10+rtc_time.Days%16;
OLED_ShowNum(96,2,tt,2,16);
OLED_ShowString(0,4,"Light= Lx",16);
OLED_ShowString(0,6,"P= KP T= C",16);
BH1750_Init();
BMP085_Init();
Init_BMP085();
del_t(200);
p=rtc_time.Secs;
while (1)
{
app_rtc_get_current_time();
if(p<rtc_time.Secs)
{
p=rtc_time.Secs;
printf("%02x:", (unsigned int)(long)rtc_time.Hours);
printf("%02x", (unsigned int)(long)rtc_time.Mins);
printf(":%02x ", (unsigned int)(long)rtc_time.Secs);
tt=rtc_time.Hours/16*10+rtc_time.Hours%16;
OLED_ShowNum(0,2,tt,2,16);
tt=rtc_time.Mins/16*10+rtc_time.Mins%16;
OLED_ShowNum(24,2,tt,2,16);
tt=rtc_time.Secs/16*10+rtc_time.Secs%16;
OLED_ShowNum(48,2,tt,2,16);
Get_Sunlight_Value();
bmp085Convert();
u=temperature1/10;
OLED_ShowNum(88,6,u,2,16);
printf("temp=%d ",u);
u=pressure/100;
OLED_ShowNum(16,6,u,4,16);
printf("press=%d \r\n",u);
del_t(10000);
}
}
}
从便于设计的角度出发,显示功能和数据记录功能的一部分已被放置到相应的检测程序中,这样就实现了环境状态检测记录器的整体设计目标。
视频演示: |