1. 传感器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);
- }
- }
- }
从便于设计的角度出发,显示功能和数据记录功能的一部分已被放置到相应的检测程序中,这样就实现了环境状态检测记录器的整体设计目标。
视频演示: