找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机+bmp180高度计输出压强,温度都有波动,高度算出来更是变化很多,怎么滤波

[复制链接]
跳转到指定楼层
楼主
ID:507691 发表于 2019-4-26 16:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
网上查看有卡尔曼滤波,怎么跟程序结合起来,keil中为什么写入pow函数就会出错
  1. #include  <REG51.H>
  2. #include  <math.h>     
  3. #include  <stdlib.h>   
  4. #include  <stdio.h>   
  5. #include  <INTRINS.H> //包含_nop_()函数定义的头文件

  6. #define   uchar unsigned char
  7. #define   uint unsigned int
  8. #define BMP180_SlaveAddress 0xee  //定义器件在IIC总线中的从地址                              
  9. #define OSS 0  // 过采样设置(注意:代码没有设置为使用其他oss值)
  10. #define   DataPort P0    //LCD1602数据端口

  11. sbit      LCM_RS=P3^5;   //LCD1602命令端口寄存器选择位,输入               
  12. sbit      LCM_RW=P3^6;   //LCD1602命令端口读写               
  13. sbit      LCM_EN=P3^4;   //LCD1602命令端口使能
  14. sbit      SCL=P2^1;      //IIC时钟引脚定义
  15. sbit      SDA=P2^0;      //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. /***************延时函数**********************/
  34. void delay(uint z)
  35. {
  36. uint x,y;
  37. for(x=z;x>0;x--)
  38. for(y=110;y>0;y--);
  39. }

  40. /**************写命令到lcm子函数*****************/
  41. void write_com(uchar com)
  42. {
  43. LCM_RS=0;
  44.         LCM_RW=0;
  45.   LCM_EN=0;        
  46. P0=com;
  47. delay(5);
  48. LCM_EN=1;
  49. delay(5);
  50. LCM_EN=0;
  51. }

  52. /***************写数据到lcm子函数****************/
  53. void write_data(uchar date)
  54. {LCM_RS=1;
  55. P0=date;
  56. delay(5);
  57. LCM_EN=1;
  58. delay(5);
  59. LCM_EN=0;
  60. }

  61. /**************初始化LCD1602*********************/
  62. void InitLcd()                                
  63. {
  64. write_com(0x38); //设置16X2显示,5X7点阵,8位数据接口
  65. write_com(0x0c);//设置开显示,不显示光标
  66. write_com(0x06);//写一个字符后地址指针加1
  67. write_com(0x01);//显示清0,数据指针清0

  68. }

  69. /****************显示指定坐标的一个字符*******************/
  70. void DisplayOneChar(uchar X,uchar Y,uchar WData)
  71. {                                                
  72. Y&=1;                                                
  73. X&=15;                                                
  74. if(Y)X|=0x40;                                       
  75. X|=0x80;                        
  76. write_com(X);               
  77. write_data(WData);               
  78. }                                                
  79. /*************************************延时5微秒函数**************************************/
  80. void Delay5us()
  81. {
  82. _nop_();_nop_();_nop_();_nop_();
  83. _nop_();_nop_();_nop_();_nop_();
  84. _nop_();_nop_();_nop_();_nop_();
  85. _nop_();_nop_();_nop_();_nop_();
  86. }
  87. /************************************延时5毫秒函数*************************************/
  88. void Delay5ms()
  89. {
  90.     WORD n = 560;
  91.     while (n--);
  92. }
  93. //获取BMP180设备ID默认值为0x55
  94. /*uchar GetBMP180DevicelD()
  95. {

  96.       uchar DevicelD=0;
  97.       BMP180_Start();  //起始信号
  98.       BMP180_SendByte(BMP180_SlaveAddress);;  //发送设备地址+写信号
  99.       BMP180_SendByte(0xD0);  //发送存储单元地址OD为ID存储寄存器
  100.       BMP180_Start();  //起始信号
  101.       BMP180_SendByte(BMP180_SlaveAddress);  //发送设备地址+读信号
  102.             DevicelD =BMP180_SendByte(0xee);
  103.       BMP180_Stop();
  104.       return DevicelD;
  105. }*/
  106. /**************************************开始信号(bmp180启动)**************************************/
  107. void BMP180_Start()
  108. {
  109.     SDA = 1;                    //拉高数据线
  110.     SCL = 1;                    //拉高时钟线
  111.     Delay5us();                 //延时
  112.     SDA = 0;                    //产生下降沿
  113.     Delay5us();                 //延时
  114.     SCL = 0;                    //拉低时钟线
  115. }
  116. /**************************************停止信号(停止)**************************************/
  117. void BMP180_Stop()
  118. {
  119.     SDA = 0;                    //拉低数据线
  120.     SCL = 1;                    //拉高时钟线
  121.     Delay5us();                 //延时
  122.     SDA = 1;                    //产生上升沿
  123.     Delay5us();                 //延时
  124. }

  125. /**************************************发送应答信号**************************************/
  126. void BMP180_SendACK(bit ack)
  127. {
  128.     SDA = ack;                  //写应答信号
  129.     SCL = 1;                    //拉高时钟线
  130.     Delay5us();                 //延时
  131.     SCL = 0;                    //拉低时钟线
  132.     Delay5us();                 //延时
  133. }
  134. /**************************************接收应答信号**************************************/
  135. bit BMP180_RecvACK()
  136. {
  137.     SCL = 1;                    //拉高时钟线
  138.     Delay5us();                 //延时
  139.     CY = SDA;                   //读应答信号
  140.     SCL = 0;                    //拉低时钟线
  141.     Delay5us();                 //延时
  142.     return CY;
  143. }
  144. /**************************************向IIC总线发送一个字节数据**************************************/
  145. void BMP180_SendByte(BYTE dat)
  146. {
  147.     BYTE i;
  148.     for (i=0; i<8; i++)         //8位计数器
  149.     {
  150.         dat <<= 1;              //移出数据的最高位
  151.         SDA = CY;               //送数据口
  152.         SCL = 1;                //拉高时钟线
  153.         Delay5us();             //延时
  154.         SCL = 0;                //拉低时钟线
  155.         Delay5us();             //延时
  156.     }
  157.     BMP180_RecvACK();
  158. }
  159. /**************************************从IIC总线接收一个字节数据**************************************/
  160. BYTE BMP180_RecvByte()
  161. {
  162.     BYTE i;
  163.     BYTE dat = 0;
  164.     SDA = 1;                    //使能内部上拉,准备读取数据,
  165.     for (i=0; i<8; i++)         //8位计数器
  166.     {
  167.         dat <<= 1;
  168.         SCL = 1;                //拉高时钟线
  169.         Delay5us();             //延时
  170.         dat |= SDA;             //读数据              
  171.         SCL = 0;                //拉低时钟线
  172.         Delay5us();             //延时
  173. }
  174.     return dat;
  175. }
  176. /*******************从BMP180中读取两字节数据******************************/
  177. short Multiple_read(uchar ST_Address)
  178. {
  179.     uchar msb, lsb;
  180.     short _data;
  181.     BMP180_Start();                          //起始信号
  182.     BMP180_SendByte(BMP180_SlaveAddress);    //发送设备地址+写信号
  183.     BMP180_SendByte(ST_Address);             //发送存储单元地址
  184.     BMP180_Start();                          //起始信号
  185.     BMP180_SendByte(BMP180_SlaveAddress+1);         //发送设备地址+读信号
  186.     msb = BMP180_RecvByte();                 //BUF[0]存储
  187.           BMP180_SendACK(0);                       //主机发送应答信号,回应ACK
  188.     lsb = BMP180_RecvByte();   
  189.     BMP180_SendACK(1);                       //最后一个数据需要回非ACK
  190.     BMP180_Stop();                           //停止信号
  191.     Delay5ms();
  192.     _data = msb << 8;
  193.     _data |= lsb;
  194.     return _data;
  195. }
  196. /******************************温度读取**************************************/
  197. long bmp180ReadTemp(void)
  198. {
  199.     BMP180_Start();                  //起始信号
  200.     BMP180_SendByte(BMP180_SlaveAddress);   //发送设备地址+写信号
  201.     BMP180_SendByte(0xF4);          // write register address
  202.     BMP180_SendByte(0x2E);       // write register data for temp
  203.     BMP180_Stop();                   //发送停止信号
  204.     delay(10);// max time is 4.5ms
  205.     return (long) Multiple_read(0xF6);      //返回温度,0.1℃
  206. }
  207. /************************压强读取*************************************/
  208. long bmp180ReadPressure(void)
  209. {
  210.     long pressure = 0;
  211.     BMP180_Start();                   //起始信号
  212.     BMP180_SendByte(BMP180_SlaveAddress);   //发送设备地址+写信号
  213.     BMP180_SendByte(0xF4);          // write register address
  214.     BMP180_SendByte(0x34);         // write register data for pressure
  215.     BMP180_Stop();                    //发送停止信号
  216.     delay(10);                      // max time is 4.5ms
  217.     pressure = Multiple_read(0xF6);
  218.     pressure &= 0x0000FFFF;
  219.     return pressure;               //返回气压值,pa

  220. }

  221. /****************初始化BMP180,读出内部标定参数**************/
  222. void Init_BMP180()
  223. {
  224.     ac1 = Multiple_read(0xAA);
  225.     ac2 = Multiple_read(0xAC);
  226.     ac3 = Multiple_read(0xAE);
  227.     ac4 = Multiple_read(0xB0);
  228.     ac5 = Multiple_read(0xB2);
  229.     ac6 = Multiple_read(0xB4);
  230.     b1 =  Multiple_read(0xB6);
  231.     b2 =  Multiple_read(0xB8);
  232.     mb =  Multiple_read(0xBA);
  233.     mc =  Multiple_read(0xBC);
  234.     md =  Multiple_read(0xBE);
  235. }
  236. double pow(double a,double b)
  237. {
  238.         double result=1;
  239.         for(;b>0;b--)
  240.         {
  241.           result*=a;
  242.         }
  243.         return result;
  244. }
  245. /*************************获取气压、温度并显示******************************/
  246. void bmp180Convert()
  247. {
  248.   unsigned int ut;
  249.   unsigned long up;
  250.         
  251.   long x1, x2, b5, b6, x3, b3, p;
  252.   unsigned long b4, b7;
  253.         
  254.         long temp,y;
  255.         
  256.   ut = bmp180ReadTemp();   // 读取温度
  257.   up = bmp180ReadPressure();  // 读取压强
  258.         
  259.         //根据芯片手册提供的公式计算补偿后的温度
  260.   x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;//x1=((ut-ac6)*ac5)/(2^15)
  261.   x2 = ((long) mc << 11) / (x1 + md);           //x2=(mc*2^11)/(x1+md)
  262.   b5 = x1 + x2;                                //b5=x1+x2
  263.   temperature = (b5 + 8) >> 4;                 //t=(b5+8)/(2^4)

  264.         // 根据芯片手册提供的公式计算补偿后的气压
  265.         b6 = b5 - 4000;
  266.   x1 = (b2 * (b6 * b6)>>12)>>11;
  267.   x2 = (ac2 * b6)>>11;
  268.   x3 = x1 + x2;
  269.   b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;  // Calculate B4
  270.   x1 = (ac3 * b6)>>13;
  271.   x2 = (b1 * ((b6 * b6)>>12))>>16;
  272.   x3 = ((x1 + x2) + 2)>>2;
  273.   b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
  274.   b7 = ((unsigned long)(up - b3) * (50000>>OSS));
  275.   if (b7 < 0x80000000)
  276.     p = (b7<<1)/b4;
  277.   else
  278.     p = (b7/b4)<<1;
  279.   x1 = (p>>8) * (p>>8);
  280.   x1 = (x1 * 3038)>>16;
  281.   x2 = (-7357 * p)>>16;
  282.   pressure = p+((x1 + x2 + 3791)>>4);
  283.         delay(50);
  284.         
  285.         temp=1.0563;
  286.         y=0.1987;
  287.         pow(temp,y);
  288.         
  289.         /*temp=pressure/101325;
  290.         y=1/5.255;
  291.         temp=pow(temp,y);
  292.         //height=(44330*(1-temp));*/
  293. //height= 44330*(1-pow((pressure/101325.0),(1.0/5.255)));  
  294.          height=(101325-pressure)*843/1000;
  295.   if(height<0)
  296.         {
  297.         height=(-height);
  298.         //height=(-123);
  299.         DisplayOneChar(0,0,'T');//温度部分
  300.   DisplayOneChar(1,0,':');
  301.         DisplayOneChar(2,0,temperature%1000/100+0x30);
  302.   DisplayOneChar(3,0,temperature%100/10+0x30);
  303.   DisplayOneChar(4,0,'.');
  304.         DisplayOneChar(5,0,temperature%10+0x30);
  305.   DisplayOneChar(6,0,0XDF);
  306.   DisplayOneChar(7,0,'C');
  307.   DisplayOneChar(8,0,'H');//海拔部分
  308.         DisplayOneChar(9,0,'-');        
  309.   DisplayOneChar(10,0,height%10000/1000+0x30);
  310.   DisplayOneChar(11,0,height%1000/100+0x30);
  311.   DisplayOneChar(12,0,height%100/10+0x30);
  312.         DisplayOneChar(13,0,height%10+0x30);
  313.   DisplayOneChar(14,0,'.');
  314.         DisplayOneChar(15,0,height*10%10+0x30);
  315.   //DisplayOneChar(15,0,'m');
  316.   DisplayOneChar(0,1,'P');//气压部分
  317.   DisplayOneChar(1,1,':');
  318.         DisplayOneChar(2,1,pressure%1000000/100000+48);
  319.   DisplayOneChar(3,1,pressure%100000/10000+48);
  320.   DisplayOneChar(4,1,pressure%10000/1000+48);
  321.   DisplayOneChar(5,1,'.');
  322.         DisplayOneChar(6,1,pressure%1000/100+48);
  323.         DisplayOneChar(7,1,pressure%100/10+48);
  324.         //DisplayOneChar(8,1,pressure%10/1+48);
  325.         DisplayOneChar(8,1,'K');
  326.   DisplayOneChar(9,1,'p');
  327.         DisplayOneChar(10,1,'a');
  328.         
  329.         }
  330.         else
  331.         {
  332.         DisplayOneChar(0,0,'T');//温度部分
  333.   DisplayOneChar(1,0,':');
  334.         DisplayOneChar(2,0,temperature%1000/100+0x30);
  335.   DisplayOneChar(3,0,temperature%100/10+0x30);
  336.   DisplayOneChar(4,0,'.');
  337.         DisplayOneChar(5,0,temperature%10+0x30);
  338.   DisplayOneChar(6,0,0XDF);
  339.   DisplayOneChar(7,0,'C');
  340.   DisplayOneChar(8,0,' ');
  341.         DisplayOneChar(9,0,'H');//海拔部分
  342.   DisplayOneChar(10,0,height%10000/1000+0x30);
  343.   DisplayOneChar(11,0,height%1000/100+0x30);
  344.   DisplayOneChar(12,0,height%100/10+0x30);
  345.         DisplayOneChar(13,0,height%10+0x30);
  346.   DisplayOneChar(14,0,'.');
  347.         DisplayOneChar(15,0,height*10%10+0x30);
  348.   //DisplayOneChar(15,0,'m');
  349.   DisplayOneChar(0,1,'P');//气压部分
  350.   DisplayOneChar(1,1,':');
  351.         DisplayOneChar(2,1,pressure%1000000/100000+48);
  352.   DisplayOneChar(3,1,pressure%100000/10000+48);
  353.   DisplayOneChar(4,1,pressure%10000/1000+48);
  354.   DisplayOneChar(5,1,'.');
  355.         DisplayOneChar(6,1,pressure%1000/100+48);
  356.         DisplayOneChar(7,1,pressure%100/10+48);
  357.         //DisplayOneChar(8,1,pressure%10/1+48);
  358.   DisplayOneChar(8,1,'K');
  359.   DisplayOneChar(9,1,'p');
  360.         DisplayOneChar(10,1,'a');
  361.   }
  362. }
  363. /**********************主程序***************************/
  364. void main()
  365. { long icid;
  366.   delay(50);                           //上电延时               
  367.   InitLcd();                      //液晶初始化
  368.   Init_BMP180();                  //初始化BMP180
  369.         /*icid = Multiple_read(0xD0);
  370.         if (icid==0xee)
  371.                    DisplayOneChar(8,1,'y');
  372.         else DisplayOneChar(9,1,'n');
  373.         while(1);*/
  374.   while(1)                        //循环
  375.   {
  376.     bmp180Convert();
  377.         delay(100);
  378.   }
  379. }
复制代码


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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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