亲爱的Dialog_Support,
我使用BLE外围作为我的项目的参考代码。BLE外围代码作为广告设备工作,但我想将其配置为扫描设备(中央)。现在,我已经做了以下变化,在现有的例子。
1.在user_config.h.
Static const struct gapm_configuration user_gapm_conf = {
///设备角色:中央、外围、观察者或广播者
。role = gap_central_mst,
struct scan_configuration {
/ / /操作的代码。
UINT8_T代码;
///自己的BD地址源
UINT8_T ADDR_SRC;
///扫描间隔
uint16_t间隔;
///扫描窗口大小
uint16_t窗口;
///扫描模式
uint8_t模式;
///扫描过滤策略
uint8_t filt_policy;
///扫描重复过滤策略
uint8_t filter_duplic;
};
Static const struct scan_configuration user_scan_conf ={
/ / /操作的代码。
.code = gapm_scan_passive,
///自己的BD地址源
.ddr_src = gapm_public_addr,
///扫描间隔
.Interval = 10,
///扫描窗口大小
.window = 5,
///扫描模式
.mode = GAP_GEN_DISCOVERY,
///扫描过滤策略
.filt_policy = scan_allow_adv_all,
///扫描重复过滤策略
.filter_duplic = SCAN_FILT_DUPLIC_EN
};
2.在user_callback_config.h.中
Static const struct app_callbacks user_app_callbacks = {
.app_on_connection = user_app_connection,
.app_on_disconnect = user_app_disconnect,
.app_on_update_params_rejected = null,
.app_on_update_params_complete =零,
.app_on_set_dev_config_complete = default_app_on_set_dev_config_complete,
.app_on_adv_nonconn_complete = null,
.app_on_adv_undirect_complete = user_app_adv_undirect_complete,
.app_on_adv_direct_complete =零,
.app_on_db_init_complete = default_app_on_db_init_complete,
.app_on_scanning_completed = user_on_scanning_Completed,
.app_on_adv_report_ind = user_on_adv_report_ind,
#if(ble_app_sec)
.app_on_pairing_request = null,
.app_on_tk_exch_nomitm = null,
.app_on_irk_exch =零,
.app_on_csrk_exch = null,
.app_on_ltk_exch =零,
.app_on_pairing_succeded =零,
.app_on_encrypt_ind =零,
.app_on_mitm_passcode_req = null,
.app_on_encrypt_req_ind = null,
.app_on_security_req_ind = null,
#endif //(ble_app_sec)
};
3.我在User_PeripherAl.c文件中添加了这些函数
void user_on_scanning_Completed(UINT8_T状态)
{
if(status == gap_err_canceled)
{
app_easy_gap_start_connection_to();
connection_timer = app_easy_timer(USER_CON_TIMEOUT, user_gapm_cancel);
}
其他的
{
user_scan_start();
}
返回;
}
静态孔隙user_scan_start(空白)
{
struct gapm_start_scan_cmd* cmd = KE_MSG_ALLOC(gapm_start_scan_cmd,
task_gapm,task_app,
gapm_start_scan_cmd);
cmd-> op.code = user_scan_conf.code;
cmd - > op。addr_src = user_scan_conf.addr_src;
cmd-> interval = user_scan_conf.interval;
cmd-> window = user_scan_conf.window;
cmd - >模式= user_scan_conf.mode;
cmd-> filt_policy = user_scan_conf.filt_policy;
cmd-> filter_duplic = user_scan_conf.filter_duplic;
//发送消息
ke_msg_send (cmd);
//我们现在是可连接的
ke_state_set(task_app,app_connectable);
}
我已经在受尊敬的文件中尝试了这些更改,但当我运行程序时,它进入nmi_handler.c。
我错过了什么?或者我做错了什么配置?请使用适当的步骤指导我配置BLE外设作为中央。
先谢谢你。
带着敬意,
Ruchi Patel.
嗨Ruchi Patel,
当设备准备开始(配置,设置并准备好)广告或扫描命令都从.default_operation_Adv,所以在那个挂钩中,您应该在准备好的情况下放置您想要的设备。所以我假设如果你在那个钩子中放置user_start_scan()函数而不是user_app_adv_start()你的设备将开始扫描过程。
谢谢mt_dialog.
谢谢你的建议。
我已经尝试过上述解决方案,但我仍然得到同样的问题。当我运行程序时,它进入nmi_handler.h。是我在user_config.h中完成的上述配置,user_callback_config.h和user_peripher.cl文件是正确的?您可以提供详细的解决方案或示例代码,展示中央功能。
带着敬意,
Ruchi Patel.
嗨Ruchi Patel,
用调试器检查user_scan_start()函数是否被触发也检查completion回调函数是否被触发你得到的错误代码是什么,如果它是一个GAP_ERROR_TIMEOUT,并且你在大约8秒的活动后得到它,这意味着你正在扫描,当你到达扫描过程的完成回调时,NMI被触发。关于你粘贴的文件和代码,我看不出有什么问题,你得到的NMI意味着代码停留在一个指令(这可能是WFI()在主循环中,如果你有睡眠禁用和BLE活动超过2.6秒,这是看门狗可以测量的最大时间)。就一个例子而言,我认为您已经熟悉了来自主机端的DSPS代码。
谢谢mt_dialog.
你好mt_dialog,
谢谢您的答复。现在我能够使用我的中央设备连接BLE_APP_PERITERAL。下一个任务是将来自中央设备的命令发送到BLE_APP_PERITELAL以切换LED。我可以使用自定义配置文件特征从中央设备发送命令,因为我们正在从BLE Scanner应用程序中进行?
带着敬意,
Ruchi Patel.
嗨Ruchi Patel,
与来自中央的自定义配置文件交互,需要在中央端实现,因为当设备连接时,中央应该启动发现过程,以便发现可用的服务和特征。当中心发现外围设备的特征后,就可以开始写和读数据,因为中心需要知道应该在外围设备上读或写的句柄。简而言之,是的,只要特征是可写的,你就可以把数据写到自定义特征中,但你必须实现中央的发现过程,然后你才能写数据。DSPS主机端实现了DSPS配置文件的发现过程,您可以将其作为参考。
谢谢mt_dialog.
感谢你的快速回复。
我需要实现自定义服务和特征的发现过程。关于发现程序,我还没有找到明确的步骤。我也经历过DSPS的例子,但由于它的复杂性,我不能正确地理解它。
1.您可以列出详细信息中发现程序的步骤吗?
2.在DSPS中,哪些文件发现的相关信息被提到了?
3.哪些功能对发现自定义服务和特征有用?
带着敬意,
Ruchi Patel.
嗨Ruchi Patel,
1.我不能提及的每一个细节发现过程在这个论坛上,您应该检查的BLE规范为了得到广泛的知识发现过程,我可以提几个关于这个过程的关键步骤,也给你一些代码片段在需求方的源代码。另外一个非常有用的文档是RW-BLE-GATT-IS.pdf,该文档包括为了完成发现过程而应该向堆栈发出和从堆栈发出的所有命令/响应。
谢谢mt_dialog.
你好Dialog_Support,
感谢客户端配置步骤。我跟着你的步骤,但我得到了错误。
1. \src\custom_profile\user_custs_config.c(47):错误:#29:预期表达式
struct attm_desc_128 custs1_att_db [cust1_idx_nb] = {};
Const struct cust_prf_func_callbacks cust_prf_funcs[] =
{
#如果(BLE_CUSTOM1_SERVER)
{TASK_CUSTS1,
custs1_att_db,
CUST1_IDX_NB,
#如果(BLE_APP_PRESENT)
app_custs1_create_db app_custs1_enable,
其他#
空,空,
# endif
custs1_init,零
},
# endif
#if(ble_custom2_server)
{TASK_CUSTS2,
空,
0,
#如果(BLE_APP_PRESENT)
app_custs2_create_db,app_custs2_enable,
其他#
空,空,
# endif
Custs2_init,null.
},
# endif
{task_none, null, 0, null, null, null}, //不移动。一定要在最后
};
我在user_custs_config.c中声明了上面的函数
在user_custs1_def.h中
extern struct attm_desc_128 custs1_att_db[CUST1_IDX_NB];
2.我应该写什么来代替#if (BLE_SPS_CLIENT)
带着敬意,
Ruchi Patel.
嗨Ruchi Patel,
1.显然,您已经在DSPS主机中放置了custs1.h include,以便包含自定义配置文件,而且您还没有声明任何作为数据库的内容,例如,检查ble_app_peripheral示例,并检查该数组中的内容。
2.我没有得到第二个问题,这只是一个定义,以便包括SPS客户端功能。
谢谢mt_dialog.
非常感谢你的步骤。这对我们帮助很大。久而久之,我能发现服务和特性。现在我的下一个任务是在客户端和服务器之间进行数据传输。请问是哪个定制功能启动数据传输程序?
感谢和问候,
Ruchi Patel.
嗨Ruchi Patel,
您的意思是,您希望执行从中心到外围设备的写入?您可以使用prf_gatt_write()命令的dsp实现例子,当然这个函数发送一个特定消息向堆栈GATTC_WRITE_CMD,,你将能够找到额外的信息在RW-BLE-GATT-IS.pdf支持网站。
谢谢mt_dialog.
嗨MT_Dialog,
是的,我想把数据从中心写入外设的特性。
正如您建议使用“prf_gatt_write()”命令,我在DSPS示例中检查了它。据我所知,有一个名为“sps_client_data_tx_req_handler”的特定处理程序,它使用“prf_gatt_write()”命令处理传输请求。因此,理想情况下,当Central发出写(data tx)请求时,应该调用该处理程序。但是,我不知道如何调用tx_req_handler。我究竟如何调用内置函数或编写自己的函数,它将调用“sps_client_data_tx_req_handler”?
感谢和问候,
Ruchi Patel.
嗨Ruchi Patel,
您看到的处理程序是DSP参考应用程序的实现,如果您想通过不调用直接函数调用,但通过发送消息并通过消息处理事件,您可以实现DSP项目的内容。当DSP希望发送数据时它实现名为SPS_CLIENT_DATA_TX_REQ的消息并将其发送到堆栈,然后将消息处理后,它触发相应的处理程序,SPS_CLIEND_DATA_TX_REQ消息通过user_send_ble_data()函数发送,以及处理程序通过该消息触发在SPS_CLIENT_CONNETed数组中的SPS_CLIENT_TASK.C文件中声明,您可以将其作为参考。
谢谢mt_dialog.
。
嗨mt_dialog,
最初我还考虑使用“user_send_ble_data()”函数通过BLE发送数据。这个函数需要数据和data_length作为参数。然后它将数据发送到一个预定的特征。但在我的情况下,我不想总是发送我的数据到一个固定的特征。
例如:
假设我有一个名为“cust_service_1”的自定义服务。在该服务中,我有一些自定义特征,如“LED_1_Brightness”,“LED_2_Brightness”等,它具有没有附加的响应属性。
现在,我想将0x57发送到“led_1_亮度”特性。
所以我想到的是一个简单的函数,它接受以下参数:
UINT8_T数据[1] = {0x57};
UINT8_T长度= 1;
void my_function_to_send_data(Service_Namecust_service_1,Charecteristic_NameLED_1_Brightness,Data_Value*数据,Data_Length长度);
因为"user_send_ble_data()"函数只接受数据,和数据长度;我如何确保我的数据被发送到我想要的正确的特征?如上例所示,我应该为服务名和特征名附加附加参数吗?或者是否有其他方法可以先在外部变量中设置服务和特征名,然后调用“user_send_ble_data()”函数,以便将数据发送到所需的特征?请帮我一下。
感谢和问候,
Ruchi Patel.
嗨Ruchi Patel,
如上所述,user_send_ble_data()是DSP使用的函数,它不是通用功能,以便将数据发送到服务上可用的任何特征。实际发送数据的处理程序是sps_client_data_tx_req_handler()和实际发送数据的函数是prf_gatt_write()。由于这是实际发送在另一侧数据的函数,因此这也是扭动数据将要发送的特征的句柄的函数。因此,通过使用相应的句柄参数调用prf_gatt_write()将更新正确的特征值。在DSP的情况下,sps_client_data_tx_req_handler始终使用的特征句柄是spsc_env-> sps.chars [spsc_srv_rx_data_char] .val_hdl。
谢谢mt_dialog.
嗨mt_dialog,
正如你在之前的评论中正确提到的,sps_client_data_tx_req_handler()是实际发送数据的函数。我想要一个简单的应用程序,用户按下按钮,它会触发中断例程。在中断例程内,我想调用sps_client_data_tx_req_handler()函数发送一些数据。该函数需要以下参数:
Static int sps_client_data_tx_req_handler(ke_msg_id_t const msgid,
Struct sps_client_data_tx_req const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
但是,我没有太多了解在每个参数中传递的内容,以便将我的数据发送到特定的特征。你能给我更多的洞察力吗?
感谢和问候,
Ruchi Patel.
嗨Ruchi Patel,
您可以添加额外的成员sps_client_data_tx_req结构并传递你想从这个成员的特点,所以当你分配一个sps_client_data_tx_req消息你也应该通过在请求你想执行的特点写,例如,当前结构有三个成员(conhdl、length和data),当消息在发送之前被分配时填充,所以添加一个额外的成员来保持您想要编写的特征。当调用sps_client_data_tx_req_handler()而不是prf_gatt_write()中的固定值时,您可以传递在sps_client_data_tx_req结构中添加的额外成员的值。
谢谢mt_dialog.
嗨MT_Dialog,
谢谢你的帮助。我成功地将数据写到一个特定的特征上。我使用了一个与你建议的稍微不同的方法,但既然它能起作用,我就不介意了。以下是我的项目的总结:
因此,我现在可以从1个BLE客户端发送数据到1个BLE外围设备。请注意,它们在整个会话中总是连接。
现在,我的项目只剩下最后一步了。有一个客户端(我正在处理),有4个外围设备。我有4个不同的用户输入按钮,根据按下的按钮,我想从我的BLE客户端发送数据到一个特定的BLE外围设备。下面是我现在要实现的示例流:
请注意,我不需要同时连接,我只需要连接到一个特定的设备,发送数据,然后断开。
我需要紧急实施这一点。所以我希望一个具体的详细解决方案。请帮忙..!!
提前致谢,
Ruchi Patel.
嗨Ruchi Patel,
您的用例是非常具体的,我无法在本论坛上留下或记录每种特定细节,请查看我的建议。
为了通过中央连接到外围设备,需要广告外设(需要广告,以便外围设备接收连接请求,仅用于扫描设备的中心,所以您将假设您的外围设备将在那里并发出没有扫描过程的连接请求,或者您也将扫描?我想您将要为您的设备使用公共地址,因为SPEG定义的静态地址,它们应该在每个重启外设的重新启动时更改,并且随机可解析需要与每个单独的设备绑定。所以假设您正在使用公共地址,并且据我所知,您的中央地址是有两个选项:
1)假设设备已全部存在,并且只要按下按钮,就无法从中中心扫描过程即可通过app_easy_gap_start_connection_to_set()和app_easy_gap_start_connection_to()发出连接以启动连接过程,但是再次您必须确保设备是广告,如果不是连接过程没有超时,如果没有人响应您必须通过您的应用程序超出过程。因此,一旦设备连接,发现过程将启动,并且设备将在连接时执行任何操作。当数据交换后,您可以调用app_easy_gap_disconnect()才能断开来自中央的外设和当发生的双连接时禁用并清理配置文件结构(取决于您的自定义配置文件的方式)。可以通过外围设备或中心发出断开连接请求。
2)关于第二个选项,您可以按下按钮并存储在全局变量中,您想要连接的相应的BD地址,因此当扫描过程返回指示标准的特定地址时,您可以发出连接请求。除了所有的剩余部分都保持不变。
谢谢mt_dialog.
嗨mt_dialog,
我的终极目标是设计一个可编程BLE远程用于控制多个调光灯。因此,遥控器最初保留在外围模式中并与Android应用程序连接。那么该应用程序将判断哪个按钮应该做哪些功能。BLE遥控器仅仍然存在于外围模式。但是一旦用户按下按钮,让我们说按钮-1,它执行以下操作:
我还没有弄清楚如何在运行时进行角色切换。所以目前,我的可编程BLE遥控器一直处于中心模式。
要在按钮上按下我的BLE遥控器上的DIMMER,我写了以下代码:
BOOL GBOOLD1CONNECT = FALSE;
空白user_button_pressed(空白)
{
gboolD1Connect = true;
// user_on_adv_report_ind(param-> rapth.adv_addr_type:0x01);
if (dimmer1_connected == true) //只有在整个连接过程完成后才为true
{
uint8_t my_data [1];
my_data [0] = 0x14;//亮度值
uint16_t my_length;
my_length = 1;
//该函数将数据从switch发送到dimmer
prf_gatt_write(con_info, val_hdl, (uint8_t *)my_data, sizeof(uint8_t) * my_length, GATTC_WRITE);
}
}
//这是Inbuilt函数,我已修改,以便在Gboold1Connect为真时才能连接到Dimmer-1
void user_on_adv_report_ind(struct gapm_adv_report_ind const * param)
{
if(gboold1connect)
{
if(!memcmp(&param-> report.data [3],user_advertise_data,user_advertise_data_len)))
{
arch_printf("Connect with %02x %02x %02x %02x",
param-> eport.adddr.addr [5],
param-> eport.addr.addr [4],
param-> eport.adddr.addr [3],
param-> eport.adddr.addr [2],
param - > report.adv_addr.addr [1],
param-> report.adddr.addr [0]);
app_easy_gap_start_connection_to_set(param-> rapth.adv_addr_type,(uint8_t *)&param-> report.adv_ddr.addr,ms_to_doubleslots(12.5));
user_gapm_cancel();
}
}
}
上面的实现可以工作,但它有一个问题。当我第一次按下遥控器的按钮,它将设置gboolD1Connect为true然后退出功能,因为dimmer1_connection.还不是真的。之后,在后台,当user_on_adv_report_ind()运行时,它会连接到调光器-1。一旦连接完成,所有的服务、特征和描述符都将被发现。最后,就在描述符发现完成之后,我在内建函数中又插入了一行dimmer1_connected = true。整个过程需要2-3秒。所以3秒后,当我再次按下按钮时,它最终会进入dimmer1_connected = = true部分并发送亮度值。所以你可以看到,我必须按两次按钮(第一个连接,2nd用于发送数据),以便能够发送数据。每当我提供连接到调光器设备的命令时,会出现此问题(通过制作gboolD1Connect为真,或使用app_easy_gap_start_connection_to_set()功能),我必须退出中断例程并允许主程序运行,以便发生实际连接。但由于我退出了我的中断例程,我将如何重新输入它并在连接外围设备时发送数据?
所以我有两个需要帮助的问题:
提前感谢你的帮助,
Ruchi Patel.
嗨,前腿,
我是否可以建议您查看一下CodeLess示例应用程序(https://support.dialog-semiconductor.com/connectivity/reference-design/smartbond-codeless-serial-link).
这个应用程序演示了中心设备和外围设备的各个方面,以及如何在角色之间进行切换。
/ MHv
嗨MHv,
你提出的建议非常好,我很高兴能继续执行。但是看了文档后,我明白实现它需要做两件主要的事情:
(1) DA1458x BLE模块与AT命令固件
(2)第三方微控制器来控制BLE模块
但在我的情况下,我在单个芯片上只有一个DA1458x BLE模块。我没有特权在同一芯片上添加另一个第三方控制器以控制BLE模块。
我希望我的DA1458X BLE模块具有固件,然后逻辑调用AT命令本身的序列以独立方式运行。
那么,是否可以在不需要终端、android app或第三方控制器等外部控制机制的情况下实现AT命令方法呢?
谢谢,
Ruchi Patel.
嗨,前腿,
实施应该只用于如何完成不同的东西的指导。通过运行代码,使用调试器,通过各种命令汇总,您将能够遵循似理的复杂任务。这里有一些例子:
CodeLess实现使用AT命令来触发不同的操作,但是应该可以编写自己的逻辑来驱动相同的功能(您可能只需要将适用的代码片段从CodeLess复制到您的项目中)
/ MHv
我无法发现特征,但我可以发现服务,我的项目BLE_APP_PERITERAL
你能告诉我怎样发现特征吗?
非常感谢!
嗨Chenpenglai,
这个论坛线程很古老,所以我建议你创造一个新的。如果您不知道您应该遵循的程序以创建新的论坛线程,请告诉我,我将为您提供所有步骤。所以请创建一个新的论坛帖子和复制你的问题。
关于您的问题,您使用的是哪个版本的SDK?您是否在SDK的BLE_APP_PHERIALLAL示例中进行了任何修改?
谢谢,PM_DIALOG.