1. 程式人生 > >靈感手環---藍牙校準時間

靈感手環---藍牙校準時間

clas receive pre 2.0 精確 撤銷 com mem OS

這是我手環系列的第二篇,最近其他的事情比較多,更新比較慢,第一篇:靈感手環第一步——0.96寸OLED顯示實驗

既然是手環,那麽時間的準確性就是所有的前提,不然就不能稱之為手環了。

之前采用DS1302芯片來作為計時模塊,但是這個芯片走時不是很準確,一天大概能走快30秒的樣子。我覺得這個很不精確。

但是高精度的時鐘模塊價格比較昂貴,所以想到利用手環上面的藍牙模塊來進行時間校準。

1、思路:

手機客戶端連接手環的藍牙,點擊校準時間按鈕,手機向手環發送手機上面獲取的時間,手環接收到時間後,按照一定的時間格式,寫入DS1302。這樣就完成了一次時間校準。

2、具體實現步驟:

主要是手環上面藍牙串口接收到時間格式 後的處理程序。

首先是串口的中斷接收函數:

     /*接受,在這裏接收藍牙發送過來的校準時間*/
    if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)    //讀取接收中斷標誌位USART_IT_RXNE 
    {
        USART_ClearITPendingBit(USART1,USART_IT_RXNE);    //清楚中斷標誌位
        
        Rx_Buffer[Rx_Counter++] = USART_ReceiveData(USART1);//接收數據到緩沖區,這個函數會自動清除中斷標誌位

在清除中斷標誌之後,循環接收藍牙串口發送過來的數據。

在接收完數據之後就是對接收的數據包進行處理:

        //檢測到這個固定長度固定格式的數據包,就認為是校準的時間,要求手機發送固定格式的時間數據包:秒 分 時 日 月 周 年
        //例如:{12.12.12.05.01.07.18.T}
        else if(Rx_Counter == 22 && Rx_Buffer[Rx_Counter-1] == T)
        {
            for(i=0; i<Rx_Counter-1; i+=3)
            {
                //數字的ascii碼,十進制0為48,乘16是因為他會以16進制存儲。
temp[j] = (Rx_Buffer[i] - 48)*16 + (Rx_Buffer[i+1] - 48) ; j++; } memcpy(init_time,temp,j); init_time[j] = \0; Rx_Counter = 0; adjust_real_time_flag = 1; //置標誌,在主循環裏面檢測,決定是否校準時間 printf("Time have adjusted."); }

因為事先我們先自己確定發送時間數據的格式,我這裏裏選擇的方式是以一個點為分隔,每個數據都是兩位數,這樣比較方便我後面的處理。最後以一個大寫的“T”來作為結束。

這樣可以將時間校準的數據包與其他命令或者區分開來。

也就是說,當串口檢測到這樣的特定格式的數據包的時候,就認為是開始了時間校準,

這裏需要註意一點就是,串口每發送或者接收一個字節,就是一個char,就進入串口中斷一次,也就是說,串口是單字節發送接收模式。

那麽我們發送的時間數據就被串口接收成了單個字符單個字符(其值為本身的ASCII值),比如下面的數組B被接收成了數組A:

技術分享圖片

這時,為了還原回我們需要的數值,需要代入字符的ASCII碼值。數字的ASCII碼都比自身數值大48,而在減去48的基礎上乘16是因為在stm32內部,

數值都是16進制表示的。先乘上16,後面處理器進行轉換的時候,就是原始數值了。

既然是校準時間,我們就可以隨時的進行校準,那麽就需要在程序的主循環內部加上一個校準時間的標誌。當標誌被置位時,就進行時間的寫入,否則不進行操作。

那麽在主函數的while內部加上如下代碼:

        //檢測是否需要校準時間
        if(adjust_real_time_flag != 0)
        {
            adjust_real_time_flag = 0;
            adjust_real_time();            //調用函數向DS1302寫入校準後的時間
        }

其中,adjust_real_time()函數為:

/*----------------------------------
**函數名稱:adjust_real_time
**功能描述:在主函數中調用,當藍牙發來時間,調用這個函數進行寫入、
**參數說明:無
**作者:Andrew
**日期:2018.5.1
-----------------------------------*/
void adjust_real_time(void)
{
    unsigned char i;    
    
    DS1302_WriteData(7,0x00); //撤銷寫保護,允許寫入數據,0x8e,0x00
    
    for(i = 0;i<7;i++)
    {
        DS1302_WriteData(i,init_time[i]); 
    }
    
    DS1302_WriteData(7,0x80);//打開寫保護功能,防止復位時時間被重置
}

到這裏,再加上之前的代碼,就能實現基於藍牙的自動校準時間。不用在校準時間的時候修改代碼了重新燒錄了。

3、目前的問題:

暫時是利用手機上面的藍牙串口APP來進行通信的,還沒有寫手機上面專門用來校準時間的APP。

4、參考資料

藍牙配置:http://blog.csdn.net/ylzmm/article/details/79138801

靈感手環---藍牙校準時間