灵感手环---蓝牙校准时间

时间:2024-01-22 21:35:53

这是我手环系列的第二篇,最近其他的事情比较多,更新比较慢,第一篇:灵感手环第一步——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