其实关键点只有两个,一个是电机的控制,另一个就是通讯协议及加解密。电机控制好办,根据电机转动的时间,使电机凸轮停止在固定的位置即可实现锁销的三种状态。只是蓝牙通讯部分,在这段学习期间,一直想自建工程并且自己实现蓝牙的通讯,由于本人愚钝,自建的工程始终不能正确广播数据,而例程中的BASS服务也始终不能去掉。时间来不及了,只能借助例程,然后添加自定义的功能了,惭愧惭愧。
例程ble_peripheral_server_bond,共包含有五个文件:
app.c:程序主文件,main入口函数;
app_bass.c:BAT服务,一直想把这个去掉,但是去掉就没有广播了;
app_config.c:硬件初始化及广播数据的参数设置;
app_customss.c:自定义通讯服务,对外提供读写接口,下手改造的就是它了;
app_msg_handler.c:处理各种消息的文件,可以不用管;
虽然这个例程已经被我精简过若干遍了,但是都以失败而告终,为了便于比对说明还是规规矩矩不做改变,只增加内容。本着最大限度地降低耦合性的原则,对于app_customss.c文件,只在CUSTOMSS_RXCharCallback函数中对外发送一个消息。这个函数就是当蓝牙接收到手机发送的消息时触发的,并且可以获得手机发送的数据。所以首先要对这些数据进行解密,然后根据指令执行对应的动作。为了实现这些功能,需要增加一个对该消息的接收函数以便后续处理。参照之前的帖子
http://bbs.elecfans.com/jishu_1971327_1_1.html,
需要增加代码的地方主要有: 1.app.h的enum appm_msg消息定义中增加:APP_BLE
2.app.c的main函数中增加MsgHandler_Add(APP_BLE, APP_BLE_Handler);
3.app_customss.c的CUSTOMSS_RXCharCallback函数中增加ke_msg_send_basic(APP_BLE, TASK_APP, length);
#define GPO_MOTOR 6
#define GPI_TOP 7
#define INT_BOTTOM 5
#define IRQ_BTN 0
uint8_t SecretKey[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; //自定义密钥
void APP_BLE_Handler(ke_msg_id_t const msg_id, void const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id)
{
uint8_t Buf[16] = {0x00}, Data[16] = {0x05};
AES128_ECB_Decrypt(app_env_cs.from_air_buffer, SecretKey, Buf);
switch (Buf[1])
{
case 0x06: //开锁
Sys_GPIO_Set_High(GPO_MOTOR); //转动电机
while ((DIO->DATA & GPIO7_HIGH) != GPIO7_HIGH) ; //等待顶部微动开关闭合
Sys_GPIO_Set_Low(GPO_MOTOR); //停止电机
Data[2] = 0x01; //自定义协议
break;
case 0x0C: //关锁
Sys_GPIO_Set_High(GPO_MOTOR); //转动电机
while ((DIO->DATA & GPIO7_HIGH) == GPIO7_HIGH) ; //等待顶部微动开关放开
Sys_GPIO_Set_Low(GPO_MOTOR); //停止电机
Data[2] = 0x02; //自定义协议
break;
default: return;
}
AES128_ECB_Encrypt(Buf, SecretKey, Data);
GATTC_SendEvtCmd(0, GATTC_NO
tiFY, 0, GATTM_GetHandle(CS_TX_VALUE_VAL0), 16, Data); //发送反馈结果到手机
}
void DIO0_IRQHandler(void)
{
uint8_t Buf[16] = {0x05, 0x01}, Data[16] = {0x00};
if ((DIO->DATA & GPIO5_HIGH) != GPIO5_HIGH) //检测到底部微动开关闭合
{
AES128_ECB_Encrypt(Buf, SecretKey, Data);
GATTC_SendEvtCmd(0, GATTC_NOTIFY, 0, GATTM_GetHandle(CS_TX_VALUE_VAL0), 16, Data); //发送反馈结果到手机
}
}
代码中引用了AES128加解密功能,RSL10有相关例程。不过硬件只支持加密,而软件加解密的例程写的又
比较繁琐,所以我用了自己的AES单元,功能是一样的,网上类似的代码也有很多,随意使用。当然,修改的东西不只是这一点点,其他一些细小的改造也是必要的,比如蓝牙数据变量要在头文件中声明才可以跨文件调用、关闭例程本身的LED超时控制、重新定义IO口和中断等,这里就不再详细说明,都会包括在后面提供的工程里。由于是开发板,增加电机控制等其他
电路不方便,就是用板载LED灯来代替电机的使能,按钮就模拟锁车状态吧。
接下来编译并运行,设置断点可观察接收到的数据以及执行的动作。使用Nordic的蓝牙调试工具模拟手机App来收发数据,只要通讯协议的数据对应上就可以了。
可以看到当手机发送开锁指令时,电机转动直到检测到开关闭合信号为止,并反馈结果;接收到锁车指令后同样电机转动,离开微动开关即可达到待锁状态;按下按键模拟手动锁车,并把锁车信息发送到手机以便和服务器进行交互完成结算收费功能。
到这里整个工程就算完成了,在此提供给工程文件下载权当参考,只是一个框架,鉴权的过程及一些容错处理没有加入进来,其他的功能请自由发挥吧。
最后能否恳请官方提供一个最简单的没有bass服务的例程,以帮助我实现最简化的目的,不甚感激,谢谢!
`