[应用方案] 【NuMaker-M471测评】环境状态检测器

[复制链接]
5156|6
 楼主| jinglixixi 发表于 2021-9-1 20:24 | 显示全部楼层 |阅读模式
环境对我们的生活质量有着重要的作用,本打算设计一个家居控制系统,无奈温湿度传感器DHT22对时钟序列的要求比较高,在M471上难以驱动。为此,只能调整设计目标完成一个环境状态检测器。
该检测器的结构框图见图1所示。
                              
1.jpg
图1 结构框图
其中传感器BMP085的作用是检测温度和大气压,是一个数字式传感器;而传感器BH1750则用于光照强度检测,也是一种数字式传感器。由于是数字式传感器,因而省去了数字标定方面的处理。其涉及的显示器件则是LCD5110液晶屏,其线路连接及显示效果如图2所示。
2.jpg
图2 线路连接及显示效果
在引脚连接方面,其连接关系如下:
1)LCD5110屏
VCC--- VREF
GND--- VSS
SCE--- PA2
RST--- PA1
D/C--- PA0
SDIN--- PA3
SCLK--- PA4
LED+--- PA5
2)BMP085
VCC  --- 3.3V
GND  --- GND
SCL  --- PC3
SDA  --- PC2
3)BH1750
VCC  --- 3.3V
GND  --- GND
SCL  --- PC4
SDA  --- PC5
出于使用灵活性的考虑,尽管所用的传感器均为I2C接口的传感器,这里则是采用I/O口模拟的方式来驱动这2个器件。
1. LCD5110屏屏显示驱动
OLED屏的作用主要在于字符、数值字符串显示,以及中文内容的显示,这方面的内容参见:
LCD5110屏显示
网址:https://bbs.21ic.com/icview-3153790-1-1.html
2.BMP085温度大气压
为使用BMP085进行检测,其初始化函数为:
  1. void Init_BMP085()
  2. {
  3. ac1 = Multiple_read(0xAA);
  4. ac2 = Multiple_read(0xAC);
  5. ac3 = Multiple_read(0xAE);
  6. ac4 = Multiple_read(0xB0);
  7. ac5 = Multiple_read(0xB2);
  8. ac6 = Multiple_read(0xB4);
  9. b1 =  Multiple_read(0xB6);
  10. b2 =  Multiple_read(0xB8);
  11. mb =  Multiple_read(0xBA);
  12. mc =  Multiple_read(0xBC);
  13. md =  Multiple_read(0xBE);
  14. }

BMP085发送与接收字节数据的函数为:
  1. void BMP085_Send_Byte(char txd)
  2. {
  3. char t;
  4. IIC_OUTPUT_MODE_SET();
  5. SCL_Clr();
  6. for(t=0;t<8;t++)
  7. {            
  8. if((txd&0x80)>>7)
  9. SDA_Set();
  10. else
  11. SDA_Clr();
  12. txd<<=1;
  13. delayMicroseconds(2);
  14. SCL_Set();
  15. delayMicroseconds(2);
  16. SCL_Clr();
  17. delayMicroseconds(2);
  18. }
  19. }

  20. char BMP085_Read_Byte(unsigned char ack)
  21. {
  22. unsigned char i,receive=0;
  23. IIC_INPUT_MODE_SET();
  24. for(i=0;i<8;i++ )
  25. {
  26. SCL_Clr();
  27. delayMicroseconds(2);
  28. SCL_Set();
  29. receive<<=1;
  30. if(IIC_SDA_IN) receive++;
  31. delayMicroseconds(1);
  32. }
  33. if (!ack)
  34. BMP085_NAck();
  35. else
  36. BMP085_Ack();
  37. return receive;
  38. }

BMP085读取温度与大气压的函数为:
  1. long bmp085ReadTemp(void)
  2. {
  3. BMP085_Start();
  4. BMP085_Send_Byte(BMP085_SlaveAddress);
  5. while(BMP085_Wait_Ack()){}
  6. BMP085_Send_Byte(0xF4);
  7. while(BMP085_Wait_Ack()){}
  8. BMP085_Send_Byte(0x2E);
  9. while(BMP085_Wait_Ack()){}
  10. BMP085_Stop();
  11. delay(10);
  12. return (long) Multiple_read(0xF6);
  13. }

  14. long bmp085ReadPressure(void)
  15. {
  16. long pressure = 0;
  17. BMP085_Start();
  18. BMP085_Send_Byte(BMP085_SlaveAddress);
  19. while(BMP085_Wait_Ack()){}
  20. BMP085_Send_Byte(0xF4);
  21. while(BMP085_Wait_Ack()){}
  22. BMP085_Send_Byte(0x34);
  23. while(BMP085_Wait_Ack()){}
  24. BMP085_Stop();
  25. delay(10);
  26. pressure = Multiple_read(0xF6);
  27. pressure &= 0x0000FFFF;
  28. return pressure;
  29. }

实现数据变换处理的函数为:
  1. void bmp085Convert()
  2. {
  3. unsigned int ut;
  4. unsigned long up;
  5. long x1, x2, b5, b6, x3, b3, p;
  6. unsigned long b4, b7;
  7. ut = bmp085ReadTemp();
  8. up = bmp085ReadPressure();
  9. x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
  10. x2 = ((long) mc << 11) / (x1 + md);
  11. b5 = x1 + x2;
  12. temperature = ((b5 + 8) >> 4);
  13. b6 = b5 - 4000;
  14. x1 = (b2 * (b6 * b6)>>12)>>11;
  15. x2 = (ac2 * b6)>>11;
  16. x3 = x1 + x2;
  17. b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
  18. x1 = (ac3 * b6)>>13;
  19. x2 = (b1 * ((b6 * b6)>>12))>>16;
  20. x3 = ((x1 + x2) + 2)>>2;
  21. b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
  22. b7 = ((unsigned long)(up - b3) * (50000>>OSS));
  23. if (b7 < 0x80000000)
  24. p = (b7<<1)/b4;
  25. else
  26. p = (b7/b4)<<1;  
  27. x1 = (p>>8) * (p>>8);
  28. x1 = (x1 * 3038)>>16;
  29. x2 = (-7357 * p)>>16;
  30. pressure = p+((x1 + x2 + 3791)>>4);
  31. }

3.BH1750光照强度
为使用BH1750进行字节数据的发送,其功能函数为:
  1. void BH1750_SendByte(char data)
  2. {
  3. char i;
  4. pinMode(SDA,OUTPUT);
  5. digitalWrite(SCL, LOW);
  6. delayMicroseconds(2);
  7. for (i=0; i<8; i++)             //8位计数器
  8. {
  9. if(data&0x80) digitalWrite(SDA, HIGH);
  10. else digitalWrite(SDA, LOW);
  11. data <<= 1;
  12. digitalWrite(SCL, HIGH);    //拉高时钟线
  13. delayMicroseconds(2);     //延时
  14. digitalWrite(SCL, LOW);    //拉低时钟线
  15. delayMicroseconds(2);     //延时
  16. }
  17. }

  18. char BH1750_RecvByte()
  19. {
  20. char i;
  21. char data = 0;
  22. IIC_INPUT_MODE_SET();
  23. for (i=0;i<8;i++)
  24. {
  25. SCL_Clr();
  26. TIMER_Delay(TIMER0, 2);
  27. SCL_Set();
  28. data <<= 1;
  29. SCL_Set();
  30. if(PC5==1) data|=0x01;
  31. TIMER_Delay(TIMER0, 1);
  32. }
  33. SCL_Clr();
  34. return data;
  35. }

获取并输出光强值的函数为:
  1. void Get_Sunlight_Value()
  2. {
  3. int dis_data=0;
  4. float temp;
  5. char i=0;
  6. unsigned int sd;
  7. Single_Write_BH1750(0x01);
  8. Single_Write_BH1750(0x10);
  9. delay(180);
  10. Multiple_Read_BH1750();
  11. for(i=0;i<3;i++)    dis_data=BUF[0];
  12. dis_data=(dis_data<<8)+BUF[1];
  13. temp=(float)dis_data/1.2;
  14. sd=temp;
  15. Serial.println(sd);
  16. }

4.实现显示效果的主程序为:
  1. int main()
  2. {
  3. uint32_t i,j;
  4. SYS_Init();
  5. GPIO_SetMode(PB, BIT14, GPIO_MODE_OUTPUT);
  6. GPIO_SetMode(PH, BIT4, GPIO_MODE_INPUT);
  7. PB14 = 1;
  8. TIMER_Delay(TIMER0, 500);
  9. LCD5110_Init();
  10. BH1750_Init();
  11. BMP085_Init();
  12. Init_BMP085();
  13. LCD_prints(0,0,"temp:");
  14. LCD_prints(0,1,"press:");
  15. LCD_prints(0,2,"light:");
  16. while(1)
  17. {
  18. Get_Sunlight_Value();
  19. bmp085Convert();
  20. LCD_printN(5,0,temperature/10,3);
  21. LCD_printN(5,1,pressure/100,5);
  22. PB14 = 0;
  23. TIMER_Delay(TIMER0, 500000);
  24. PB14 = 1;
  25. TIMER_Delay(TIMER0, 500000);
  26. }
  27. }


redone 发表于 2021-9-11 11:09 | 显示全部楼层
传感器不少啊。哈哈哈
 楼主| jinglixixi 发表于 2021-9-11 15:31 | 显示全部楼层
koala889 发表于 2021-9-18 16:43 | 显示全部楼层
nice,楼主好强大
 楼主| jinglixixi 发表于 2021-9-18 17:20 | 显示全部楼层
感谢支持!!!
onlycook 发表于 2021-9-24 10:30 来自手机 | 显示全部楼层
楼主优秀啊,可以拜师吗
 楼主| jinglixixi 发表于 2021-9-24 14:51 | 显示全部楼层
onlycook 发表于 2021-9-24 10:30
楼主优秀啊,可以拜师吗

优秀就过誉了,只是喜欢而已。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

521

主题

2949

帖子

39

粉丝
快速回复 在线客服 返回列表 返回顶部