当我从GPIO中断中唤醒时,我想更改UUID的最后一个字节,以指示是哪个GPIO唤醒了它。使用beacon_v_5.40.2_0项目,我声明回调函数如下:
空白tilt_wakeup_cb(空白)
{
if(GetBits16(系统状态寄存器,PER向下))
{
//从外部唤醒GPIO返回GPIO功能
如果(DEVELOPMENT_DEBUG)
GPIO_保留();
periph_init ();
}
倾斜上升标志=1;
用户_广告_操作();
}
这是允许的吗?
我计划使用一个标志来确定设备是被GPIO中断唤醒还是从其计时器唤醒,基于此信息,我计划编辑用户\u update\u ibeacon\u adv\u字符串,如下所示:
无效用户\u更新\u ibeacon\u adv\u字符串(结构用户\u i\u信标\u配置\u标记*数据,结构用户\u信标\u配置\u标记配置)
{
.......
//添加DL
if(倾斜\上升\标志){
如果(!GPIO_GetPinStatus (GPIO_PORT_2 GPIO_PIN_0)) {
数据->uuid[15]=1;
}否则如果(!GPIO_GetPinStatus(GPIO_端口_2,GPIO_引脚_1)){
数据- > uuid [15] = 2;
}否则如果(!GPIO_GetPinStatus(GPIO_端口_2,GPIO_引脚_2)){
数据- > uuid [15] = 3;
}否则如果(!GPIO_GetPinStatus(GPIO_端口_2,GPIO_引脚_3)){
数据- > uuid [15] = 4;
} else if (!GPIO_GetPinStatus (GPIO_PORT_2 GPIO_PIN_4)) {
数据->uuid[15]=5;
} else if (!GPIO_GetPinStatus (GPIO_PORT_2 GPIO_PIN_5)) {
数据- > uuid [15] = 6;
}
tilt_wk_flag = 0;
}否则{
数据->uuid[15]=0;
}
//
.....
}
在测试这段代码时,当GPIO被拉低以强制唤醒时,似乎没有做任何事情。
在user_on_init ()
我在函数中添加了以下内容:
wkupct_寄存器_回调(倾斜_唤醒_cb);
x3f0000 x3f0000 wkupct_enable_irq (0, 0, 0);//开启P2_0到P2_5的中断
我修改回调如下,但似乎仍然不工作。使用Jlink跟踪,我可以看到它进入回调函数,但它没有发布新的UUID:
嗨,迪奥,
您只需对此进行调试,如果发生唤醒中断,您可以在用户\u update\u ibeacon\u adv\u string()中放置一个断点,并检查代码是否通过该函数,以及是否满足更改播发字符串的条件。
由于MT_dialog
调用user_advertise_operation()应该没有问题;在回调函数中?收音机和其他东西都应该开着,而且在按我的方式安装时应该做广告?
只是确保我没有违反一些规则,我们不能在从GPIO中断中醒来后立即发布广告。
谢谢
嗯,不建议直接从唤醒开始广告操作。虽然这应该可以工作,但在ble_app_sleemode中可以找到启动操作的正确方法。请检查app_按钮\u press_cb(),但即使不按此操作,您的设备也应该能够启动广告。例如,如果您调用用户\u app_adv_start()(我想这与您实现的用户_advertive_操作相同)直接从app_按钮按_cb()并移除设备将要发布的app_easy_wakeup()。但是使用app_easy_wakeup()API的建议方法是。
由于MT_dialog
当没有GPIO中断发生,并且设备在时间间隔内唤醒时,我手机上的信标扫描应用程序会显示所有广告事件。
当GPIO中断确实发生时,单步执行代码,代码似乎做了它应该做的事情,但我从未在scanner应用程序中看到正确的值。。。
不知为何,我认为在这种情况下,数据并没有被大肆宣传。app_easy_gap_non_connectable_advertise_start()用于这两个场景。对于GPIO中断情况,我将cmd->intv_min和cmd->intv_max更改为0。或者把这两个空着,都没有运气。
这是代码。
嗨dlo,
如果代码执行了它应该执行的操作,并且您得到了中断和您想要的数据,并且您看到设备仍在进行广告,但是使用了旧值,那么您在广告字符串中放置数据的方式应该有问题。在使用新值更新广告字符串之后,我假设您停止广告,使用新值更新广告字符串,然后使用user_advertive_操作重新启动广告。调用app_easy_gap_non_connectable_advision_get_active()函数,让SDK填充新消息,然后在广告字符串中添加自定义数据,要调试它,您可以在代码中一步一步地进行,并检查携带播发命令的cmd指针是否在代码中的某个点包含您要放置的播发数据(检查cmd->host.adv_数据数组,并检查您的数据是否附加在此数组中)。
由于MT_dialog
所以我测试了你的建议,发现了一些奇怪的行为。
当使用定时器唤醒间隔并禁用wkupct时,会在user_update_ibeacon_adv_string中轮询GPIO,并相应地更新UUID的最后一个字节。我可以在扫描程序中看到这些变化,一切正常运行。
然后,我通过以下方式启用wkupct:
wkupct_寄存器_回调(倾斜_唤醒_cb);
x3f0000 x3f0000 wkupct_enable_irq (0, 0, 0);//开启P2_0到P2_5的中断
在此之后,我在scanner应用程序中再也看不到UUID更改的最后一个字节。由于更新播发字符串和播发使用了相同的代码,我假设这两个函数工作正常。现在来了解为什么启用wkupct和调用用户_Advertision_操作不再正常工作。
我试图跟踪cmd->info->host->adv_数据,但没有一个值与UUID或任何可识别的内容匹配。
代码只使用对话框代码user_advertise_operation();没有任何修改。
我修改了对话框提供的代码user_update_ibeacon_adv_string
无效用户\u更新\u ibeacon\u adv\u字符串(结构用户\u i\u信标\u配置\u标记*数据,结构用户\u信标\u配置\u标记配置)
{
memcpy(数据- > adv_header ADV_HEADER_iBEACON 2);
数据->公司亚博全网id[0]=(uint8\u t)(配置公司id&0xff);
Data -亚博全网>company_id[1] = (uint8_t) (config.company_id>>8);
数据->数据类型=iBEACON数据类型;
数据- > beacon_length = ADV_DATA_LENGTH;
memcpy(数据- > uuid,配置。uuid, 16);
//添加DL
if(倾斜\上升\标志){
如果(!GPIO_GetPinStatus (GPIO_PORT_2 GPIO_PIN_0)) {
数据->uuid[15]=1;
}否则如果(!GPIO_GetPinStatus(GPIO_端口_2,GPIO_引脚_1)){
数据- > uuid [15] = 2;
}否则如果(!GPIO_GetPinStatus(GPIO_端口_2,GPIO_引脚_2)){
数据- > uuid [15] = 3;
}否则如果(!GPIO_GetPinStatus(GPIO_端口_2,GPIO_引脚_3)){
数据- > uuid [15] = 4;
} else if (!GPIO_GetPinStatus (GPIO_PORT_2 GPIO_PIN_4)) {
数据->uuid[15]=5;
} else if (!GPIO_GetPinStatus (GPIO_PORT_2 GPIO_PIN_5)) {
数据- > uuid [15] = 6;
}
tilt_wkup_flag = 0;
}否则{
数据->uuid[15]=0;
}
//
数据->发送功率=配置功率;
}
编写wkupct回调:
空白tilt_wakeup_cb(空白)
{
if(GetBits16(系统状态寄存器,PER向下))
{
//从外部唤醒GPIO返回GPIO功能
如果(DEVELOPMENT_DEBUG)
GPIO_保留();
periph_init ();
}
如果(arch_ble_ext_wakeup_get ())
{
arch_set_sleep_mode (app_default_sleep_mode);//设置默认休眠模式
arch_ble_force_wakeup ();//强制BLE唤醒
arch_ble_ext_wakeup_off();//禁用外部唤醒
}
倾斜上升标志=1;
用户_广告_操作();
wkupct_enable_irq(0x003F0000,0x003F0000,1,0);//为P2_0到P2_5启用中断
}
感谢您一直以来的支持!
找到了更多的信息。
我在tilt_wakeup_cb()中删除了对用户_Advertision_operation()的调用,现在在scanner应用程序中看到了预期的更改。问题是,它最终会在大约5-10个广告间隔后被记录下来。(我将广告间隔设置为5秒,在gpio拉低后大约55秒收到更改的数据包)。
这似乎表明,在将实际事件放入队列之前,需要清除广告数据缓冲区?这似乎正确吗?
你说我应该停止广告,更新广告字符串,然后重新开始广告。如果我这样做,我的解释正确吗?
app_easy_gap_advertise_stop();
用户_广告_操作();
user_advertise_operation()的代码;是默认的对话框1:
作废用户\广告\操作(作废)
{
结构gapm\u start\u advision\u cmd*cmd;
current_advertising_string = next_advertising_string;
当前广告模式=下一个广告模式;
if(当前广告模式==不可连接模式)
{
//获取指向BLE数据包的指针
cmd=app_easy_gap_non_connectable_advertive_get_active();
user_adv_restarted=true;
cmd->info.host.adv\u data\u len=user\u load\u beacon\u config(cmd);
//开始宣传不可连接的外围设备。
if(APP_CONNECTED==ke_state_get(TASK_APP))
{
//不要在连接状态下播发不可连接的播发
}
其他的
{
if(用户\闪烁\信标\配置\加载)
{
cmd - > intv_min = MS_TO_BLESLOTS (user_beacon_config.adv_int);
cmd - > intv_max = MS_TO_BLESLOTS (user_beacon_config.adv_int);
}
app_easy_gap_non_connectable_advertise_start ();
}
}
else if(当前广告模式==无向广告模式)
{
//获取指向BLE数据包的指针
cmd = app_easy_gap_undirected_advertise_get_active ();
user_adv_restarted=true;
cmd->info.host.adv\u data\u len=user\u load\u beacon\u config(cmd);
if (current_advertising_string == SUOTA_ADVERTISING_STRING)
{
更新广告数据(用户发布广告,用户发布广告);
用户\更新\广告\字符串(cmd,(void*)动态\广告\字符串、SUOTA \广告\字符串、用户\广告\ SUOTA \ LEN);
}
//开始为无向外围设备做广告。
app_easy_gap_undirected_advertized_start();
}
}
关于我要做的事情的背景,如果可能的话请告诉我。
当GPIO2_0变低时,我想发送UUID以0结尾的广告。手机应用程序将记录它收到广告的时间。当另一个GPIO变低时,比如说GPIO2_1,我想发送UUID以1结尾的广告。手机将记录它收到广告的时间,并计算两者之间的时间差两个广告。时间差对我如何处理数据至关重要。这是实现这一目标的可靠方法吗?还是存在某种类型的限制,不允许我实现这一目标?
再次感谢您一直以来的支持。
嗨dlo,
关于更新580上的广告字符串,为了正确地停止、更新广告字符串并再次开始广告,您必须发出停止命令,然后等待堆栈回复广告确实已停止(SDK将通知您,广告已停止,无向广告的应用程序已完成,对于不可连接的广告,还有相应的回调-请检查裸体示例,以获得比信标更简单的参考)。因此,当堆栈通知您播发已完成且发生回调时,您可以从该回调调用将要更新的新播发字符串的开始。您不能调用停止播发,然后立即调用函数以开始。我想这是您的主要问题。
关于你正在尝试实现什么和计时两个广告数据之间的差异,请注意,广告不是一个可靠的方式发送数据,这意味着没有保证你将发送的数据将在特定的时间到达扫描仪,由于其他广告设备和协议之间会有冲突,在一般情况下,对平均值的干扰,所以在广告过程中,没有保证无论外设将发送什么,扫描仪将最确定地接收。所以请注意这一点。
由于MT_dialog
感谢您的持续支持。我尝试在barebone项目中实现该示例,但它似乎仍然不起作用。我不知道还可以尝试什么,但由于您提到无法保证数据到达扫描仪,我们需要找到其他解决方案。
嗨dlo,
是的,由于拥挤的平均值、范围或噪声,无法保证广告字符串将到达中心,协议没有一种机制使中心确认接收到emmited广告字符串的外围设备,这仅在连接期间发生。
由于MT_dialog