亲爱的Dialog_Support,
我使用BLE外围设备作为我的项目的参考代码。BLE外设代码作为广告设备工作,但我想将其配置为扫描设备(中央)。现在我已经在现有的例子中做了以下更改。
1.在user_config.h
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;
};
user_scan_conf ={
///操作代码。
.code = GAPM_SCAN_PASSIVE,
///设备自己的BD地址源
.addr_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
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 = NULL,
.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 = NULL,
.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,
#如果(BLE_APP_SEC)
.app_on_pair = NULL,
.app_on_tk_exch_nomitm = NULL,
.app_on_irk_exch = NULL
.app_on_csrk_exch = NULL,
.app_on_ltk_exch = NULL,
. app_on_pairing_succeeded = NULL
.app_on_encrypt_ind = NULL,
.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文件中添加了这些函数
无效user_on_scanning_completed (uint8_t status)
{
if(status == gap_err_cancelled)
{
app_easy_gap_start_connection_to ();
connection_timer = app_easy_timer(USER_CON_TIMEOUT, user_gapm_cancel);
}
其他的
{
user_scan_start ();
}
返回;
}
静态void user_scan_start(void)
{
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 ->窗口= user_scan_conf.窗口;
Cmd ->mode = 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外围设备作为中心。
提前谢谢你。
与问候,
前腿帕特尔
嗨,鲁奇·帕特尔,
当设备准备好启动(配置、设置并准备好运行)时,从.default_operation_adv获取广告或扫描命令,因此在该钩子中,您应该放置任何您希望设备在准备好运行时执行的操作。因此,我假设如果您在该钩子中放置user_start_scan()函数而不是user_app_adv_start(),您的设备将启动扫描过程。
由于MT_dialog
谢谢你的建议。
我已经尝试了上面的解决方案,但我仍然得到同样的问题。当我运行程序时,它进入nmi_handler.h。我在user_config.h, user_callback_config.h和user_peripheral.c文件中所做的上述配置是否正确?你能提供一个详细的解决方案或示例代码演示中心功能。
与问候,
前腿帕特尔
嗨,鲁奇·帕特尔,
用调试器检查user_scan_start()函数是否被触发,如果它被触发,也检查完成回调,你得到的错误代码是什么,如果它是一个GAP_ERROR_TIMEOUT,你在大约8秒的活动后得到它,这意味着你正在扫描,当你到达扫描过程的完成回调时,NMI被触发。关于你粘贴的文件和代码,我看不出它们有什么问题,你得到的NMI意味着代码在相当长一段时间内停留在指令中(如果你禁用睡眠并且没有BLE活动超过2.6秒,则可能是主循环中的WFI(),这是watchdog可以测量的最大时间)。就示例而言,我认为您已经从主机端熟悉了dsp代码。
由于MT_dialog
你好MT_Dialog,
谢谢你的回复。现在我可以将ble_app_peripheral与我的中心设备连接起来。下一个任务是从中央设备向ble_app_peripheral发送命令以切换LED。我可以使用自定义配置文件特性从中央设备发送命令到ble_app_peripheral,因为我们正在从BLE扫描仪应用程序中做?
与问候,
前腿帕特尔
嗨,鲁奇·帕特尔,
与来自中心的自定义概要文件进行交互需要在中心端实现,因为当设备连接时,中心应该启动发现过程以发现可用的服务和特征。在中央服务器发现外围端的特征之后,它就可以开始读写数据,因为中央服务器需要知道应该在外围端的读写哪些句柄。简而言之,只要特征是可写的,就可以将数据写入自定义特征,但必须执行中央侧的发现程序,然后才能写入数据。DSPS主机端实现了DSPS配置文件的发现过程,可以作为参考。
由于MT_dialog
感谢您的快速回复。
我需要实现定制服务和特征的发现过程。我还没有找到关于取证程序的明确步骤。我也通过了dsp的例子,但由于它的复杂性,我不能正确地理解它。
1.你能详细列出取证程序的步骤吗?
2.参考DSPS,哪些文件发现的相关信息被提及?
3.哪些功能对发现自定义服务和特征有用?
与问候,
前腿帕特尔
嗨,鲁奇·帕特尔,
1.我不能在这个论坛上提到发现过程的每一个细节,你应该检查BLE规范,以便获得发现过程的广泛知识,我可以提到关于这个过程的几个关键步骤,并在dsp源代码中给你一些代码片段,以便遵循。还有一个非常有用的文档是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] = {};
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
#如果(BLE_CUSTOM2_SERVER)
{TASK_CUSTS2,
空,
0,
#如果(BLE_APP_PRESENT)
app_custs2_create_db app_custs2_enable,
其他#
空,空,
# endif
custs2_init,零
},
# 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)
与问候,
前腿帕特尔
嗨,鲁奇·帕特尔,
1.显然,您已经在dsp主机中放置了custs1.h包含,以便包含自定义配置文件,并且您没有声明任何内容作为数据库,例如检查ble_app_peripheral示例并检查该数组内的内容。
2.我不明白第二个问题,这只是为了包含SPS客户端功能而定义的。
由于MT_dialog
非常感谢你的步骤。这对我们帮助很大。经过很长一段时间,我能够发现服务和特点。现在我的下一个任务是客户机和服务器之间的数据传输。请问是哪个自定义函数启动数据传输程序?
谢谢你,
前腿帕特尔
嗨,鲁奇·帕特尔,
您的意思是,您希望执行从中央到外设特征的写操作?您可以使用dsp示例实现的prf_gatt_write()命令,当然该函数会向堆栈发送一个特定的消息,即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提出写(数据发送)请求,就应该调用该处理程序。但是,我不明白如何调用tx_req_handler。我究竟如何调用内置函数或编写自己的函数,这将调用“sps_client_data_tx_req_handler”?
谢谢你,
前腿帕特尔
嗨,鲁奇·帕特尔,
您看到的处理程序是DSPS参考应用程序的实现,如果您希望通过不调用直接函数调用,而是通过发送消息并通过消息处理事件来触发写入事件,则可以实现类似于DSPS项目的东西。当dsp希望发送数据时,它实现一个名为SPS_CLIENT_DATA_TX_REQ的消息并将其发送到堆栈,然后堆栈一旦处理该消息就触发相应的处理程序,SPS_CLIENT_DATA_TX_REQ消息通过user_send_ble_data()函数发送,由该消息触发的处理程序在sps_client_connected数组中的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_Brightness”特征。
所以我想到的是一个简单的函数,它接受以下参数:
Uint8_t data[1] = {0x57};
Uint8_t = 1;
my_function_to_send_data ()Service_NameCust_Service_1,Charecteristic_NameLED_1_Brightness,Data_Value*数据,Data_Length长度);
由于"user_send_ble_data()"函数只接受Data和Data Length;我如何确保我的数据被发送到我想要的正确特征?我是否应该像上面的示例那样为服务名称和特征名称附加额外的参数?或者是否有其他方法可以首先在外部的某个变量中设置服务和特征名称,然后调用“user_send_ble_data()”函数,从而将数据发送到所需的特征?请帮我一下。
谢谢你,
前腿帕特尔
嗨,鲁奇·帕特尔,
如上所述,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 ()函数发送一些数据。该函数需要以下参数:
静态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)
但是,我不太清楚在每个参数中传递什么以便将我的数据发送到特定的特征。你能给我更多的见解吗?
谢谢你,
前腿帕特尔
嗨,鲁奇·帕特尔,
你可以在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外设发送数据。请注意,它们在整个会话过程中始终处于连接状态。
现在,我的项目只剩下最后一步了。有1个客户端(我正在工作),有4个外围设备。我有4个不同的用户输入按钮,并根据按下的按钮,我想从我的BLE客户端发送数据到特定的BLE外围设备。下面是我现在想要实现的示例流程:
请注意,我不想同时连接,我只需要连接到一个特定的设备,发送数据,然后断开连接。
我迫切需要执行这个。所以我希望你能给出具体的解决方案。请帮. . ! !
提前感谢,
前腿帕特尔
嗨,鲁奇·帕特尔,
你的用例非常具体,我无法预见或记录这个论坛上的每一个具体细节,请检查下面我的建议。
为了通过中心连接到外设,外设需要做广告(为了让外设接收连接请求,需要做广告,而不仅仅是让中心扫描设备),所以您是要假设外设在那里,并且在没有扫描过程的情况下发出连接请求,还是也要进行扫描?我假设您将为您的设备使用公共地址,因为规范定义的静态地址应该在每次重新启动外设时更改,并且随机可解析需要与每个单独的设备绑定。因此,假设您使用的是公共地址,并且据我所知,这些地址为您的中央所知,有两种选择:
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遥控器仍然只处于外设模式。但是一旦用户按下一个按钮,假设是button-1,它就会做以下操作:
我还没有弄清楚如何在运行时做角色切换。所以目前,我的可编程BLE遥控器一直处于中央模式。
为了在BLE遥控器上按下一个按钮来操作调光器,我编写了以下代码:
bool gboolD1Connect = false;
空白user_button_pressed(空白)
{
gboolD1Connect = true;
/ / user_on_adv_report_ind (param - >报告。adv_addr_type: 0 x01);
if (dimmer1_connected == true) //只有在整个连接过程完成后才会为true
{
uint8_t my_data [1];
My_data [0] = 0x14;//亮度值
uint16_t my_length;
My_length = 1;
//该函数将数据从开关发送到调光器
prf_gatt_write(con_info, val_hdl, (uint8_t *)my_data, sizeof(uint8_t) * my_length, GATTC_WRITE);
}
}
//这是内置函数,我修改了它,使其仅在gboolD1Connect为true时连接到dimmer-1
Void user_on_adv_report_ind(struct gapm_adv_report_ind const * param)
{
如果(gboolD1Connect)
{
如果(! memcmp (param - >报告。数据[3],USER_ADVERTISE_DATA, USER_ADVERTISE_DATA_LEN))
{
arch_printf("连接%02x %02x %02x %02x %02x %02x %02x %02x %02x",
param - > report.adv_addr.addr [5],
param - > report.adv_addr.addr [4],
param - > report.adv_addr.addr [3],
param - > report.adv_addr.addr [2],
param - > report.adv_addr.addr [1],
param - > report.adv_addr.addr [0]);
app_easy_gap_start_connection_to_set (param - >报告。Adv_addr_type, (uint8_t *)¶m->报告。addr, MS_TO_DOUBLESLOTS (12.5));
user_gapm_cancel ();
}
}
}
上述实现工作,但它有一个问题。当我第一次按遥控器按钮的时候,它会设置gboolD1Connect为true,然后退出函数,因为dimmer1_connected还不是真的。之后,在后台,当user_on_adv_report_ind ()运行时,它将与调光器-1连接。一旦连接完成,就会发现所有的服务、特征和描述符。最后,就在描述符发现完成之后,我在要生成的内置函数中又插入了一行Dimmer1_connected = true。整个过程需要2-3秒。3秒后,当我再次按下按钮时,它最终会进入Dimmer1_connected == true并发送亮度值。如你所见,我得按两次按钮(1用于连接,2用于发送数据)能够发送数据。出现这个问题是因为每当我给一个命令连接到一个调光器设备(通过使gboolD1ConnectTo true, or by useapp_easy_gap_start_connection_to_set ()函数),我必须退出中断例程并允许主程序运行,这样实际的连接才能发生。但是既然我已经退出了我的中断程序,我将如何重新进入它并发送数据一旦外围设备连接?
所以我有两个问题需要帮助:
提前感谢你的帮助。
前腿帕特尔
嗨,前腿,
我可以建议您看一下无代码示例应用程序(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固件,然后逻辑地调用AT命令本身的序列以独立方式操作。
那么,是否可以在不需要终端、android app、第三方控制器等外部控制机制的情况下实现AT命令方式呢?
谢谢,
前腿帕特尔
嗨,前腿,
实现应该只是用于指导如何完成不同的事情。通过运行代码并使用调试器逐步执行各种命令,您将能够了解如何完成看似复杂的任务。这里有几个例子:
CodeLess实现使用AT命令来触发不同的操作,但是应该可以编写自己的逻辑来驱动相同的功能(您可能只是将CodeLess中适用的代码片段复制到您的项目中)。
/ MHv
我无法发现特性,但我可以发现服务,我的项目基于ble_app_peripheral
你能告诉我如何发现特色吗?
非常感谢!
嗨chenpenglai,
这个论坛的主题是非常古老的,所以我建议你创建一个新的。如果你不知道你应该遵循的程序,以创建一个新的论坛线程,请让我知道,我将为您提供所需的所有步骤。所以,请创建一个新的论坛帖子,并复制粘贴你的问题。
关于你的问题,你使用的是哪个版本的SDK ?您是否对SDK的ble_app_peripheral示例做了任何修改?
谢谢,PM_Dialog