找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4665|回复: 6
收起左侧

单片机+BMP180+LCD1602温度气压高度计源程序

[复制链接]
ID:33449 发表于 2018-11-3 10:36 | 显示全部楼层 |阅读模式
89c90单片机做的1602液晶显示BMP180气压

单片机源程序如下:
  1. #include  <REG52.H>
  2. #include  <math.h>    //Keil library
  3. #include  <stdlib.h>  //Keil library
  4. #include  <stdio.h>   //Keil library
  5. #include  <INTRINS.H> //Keil library

  6. #define   uchar unsigned char
  7. #define   uint unsigned int
  8. #define BMP085_SlaveAddress   0xee  //定义器件在IIC总线中的从地址                              
  9. #define OSS 0// Oversampling Setting (note: code is not set up to use other OSS values)
  10. #define   DataPort P0    //LCD1602数据端口

  11. sbit      LCM_RS=P2^4;   //LCD1602命令端口               
  12. sbit      LCM_RW=P2^5;   //LCD1602命令端口               
  13. sbit      LCM_EN=P2^6;   //LCD1602命令端口
  14. sbit  SCL=P1^0;      //IIC时钟引脚定义
  15. sbit   SDA=P1^1;      //IIC数据引脚定义
  16. int  dis_data;                              //变量
  17. typedef unsigned char  BYTE;
  18. typedef unsigned short WORD;
  19. long  temperature;//温度值
  20. long  pressure;//压力值
  21. long  height;//相对海拔高度值
  22. short ac1;
  23. short ac2;
  24. short ac3;
  25. unsigned short ac4;
  26. unsigned short ac5;
  27. unsigned short ac6;
  28. short b1;
  29. short b2;
  30. short mb;
  31. short mc;
  32. short md;

  33. void delay(unsigned int k)        
  34. {                                                
  35. unsigned int i,j;                                
  36. for(i=0;i<k;i++)
  37. {                        
  38. for(j=0;j<121;j++)                        
  39. {;}}                                                
  40. }
  41. /*******************************/
  42. void WaitForEnable(void)        
  43. {                                       
  44. DataPort=0xff;               
  45. LCM_RS=0;LCM_RW=1;_nop_();
  46. LCM_EN=1;_nop_();_nop_();
  47. while(DataPort&0x80);        
  48. LCM_EN=0;                                
  49. }                                       
  50. /*******************************/
  51. void WriteCommandLCM(uchar CMD,uchar Attribc)
  52. {                                       
  53. if(Attribc)WaitForEnable();        
  54. LCM_RS=0;LCM_RW=0;_nop_();
  55. DataPort=CMD;_nop_();        
  56. LCM_EN=1;_nop_();_nop_();LCM_EN=0;
  57. }                                       
  58. /*******************************/
  59. void WriteDataLCM(uchar dataW)
  60. {                                       
  61. WaitForEnable();               
  62. LCM_RS=1;LCM_RW=0;_nop_();
  63. DataPort=dataW;_nop_();        
  64. LCM_EN=1;_nop_();_nop_();LCM_EN=0;
  65. }               
  66. /***********************************/
  67. void InitLcd()                                
  68. {                        
  69. WriteCommandLCM(0x38,1);        
  70. WriteCommandLCM(0x08,1);        
  71. WriteCommandLCM(0x01,1);        
  72. WriteCommandLCM(0x06,1);        
  73. WriteCommandLCM(0x0c,1);
  74. }                        
  75. /***********************************/
  76. void DisplayOneChar(uchar X,uchar Y,uchar DData)
  77. {                                                
  78. Y&=1;                                                
  79. X&=15;                                                
  80. if(Y)X|=0x40;                                       
  81. X|=0x80;                        
  82. WriteCommandLCM(X,0);               
  83. WriteDataLCM(DData);               
  84. }                                                
  85. ///**************************************
  86. //延时5微秒(STC90C52RC@12M)
  87. //不同的工作环境,需要调整此函数,注意时钟过快时需要修改
  88. //当改用1T的MCU时,请调整此延时函数
  89. //**************************************/
  90. //void Delay5us();
  91. void Delay5us()
  92. {
  93. _nop_();_nop_();_nop_();_nop_();
  94. _nop_();_nop_();_nop_();_nop_();
  95. _nop_();_nop_();_nop_();_nop_();
  96. _nop_();_nop_();_nop_();_nop_();
  97. }
  98. /**************************************
  99. 延时5毫秒(STC90C52RC@12M)
  100. 不同的工作环境,需要调整此函数
  101. 当改用1T的MCU时,请调整此延时函数
  102. **************************************/
  103. void Delay5ms()
  104. {
  105.     WORD n = 560;
  106.     while (n--);
  107. }
  108. /**************************************
  109. 起始信号
  110. **************************************/
  111. void BMP085_Start()
  112. {
  113.     SDA = 1;                    //拉高数据线
  114.     SCL = 1;                    //拉高时钟线
  115.     Delay5us();                 //延时
  116.     SDA = 0;                    //产生下降沿
  117.     Delay5us();                 //延时
  118.     SCL = 0;                    //拉低时钟线
  119. }
  120. /**************************************
  121. 停止信号
  122. **************************************/
  123. void BMP085_Stop()
  124. {
  125.     SDA = 0;                    //拉低数据线
  126.     SCL = 1;                    //拉高时钟线
  127.     Delay5us();                 //延时
  128.     SDA = 1;                    //产生上升沿
  129.     Delay5us();                 //延时
  130. }

  131. /**************************************
  132. 发送应答信号
  133. 入口参数:ack (0:ACK 1:NAK)
  134. **************************************/
  135. void BMP085_SendACK(bit ack)
  136. {
  137.     SDA = ack;                  //写应答信号
  138.     SCL = 1;                    //拉高时钟线
  139.     Delay5us();                 //延时
  140.     SCL = 0;                    //拉低时钟线
  141.     Delay5us();                 //延时
  142. }
  143. /**************************************
  144. 接收应答信号
  145. **************************************/
  146. bit BMP085_RecvACK()
  147. {
  148.     SCL = 1;                    //拉高时钟线
  149.     Delay5us();                 //延时
  150.     CY = SDA;                   //读应答信号
  151.     SCL = 0;                    //拉低时钟线
  152.     Delay5us();                 //延时
  153.     return CY;
  154. }
  155. /**************************************
  156. 向IIC总线发送一个字节数据
  157. **************************************/
  158. void BMP085_SendByte(BYTE dat)
  159. {
  160.     BYTE i;
  161.     for (i=0; i<8; i++)         //8位计数器
  162.     {
  163.         dat <<= 1;              //移出数据的最高位
  164.         SDA = CY;               //送数据口
  165.         SCL = 1;                //拉高时钟线
  166.         Delay5us();             //延时
  167.         SCL = 0;                //拉低时钟线
  168.         Delay5us();             //延时
  169.     }
  170.     BMP085_RecvACK();
  171. }
  172. /**************************************
  173. 从IIC总线接收一个字节数据
  174. **************************************/
  175. BYTE BMP085_RecvByte()
  176. {
  177.     BYTE i;
  178.     BYTE dat = 0;
  179.     SDA = 1;                    //使能内部上拉,准备读取数据,
  180.     for (i=0; i<8; i++)         //8位计数器
  181.     {
  182.         dat <<= 1;
  183.         SCL = 1;                //拉高时钟线
  184.         Delay5us();             //延时
  185.         dat |= SDA;             //读数据              
  186.         SCL = 0;                //拉低时钟线
  187.         Delay5us();             //延时
  188. }
  189.     return dat;
  190. }
  191. //*********************************************************
  192. //读出BMP085内部数据,连续两个
  193. //*********************************************************
  194. short Multiple_read(uchar ST_Address)
  195. {
  196.     uchar msb, lsb;
  197.     short _data;
  198.     BMP085_Start();                          //起始信号
  199.     BMP085_SendByte(BMP085_SlaveAddress);    //发送设备地址+写信号
  200.     BMP085_SendByte(ST_Address);             //发送存储单元地址
  201.     BMP085_Start();                          //起始信号
  202.     BMP085_SendByte(BMP085_SlaveAddress+1);         //发送设备地址+读信号
  203.     msb = BMP085_RecvByte();                 //BUF[0]存储
  204.     BMP085_SendACK(0);                       //回应ACK
  205.     lsb = BMP085_RecvByte();   
  206.     BMP085_SendACK(1);                       //最后一个数据需要回NOACK
  207.     BMP085_Stop();                           //停止信号
  208.     Delay5ms();
  209.     _data = msb << 8;
  210.     _data |= lsb;
  211.     return _data;
  212. }
  213. //********************************************************************
  214. long bmp085ReadTemp(void)
  215. {
  216.     BMP085_Start();                  //起始信号
  217.     BMP085_SendByte(BMP085_SlaveAddress);   //发送设备地址+写信号
  218.     BMP085_SendByte(0xF4);          // write register address
  219.     BMP085_SendByte(0x2E);       // write register data for temp
  220.     BMP085_Stop();                   //发送停止信号
  221.     delay(10);// max time is 4.5ms
  222.     return (long) Multiple_read(0xF6);
  223. }
  224. //*************************************************************
  225. long bmp085ReadPressure(void)
  226. {
  227.     long pressure = 0;
  228.     BMP085_Start();                   //起始信号
  229.     BMP085_SendByte(BMP085_SlaveAddress);   //发送设备地址+写信号
  230.     BMP085_SendByte(0xF4);          // write register address
  231.     BMP085_SendByte(0x34);         // write register data for pressure
  232.     BMP085_Stop();                    //发送停止信号
  233.     delay(10);                      // max time is 4.5ms
  234.     pressure = Multiple_read(0xF6);
  235.     pressure &= 0x0000FFFF;
  236.     return pressure;
  237. }
  238. //**************************************************************

  239. //初始化BMP085,根据需要请参考pdf进行修改**************
  240. void Init_BMP085()
  241. {
  242.     ac1 = Multiple_read(0xAA);
  243.     ac2 = Multiple_read(0xAC);
  244.     ac3 = Multiple_read(0xAE);
  245.     ac4 = Multiple_read(0xB0);
  246.     ac5 = Multiple_read(0xB2);
  247.     ac6 = Multiple_read(0xB4);
  248.     b1 =  Multiple_read(0xB6);
  249.     b2 =  Multiple_read(0xB8);
  250.     mb =  Multiple_read(0xBA);
  251.     mc =  Multiple_read(0xBC);
  252.     md =  Multiple_read(0xBE);
  253. }
  254. //***********************************************************************
  255. void bmp085Convert()//换算
  256. {
  257.   unsigned int ut;
  258.   unsigned long up;
  259.   long x1, x2, b5, b6, x3, b3, p;
  260.   unsigned long b4, b7;
  261.   ut = bmp085ReadTemp();   // 读取温度
  262.   up = bmp085ReadPressure();  // 读取压强
  263.   x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
  264.   x2 = ((long) mc << 11) / (x1 + md);
  265.   b5 = x1 + x2;
  266.   temperature = ((b5 + 8) >> 4);
  267.   b6 = b5 - 4000;
  268.   // Calculate B3
  269.   x1 = (b2 * (b6 * b6)>>12)>>11;
  270.   x2 = (ac2 * b6)>>11;
  271.   x3 = x1 + x2;
  272.   b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
  273.   // Calculate B4
  274.   x1 = (ac3 * b6)>>13;
  275.   x2 = (b1 * ((b6 * b6)>>12))>>16;
  276.   x3 = ((x1 + x2) + 2)>>2;
  277.   b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
  278.   b7 = ((unsigned long)(up - b3) * (50000>>OSS));
  279.   if (b7 < 0x80000000)
  280.     p = (b7<<1)/b4;
  281.   else
  282.     p = (b7/b4)<<1;
  283.   x1 = (p>>8) * (p>>8);
  284.   x1 = (x1 * 3038)>>16;
  285.   x2 = (-7357 * p)>>16;
  286.   pressure = p+((x1 + x2 + 3791)>>4);
  287.   height=(101325-pressure)*843/100;
  288.   DisplayOneChar(0,0,'T');//温度部分
  289.   DisplayOneChar(1,0,':');
  290.   DisplayOneChar(4,0,'.');
  291.   DisplayOneChar(6,0,0XDF);
  292.   DisplayOneChar(7,0,'C');
  293.   DisplayOneChar(9,0,'H');//海拔部分
  294.   DisplayOneChar(13,0,'.');
  295.   DisplayOneChar(15,0,'m');
  296.   DisplayOneChar(0,1,'P');//气压部分
  297.   DisplayOneChar(1,1,':');
  298.   DisplayOneChar(5,1,'.');
  299.   DisplayOneChar(7,1,'K');
  300.   DisplayOneChar(8,1,'p');
  301.   DisplayOneChar(2,0,temperature/100+48);
  302.   DisplayOneChar(3,0,temperature%100/10+48);
  303.   DisplayOneChar(5,0,temperature%10+48);
  304.   DisplayOneChar(10,0,height/10000+48);
  305.   DisplayOneChar(11,0,height%10000/1000+48);
  306.   DisplayOneChar(12,0,height%1000/100+48);
  307.   DisplayOneChar(14,0,height%100/10+48);
  308.   DisplayOneChar(2,1,pressure/100000+48);
  309.   DisplayOneChar(3,1,pressure%100000/10000+48);
  310.   DisplayOneChar(4,1,pressure%10000/1000+48);
  311.   DisplayOneChar(6,1,pressure%1000/100+48);
  312. }
  313. //*********************************************************
  314. //******主程序********
  315. //*********************************************************
  316. void main()
  317. {
  318.   delay(50);                           //上电延时               
  319.   InitLcd();                      //液晶初始化
  320.   Init_BMP085();                  //初始化BMP085
  321.   while(1)                        //循环
  322.   {
  323.     bmp085Convert();
  324.         delay(100);
  325.   }
  326. }
复制代码

所有资料51hei提供下载:
LCD1602做的温度气压高度计单片机程序.rar (42.17 KB, 下载次数: 93)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:79544 发表于 2019-3-28 09:37 | 显示全部楼层
很详细的注释程序,感谢分享
回复

使用道具 举报

ID:502076 发表于 2019-3-31 23:13 | 显示全部楼层
我也希望使用这个程序。
回复

使用道具 举报

ID:507691 发表于 2019-4-26 16:19 | 显示全部楼层
腾飞的龙 发表于 2019-3-28 09:37
很详细的注释程序,感谢分享

你的显示是好的嘛
压强有波动吗
高度不会一直变化吗
回复

使用道具 举报

ID:507691 发表于 2019-4-26 16:22 | 显示全部楼层
我显示出来压强会有波动,高度差更多,有什么办法解决吗
有人知道卡尔曼滤波怎么用到这吗
回复

使用道具 举报

ID:645297 发表于 2019-11-28 19:48 | 显示全部楼层
里面有仿真嘛
回复

使用道具 举报

ID:787757 发表于 2020-6-23 15:42 来自手机 | 显示全部楼层
具体的连线怎么连?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表