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


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

  • 相关阅读:
    非线性数据结构——树
    排序算法之插入排序
    web框架之environment处理
    web开发之http和wsgi
    python os模块和shutil模块
    python路径操作
    stringIO和bytesIO
    python文件操作
    设计模式
    设计模式
  • 原文地址:https://www.cnblogs.com/qsyll0916/p/8977364.html
Copyright © 2020-2023  润新知