你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

[STM32WB55评测 ]蓝牙同步时间

[复制链接]
dvacos 发布时间:2023-7-27 22:45

本文是介绍如何接收手机发送的时间戳,解析后显示在OLED屏幕上。 本次我选择用IIC驱动0.91寸的OLED(分辨率128 * 32),来手机通过蓝牙发送的时间戳,解析后在OLED上当前显示时间。

1、驱动OLED屏幕

这种OLED屏幕是某宝最容易找到的屏幕之一,科普什么的,去百度,我就不赘述了。

屏幕的驱动IC是 SSD1306,所以我们驱动这块屏幕是控制主控把我们想要现实的内容按SSD1306能够识别的格式整理后,通过IIC发送给 SSD1306 ,接到数据后SSD1306会按照对应的格式解析 并 显示在屏幕上。

和大多数传感器一样我们需要初始化OLED屏幕,设定分辨率,左上角坐标、刷图方式等等,以下是我找到的初始化参数。 PS:注意每一款屏幕的初始化参数都是不一致的!!需要确认参数是否可用。

0xAE //--display off
0x40 //---set low column address
0xB0 //---set high column address
0xC8 //-not offset
0x81 // contract control
0xFF //--128
0xA1 //set segment remap
0xA6 //--normal / reverse
0xA8 //--set multiplex ratio(1 to 64)
0x1F
0xD3 //-set display offset
0x00
0xD5 //set osc division
0xF0
0xD9 //Set Pre-Charge Period
0x22
0xDA //set com pin configuartion
0x02
0xDB //set Vcomh
0x49
0x8D //set charge pump enable
0x14
0xAF //--turn on oled panel

具体代表什么,可用对照SSD1306的规格书,一一理解。

将以上的数据通过IIC正确发送数据后,就可以成功初始化屏幕了。下图是屏幕初始化成功的效果。

image.png

至此我们就验证了IIC 和 屏幕通讯正常,初始化正常后就移植gui代码,就可以显示任意数据了。 后续我会写文章一起讨论的,本次先跳过。

2、解析时间戳

C语言的标准库里有解析时间戳的函数,我们按照规范调用即可,有人应该会问时间戳是什么吧!

什么是时间戳?

Unix 时间戳是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒。 时间戳只表示1970年1月1日到当前的秒数,但是本地的时间通常不能直接时间戳来转化,除非你恰好在0时区。

我们初中地理就有学过时区概念,时区是为了按统一标准分区计时,将地球表面按经线分为24区。 每一时区的经度宽为15度,每区按中央子午线上的时间作为该区的标准时,具体实施中往往根据各国的行政区界或自然界线来确定。

中国使用东8区(中国幅员辽阔,跨越了多个时区,选择东8区作为统一时间,是应为北京在东8区),所以我们使用时间戳需要加上8小时的秒数(28,800),才能转化为本地时间!!

time 标准库

time.h 头文件定义了四个变量类型、两个宏和各种操作日期和时间的函数,其中我们要用到一个叫 tm 的结构体 和 localtime这个函数

tm 结构的定义如下:

struct tm {
   int tm_sec;         /* 秒,范围从 0 到 59        */
   int tm_min;         /* 分,范围从 0 到 59        */
   int tm_hour;        /* 小时,范围从 0 到 23        */
   int tm_mday;        /* 一月中的第几天,范围从 1 到 31    */
   int tm_mon;         /* 月,范围从 0 到 11        */
   int tm_year;        /* 自 1900 年起的年数        */
   int tm_wday;        /* 一周中的第几天,范围从 0 到 6    */
   int tm_yday;        /* 一年中的第几天,范围从 0 到 365    */
   int tm_isdst;       /* 夏令时                */
};

具体实现的代码如下:



struct tm *ts;
time_t now;
char str_time[80];

now=1688628481;
ts = localtime( &now );

sprintf(str_time,"%04d-%02d-%02d %02d:%02d:%02d",
            ts->tm_year+1900,
            ts->tm_mon+1, 
            ts->tm_mday,
            ts->tm_hour+8, //时区要加8
            ts->tm_min, 
            ts->tm_sec );

调用localtime解析时间戳后,赋值给ts这个结构体,然后再将得到的时间,拼接、处理后得到我们想要显示的数据!!

注意调用localtime转化出来的数据中的,年是当前年减去1900,月是当前月减去1,而且是0时区 的小时。所以年+1900,月+1,而且在东8区,还要把小时+8,这样处理后才是正常显示的中国本地时间。

3、接收手机下发的时间

结合前文 ,我们已经学会了使用蓝牙下发数据,并判断是什么数据,来控制点灯。在本文里我会使用手机下发时间戳,WB55接收后,将数据按照格式拼接起来,并且赋值给全局变量后显示在屏幕上,完成时间同步功能。

发送数据

不同设备之间的数据传输会涉及数据发送的大小端的问题,可以理解为顺序 和 逆序发送数据。 我写此文章时 时间戳是 1690176600 对应的北京时间是 2023-07-24 13:30:00。 对应的16进制数是64 BE 0C 58

接收数据

手机发送的数据都是U8的,所以我们需要把接收到的数据,拼接处理后,才能传参给localtime这个函数。

custom_stm.c


case ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE:
  /* USER CODE BEGIN EVT_BLUE_GATT_ATTRIBUTE_MODIFIED_BEGIN */

  /* USER CODE END EVT_BLUE_GATT_ATTRIBUTE_MODIFIED_BEGIN */
  attribute_modified = (aci_gatt_attribute_modified_event_rp0*)blecore_evt->data;
  if (attribute_modified->Attr_Handle == (CustomContext.CustomBle_Stm32Hdle + CHARACTERISTIC_VALUE_ATTRIBUTE_OFFSET))
  {
    return_value = SVCCTL_EvtAckFlowEnable;
    /* USER CODE BEGIN CUSTOM_STM_Service_1_Char_1_ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE */
    printf(" ----- %02x %02x %02x %02x -----\n",
              attribute_modified->Attr_Data[0],attribute_modified->Attr_Data[1],
              attribute_modified->Attr_Data[2],attribute_modified->Attr_Data[3]);
    extern uint32_t timestamp;

    timestamp=((uint32_t)attribute_modified->Attr_Data[0] << 24) |   
              ((uint32_t)attribute_modified->Attr_Data[1] << 16) | 
              ((uint32_t)attribute_modified->Attr_Data[2] << 8) | 
               ((uint32_t)attribute_modified->Attr_Data[3]);

      get_time(timestamp);

    /* USER CODE END CUSTOM_STM_Service_1_Char_1_ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE */
  } /* if (attribute_modified->Attr_Handle == (CustomContext.CustomBle_Stm32Hdle + CHARACTERISTIC_VALUE_ATTRIBUTE_OFFSET))*/
  /* USER CODE BEGIN EVT_BLUE_GATT_ATTRIBUTE_MODIFIED_END */

  /* USER CODE END EVT_BLUE_GATT_ATTRIBUTE_MODIFIED_END */
  break;

接收数据的LOG

image.png

细说处理数据

手机发送的数据都是U8的,所以我们需要把接收到的数据,拼接处理后

timestamp=((uint32_t)attribute_modified->Attr_Data[0] << 24)  |   
           ((uint32_t)attribute_modified->Attr_Data[1] << 16) | 
           ((uint32_t)attribute_modified->Attr_Data[2] << 8)  | 
           ((uint32_t)attribute_modified->Attr_Data[3]);

以上的代码是将接收到的U8强转成U32,然后左移之后,按照大端序拼接成一个U32的数据。

接收前后显示效果

image.png

image.png

视频效果

tutieshi_640x360_12s.gif

image.png
收藏 评论0 发布时间:2023-7-27 22:45

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版