基於STM32設計的健康檢測裝置(測溫心率計步)

2021-12-31 10:00:11

1. 專案介紹

本文介紹的專案是基於STM32設計的健康檢測裝置,支援體溫測量,心率檢測,支援運動計步(採用MPU6050陀螺儀實現),支援WIFI傳輸資料到手機APP列印顯示。

硬體環境介紹:

MCU採用STM32F103C8T6

心率感測器採用PulseSensor

體溫檢測感測器採用紅外測溫感測器

運動計步功能採用MPU6050陀螺儀實現

OLED顯示屏採用0.96寸中景園電子的OLED顯示屏-SPI介面

程式設計軟體採用:  keil5

心率感測器:

image-20211230181809837

MPU6050感測器:

image-20211230181847836

體溫測溫模組

image-20211230181941292

OLED顯示屏:

image-20211230182017395

硬體效果圖:

image-20211230180229460

image-20211230180246350

image-20211230180313959

image-20211230180519337

工程原始碼截圖:

image-20211230181643594

專案原始碼下載地址: 基於STM32設計的健康檢測裝置(測溫心率計步)原始碼.zip-嵌入式檔案類資源-CSDN下載

視訊演示地址:

基於STM32設計的健康檢測裝置(測溫心率計步)

2. 專案原始碼介紹

2.1 計步功能實現程式碼

計步功能是通過MPU6050陀螺儀測量計算得到,下面貼出計步演演算法的核心實現程式碼.

/*******************************************************************************
檔名:         stepAlgorithm.c
描述   :        計步演演算法
*******************************************************************************/
​
#include "stepAlgorithm.h"
#include "rtc.h"
#include "math.h"
#include "mpu6050.h"
​
#define TRUE 1   
#define FALSE 0
#define VALUE_NUM 4
​
​
sportsInfo_t userSportsInfo;
//存放三軸資料  
float oriValues[3] = {0};    
//用於存放計算閾值的波峰波谷差值  
float tempValue[VALUE_NUM] ={0};  
int tempCount = 0;  
//是否上升的標誌位  
u8 isDirectionUp = FALSE;  
//持續上升次數  
int continueUpCount = 0;  
//上一點的持續上升的次數,為了記錄波峰的上升次數  
int continueUpFormerCount = 0;  
//上一點的狀態,上升還是下降  
u8 lastStatus = FALSE;  
//波峰值  
float peakOfWave = 0;  
//波谷值  
float valleyOfWave = 0;  
//此次波峰的時間  
long timeOfThisPeak = 0;  
//上次波峰的時間  
long timeOfLastPeak = 0;  
//當前的時間  
long timeOfNow = 0;  
//當前感測器的值  
float gravityNew = 0;  
//上次感測器的值  
float gravityOld = 0;  
//動態閾值需要動態的資料,這個值用於這些動態資料的閾值  
float initialValue = (float) 1.3;  
//初始閾值  
float ThreadValue = (float) 2.0;
//三軸軸值
accValue_t accValue;
//行走資訊:卡路里、里程、步數
static sportsInfo_t sportsInfo;
//計步快取
static u8 stepTempCount =0;
​
/*******************************************************************************
* 函數名:onSensorChanged
* 功能描述: G-Sensor工作後會一直呼叫這個函數對三軸資料進行平方和開根號的處理  
*                   呼叫DetectorNewStep檢測步子 
*                   
* 引數說明:  
*                 輸入:
*                       pAccValue:G-sensor的原始資料
*                       timeStamp_p:動態時間戳
* 返回值說明:
* 修改記錄:
*******************************************************************************/
sportsInfo_t *onSensorChanged(accValue_t *pAccValue,timeStamp_t *timeStamp_p,personInfo_t * personInfo) 
{  
  accValue_t *p = pAccValue;
  personInfo_t *userInfo = personInfo;
  timeStamp_t *time_p = timeStamp_p;
  oriValues[0] = p->accX;
  oriValues[1] = p->accY;
  oriValues[2] = p->accZ;
  //對三軸資料進行平方和開根號的處理 
  gravityNew = (float) sqrt(oriValues[0] * oriValues[0]+ oriValues[1] * oriValues[1] + oriValues[2] * oriValues[2]);  
  //檢測步子
  return DetectorNewStep(gravityNew,time_p,userInfo); 
}  
​
​
/*******************************************************************************
* 函數名:DetectorNewStep
* 功能描述: 
*         步伐更新:如果檢測到了波峰,並且符合時間差以及閾值的條件,則判定為1步       
*         閥值更新:符合時間差條件,波峰波谷差值大於initialValue,則將該差值納入閾值的計算中       
* 引數說明:  
輸入:
values:經過處理的G-sensor資料
timeStamp_p:時間戳
* 返回值說明:
* 修改記錄:sportsInfo_t *onSensorChanged(accValue_t *pAccValue,timeStamp_t *timeStamp_p,personInfo_t * personInfo)
*******************************************************************************/
sportsInfo_t *DetectorNewStep(float values,timeStamp_t *timeStamp_p,personInfo_t * personInfo) 
{  
  static u32 time_old;
  personInfo_t *userInfo = personInfo;
  static u32 step_per_2_second;  //每兩秒所走的步數
  float step_lenth,walk_speed,walk_distance,Calories;//步長
  u32 time_now;
  timeStamp_t *time_p = timeStamp_p;
  if (gravityOld == 0) 
  {  
    gravityOld = values;  
  } 
  else 
  {  
    if (DetectorPeak(values, gravityOld))//檢測到波峰
    {  
      timeOfLastPeak = timeOfThisPeak;//更新上次波峰的時間  
      //將時間戳轉換為以毫秒ms為單位
      time_now = timeOfNow = ((time_p->hour*60+time_p->minute)*60+time_p->second)*1000+time_p->twentyMsCount*20; //獲取時間 ,並轉化為毫秒
      //如果檢測到了波峰,並且符合時間差以及閾值的條件,則判定為1步 
      if (  (timeOfNow - timeOfLastPeak >= 250 )//Jahol Fan 修改為300,防止輕微動都也會檢測步子
          //&& (timeOfNow - timeOfLastPeak <= 2000)
          &&(peakOfWave - valleyOfWave >= ThreadValue)
            )
      {  
        timeOfThisPeak = timeOfNow; //更新此次波峰時間 
        
        
        stepTempCount++;//Jahol:加1為兩步
        step_per_2_second ++;
        //Jahol:這樣計算卡路里,不能濾除人為的誤操作,導致的結果是:里程和卡路里偏大
        if((time_now - time_old) >= 2000 )    //如果時間過了2秒
        {
​
          if( 1 == step_per_2_second )                 
          {
            step_lenth = userInfo->height/5;
          }
          else if( 2 == step_per_2_second )
          {
            step_lenth = userInfo->height/4;
          }
          else if( 3 == step_per_2_second )
          {
            step_lenth = userInfo->height/3;
          }
          else if( 4 == step_per_2_second )
          {
            step_lenth = userInfo->height/2;
          }
          else if(5 == step_per_2_second)             //Jahol:為了使計步準確,設定上限值為5步,犧牲卡路里準確性
          {
            step_lenth = userInfo->height/1.2f;
          }
          else if( 7 == step_per_2_second )
          {
            step_lenth = userInfo->height;
          }
          else if(step_per_2_second >= 8)               //      step_diff>8
          {
            step_lenth = userInfo->height*1.2f;
          }
          else 
          {
            step_lenth = 0;
          }
          walk_speed = step_per_2_second*step_lenth/2;   //速度 ,單位:米/秒
          walk_distance  = step_per_2_second*step_lenth; //行走距離,單位:米
          Calories = 4.5f*walk_speed*(userInfo->weight/2)/1800;  //Jahol:weight是以kg為單位
          sportsInfo.calories  += Calories;
          sportsInfo.distance  += walk_distance;        
          time_old = time_now;         //更新時間
          step_per_2_second = 0;
          
        }   
        else 
        {
          //do nothing
        }       
        /* 
        * 處理無效運動: 
        * 1.連續記錄5才開始計步 
        * 2.例如記錄的步使用者停住超過3秒,則前面的記錄失效,下次從頭開始 
        * 3.連續4記錄了步使用者還在運動,之前的資料才有效 
        * */                
        if ((stepTempCount< 5 )&&(timeOfNow - timeOfLastPeak >= 3000))          
        {
          stepTempCount = 0;
        }
        else if((stepTempCount>= 5)&&(timeOfNow - timeOfLastPeak <= 3000))
        {
          sportsInfo.stepCount += stepTempCount;          
          stepTempCount         = 0;                
        }
        else
        {
          //do nothing
        }
        
        
      }  
      //Jahol:更新閥值,問題:閥值不會一直變大,不能變小?
      if (timeOfNow - timeOfLastPeak >= 250  
          && (peakOfWave - valleyOfWave >= initialValue)) 
      {  
        timeOfThisPeak = timeOfNow;  
        ThreadValue = Peak_Valley_Thread(peakOfWave - valleyOfWave);//更新閥值  
      }  
    }  
  }  
  gravityOld = values;  
  return &sportsInfo;
}
​
/*******************************************************************************
* 函數名:DetectorPeak
* 功能描述: 
*檢測波峰 。以下四個條件判斷為波峰: 
*(1)目前點為下降的趨勢:isDirectionUp為FALSE 
*(2)之前的點為上升的趨勢:lastStatus為TRUE 
*(3)到波峰為止,持續上升大於等於2次
*(4)波峰值大於20 //Jahol:把這個值修改為15
*記錄波谷值 :
*(1)觀察波形圖,可以發現在出現步子的地方,波谷的下一個就是波峰,有比較明顯的特徵以及差值 
*(2)所以要記錄每次的波谷值,為了和下次的波峰做對比     
* 引數說明:  
*       輸入:
*           newValue:最新的經過處理的G-sensor資料
*           oldValue:前一個處理的G-sensor資料
* 返回值說明:
* 修改記錄:
*******************************************************************************/
u8 DetectorPeak(float newValue, float oldValue) 
{  
  lastStatus = isDirectionUp;  
  if (newValue >= oldValue) //取樣資料呈上升趨勢
  {  
    isDirectionUp = TRUE;  
    continueUpCount++;  
  }
  else                      //資料呈下降趨勢
  {  
    continueUpFormerCount = continueUpCount;  
    continueUpCount = 0;  
    isDirectionUp = FALSE;  
  }  
  
  if ((!isDirectionUp) && lastStatus  
      && (continueUpFormerCount >= 2 || oldValue >= 20))
    
  {  
    peakOfWave = oldValue;  
    return TRUE;  
  } 
  else if ((!lastStatus) && isDirectionUp) 
  {  
    valleyOfWave = oldValue;  
    return FALSE;  
  }
  else
  {  
    return FALSE;  
  }  
}
/*******************************************************************************
* 函數名:Peak_Valley_Thread
* 功能描述:  
*                   閾值的計算 
*                       1.通過波峰波谷的差值計算閾值 
*                       2.記錄4個值,存入tempValue[]陣列中 
*                       3.在將陣列傳入函數averageValue中計算閾值 
*                   
* 引數說明: 
* 返回值說明:
* 修改記錄:
*******************************************************************************/
float Peak_Valley_Thread(float value) 
{  
  float tempThread = ThreadValue; 
  u8 i = 0;
  if (tempCount < VALUE_NUM)
  {  
    tempValue[tempCount] = value;  
    tempCount++;  
  } 
  else 
  {  
    tempThread = averageValue(tempValue, VALUE_NUM);//計算閥值  
    for ( i = 1;i < VALUE_NUM;i++)//線性移位更新
    {  
      tempValue[i - 1] = tempValue[i];  
    }  
    tempValue[VALUE_NUM - 1] = value;  
  }  
  return tempThread;  
  
}
​
/*******************************************************************************
* 函數名:averageValue
* 功能描述:  
*        梯度化閾值 
*           1.計算陣列的均值 
*           2.通過均值將閾值梯度化在一個範圍裡 
*                   
* 引數說明: 
* 返回值說明:
* 修改記錄:
*******************************************************************************/
float averageValue(float value[], int n)
{  
  float ave = 0;  
  u8 i =0;
  for ( i = 0; i < n; i++)
  {  
    ave += value[i];//求和  
  }  
  ave = ave / VALUE_NUM;//求平均值  
  if (ave >= 8)  
    ave = (float) 4.3;  //????
  else if (ave >= 7 && ave < 8)  
    ave = (float) 3.3;  
  else if (ave >= 4 && ave < 7)  
    ave = (float) 2.3;  
  else if (ave >= 3 && ave < 4)  
    ave = (float) 2.0;  
  else
  {  
    ave = (float) 1.3;  
  }  
  return ave;  
}
​
​
personInfo_t user_info;
u8 WatchInfo_init(void)
{
  WatchInfo_setUserInfo(170,134); //設定身高、體重用於計算卡路里消耗
    return 0;  //初始化成功返回0
}
/**********************************************************************************************************
 * 函數名:        WatchInfo_setUserInfo
 * 功能描述:      設定手錶使用者的個人資訊
 * 引數說明:  
 * 返回值說明:
 * 修改記錄:
**********************************************************************************************************/
u8 WatchInfo_setUserInfo(u8 height,u8 weight)
{
    user_info.height = ((float)height)/100;
    user_info.weight = ((float)weight)/2;
  return 0;//成功 0
}
​
​
personInfo_t * WatchInfo_getUserInfo(u8 *error)
{
    u8 err;
    err = 0;//0表示獲取成功
    error = &err;
  return &user_info;
}

2.2 ESP8266 WIFI模組

裝置測量的資料最終通過WIFI傳遞給手機APP顯示,下面列出ESP8266的核心程式碼。

#include "esp8266.h"
extern u8  USART3_RX_BUF[USART3_MAX_RECV_LEN];      //接收緩衝,最大USART3_MAX_RECV_LEN位元組
extern u8  USART3_TX_BUF[USART3_MAX_SEND_LEN];      //傳送緩衝,最大USART3_MAX_SEND_LEN位元組
extern vu16 USART3_RX_STA;                                              //接收資料狀態
​
/// 
//使用者設定區
​
//連線埠號:8086,可自行修改為其他埠.
const u8 portnum[]="8089";       
​
//WIFI STA模式,設定要去連線的路由器無線引數,請根據你自己的路由器設定,自行修改.
const u8 wifista_ssid[]="wbyq1";            //路由器SSID號
const u8 wifista_encryption[]="wpa2_aes";   //wpa/wpa2 aes加密方式
const u8 wifista_password[]="123456789";    //連線密碼
​
//WIFI AP模式,模組對外的無線引數,可自行修改.
const u8 wifiap_ssid[]="Cortex_M3";           //對外SSID號
const u8 wifiap_encryption[]="wpawpa2_aes"; //wpa/wpa2 aes加密方式
const u8 wifiap_password[]="12345678";        //連線密碼 
​
​
/*
函數功能:向ESP82668266傳送命令
函數引數:
                cmd:傳送的命令字串
                ack:期待的應答結果,如果為空,則表示不需要等待應答
                waittime:等待時間(單位:10ms)
返 回 值:
                 0,傳送成功(得到了期待的應答結果)
         1,傳送失敗
*/
u8 ESP8266_SendCmd(u8 *cmd,u8 *ack,u16 waittime)
{
    u8 res=0; 
    USART3_RX_STA=0;
    UsartStringSend(USART3,cmd);//傳送命令
    if(ack&&waittime)       //需要等待應答
    {
        while(--waittime)   //等待倒計時
        {
            DelayMs(10);
            if(USART3_RX_STA&0X8000)//接收到期待的應答結果
            {
                if(ESP8266_CheckCmd(ack))
                {
                    res=0;
                    //printf("cmd->ack:%s,%s\r\n",cmd,(u8*)ack);
                    break;//得到有效資料 
                }
                USART3_RX_STA=0;
            } 
        }
        if(waittime==0)res=1; 
    }
    return res;
}
​
​
/*
函數功能:ESP8266傳送命令後,檢測接收到的應答
函數引數:str:期待的應答結果
返 回 值:0,沒有得到期待的應答結果
                 其他,期待應答結果的位置(str的位置)
*/
u8* ESP8266_CheckCmd(u8 *str)
{
    char *strx=0;
    if(USART3_RX_STA&0X8000)  //接收到一次資料了
    { 
        USART3_RX_BUF[USART3_RX_STA&0X7FFF]=0;//新增結束符
        strx=strstr((const char*)USART3_RX_BUF,(const char*)str); //查詢是否應答成功
        printf("RX=%s",USART3_RX_BUF);
    }
    return (u8*)strx;
}
​
/*
函數功能:向ESP8266傳送指定資料
函數引數:
                data:傳送的資料(不需要新增回車)
                ack:期待的應答結果,如果為空,則表示不需要等待應答
                waittime:等待時間(單位:10ms)
返 回 值:0,傳送成功(得到了期待的應答結果)luojian
*/
u8 ESP8266_SendData(u8 *data,u8 *ack,u16 waittime)
{
    u8 res=0; 
    USART3_RX_STA=0;
    UsartStringSend(USART3,data);//傳送資料
    if(ack&&waittime)       //需要等待應答
    {
        while(--waittime)   //等待倒計時
        {
            DelayMs(10);
            if(USART3_RX_STA&0X8000)//接收到期待的應答結果
            {
                if(ESP8266_CheckCmd(ack))break;//得到有效資料 
                USART3_RX_STA=0;
            } 
        }
        if(waittime==0)res=1; 
    }
    return res;
}
    
    
​
/*
函數功能:ESP8266退出透傳模式
返 回 值:0,退出成功;
         1,退出失敗
*/
u8 ESP8266_QuitTrans(void)
{
    while((USART3->SR&0X40)==0);    //等待傳送空
    USART3->DR='+';      
    DelayMs(15);                    //大於串列埠組幀時間(10ms)
    while((USART3->SR&0X40)==0);    //等待傳送空
    USART3->DR='+';      
    DelayMs(15);                    //大於串列埠組幀時間(10ms)
    while((USART3->SR&0X40)==0);    //等待傳送空
    USART3->DR='+';      
    DelayMs(500);                   //等待500ms
    return ESP8266_SendCmd("AT","OK",20);//退出透傳判斷.
}
​
​
/*
函數功能:獲取ESP82668266模組的AP+STA連線狀態
返 回 值:0,未連線;1,連線成功
*/
u8 ESP8266_ApStaCheck(void)
{
    if(ESP8266_QuitTrans())return 0;              //退出透傳 
    ESP8266_SendCmd("AT+CIPSTATUS",":",50); //傳送AT+CIPSTATUS指令,查詢連線狀態
    if(ESP8266_CheckCmd("+CIPSTATUS:0")&&
         ESP8266_CheckCmd("+CIPSTATUS:1")&&
         ESP8266_CheckCmd("+CIPSTATUS:2")&&
         ESP8266_CheckCmd("+CIPSTATUS:4"))
        return 0;
    else return 1;
}
​
​
/*
函數功能:獲取ESP8266模組的連線狀態
返 回 值:0,未連線;1,連線成功.
*/
u8 ESP8266_ConstaCheck(void)
{
    u8 *p;
    u8 res;
    if(ESP8266_QuitTrans())return 0;              //退出透傳 
    ESP8266_SendCmd("AT+CIPSTATUS",":",50); //傳送AT+CIPSTATUS指令,查詢連線狀態
    p=ESP8266_CheckCmd("+CIPSTATUS:"); 
    res=*p;                                                                 //得到連線狀態    
    return res;
}
​
/*
函數功能:獲取ip地址
函數引數:ipbuf:ip地址輸出快取區
*/
void ESP8266_GetWanip(u8* ipbuf)
{
      u8 *p,*p1;
        if(ESP8266_SendCmd("AT+CIFSR\r\n","OK",50))//獲取WAN IP地址失敗
        {
            ipbuf[0]=0;
            return;
        }       
        p=ESP8266_CheckCmd("\"");
        p1=(u8*)strstr((const char*)(p+1),"\"");
        *p1=0;
        sprintf((char*)ipbuf,"%s",p+1); 
}
​
/*
函數功能:將收到的AT指令應答資料返回給電腦串列埠
參    數:mode:0,不清零USART3_RX_STA;
                             1,清零USART3_RX_STA;
*/
void ESP8266_AtResponse(u8 mode)
{
    if(USART3_RX_STA&0X8000)        //接收到一次資料了
    { 
        USART3_RX_BUF[USART3_RX_STA&0X7FFF]=0;//新增結束符
        printf("%s",USART3_RX_BUF); //傳送到串列埠
        if(mode)USART3_RX_STA=0;
    } 
}
​
​
/*
函數功能:ESP8266 AP模式+TCP伺服器模式測試
*/
void ESP8266_APorServer(void)
{
    u8 p[100],key;
    u8 ipbuf[20];
//  u32 rlen=0; //接收長度
//  u32 constate,t=0;
    while(ESP8266_SendCmd("AT\r\n","OK",20))//檢查WIFI模組是否線上
    {
        ESP8266_QuitTrans();//退出透傳
        ESP8266_SendCmd("AT+CIPMODE=0\r\n","OK",200);  //關閉透傳模式 
        printf("未檢測到模組,正在嘗試連線模組...\r\n");
        DelayMs(800);
    }
    printf("ESP8266模組檢測OK!\r\n");
    
    while(ESP8266_SendCmd("ATE0\r\n","OK",20)); //關閉回顯
    
    printf("請用裝置連線WIFI熱點:%s,%s,%ss\r\n",(u8*)wifiap_ssid,(u8*)wifiap_encryption,(u8*)wifiap_password);
    
    /*1. 設定WIFI AP模式 */
    ESP8266_SendCmd("AT+CWMODE=2\r\n","OK",50);
    
    /*2. 重新啟動模組 */
    ESP8266_SendCmd("AT+RST\r\n","OK",20);
    
    /*3. 延時3S等待重新啟動成功*/
    DelayMs(1000);            
    DelayMs(1000);
    DelayMs(1000);
    
    /*5. 設定模組AP模式無線引數*/
    sprintf((char*)p,"AT+CWSAP=\"%s\",\"%s\",1,4\r\n",wifiap_ssid,wifiap_password); 
    ESP8266_SendCmd(p,"OK",1000);
    
    /*4. 設定多連線模式:0單連線,1多連線(伺服器模式必須開啟)*/
    ESP8266_SendCmd("AT+CIPMUX=1\r\n","OK",20); 
    
    /*5. 開啟Server模式(0,關閉;1,開啟),埠號為portnum */
    sprintf((char*)p,"AT+CIPSERVER=1,%s\r\n",(u8*)portnum);
    ESP8266_SendCmd(p,"OK",50);
    
    /*6. 獲取當前模組的IP*/
    ESP8266_GetWanip(ipbuf);//
    printf("IP地址:%s 埠:%s",ipbuf,(u8*)portnum);
  
    USART3_RX_STA=0; //清空串列埠的接收標誌位
//  while(1)
//  {
//      key=GetKeyVal(1);//退出測試
//      if(key==1)
//      { 
//      printf("退出測試!\r\n");            
//          ESP8266_QuitTrans();    //退出透傳
//          ESP8266_SendCmd("AT+CIPMODE=0","OK",20);   //關閉透傳模式
//          break;                                               
//      }
//      else if(key==2) //傳送資料 
//      {
//              ESP8266_SendCmd("AT+CIPSEND=0,12\r\n","OK",200); //設定傳送資料長度為12個
//              ESP8266_SendData("ESP8266測試!","OK",100);       //傳送指定長度的資料
//              DelayMs(200);
//      }
//      t++;
//      DelayMs(10);
//      if(USART3_RX_STA&0X8000)          //接收到一次資料了
//      { 
//          rlen=USART3_RX_STA&0X7FFF;  //得到本次接收到的資料長度
//          USART3_RX_BUF[rlen]=0;        //新增結束符 
//          printf("接收的資料: rlen=%d,%s",rlen,USART3_RX_BUF); //傳送到串列埠   
//          USART3_RX_STA=0;
//          if(constate!=3)t=1000;        //狀態為還未連線,立即更新連線狀態
//          else t=0;                   //狀態為已經連線了,10秒後再檢查
//      }
//      if(t==1000)//連續10秒鐘沒有收到任何資料,檢查連線是不是還存在.
//      {
            constate=ESP8266_ConstaCheck();//得到連線狀態
            if(!constate)printf("連線失敗!\r\n");
//          t=0;
//      }
//      if((t%20)==0)LED2=!LED2;
//      ESP8266_AtResponse(1);
//  }
}   

2.3 體溫檢測模組

體溫檢測模組是串列埠介面,傳送指令返回資料,程式碼如下:

#include "TEMPERATURE.H"
/*
傳送一個位元組
*/
void UsartSendByte(uint8_t data)
{
    USART2->DR=data;
      while(!(USART2->SR&(1<<7))){}
}
​
/*
溫度模組檢測初始化
*/
void TemPeratureInit(void)
{
    UsartInit(USART2,36,9600); //串列埠初始化
    DelayMs(2);            //延時啟動
    UsartSendByte(0xA5);
    UsartSendByte(0x45);   //傳送讀方位角指令
    UsartSendByte(0xEA);
}
u8 TEMP_data[20]={0},Receive_ok=0;
u8 tem_flag=0;
//讀取溫度資訊
void GetTemInfo(float *buff)
{
      u8 sum=0,i;
        if(Receive_ok)//串列埠接收完畢
        {
            for(sum=0,i=0;i<(TEMP_data[3]+4);i++)//TEMP_data[3]=4
            sum+=TEMP_data[i];
            if(sum==TEMP_data[i])//校驗和判斷
            {
                buff[0]=(float)((TEMP_data[4]<<8)|TEMP_data[5])/100;  //得到真實溫度
                buff[1]=(float)((TEMP_data[6]<<8)|TEMP_data[7])/100;  //得到真實溫度
                tem_flag=1;
           }
            Receive_ok=0;//處理資料完畢標誌
        }
}