找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2499|回复: 16
打印 上一主题 下一主题
收起左侧

基于51单片机+bmp180的数字海拔计程序

  [复制链接]
跳转到指定楼层
楼主
12684液晶屏,bmp180传感器,51单片机

单片机源程序如下:
  1. #include  <reg51.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. #include<absacc.h>
  7. #include "lcd.h"
  8. #include "BMP180.H"
  9. /*定义传感器内部的EEPROM存储单元里面11个值*/
  10. #define   uchar unsigned char
  11. #define   uint unsigned int
  12. typedef unsigned char  BYTE;
  13. typedef unsigned short WORD;
  14. #define BMP085_SlaveAddress   0xee  //定义器件在IIC总线中的从地址
  15. short ac1;
  16. short ac2;
  17. short ac3;
  18. unsigned short ac4;
  19. unsigned short ac5;
  20. unsigned short ac6;
  21. short b1;
  22. short b2;
  23. uchar idata flag;
  24. int idata AltitudeTemp[10]={0,0,0,0,0,0,0,0,0,0};              // 海拔高度的10个临时值,取平均值
  25. short mb;
  26. short mc;
  27. short md;
  28. #define OSS 0// Oversampling Setting (note: code is not set up to use other OSS values)
  29. uchar code PressureTitle[16]=   {"气压温度测量"};
  30. uchar idata ShowPressure[16]=   {"高度:        米"};
  31. uchar idata ShowTemperature[16]={"温度:       . ℃"};
  32. uchar idata ShowAltitude[16]=   {"电压:        . V"};
  33. uchar code HZW0[10]={"欢迎使用"};
  34. uchar code HZW1[12]={"海拔高度计"};
  35. uchar code Blank[16];
  36. bit ack;
  37. sbit DA = P2^0;
  38. sbit CK = P2^1;
  39. sbit CS = P2^2;
  40. uchar TaskFlag;
  41. //*延时us级函数
  42.            
  43. void Delay5us()
  44. {
  45. _nop_();_nop_();_nop_();_nop_();
  46. _nop_();_nop_();_nop_();_nop_();
  47. _nop_();_nop_();_nop_();_nop_();
  48. _nop_();_nop_();_nop_();_nop_();
  49. }
  50. /**************************************
  51. 延时5毫秒(STC90C52RC@12M)
  52. 不同的工作环境,需要调整此函数
  53. 当改用1T的MCU时,请调整此延时函数
  54. **************************************/
  55. void Delay1ms(uint xms)
  56. {        uint a,b;
  57.    for(a=0;a<110;a++)
  58.     for(b=0;b<xms;b++);
  59. }

  60. void Delay5ms()
  61. {
  62.     WORD n = 560;
  63.     while (n--);
  64. }
  65. /**************************************
  66. 起始信号
  67. **************************************/
  68. void BMP085_Start()
  69. {
  70.     SDA = 1;                    //拉高数据线
  71.     SCL = 1;                    //拉高时钟线
  72.     Delay5us();                 //延时
  73.     SDA = 0;                    //产生下降沿
  74.     Delay5us();                 //延时
  75.     SCL = 0;                    //拉低时钟线
  76. }
  77. /**************************************
  78. 停止信号
  79. **************************************/
  80. void BMP085_Stop()
  81. {
  82.     SDA = 0;                    //拉低数据线
  83.     SCL = 1;                    //拉高时钟线
  84.     Delay5us();                 //延时
  85.     SDA = 1;                    //产生上升沿
  86.     Delay5us();                 //延时
  87. }

  88. /**************************************
  89. 发送应答信号
  90. 入口参数:ack (0:ACK 1:NAK)
  91. **************************************/
  92. void BMP085_SendACK(bit ack)
  93. {
  94.     SDA = ack;                  //写应答信号
  95.     SCL = 1;                    //拉高时钟线
  96.     Delay5us();                 //延时
  97.     SCL = 0;                    //拉低时钟线
  98.     Delay5us();                 //延时
  99. }
  100. /**************************************
  101. 接收应答信号
  102. **************************************/
  103. bit BMP085_RecvACK()
  104. {
  105.     SCL = 1;                    //拉高时钟线
  106.     Delay5us();                 //延时
  107.     CY = SDA;                   //读应答信号
  108.     SCL = 0;                    //拉低时钟线
  109.     Delay5us();                 //延时
  110.     return CY;
  111. }
  112. /**************************************
  113. 向IIC总线发送一个字节数据
  114. **************************************/
  115. void BMP085_SendByte(BYTE dat)
  116. {
  117.     BYTE i;
  118.     for (i=0; i<8; i++)         //8位计数器
  119.     {
  120.         dat <<= 1;              //移出数据的最高位
  121.         SDA = CY;               //送数据口
  122.         SCL = 1;                //拉高时钟线
  123.         Delay5us();             //延时
  124.         SCL = 0;                //拉低时钟线
  125.         Delay5us();             //延时
  126.     }
  127.     BMP085_RecvACK();
  128. }
  129. /**************************************
  130. 从IIC总线接收一个字节数据
  131. **************************************/
  132. BYTE BMP085_RecvByte()
  133. {
  134.     BYTE i;
  135.     BYTE dat = 0;
  136.     SDA = 1;                    //使能内部上拉,准备读取数据,
  137.     for (i=0; i<8; i++)         //8位计数器
  138.     {
  139.         dat <<= 1;
  140.         SCL = 1;                //拉高时钟线
  141.         Delay5us();             //延时
  142.         dat |= SDA;             //读数据              
  143.         SCL = 0;                //拉低时钟线
  144.         Delay5us();             //延时
  145. }
  146.     return dat;
  147. }
  148. //*********************************************************
  149. //读出BMP085内部数据,连续两个
  150. //*********************************************************
  151. short Multiple_read(uchar ST_Address)
  152. {
  153.     uchar msb, lsb;
  154.     short _data;
  155.     BMP085_Start();                          //起始信号
  156.     BMP085_SendByte(BMP085_SlaveAddress);    //发送设备地址+写信号
  157.     BMP085_SendByte(ST_Address);             //发送存储单元地址
  158.     BMP085_Start();                          //起始信号
  159.     BMP085_SendByte(BMP085_SlaveAddress+1);         //发送设备地址+读信号
  160.     msb = BMP085_RecvByte();                 //BUF[0]存储
  161.     BMP085_SendACK(0);                       //回应ACK
  162.     lsb = BMP085_RecvByte();   
  163.     BMP085_SendACK(1);                       //最后一个数据需要回NOACK
  164.     BMP085_Stop();                           //停止信号
  165.     Delay5ms();
  166.     _data = msb << 8;
  167.     _data |= lsb;
  168.     return _data;
  169. }
  170. //********************************************************************
  171. long bmp085ReadTemp(void)
  172. {
  173.     BMP085_Start();                  //起始信号
  174.     BMP085_SendByte(BMP085_SlaveAddress);   //发送设备地址+写信号
  175.     BMP085_SendByte(0xF4);          // write register address
  176.     BMP085_SendByte(0x2E);       // write register data for temp
  177.     BMP085_Stop();                   //发送停止信号
  178.     Delay1ms(10);// max time is 4.5ms
  179.     return (long) Multiple_read(0xF6);
  180. }
  181. //*************************************************************
  182. long bmp085ReadPressure(void)
  183. {
  184.     long pressure = 0;
  185.     BMP085_Start();                   //起始信号
  186.     BMP085_SendByte(BMP085_SlaveAddress);   //发送设备地址+写信号
  187.     BMP085_SendByte(0xF4);          // write register address
  188.     BMP085_SendByte(0x34);         // write register data for pressure
  189.     BMP085_Stop();                    //发送停止信号
  190.     Delay1ms(10);                      // max time is 4.5ms
  191.     pressure = Multiple_read(0xF6);
  192.     pressure &= 0x0000FFFF;
  193.     return pressure;
  194. }
  195. //**************************************************************

  196. //初始化BMP085,根据需要请参考pdf进行修改**************
  197. void Init_BMP085()
  198. {
  199.     ac1 = Multiple_read(0xAA);
  200.     ac2 = Multiple_read(0xAC);
  201.     ac3 = Multiple_read(0xAE);
  202.     ac4 = Multiple_read(0xB0);
  203.     ac5 = Multiple_read(0xB2);
  204.     ac6 = Multiple_read(0xB4);
  205.     b1 =  Multiple_read(0xB6);
  206.     b2 =  Multiple_read(0xB8);
  207.     mb =  Multiple_read(0xBA);
  208.     mc =  Multiple_read(0xBC);
  209.     md =  Multiple_read(0xBE);
  210. }

  211. void da5615(unsigned int da)
  212. {
  213.   unsigned char i;
  214.   da <<= 6;//10有效数据左对齐
  215.   CS = 0;
  216.   CK = 0;
  217.   for (i=0;i<12;i++)
  218.   {
  219.     DA = (bit)(da & 0x8000);
  220.     CK = 1;
  221.     da <<= 1;
  222.     CK = 0;
  223.   }
  224.   CS = 1;
  225.   CK = 0;
  226. }

  227. /*    函数名:BMP085_Get_Param(bit choice)      功能:读出转换后的温度或气压值 当实参为1时,返回气压;当实参为0时,返回温度
  228.       备注:返回温度值为0.1,调用时转换为1。气压为Pa,调用时气压转换hPa    */
  229. long BMP085_Get_Param(bit choice)
  230. {
  231.   long ut;
  232.   long up;
  233.   long x1, x2, b5, b6, x3, b3, p;
  234.   unsigned long b4, b7;
  235.   long temperature;
  236.   long pressure;//压力值
  237.   ut = bmp085ReadTemp();   // 读取温度
  238.   up = bmp085ReadPressure();  // 读取压强
  239.   x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
  240.   x2 = ((long) mc << 11) / (x1 + md);
  241.   b5 = x1 + x2;
  242.   temperature = ((b5 + 8) >> 4);
  243.   if(choice==0)
  244.   return (long)temperature;          
  245.   b6 = b5 - 4000;
  246.   // Calculate B3
  247.   x1 = (b2 * (b6 * b6)>>12)>>11;
  248.   x2 = (ac2 * b6)>>11;
  249.   x3 = x1 + x2;
  250.   b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
  251.   // Calculate B4
  252.   x1 = (ac3 * b6)>>13;
  253.   x2 = (b1 * ((b6 * b6)>>12))>>16;
  254.   x3 = ((x1 + x2) + 2)>>2;
  255.   b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
  256.   b7 = ((unsigned long)(up - b3) * (50000>>OSS));
  257.   if (b7 < 0x80000000)
  258.     p = (b7<<1)/b4;
  259.   else
  260.     p = (b7/b4)<<1;
  261.   x1 = (p>>8) * (p>>8);
  262.   x1 = (x1 * 3038)>>16;
  263.   x2 = (-7357 * p)>>16;
  264.   pressure = p+((x1 + x2 + 3791)>>4);
  265.   return (long)pressure;
  266.   }

  267. /*    函数名:BMP085_Get_Altitude     功能:获取海拔高度值
  268.       备注:返回高度值为米,调用时再转换成带小数以米为单位的高度值    */
  269. int Get_Altitude()
  270.         {
  271.     float pressure;
  272.     float altitude;
  273.           pressure=(float)BMP085_Get_Param(1);  //获取气压值
  274.     altitude=44330*(1-pow(pressure/101325,1/5.255));  //根据芯片手册提供的公式计算海拔高度 单位:米
  275.            altitude*=100;
  276. return(int)altitude;
  277.   }

  278. /*       LCD程序           */
  279. void ConvPressure() //       转换气压,用于LCD的显示
  280. {
  281.   long Pressure;
  282.         Pressure=BMP085_Get_Param(1);
  283.         if(Pressure>=0)ShowPressure[6]='+';
  284.         else
  285.          {
  286.            ShowPressure[6]='-';
  287.                  Pressure=~Pressure;
  288.          }
  289. //         ShowPressure[7]=Pressure%1000000/100000+48;
  290. //         ShowPressure[8]=Pressure%100000/10000+48;
  291. //         ShowPressure[9]=Pressure%10000/1000+48;
  292. //         ShowPressure[10]='.';
  293. //         ShowPressure[11]=Pressure%1000/100+48;
  294. //         ShowPressure[13]='K';
  295. //         
  296. }
  297. void ConvTemperature()   //转换气温,用于LCD显示
  298. {
  299.   int Temperature;
  300.         Temperature=(int)BMP085_Get_Param(0);
  301.         if(Temperature>=0)ShowTemperature[6]='+';
  302.         else
  303.          {
  304.            ShowTemperature[6]='-';
  305.                 Temperature=~Temperature;
  306.        
  307.          }
  308.           ShowTemperature[10]=Temperature%1000/100+48;
  309.                 ShowTemperature[11]=Temperature%100/10+48;
  310.                 ShowTemperature[13]=Temperature%10+48;
  311. }
  312. void ConvAltitude()
  313. {
  314.    uint voltage;
  315.    uint ab5;
  316.    uchar a;
  317.    uchar ab1,ab2,ab3,ab4,ab6;
  318.    unsigned char xiaoshu,zhengshu,xiaoshu2;  
  319.      long Altitude;
  320.         Altitude=Get_Altitude();
  321.         if(Altitude>=0)ShowAltitude[6]='+';
  322.         else
  323.           {
  324.                   ShowAltitude[6]='-';
  325.                    Altitude=~Altitude;
  326.                 }
  327.                 /* 最多10次测量值的平均值为测量结果*/
  328.      flag++;
  329.   if(flag>=10) flag=0;
  330.    AltitudeTemp[flag]=Altitude;
  331.    for(a=0;a<10;a++)
  332.         Altitude+=AltitudeTemp[a];
  333.         Altitude/=11;

  334.     ab1=Altitude/10000;
  335.         ab2=Altitude%10000/1000;
  336.         ab3=Altitude%1000/100;
  337.         ab4=Altitude%100/10;
  338.         ab5=ab1*1000+ab2*100+ab3*10+ab4;
  339.     ab6=(int)(ab5/4);
  340.     da5615(ab6);
  341.         voltage=ab5*2;
  342.         zhengshu=voltage/1000;
  343.         xiaoshu=voltage%1000/100;
  344.         xiaoshu2=voltage%100/10;
  345.         if(xiaoshu2>=5)
  346.         {
  347.           xiaoshu=xiaoshu+1;
  348.           }

  349.                 ShowPressure[9]=Altitude/10000+48;
  350.                 ShowPressure[10]=Altitude%10000/1000+48;
  351.                 ShowPressure[11]=Altitude%1000/100+48;
  352.                 ShowPressure[12]=Altitude%100/10+48;
  353.                
  354.                 ShowAltitude[12]=zhengshu+0x30;
  355.                 ShowAltitude[14]=xiaoshu+0x30;
  356.                
  357.        
  358. }

  359. /*   文字显示函数        形式参数格式规定: x轴位置,从左到右,以两个字符或一个汉字作为一格取值范围(0-7)  y轴位置,从上到下,以一个汉字为一格,取值范围为(0-3)
  360.   数组名称,将数组的值以指针形式访问                   显示数量,将数组里面的指定数量的内容显示出来,取值范围(0-15)  */

  361. void Show_BMP085_Result()           //显示测量结果
  362. {
  363. //  ConvPressure();
  364.         ConvTemperature();
  365.         ConvAltitude();
  366.         WordDisplay(1,0,PressureTitle,12);     //气压温度测量
  367.         WordDisplay(0,1,ShowPressure,16);    //  气压  Pa  
  368.         …………
  369. …………
  370. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
见7楼




微信图片_20181022081624.jpg (78.98 KB, 下载次数: 17)

电压当时是进行了一个数模转换

电压当时是进行了一个数模转换

评分

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

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享分享 分享淘帖 顶 踩
回复

使用道具 举报

沙发
admin 发表于 2018-10-22 15:09 | 只看该作者
楼主能分享下制作资料吗?
回复

使用道具 举报

板凳
鹈鹕 发表于 2018-10-22 15:29 | 只看该作者
【程序】在哪?
回复

使用道具 举报

地板
 楼主| 单片机小白0 发表于 2018-10-23 14:57 | 只看该作者
鹈鹕 发表于 2018-10-22 15:29
【程序】在哪?

诶,我明明上传附件了
回复

使用道具 举报

5#
 楼主| 单片机小白0 发表于 2018-10-23 14:58 | 只看该作者
admin 发表于 2018-10-22 15:09
楼主能分享下制作资料吗?

源程序好像上传了
回复

使用道具 举报

6#
admin 发表于 2018-10-24 02:27 | 只看该作者
回帖点击,输入框右上角的高级模式可以上传附件,文件要小于20兆
回复

使用道具 举报

7#
 楼主| 单片机小白0 发表于 2018-10-24 07:31 | 只看该作者
好了抱歉

海拔计.rar

76.93 KB, 下载次数: 114, 下载积分: 黑币 -5

评分

参与人数 1黑币 +100 收起 理由
admin + 100 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

8#
FGH116 发表于 2018-10-24 09:06 | 只看该作者
多谢了。。。。。刚下来看看。。。。
回复

使用道具 举报

9#
w251213177 发表于 2019-1-7 13:00 | 只看该作者
有没有原理图?
回复

使用道具 举报

10#
15185 发表于 2019-3-8 22:34 | 只看该作者
你好,我用的是1T的stc15f2k60s2,那个延时程序该怎么改呀
回复

使用道具 举报

11#
jjj12345 发表于 2019-7-24 10:36 | 只看该作者
下载了,看能不能移植到AVR
回复

使用道具 举报

12#
zqy1818 发表于 2019-10-19 10:05 | 只看该作者
感谢分享资源
回复

使用道具 举报

13#
xinyuey 发表于 2020-3-31 15:20 | 只看该作者
protues能仿真出来吗
回复

使用道具 举报

14#
wbwcf13e 发表于 2020-8-11 18:12 | 只看该作者
我做了一下仿真,发现显示屏黑屏,不显示字符。谁能做个仿真文件让我试一下?
回复

使用道具 举报

15#
lgxnb 发表于 2020-8-14 14:30 | 只看该作者
wbwcf13e 发表于 2020-8-11 18:12
我做了一下仿真,发现显示屏黑屏,不显示字符。谁能做个仿真文件让我试一下?

老哥仿真有了吗
回复

使用道具 举报

16#
wbwcf13e 发表于 2020-8-14 19:01 | 只看该作者
lgxnb 发表于 2020-8-14 14:30
老哥仿真有了吗

仿真不显示字,黑屏。不知何故?还望高人指点。
回复

使用道具 举报

17#
wbwcf13e 发表于 2020-10-18 09:45 | 只看该作者
我现在只能在板上实验,可以显字。就是误差太大了,电压一高一点点海拔高几十米!是什么原因?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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