这是我手环系列的第二篇,最近其他的事情比较多,更新比较慢,第一篇:灵感手环第一步——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”来作为结束。
这样可以将时间校准的数据包与其他命令或者区分开来。
![](/qrcode.jpg)
也就是说,当串口检测到这样的特定格式的数据包的时候,就认为是开始了时间校准,
这里需要注意一点就是,串口每发送或者接收一个字节,就是一个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。