您的位置:首页

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

2018-05-01 20:46 267 查看
这是我手环系列的第二篇,最近其他的事情比较多,更新比较慢,第一篇:灵感手环第一步——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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: