找回密码
 立即注册

QQ登录

只需一步,快速开始

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

一个基于STC12单片机的无线运动监测器设计 含源码与视频

[复制链接]
跳转到指定楼层
楼主
ID:284943 发表于 2018-6-25 15:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
毕设结束了,本来是想搞一个简单的计步器的,这功能加的太多给变成运动监测器了。使用2个STC12C5A60S2,4个HC05,还有NEO-7N,PULSE SENSOR,BMP180,ADXL345以及简单的1602和几个独立按键,实现的功能相当全面,具体如下:有效检测人体的运动状态信息,记录行动步数,并且能够显示心率,具体定位信息(经纬度,时间,日期,海拔高度,运动速度),温度,气压。大体原理是:通过蓝牙由一个发送单片机将记录的经过处理的数据(步数信息和心率信息)无线发送,接收单片机一方面通过蓝牙无线接收(发送单片机发送的数据),另一方面通过蓝牙无线接收GPS的数据。并且将数据在LCD1602上显示,独立按键在接收单片机上负责LCD1602显示翻页的功能。正常本科的毕业设计应该不会用到如此多的功能,选其中几个功能实现一下就可以了,反正就是能混则混。具体的程序,原理图还有视频我会贴出来的。视频我发个百度网盘的链接吧 https://pan.baidu.com/s/1rQXeFTQxPRO0yWu5yOeLZQ     

单片机源程序:
  1. #include  <stc12c5a60s2.h>        
  2. #include  <math.h>   
  3. #include  <stdio.h>           
  4. #include  <INTRINS.H>
  5. #define   uchar unsigned char
  6. #define   uint unsigned int        
  7. //**************************************
  8. #define false 0
  9. #define true 1
  10. #define FOSC 11059200L                //系统时钟
  11. #define BAUD 115200                                //波特率
  12. #define T0MS (65536-FOSC/12/500)                //500HZ在12T模式下
  13. //**************************************
  14. #define ADC_POWER 0x80                        //ADC功率控制位
  15. #define ADC_FLAG 0x10                        //ADC完成标志
  16. #define ADC_START 0x08;                        //ADC开始控制位
  17. #define ADC_SPEEDLL 0x00                //转换速度控制位SPEED0和SPEED1,共四种状态,对应四种转换速度
  18. #define ADC_SPEEDL 0x20                        
  19. #define ADC_SPEEDH 0x40                        
  20. #define ADC_SPEEDHH 0x60               
  21. #define ADC_MASK 0x01
  22. //**************************************
  23. sbit          SCL=P1^1;      //IIC时钟引脚定义
  24. sbit           SDA=P1^2;      //IIC数据引脚定义
  25. //**************************************
  26. #define        SlaveAddress   0xA6          //定义器件在IIC总线中的从地址,根据ALT  ADDRESS地址引脚不同修改
  27.                               //ALT  ADDRESS引脚接地时地址为0xA6,接电源时地址为0x3A
  28. typedef unsigned char  BYTE;
  29. typedef unsigned short WORD;

  30. #define length  10
  31. uchar  buffer[length];


  32. unsigned char ADXL345_FLAG=0;
  33. unsigned char START_FLAG=0;
  34. unsigned char number=0;

  35. unsigned char idata bad_flag[3];
  36. unsigned int idata array0[3]={1,1,1};
  37. unsigned int idata array1[3]={1,1,1};
  38. unsigned int idata array2[3]={0,0,0};
  39. unsigned int idata adresult[3];
  40. unsigned int idata max[3]={0,0,0};
  41. unsigned int idata min[3]={1000,1000,1000};
  42. unsigned int idata dc[3]={500,500,500};
  43. unsigned int idata vpp[3]={30,30,30};        
  44. unsigned int idata precision[3]={5,5,5};        
  45. unsigned int idata old_fixed[3];
  46. unsigned int idata new_fixed[3];
  47. unsigned int idata STEPS=0;

  48. BYTE BUF[16];                         //接收数据缓存区              
  49. uchar ge,shi,bai,qian,wan;           //显示变量


  50. void delay(unsigned int n);
  51. void Init_ADXL345(void);             //初始化ADXL345
  52. void Send_Byte(unsigned char *temp);
  53. void conversion(uint temp_data);
  54. void  Single_Write_ADXL345(uchar REG_Address,uchar REG_data);   //单个写入数据
  55. uchar Single_Read_ADXL345(uchar REG_Address);                   //单个读取内部寄存器数据
  56. void  Multiple_Read_ADXL345();                                  //连续的读取内部寄存器数据
  57. //------------------------------------
  58. void Delay5us();
  59. void Delay5ms();
  60. void ADXL345_Start();
  61. void ADXL345_Stop();
  62. void ADXL345_SendACK(bit ack);
  63. bit  ADXL345_RecvACK();
  64. void ADXL345_SendByte(BYTE dat);
  65. BYTE ADXL345_RecvByte();
  66. void ADXL345_ReadPage();
  67. void ADXL345_WritePage();


  68. void UART_init(void);
  69. void ADC_init(unsigned char channel);
  70. void T0_init(void);
  71. //------------------------------------
  72. unsigned char PulsePin = 0;       // P1.0为传感器输入口
  73. // 这些变量是在中断服务程序执行期间使用的
  74. volatile unsigned int BPM;                   // 用于保持脉搏
  75. volatile unsigned int Signal;                // 保存传入的原始数据
  76. volatile unsigned int IBI = 600;             // 保存相邻心跳之间的时间间隔
  77. volatile bit Pulse = false;     // 脉搏波高时为真,低时为假
  78. volatile bit QS = false;        // 当单片机发现一个心跳时变为真
  79. volatile int rate[10];                    //数组,保存最后10个IBI值
  80. volatile unsigned long sampleCounter = 0;          // 用于确定脉冲时间
  81. volatile unsigned long lastBeatTime = 0;           // 用于发现IBI
  82. volatile int Peak =512;                      //用于发现脉搏波峰值
  83. volatile int Trough = 512;                     // 用于发现脉搏波谷
  84. volatile int thresh = 512;                // 用于发现心跳的即时时刻
  85. volatile int amp = 100;                   //用于保持脉冲波形的幅度
  86. volatile bit firstBeat = true;        // 用于开始合理的BPM
  87. volatile bit secondBeat = false;      
  88. static unsigned char order=0;
  89. unsigned char DisBuff[4]={0};
  90. //------------------------------------
  91. void conversion(uint temp_data)  
  92. {  
  93.     wan=temp_data/10000+0x30 ;
  94.     temp_data=temp_data%10000;   //取余运算
  95.         qian=temp_data/1000+0x30 ;
  96.     temp_data=temp_data%1000;    //取余运算
  97.     bai=temp_data/100+0x30   ;
  98.     temp_data=temp_data%100;     //取余运算
  99.     shi=temp_data/10+0x30    ;
  100.     temp_data=temp_data%10;      //取余运算
  101.     ge=temp_data+0x30;         
  102. }

  103. void Delay5us()
  104. {
  105.     _nop_();_nop_();_nop_();_nop_();
  106.     _nop_();_nop_();_nop_();_nop_();
  107.         _nop_();_nop_();_nop_();_nop_();
  108. }

  109. void Delay5ms()
  110. {
  111.     WORD n = 560;

  112.     while (n--);
  113. }

  114. void ADXL345_Start()            //起始信号
  115. {
  116.     SDA = 1;                    //拉高数据线
  117.     SCL = 1;                    //拉高时钟线
  118.     Delay5us();                 //延时
  119.     SDA = 0;                    //产生下降沿
  120.     Delay5us();                 //延时
  121.     SCL = 0;                    //拉低时钟线
  122. }

  123. void ADXL345_Stop()             //停止信号
  124. {
  125.     SDA = 0;                    //拉低数据线
  126.     SCL = 1;                    //拉高时钟线
  127.     Delay5us();                 //延时
  128.     SDA = 1;                    //产生上升沿
  129.     Delay5us();                 //延时
  130. }

  131. void ADXL345_SendACK(bit ack)   //发送应答信号 入口参数:ack(0:ACK 1:NAK)
  132. {
  133.     SDA = ack;                  //写应答信号
  134.     SCL = 1;                    //拉高时钟线
  135.     Delay5us();                 //延时
  136.     SCL = 0;                    //拉低时钟线
  137.     Delay5us();                 //延时
  138. }

  139. bit ADXL345_RecvACK()           //接收应答信号
  140. {
  141.     SCL = 1;                    //拉高时钟线
  142.     Delay5us();                 //延时
  143.     CY = SDA;                   //读应答信号
  144.     SCL = 0;                    //拉低时钟线
  145.     Delay5us();                 //延时
  146.     return CY;
  147. }

  148. void ADXL345_SendByte(BYTE dat) //向IIC总线发送一字节数据
  149. {
  150.     BYTE i;
  151.     for (i=0; i<8; i++)         //8位计数器
  152.     {
  153.         dat <<= 1;              //移出数据的最高位
  154.         SDA = CY;               //送数据口
  155.         SCL = 1;                //拉高时钟线
  156.         Delay5us();             //延时
  157.         SCL = 0;                //拉低时钟线
  158.         Delay5us();             //延时
  159.     }
  160.     ADXL345_RecvACK();
  161. }

  162. BYTE ADXL345_RecvByte()         //从IIC总线接收一字节数据
  163. {
  164.     BYTE i;
  165.     BYTE dat = 0;
  166.     SDA = 1;                    //使能内部上拉,准备读取数据,
  167.     for (i=0; i<8; i++)         //8位计数器
  168.     {
  169.         dat <<= 1;
  170.         SCL = 1;                //拉高时钟线
  171.         Delay5us();             //延时
  172.         dat |= SDA;             //读数据               
  173.         SCL = 0;                //拉低时钟线
  174.         Delay5us();             //延时
  175.     }
  176.     return dat;
  177. }

  178. void Single_Write_ADXL345(uchar REG_Address,uchar REG_data) //单字节写入
  179. {
  180.     ADXL345_Start();                  //起始信号
  181.     ADXL345_SendByte(SlaveAddress);   //发送设备地址+写信号
  182.     ADXL345_SendByte(REG_Address);    //内部寄存器地址,请参考中文pdf22页
  183.     ADXL345_SendByte(REG_data);       //内部寄存器数据,请参考中文pdf22页
  184.     ADXL345_Stop();                   //发送停止信号
  185. }

  186. uchar Single_Read_ADXL345(uchar REG_Address)  //单字节读取
  187. {  uchar REG_data;
  188.     ADXL345_Start();                          //起始信号
  189.     ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
  190.     ADXL345_SendByte(REG_Address);                   //发送存储单元地址,从0开始        
  191.     ADXL345_Start();                          //起始信号
  192.     ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
  193.     REG_data=ADXL345_RecvByte();              //读出寄存器数据
  194.         ADXL345_SendACK(1);   
  195.         ADXL345_Stop();                           //停止信号
  196.     return REG_data;
  197. }

  198. void Multiple_read_ADXL345(void)            //连续读出ADXL345内部加速度数据,地址范围0x32~0x37
  199. {   uchar i;
  200.     ADXL345_Start();                          //起始信号
  201.     ADXL345_SendByte(SlaveAddress);           //发送设备地址+写信号
  202.     ADXL345_SendByte(0x32);                   //发送存储单元地址,从0x32开始        
  203.     ADXL345_Start();                          //起始信号
  204.     ADXL345_SendByte(SlaveAddress+1);         //发送设备地址+读信号
  205.          for (i=0; i<6; i++)                      //连续读取6个地址数据,存储中BUF
  206.     {
  207.         BUF[i] = ADXL345_RecvByte();          //BUF[0]存储0x32地址中的数据
  208.         if (i == 5)
  209.         {
  210.            ADXL345_SendACK(1);                //最后一个数据需要回NOACK
  211.         }
  212.         else
  213.         {
  214.           ADXL345_SendACK(0);                //回应ACK
  215.        }
  216.    }
  217.     ADXL345_Stop();                          //停止信号
  218.     Delay5ms();
  219. }

  220. void Init_ADXL345()                   //初始化ADXL345,根据需要请参考pdf进行修改
  221. {
  222.    Single_Write_ADXL345(0x31,0x0B);   //测量范围,正负16g,13位模式
  223.    Single_Write_ADXL345(0x2C,0x08);   //速率设定为12.5 参考pdf13页
  224.    Single_Write_ADXL345(0x2D,0x08);   //选择电源模式   参考pdf24页
  225.    Single_Write_ADXL345(0x2E,0x80);   //使能 DATA_READY 中断
  226.    Single_Write_ADXL345(0x1E,0x00);   //X 偏移量 根据测试传感器的状态写入pdf29页
  227.    Single_Write_ADXL345(0x1F,0x00);   //Y 偏移量 根据测试传感器的状态写入pdf29页
  228.    Single_Write_ADXL345(0x20,0x05);   //Z 偏移量 根据测试传感器的状态写入pdf29页
  229. }

  230. void step_counter(void)
  231. {
  232.         static uchar sampling_counter=0;
  233.         uchar jtemp;
  234.         ADXL345_FLAG=0;
  235.         Multiple_read_ADXL345();    //连续读取加速度
  236.         //--------------------------采样滤波----------------------//
  237.         for(jtemp=0;jtemp<=2;jtemp++)  //求平均值,计算最大值和最小值
  238.         {               
  239.                 array2[jtemp]=array1[jtemp];                      // array0[3]={1,1,1}
  240.                 array1[jtemp]=array0[jtemp];                      // array1[3]={1,1,1}
  241.                 array0[jtemp]=BUF[2*jtemp]+(BUF[2*jtemp+1]<<8);   // array2[3]={0,0,0}               
  242.                 adresult[jtemp]=array0[jtemp]+array1[jtemp]+array2[jtemp];
  243.                 adresult[jtemp]=adresult[jtemp]/3;  //连续三个的平均值
  244.                 if(adresult[jtemp]>max[jtemp])     //max[3]={0,0,0}
  245.                {
  246.                                                          max[jtemp]=adresult[jtemp];
  247.                                                          }
  248.                 if(adresult[jtemp]<min[jtemp])     //min[3]={1000,1000,1000}
  249.              {
  250.                                                  min[jtemp]=adresult[jtemp];
  251.                                                  }
  252.         }
  253.           sampling_counter=sampling_counter+1;
  254.         //---------------------------------计算动态门限和动态精度-----------------------//
  255.     if(sampling_counter>=50) //每50个采样更新一次
  256.     {               
  257.               sampling_counter=0;                        
  258.                 for(jtemp=0;jtemp<=2;jtemp++)
  259.                 {
  260.                 vpp[jtemp]=max[jtemp]-min[jtemp];       //vpp[3]={30,30,30}
  261.                 dc[jtemp] =min[jtemp]+(vpp[jtemp]>>1);  //dc[3]={500,500,500}  动态门限
  262.                 min[jtemp]=1023;
  263.                 bad_flag[jtemp]=0;
  264.                   if(vpp[jtemp]>=160)
  265.                      {
  266.                       precision[jtemp]=vpp[jtemp]/32;  //动态精度  precision[3]={5,5,5}
  267.                      }
  268.                 else if((vpp[jtemp]>=50)&& (vpp[jtemp]<160))            
  269.                      {
  270.                       precision[jtemp]=4;
  271.                      }
  272.                 else if((vpp[jtemp]>=15) && (vpp[jtemp]<50))  
  273.                      {
  274.                      precision[jtemp]=3;
  275.                      }                          
  276.                 else
  277.                      {
  278.                      precision[jtemp]=2;
  279.                      bad_flag[jtemp]=1;
  280.                      }
  281.                 }
  282.           }               
  283.         //--------------------------线性移位寄存器-------------------------------------
  284.         for(jtemp=0;jtemp<=2;jtemp++)  //用动态精度来滤波
  285.         {
  286.             old_fixed[jtemp]=new_fixed[jtemp];
  287.             if(adresult[jtemp]>=new_fixed[jtemp])                        
  288.             {   
  289.               if((adresult[jtemp]-new_fixed[jtemp])>=precision[jtemp])
  290.                 {
  291.                          new_fixed[jtemp]=adresult[jtemp];
  292.                       }
  293.             }
  294.             else if(adresult[jtemp]<new_fixed[jtemp])
  295.                 {   
  296.                    if((new_fixed[jtemp]-adresult[jtemp])>=precision[jtemp])   
  297.                        {
  298.                          new_fixed[jtemp]=adresult[jtemp];
  299.                        }
  300.                 }
  301.         }
  302.         //------------------------- 动态门限判决----------------------------------
  303.         if((vpp[0]>=vpp[1])&&(vpp[0]>=vpp[2]))  //x轴加速度变化最大
  304.         {
  305.                 if((old_fixed[0]>=dc[0])&&(new_fixed[0]<dc[0])&&(bad_flag[0]==0))  //判决是否走步      
  306.                 {
  307.                         STEPS=STEPS+1;
  308.                 }
  309.         }
  310.         else if((vpp[1]>=vpp[0])&&(vpp[1]>=vpp[2])) //y轴加速度变化最大
  311.         {
  312.                 if((old_fixed[1]>=dc[1])&&(new_fixed[1]<dc[1])&&(bad_flag[1]==0))        
  313.                 {
  314.                         STEPS=STEPS+1;
  315.                 }
  316.         }
  317.         else if((vpp[2]>=vpp[1])&&(vpp[2]>=vpp[0])) //z轴加速度变化最大
  318.         {
  319.                 if((old_fixed[2]>=dc[2])&&(new_fixed[2]<dc[2])&&(bad_flag[2]==0))        
  320.                 {
  321.                         STEPS=STEPS+1;
  322.                 }
  323.         }
  324.         conversion(STEPS);           
  325.                 buffer[4] =wan;
  326.     buffer[5] =qian;
  327.     buffer[6] =bai;
  328.     buffer[7] =shi;
  329.                 buffer[8] =ge;
  330.                 buffer[9] ='\0'; //终止符
  331.                         
  332. }

  333. void delay(unsigned int n)
  334. {
  335.         unsigned int i,j;
  336.         for(i=0;i<n;i++)
  337.                 for(j=0;j<100;j++);
  338. }

  339. void sys_init()
  340. {
  341.   UART_init();             //串口初始化
  342.         ADC_init(PulsePin);
  343.   T0_init();                 // 定时器初始化,设置为每2ms读取一次信号  
  344.         Init_ADXL345();
  345. }

  346. void main(void)
  347. {
  348.         uchar devid;
  349.   delay(500);                          //上电延时        
  350.         sys_init();                   //系统初始化
  351.         devid=Single_Read_ADXL345(0X00);//读出的数据为0XE5,表示正确
  352.         while(1)
  353.         {        
  354.                 step_counter();             //步数计算
  355.                 buffer[0]='

  356. [/font]
  357. ;              //判断标志$
  358.                 if (QS == true)
  359.                                 {                       // 当单片机发现心跳时,量化自标记为true                                                                                   
  360.     buffer[1] =BPM/100+48;
  361.     buffer[2] =BPM%100/10+48;
  362.                 buffer[3] =BPM%10+48;                                                
  363.                                 QS = false;                                          // 下一次重置量化自标记                                
  364.                                  }
  365.                 Send_Byte(buffer);                    //发送数据                                       
  366. }
  367. }

  368. void UART_init(void)     //串口初始化
  369. {
  370.         PCON &= 0x7F;                //波特率不倍速
  371.         SCON = 0x50;                //8位数据,可变波特率
  372.         AUXR |= 0x04;                //独立波特率发生器时钟为Fosc,即1T
  373.         BRT = 0xDC;                //设置独立波特率发生器重装值
  374.         AUXR |= 0x01;                //串口一选择独立波特率发生器为波特率发生器
  375.         AUXR |= 0x10;                //启用独立波特率发生器
  376. }

  377. void Send_Byte(unsigned char *temp)      //发送一串数据
  378. {
  379.         unsigned char i=0;
  380.              ES=0;         //禁止串口中断  
  381.            while(temp[i] != '\0')
  382.             {
  383.                    SBUF=*(temp+i);
  384.                         i++;               
  385.                         while(TI==0);        //发送数据完毕时,TI会自动置高
  386.                         TI=0;                    //发送数据完毕,将TI清零,准备下一次发送
  387.                 }
  388.            ES=1;              //清零串口中断发送标志                                                               
  389. }

  390. void T0_init(void)  //定时器初始化
  391.         {     
  392.         TMOD |= 0x01;        //16位定时器
  393.         TL0=T0MS;
  394.         TH0=T0MS>>8;
  395.         TR0=1;                //启动定时器0
  396.         ET0=1;                //启用定时器中断
  397.   EA=1;     //确保全局中断已启用     
  398. }
  399. void ADC_init(unsigned char channel)  //ADC初始化
  400. {
  401.         P1ASF=ADC_MASK<<channel;        //启用PulsePin作为ADC输入
  402.         ADC_RES=0;        //清除之前的ADC结果
  403.         ADC_RESL=0;        //清除之前的ADC结果
  404.         AUXR1 |= 0x04;        //调整ADC结果的格式
  405.         ADC_CONTR=channel|ADC_POWER|ADC_SPEEDLL|ADC_START;        //开启AFC并开始转换
  406. }
  407. unsigned int analogRead(unsigned char channel)
  408. {
  409.         unsigned int result;
  410.         ADC_CONTR &=!ADC_FLAG;        //清除ADC FLAG
  411.         result=ADC_RES;
  412.         result=result<<8;
  413.         result+=ADC_RESL;
  414.         ADC_CONTR|=channel|ADC_POWER|ADC_SPEEDLL|ADC_START;
  415.         return result;
  416. }
  417. // Timer 0中断子程序,每2MS中断一次,读取AD值,计算心率值
  418. void Timer0_rountine(void) interrupt 1
  419. {                       
  420.   int N;
  421.         unsigned char i;
  422.         // 保持最后10个IBI值的runningtotal
  423.   unsigned int runningTotal = 0;                  // 清除runningTotal变量   
  424.         EA=0;                                      // 禁用中断
  425.         TL0=T0MS;
  426.         TH0=T0MS>>8;                                //重新加载16位定时器0
  427.   Signal = analogRead(PulsePin);              // 读取传感器值
  428.   sampleCounter += 2;                         // 以ms为单位跟踪变量
  429.   N = sampleCounter - lastBeatTime;       // 监视自上次跳动以来的时间以避免噪音
  430.     //  找到脉搏的波峰和波谷
  431.   if(Signal < thresh && N > (IBI/5)*3){       // 通过等待最后IBI的3/5以避免严重的噪音
  432.     if (Signal < Trough){                        // T是低谷
  433.       Trough = Signal;                         // 跟踪脉搏波的最低点
  434.     }
  435.   }
  436.   if(Signal > thresh && Signal > Peak){          // thresh条件有助于避免噪音
  437.     Peak = Signal;                             // P是峰值
  438.   }                                        // 跟踪脉搏波的最高点
  439.   // 每次出现脉冲信号时都会激增
  440.   if (N > 250){                                   // 避免高频噪音
  441.     if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) )
  442.                         {        
  443.       Pulse = true;                               // 当我们认为有脉冲时设置脉冲标志
  444.       IBI = sampleCounter - lastBeatTime;         //以ms为单位测量心跳之间的时间
  445.       lastBeatTime = sampleCounter;               // 跟踪下一个脉冲的时间
  446.       if(secondBeat){                        // 如果这是第二次心跳
  447.         secondBeat = false;                  // 清除第二次心跳标志
  448.         for(i=0; i<=9; i++){             // 在启动时记录运行总数以获得实际的BPM
  449.           rate[i] = IBI;                     
  450.         }
  451.       }
  452.       if(firstBeat){                         // 如果这是我们第一次发现心跳
  453.         firstBeat = false;                   // 清除第一次心跳标志
  454.         secondBeat = true;                   // 设置第二次心跳标志
  455.         EA=1;                               // 再次启用中断
  456.         return;                              // IBI值不可靠,丢弃它
  457.       }   
  458.       for(i=0; i<=8; i++){                // 移动速率数组中的数据
  459.         rate[i] = rate[i+1];                  // 放弃最早的IBI值
  460.         runningTotal += rate[i];              //加载9个最早的ibi值
  461.       }
  462.       rate[9] = IBI;                          //将最新的IBI添加到速率数组中
  463.       runningTotal += rate[9];                // 将最新的IBI添加到runningtotal
  464.       runningTotal /= 10;                     //求最后10个IBI的平均值
  465.       BPM = 60000/runningTotal;               // 一分钟内可以发现多少个心跳,这就是BPM
  466.                         if(BPM>200)BPM=200;                        //限制BPM最高显示值
  467.                         if(BPM<30)BPM=30;                                //限制BPM最低显示值                        
  468.                   DisBuff[2]   = BPM%10+48;//取个位数
  469.                         DisBuff[1]   = BPM%100/10+48; //取十位数
  470.                         DisBuff[0]   = BPM/100+48;           //百位数
  471.                         if(DisBuff[0]==48)
  472.                                 DisBuff[0]=32;               
  473.       QS = true;                              //设置量化自我标志
  474.     }                       
  475.   }
  476.   if (Signal < thresh && Pulse == true){   // 当数值下降时,心跳结束

  477.     Pulse = false;                         // 重置脉冲标志,以便下次执行
  478.     amp = Peak - Trough;                           // 得到脉搏波的幅度
  479.     thresh = amp/2 + Trough;                    // 将幅度设置为50%
  480.     Peak = thresh;                            // 重置以便下次使用
  481.     Trough = thresh;
  482.   }
  483.   if (N > 2500){                           // 如果2.5秒内没有心跳
  484.     thresh = 512;                          // 设置thresh默认值
  485.     Peak = 512;                               // 设置P默认值
  486.     Trough = 512;                               // 设置T默认值
  487.     lastBeatTime = sampleCounter;          // 使lastBeatTime保持最新状态        
  488.     firstBeat = true;                      //设置这些以避免噪声
  489.     secondBeat = false;                    // 当我们得到心跳回来
  490.   }
  491.   EA=1;                                   // 完成后启用中断        
  492. }
  493. #include  <stc12c5a60s2.h>        
  494. #include  <math.h>   
  495. #include  <stdio.h>           
  496. #include  <INTRINS.H>
  497. #include  <stdlib.h>  
  498. //------------------------------------
  499. #define   uchar unsigned char
  500. #define   uint unsigned int   

  501. #define S2RI 0x01   //串口2接收中断请求标志位  
  502. #define S2TI 0x02   //串口2发送中断请求标志位
  503. unsigned char flag2,temp2;  
  504. unsigned char Buffer[10];
  505. unsigned char RXCount = 0;
  506. unsigned char Display_Buffer[10];
  507. //------------------------------------
  508. #define BMP180_SlaveAddress   0xee          //定义器件在IIC总线中的地址                              
  509. #define OSS 0        // 过采样设置  代码未设置为使用其他oss值
  510. typedef unsigned char  BYTE;
  511. typedef unsigned short WORD;
  512. uchar ge,shi,bai,qian,wan,shiwan;           //显示变量
  513. int  dis_data;                              //变量
  514. short ac1;
  515. short ac2;
  516. short ac3;
  517. unsigned short ac4;
  518. unsigned short ac5;
  519. unsigned short ac6;
  520. short b1;
  521. short b2;
  522. short mb;
  523. short mc;
  524. short md;
  525. //------------------------------------
  526. //按键 IO设置
  527. sbit KEY1 = P2^3;
  528. sbit KEY2 = P2^2;
  529. sbit KEY3 = P2^1;
  530. sbit KEY4 = P2^0;
  531. //LCD1602 IO设置
  532. #define LCD1602_PORT P0
  533. sbit LCD1602_RS = P2^5; //数据 命令选择
  534. sbit LCD1602_RW = P2^6; //读 写选择
  535. sbit LCD1602_EN = P2^7; //使能信号
  536. //------------------------------------
  537. sbit SCL=P1^4;      //IIC时钟引脚定义
  538. sbit SDA=P1^5;      //IIC数组引脚定义
  539. //------------------------------------
  540. void gps(void);
  541. void display_receive(void);
  542. extern void LCD1602_delay_ms(unsigned int n);
  543. extern void LCD1602_write_com(unsigned char com);
  544. extern void LCD1602_write_data(unsigned char dat);
  545. extern void LCD1602_write_word(unsigned char *s);
  546. extern void Init_LCD1602();
  547. extern void Delay_ms(unsigned int n);
  548. extern void Uart_Init();
  549. //------------------------------------
  550. unsigned char KEY_NUM = 0;
  551. bit Page;
  552. unsigned char xdata Display_GPGGA_Buffer[68];
  553. unsigned char xdata Display_GPRMC_Buffer[68];
  554. bit Flag_OV = 0;
  555. bit Flag_Calc_GPGGA_OK = 0;
  556. bit Flag_Calc_GPRMC_OK = 0;
  557. unsigned char RX_Buffer[68];
  558. unsigned char RX_Count = 0;
  559. unsigned char Hour = 0,Min_High = 0,Min_Low = 0,Sec_High = 0,Sec_Low = 0;
  560. unsigned char Month = 0,Day = 0,Month_High = 0, Month_Low = 0,Day_Low = 0 ,Day_High = 0, Year_High = 0,Year_Low = 0;
  561. unsigned int Year = 0;
  562. bit Flag_GPS_OK = 0;
  563. unsigned char MaxDay = 0;
  564. extern void Scan_Key();
  565. extern void UTCDate2LocalDate(void);
  566. extern bit IsLeapYear(unsigned int uiYear);        
  567. extern unsigned char GetMaxDay(unsigned char Month_Value,unsigned int Year_Value);
  568. extern unsigned char RX_Buffer[68];
  569. extern unsigned char RX_Count;
  570. extern unsigned char Hour,Min_High,Min_Low,Sec_High,Sec_Low;
  571. extern unsigned char Month,Day,Month_High, Month_Low,Day_Low ,Day_High, Year_High,Year_Low;
  572. extern unsigned int Year;
  573. extern unsigned char MaxDay;
  574. extern bit Flag_GPS_OK;
  575. //------------------------------------
  576. void conversion(long temp_data);
  577. void  Single_Write(uchar SlaveAddress,uchar REG_Address,uchar REG_data);   
  578. uchar Single_Read(uchar REG_Address);                                      
  579. void  Multiple_Read(uchar,uchar);                                          
  580. void delay(unsigned int k);
  581. void Delay5us();
  582. void Delay5ms();
  583. void BMP180_Start();
  584. void BMP180_Stop();
  585. void BMP180_SendACK(bit ack);
  586. bit  BMP180_RecvACK();
  587. void BMP180_SendByte(BYTE dat);
  588. BYTE BMP180_RecvByte();
  589. void BMP180_ReadPage();
  590. void BMP180_WritePage();
  591. void Init_BMP180(void);
  592. void bmp180Convert(void);
  593. //------------------------------------
  594. void UTCDate2LocalDate(void)          //UTC日期和当前日期的转换
  595. {
  596.         Day = (Day_High - 0x30) * 10 + (Day_Low-0x30) + 1;                //日  加一
  597.         Month = (Month_High - 0x30) * 10 + (Month_Low - 0x30);
  598.         Year = 2000 + (Year_High - 0x30) * 10 + (Year_Low - 0x30);
  599.         
  600.         MaxDay = GetMaxDay(Month,Year);                                //获取当月 天数 最大值
  601.         if(Day > MaxDay)                //溢出
  602.         {
  603.                 Day = 1;
  604.                 Month += 1;
  605.                 if(Month > 12)
  606.                 {
  607.                         Year+=1;
  608.                 }
  609.         }
  610.         Day_High = Day/10 + 0x30;                                //转换日期值为ASCII
  611.         Day_Low = Day%10 + 0x30;
  612.         Month_High = Month/10 + 0x30;                        //转换月份值为ASCII
  613.         Month_Low = Month%10 + 0x30;
  614.         Year_High = Year%100/10 + 0x30;                        //转换年份值为ASCII
  615.         Year_Low = Year%10 + 0x30;                        
  616. }

  617. unsigned char GetMaxDay(unsigned char Month_Value,unsigned int Year_Value) //获取当月日期的最大值
  618. {
  619.         unsigned char iDays;
  620.         switch(Month_Value)
  621.         {
  622.                 case 1:
  623.                 case 3:
  624.                 case 5:
  625.                 case 7:
  626.                 case 8:
  627.                 case 10:
  628.                 case 12:
  629.                         {
  630.                                 iDays = 31;
  631.                         }
  632.                         break;
  633.                 case 2:
  634.                         {
  635.                                 //2月份比较特殊,需要根据是不是闰年来判断当月是28天还29天
  636.                                 iDays = IsLeapYear(Year_Value)?29:28;
  637.                         }
  638.                         break;
  639.                 case 4:
  640.                 case 6:
  641.                 case 9:
  642.                 case 11:
  643.                         {
  644.                                 iDays = 30;
  645.                         }
  646.                         break;
  647.                 default : break;
  648.         }
  649.         return(iDays);                                                
  650. }

  651. bit IsLeapYear(unsigned int uiYear)    //闰年检测
  652. {
  653.         return (((uiYear%4)==0)&&((uiYear%100)!=0))||((uiYear%400)==0);
  654. }

  655. void Uart_Init()                //串口初始化函数                                                     
  656. {
  657.         SCON = 0X50;  //UART方式1;8位UART
  658.         REN  = 1;     //允许串行口接收数据
  659.         PCON = 0x00;  //SMOD=0;波特率不加倍
  660.         TMOD = 0x20;  //T1方式2,用于产生波特率
  661.         TH1  = 0xFD;  //装初值
  662.         TL1  = 0xFD;
  663.         TR1  = 1;     //启动定时器1
  664.         EA   = 1;     //打开全局中断控制
  665.         ES   = 1;     //打开串行口中断
  666.         
  667.          AUXR &= 0xF7;                //波特率不倍速
  668.         S2CON = 0x50;                //8位数据,可变波特率
  669.         AUXR &= 0xFB;                //独立波特率发生器时钟为Fosc/12,即12T
  670.         BRT = 0xFD;                //设定独立波特率发生器重装值
  671.         AUXR |= 0x10;                //启动独立波特率发生器
  672.     IE2 =0x01;  //开串口二中断  ES2=1
  673.     EA=1;        
  674. }

  675. void RECEIVE_DATA(void) interrupt 4  using 3                //串口一中断接收,接收gps数据
  676. {
  677.         unsigned char temp = 0;
  678.         ES=0;
  679.         temp = SBUF;
  680.         RI = 0;

  681.         
  682.         if(temp == '

  683. [/font]
  684. )
  685.         {
  686.                 RX_Count = 0;
  687.                 Flag_GPS_OK = 0;               
  688.         }

  689.         RX_Buffer[RX_Count++] = temp;

  690.         if(RX_Count >= 59)
  691.         {
  692.                 RX_Count = 59;
  693.                 Flag_GPS_OK = 1;               
  694.         }

  695.         ES=1;
  696. }

  697. void UART_2Interrupt(void) interrupt 8 using 1     //串口二中断接收
  698. {  
  699.     if(S2CON&S2RI)  
  700.     {  
  701.         S2CON&=~S2RI;  
  702.         flag2=1;  
  703.         temp2=S2BUF;
  704.                         Buffer[RXCount++] = temp2;
  705.     }   
  706.                 if(S2CON&S2TI)
  707.                 {
  708.                         S2CON&=~S2TI;
  709.                 }
  710. }
  711.                         
  712. void Delay_ms(unsigned int n)
  713. {
  714.         unsigned int  i,j;
  715.         for(i=0;i<n;i++)
  716.                 for(j=0;j<123;j++);
  717. }

  718. void LCD1602_delay_ms(unsigned int n)
  719. {
  720.         unsigned int  i,j;
  721.         for(i=0;i<n;i++)
  722.                 for(j=0;j<123;j++);
  723. }

  724. void LCD1602_write_com(unsigned char com)  //1602写指令
  725. {
  726.         LCD1602_RS = 0;
  727.         LCD1602_delay_ms(1);
  728.         LCD1602_EN = 1;
  729.         LCD1602_PORT = com;
  730.         LCD1602_delay_ms(1);
  731.         LCD1602_EN = 0;
  732. }

  733. void LCD1602_write_data(unsigned char dat) //1602写数据
  734. {
  735.         LCD1602_RS = 1;
  736.         LCD1602_delay_ms(1);        
  737.         LCD1602_PORT = dat;
  738.         LCD1602_EN = 1;
  739.         LCD1602_delay_ms(1);
  740.         LCD1602_EN = 0;
  741. }

  742. void LCD1602_write_word(unsigned char *s) //1602连续写字符
  743. {
  744.         while(*s>0)
  745.         {
  746.                 LCD1602_write_data(*s);
  747.                 s++;
  748.         }
  749. }

  750. void Init_LCD1602()          //初始化1602
  751. {
  752.         LCD1602_EN = 0;
  753.         LCD1602_RW = 0;                                                 //设置为写状态
  754.         LCD1602_write_com(0x38);         //显示模式设定  16*2显示 5*7点阵  8位数据口
  755.         LCD1602_write_com(0x0c);         //开关显示、光标有无设置、光标闪烁设置
  756.         LCD1602_write_com(0x06);         //写一个字符后指针加一
  757.         LCD1602_write_com(0x01);         //清屏指令
  758. }

  759. void display_receive()       //显示串口二接收到的内容,即从另一个单片机接收到的步数和心率数据
  760. {
  761.         if (Buffer[0]=='

  762. [/font]
  763. )        
  764.         {unsigned char i;
  765.                 for( i = 0; i < 10 ; i++)
  766.                 {
  767.                         Display_Buffer[i] = Buffer[i];
  768.                 }
  769.         LCD1602_write_com(0X01);         //清屏
  770.         Delay_ms(50);
  771.         LCD1602_write_com(0x80);                //指针设置
  772.         LCD1602_write_word("STEPS:");
  773.         LCD1602_write_data(Display_Buffer[4]);
  774.         LCD1602_write_data(Display_Buffer[5]);
  775.         LCD1602_write_data(Display_Buffer[6]);
  776.         LCD1602_write_data(Display_Buffer[7]);
  777.         LCD1602_write_data(Display_Buffer[8]);
  778.         
  779.         LCD1602_write_com(0x80+0x40);                        //设置指针  0xc0
  780.         LCD1602_write_word("BPM:");
  781.         LCD1602_write_data(Display_Buffer[1]);
  782.         LCD1602_write_data(Display_Buffer[2]);
  783.         LCD1602_write_data(Display_Buffer[3]);
  784.         }
  785. }

  786. void Scan_Key()              //扫描按键
  787. {
  788.         if( KEY1 == 0 )                                                 //按键1扫描
  789.         {
  790.                 Delay_ms(10);                                        //延时去抖
  791.                 if( KEY1 == 0 )
  792.                 {
  793.                         while(KEY1 == 0);                        //等待松手
  794.                         KEY_NUM = 3;
  795.                         Page = ~Page;
  796.                         LCD1602_write_com(0X01);        //清屏
  797.                 }
  798.         }
  799. }

  800. void Delay5000ms()                //@11.0592MHz stc12 延时5秒
  801. {
  802.         unsigned char i, j, k;
  803.         i = 211;
  804.         j = 30;
  805.         k = 11;
  806.         do
  807.         {
  808.                 do
  809.                 {
  810.                         while (--k);
  811.                 } while (--j);
  812.         } while (--i);
  813. }
  814. //------------------------------------
  815. void main()       //主程序
  816. {
  817.         Init_LCD1602(); //初始化1602
  818.         Init_BMP180();  //初始化bmp180
  819.         Delay_ms(1000);
  820.         LCD1602_write_com(0x80); //显示欢迎界面
  821.         LCD1602_write_word("WELCOME");
  822.         LCD1602_write_com(0x80+0x40);        
  823.         LCD1602_write_word("sanshuige");
  824.         Delay_ms(10000);
  825.         LCD1602_write_com(0X01); //显示温度,气压界面
  826.         bmp180Convert();
  827.         Delay5000ms();
  828.         LCD1602_write_com(0X01);
  829.         Uart_Init();             //双串口初始化
  830.         while(1)
  831.         {
  832.                 gps();         //处理gps数据
  833.                 Scan_Key();                 //按键扫描        
  834. //显示gps界面一,按下key1后显示gps界面二。连续按key1,在2个界面之间来回切换显示               
  835.                 if (KEY2==0)
  836.                 {
  837.                 while(1)
  838.                 {
  839.                         display_receive(); //如果按下key2,显示步数和心率界面
  840.                   Delay_ms(2000);
  841.                                 if (KEY1==0)     //在步数和心率界面下按下key1,则跳回gps界面
  842.                                 {
  843.                                         break;
  844.                                 }
  845.                 }
  846.                 }               
  847.         }
  848. }

  849. void gps()    //处理和显示串口一接收到的gps数据
  850. {
  851.         unsigned char i = 0;
  852.         if(Flag_GPS_OK == 1 && RX_Buffer[4] == 'G' && RX_Buffer[6] == ',' && RX_Buffer[13] == '.')                        //确定是否收到"GPGGA"这一帧数据
  853.                 {
  854.                         for( i = 0; i < 68 ; i++)
  855.                         {
  856.                                 Display_GPGGA_Buffer[i] = RX_Buffer[i];        
  857.                         }
  858.                         Hour = (Display_GPGGA_Buffer[7]-0x30)*10+(Display_GPGGA_Buffer[8]-0x30)+8;                        //UTC时间转换到北京时间                UTC+8  0x30为ascii转换为数字
  859.                         if( Hour >= 24)                                //溢出
  860.                         {
  861.                                 Hour %= 24;                                //获取当前Hour
  862.                                 Flag_OV = 1;                        //日期进位
  863.                         }
  864.                         else
  865.                         {
  866.                                 Flag_OV = 0;
  867.                         }
  868.                         Min_High = Display_GPGGA_Buffer[9];
  869.                         Min_Low = Display_GPGGA_Buffer[10];        
  870.                         Sec_High = Display_GPGGA_Buffer[11];
  871.                         Sec_Low = Display_GPGGA_Buffer[12];
  872.                         Flag_Calc_GPGGA_OK = 1;
  873.                 }

  874.                 if(Page == 0 && Flag_Calc_GPGGA_OK == 1)
  875.                 {
  876.                         Flag_Calc_GPGGA_OK = 0;
  877.                         LCD1602_write_com(0x80);                        //设置指针
  878.                         LCD1602_write_data(Hour/10+0x30);
  879.                         LCD1602_write_data(Hour%10+0x30);
  880.                         LCD1602_write_data(':');
  881.                         LCD1602_write_data(Min_High);
  882.                         LCD1602_write_data(Min_Low);
  883.                         LCD1602_write_data(':');
  884.                         LCD1602_write_data(Sec_High);
  885.                         LCD1602_write_data(Sec_Low);
  886.                         LCD1602_write_word("  ");        
  887.                         LCD1602_write_data(Display_GPGGA_Buffer[54]);        
  888.                         LCD1602_write_data(Display_GPGGA_Buffer[55]);        
  889.                         LCD1602_write_data(Display_GPGGA_Buffer[56]);        
  890.                         LCD1602_write_data(Display_GPGGA_Buffer[57]);
  891.                         LCD1602_write_word("m");
  892.                         LCD1602_write_com(0x80+0x40);                        //设置指针               
  893.                         LCD1602_write_data(Display_GPGGA_Buffer[28]);                        //N 或者 S
  894.                         LCD1602_write_data(Display_GPGGA_Buffer[17]);                        //纬度
  895.                         LCD1602_write_data(Display_GPGGA_Buffer[18]);                        //纬度
  896.                         LCD1602_write_data(0xdf);                                                                //度
  897.                         LCD1602_write_data(Display_GPGGA_Buffer[19]);                        //纬度
  898.                         LCD1602_write_data(Display_GPGGA_Buffer[20]);                        //纬度
  899.                         LCD1602_write_word("'");                                                                //秒                        
  900.                         LCD1602_write_data(Display_GPGGA_Buffer[42]);                        //E 或者 W
  901.                         LCD1602_write_data(Display_GPGGA_Buffer[30]);                        //经度
  902.                         LCD1602_write_data(Display_GPGGA_Buffer[31]);        
  903.                         LCD1602_write_data(Display_GPGGA_Buffer[32]);        
  904.                         LCD1602_write_data(0xdf);                                                               
  905.                         LCD1602_write_data(Display_GPGGA_Buffer[33]);                        
  906.                         LCD1602_write_data(Display_GPGGA_Buffer[34]);               
  907.                         LCD1602_write_word("'");                                                
  908.                 }        
  909.                 if(Flag_GPS_OK == 1 && RX_Buffer[4] == 'M' && RX_Buffer[52] == ',' && RX_Buffer[59] == ',')                        //确定是否收到"GPRMC"这一帧数据
  910.                 {
  911.                         for( i = 0; i < 68 ; i++)
  912.                         {
  913.                                 Display_GPRMC_Buffer[i] = RX_Buffer[i];        
  914.                         }
  915.                         Year_High = Display_GPRMC_Buffer[57];
  916.                         Year_Low = Display_GPRMC_Buffer[58];
  917.                         Month_High = Display_GPRMC_Buffer[55];
  918.                         Month_Low = Display_GPRMC_Buffer[56];
  919.                         Day_High = Display_GPRMC_Buffer[53];
  920.                         Day_Low = Display_GPRMC_Buffer[54];
  921.                         if(Flag_OV == 1)                        //有进位
  922.                         {
  923.                                 UTCDate2LocalDate();                        //UTC日期转换为北京时间               
  924.                         }
  925.                         Flag_Calc_GPRMC_OK = 1;
  926.                 }
  927.                 if(Page == 1 && Flag_Calc_GPRMC_OK == 1)
  928.                 {                        
  929.                         Flag_Calc_GPRMC_OK = 0;
  930.                         LCD1602_write_com(0x80);                        //设置指针
  931.                         LCD1602_write_word("20");
  932.                         LCD1602_write_data(Year_High);
  933.                         LCD1602_write_data(Year_Low);
  934.                         LCD1602_write_data('-');        
  935.                         LCD1602_write_data(Month_High);
  936.                         LCD1602_write_data(Month_Low);
  937.                         LCD1602_write_data('-');
  938.                         LCD1602_write_data(Day_High);
  939.                         LCD1602_write_data(Day_Low);                                                
  940.                         LCD1602_write_com(0x80+0x40);                        //设置指针
  941.                         LCD1602_write_word("Speed:");                                //显示内容
  942.                         LCD1602_write_data(Display_GPRMC_Buffer[46]);               
  943.                         LCD1602_write_data(Display_GPRMC_Buffer[47]);               
  944.                         LCD1602_write_data(Display_GPRMC_Buffer[48]);                        
  945.                         LCD1602_write_data(Display_GPRMC_Buffer[49]);        
  946.                         LCD1602_write_data(Display_GPRMC_Buffer[50]);                        
  947.                         LCD1602_write_word("m/s");                                                        
  948.                 }                                
  949.         }
  950.         
  951.         void conversion(long temp_data)  //转变函数
  952. {  
  953.    
  954.     shiwan=temp_data/100000+0x30 ;
  955.     temp_data=temp_data%100000;   //取余运算
  956.     wan=temp_data/10000+0x30 ;
  957.     temp_data=temp_data%10000;   
  958.     qian=temp_data/1000+0x30 ;
  959.     temp_data=temp_data%1000;   
  960.     bai=temp_data/100+0x30   ;
  961.     temp_data=temp_data%100;     
  962.     shi=temp_data/10+0x30    ;
  963.     temp_data=temp_data%10;      
  964.     ge=temp_data+0x30;         
  965. }
  966. void delay(unsigned int k)        
  967. {                                                
  968.     unsigned int i,j;                                
  969.    for(i=0;i<k;i++)
  970. {                        
  971.    for(j=0;j<121;j++)                        
  972.    {;}
  973. }                                                
  974. }

  975. void Delay5us()
  976. {
  977.     _nop_();_nop_();_nop_();_nop_();
  978.     _nop_();_nop_();_nop_();_nop_();
  979.         _nop_();_nop_();_nop_();_nop_();
  980.         _nop_();_nop_();_nop_();_nop_();
  981. }

  982. void Delay5ms()
  983. {
  984.     WORD n = 560;

  985.     while (n--);
  986. }

  987. void BMP180_Start()             //起始信号
  988. {
  989.     SDA = 1;                    //拉高数据线
  990.     SCL = 1;                    //拉高时钟线
  991.     Delay5us();                 //延时
  992.     SDA = 0;                    //产生下降沿
  993.     Delay5us();                 //延时
  994.     SCL = 0;                    //拉低时钟线
  995. }

  996. void BMP180_Stop()              //停止信号
  997. {
  998.     SDA = 0;                    //拉低数据线
  999.     SCL = 1;                    //拉高时钟线
  1000.     Delay5us();                 //延时
  1001.     SDA = 1;                    //产生上升沿
  1002.     Delay5us();                 //延时
  1003. }

  1004. void BMP180_SendACK(bit ack)    //发送应答信号 入口参数:ack(0:ACK  1:NAK)
  1005. {
  1006.     SDA = ack;                  //写应答信号
  1007.     SCL = 1;                    //拉高时钟线
  1008.     Delay5us();                 //延时
  1009.     SCL = 0;                    //拉低时钟线
  1010.     Delay5us();                 //延时
  1011. }

  1012. bit BMP180_RecvACK()            //接收应答信号
  1013. {
  1014.     SCL = 1;                    //拉高时钟线
  1015.     Delay5us();                 //延时
  1016.     CY = SDA;                   //读应答信号
  1017.     SCL = 0;                    //拉低时钟线
  1018.     Delay5us();                 //延时

  1019.     return CY;
  1020. }

  1021. void BMP180_SendByte(BYTE dat)   //向iic总线发送一个字节数据
  1022. {
  1023.     BYTE i;

  1024.     for (i=0; i<8; i++)         //8位计数器
  1025.     {
  1026.         dat <<= 1;              //移出数据的最高位
  1027.         SDA = CY;               //送数据口
  1028.         SCL = 1;                //拉高时钟线
  1029.         Delay5us();             //延时
  1030.         SCL = 0;                //拉低时钟线
  1031.         Delay5us();             //延时
  1032.     }
  1033.     BMP180_RecvACK();
  1034. }

  1035. BYTE BMP180_RecvByte()         //从iic总线接收一个字节数据                 
  1036. {
  1037.     BYTE i;
  1038.     BYTE dat = 0;

  1039.     SDA = 1;                    //使能内部上拉,准备读取数据
  1040.     for (i=0; i<8; i++)         //8位计数器
  1041.     {
  1042.         dat <<= 1;
  1043.         SCL = 1;                //拉高时钟线
  1044.         Delay5us();             //延时
  1045.         dat |= SDA;             //读数据              
  1046.         SCL = 0;                //拉低时钟线
  1047.         Delay5us();             //延时
  1048.     }
  1049.     return dat;
  1050. }

  1051. short Multiple_read(uchar ST_Address)       //读出bmp180内部数据 连续两个
  1052. {   
  1053.         uchar msb, lsb;
  1054.         short _data;
  1055.     BMP180_Start();                          //起始信号
  1056.     BMP180_SendByte(BMP180_SlaveAddress);    //发送设备地址+写信号
  1057.     BMP180_SendByte(ST_Address);             //发送存储单元地址
  1058.     BMP180_Start();                          //起始信号
  1059.     BMP180_SendByte(BMP180_SlaveAddress+1);  //发送设备地址+读信号

  1060.     msb = BMP180_RecvByte();                 //BUF[0]存储
  1061.     BMP180_SendACK(0);                       //回应ACK
  1062.     lsb = BMP180_RecvByte();     
  1063.     BMP180_SendACK(1);                       //最后一个数据需要回NOACK

  1064.     BMP180_Stop();                           //停止信号
  1065.     Delay5ms();
  1066.     _data = msb << 8;
  1067.     _data |= lsb;        
  1068.     return _data;
  1069. }

  1070. long bmp180ReadTemp(void)
  1071. {

  1072.     BMP180_Start();                  //起始信号
  1073.     BMP180_SendByte(BMP180_SlaveAddress);   //发送设备地址+写信号
  1074.     BMP180_SendByte(0xF4);                  //写寄存器地址
  1075.     BMP180_SendByte(0x2E);               // 写入温度的寄存器数据
  1076.     BMP180_Stop();                   //发送停止信号
  1077.         delay(10);      
  1078.         
  1079.         return (long) Multiple_read(0xF6);
  1080. }

  1081. long bmp180ReadPressure(void)
  1082. {
  1083.         long pressure = 0;

  1084.     BMP180_Start();                   //起始信号
  1085.     BMP180_SendByte(BMP180_SlaveAddress);   //发送设备地址+写信号
  1086.     BMP180_SendByte(0xF4);                  // 写寄存器地址
  1087.     BMP180_SendByte(0x34);                 // 写入气压的寄存器数据
  1088.     BMP180_Stop();                    //发送停止信号
  1089.         delay(10);                           
  1090.         
  1091.         pressure = Multiple_read(0xF6);
  1092.         pressure &= 0x0000FFFF;
  1093.         
  1094.         return pressure;        
  1095.         
  1096. }

  1097. void Init_BMP180()                     //初始化bmp180
  1098. {
  1099.         ac1 = Multiple_read(0xAA);
  1100.         ac2 = Multiple_read(0xAC);
  1101.         ac3 = Multiple_read(0xAE);
  1102.         ac4 = Multiple_read(0xB0);
  1103.         ac5 = Multiple_read(0xB2);
  1104.         ac6 = Multiple_read(0xB4);
  1105.         b1 =  Multiple_read(0xB6);
  1106.         b2 =  Multiple_read(0xB8);
  1107.         mb =  Multiple_read(0xBA);
  1108.         mc =  Multiple_read(0xBC);
  1109.         md =  Multiple_read(0xBE);
  1110. }

  1111. void bmp180Convert()    //读取并在1602上显示温度和气压数据
  1112. {
  1113.         long ut;
  1114.         long up;
  1115.         long x1, x2, b5, b6, x3, b3, p;
  1116.         unsigned long b4, b7;
  1117.         long  temperature;
  1118.         long  pressure;
  1119.         
  1120.         ut = bmp180ReadTemp();
  1121.         ut = bmp180ReadTemp();           //读取温度
  1122.         up = bmp180ReadPressure();
  1123.         up = bmp180ReadPressure();  //读取大气压
  1124.         
  1125.         x1 = ((long)ut - ac6) * ac5 >> 15;
  1126.         x2 = ((long) mc << 11) / (x1 + md);
  1127.         b5 = x1 + x2;
  1128.          temperature = (b5 + 8) >> 4;
  1129.         LCD1602_write_com(0X01);        //清屏
  1130.         Delay_ms(50);
  1131.         conversion(temperature);
  1132.         LCD1602_write_word("temp:");
  1133.         LCD1602_write_data(bai);
  1134.         LCD1602_write_data(shi);
  1135.         LCD1602_write_word(".");
  1136.         LCD1602_write_data(ge);
  1137.         LCD1602_write_data(0XDF);  //温度单位
  1138.         LCD1602_write_word("C");

  1139.         b6 = b5 - 4000;
  1140.         x1 = (b2 * (b6 * b6 >> 12)) >> 11;
  1141.         x2 = ac2 * b6 >> 11;
  1142.         x3 = x1 + x2;
  1143.         b3 = (((long)ac1 * 4 + x3) + 2)/4;
  1144.         x1 = ac3 * b6 >> 13;
  1145.         x2 = (b1 * (b6 * b6 >> 12)) >> 16;
  1146.         x3 = ((x1 + x2) + 2) >> 2;
  1147.         b4 = (ac4 * (unsigned long) (x3 + 32768)) >> 15;
  1148.         b7 = ((unsigned long) up - b3) * (50000 >> OSS);
  1149.         if( b7 < 0x80000000)
  1150.              p = (b7 * 2) / b4 ;
  1151.            else  
  1152.              p = (b7 / b4) * 2;
  1153.         x1 = (p >> 8) * (p >> 8);
  1154.         x1 = (x1 * 3038) >> 16;
  1155.         x2 = (-7357 * p) >> 16;
  1156.         pressure = p + ((x1 + x2 + 3791) >> 4);
  1157.         LCD1602_write_com(0x80+0x40);                        //设置指针
  1158.         conversion(pressure);
  1159.         LCD1602_write_word("atm:");
  1160.         LCD1602_write_data(shiwan);
  1161.         LCD1602_write_data(wan);
  1162.         LCD1602_write_data(qian);
  1163.         LCD1602_write_word(".");
  1164.         LCD1602_write_data(bai);
  1165.         LCD1602_write_data(shi);
  1166.         LCD1602_write_word("Kpa");
  1167.         }
复制代码
全部资料51hei下载地址:
新建文件夹.rar (936.23 KB, 下载次数: 44)



评分

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

查看全部评分

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

使用道具 举报

沙发
ID:380389 发表于 2018-8-28 18:39 来自手机 | 只看该作者
感谢分享很实用
回复

使用道具 举报

板凳
ID:434366 发表于 2019-11-26 20:24 | 只看该作者
这个是模块化编程吗
回复

使用道具 举报

地板
ID:434366 发表于 2019-11-26 20:25 | 只看该作者
这个是模块化编程吗?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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