物联网智能家居DIY_TC32系列文章目录
一、前言
上回说到已经完成TC32的点灯,现在结合BLE_AT例程里的串口透传,搞一个小程序点灯。
主要分为两个部分:TC32端,与微信小程序端。
本篇文章主要记录TC32端的修订实现,目前还没办法完全理解整个AT例程的框架,只知道如何修改代码以实现小程序点灯功能。
小程序直接选用安信可教程上提供的例程,下一篇将介绍如何进行二次修改。
二、前置条件
UB18 + TC32 + 串口线
三、本文参考资料
SDK源码与注释
四、正文部分
4.1 GPIO初始化
在上一篇的blink例程中可以得到TC32的GPIO初始化还是比较简单的。
GPIO共有以下几种模式:
GPIO / MSPI / SWIRE / UART / I2C / SPI / I2S / AMIC / DMIC / SDM / USB / ADC / CMP / ATS / PWM / PWM_N
将IO口设为输出模式只需要以下几个步骤:
1. 将GPIO口设为GPIO模式
2. 使能output并禁能input
3. 最后将电平写入GPIO即可
gpio_write(GPIO_PC2, 0);
将IO口设为输入模式只需要以下几个步骤:
1. 将GPIO口设为GPIO模式
2. 设置为上拉或下拉模式,同时设置相应电阻
PM_PIN_PULLUP_1M / PM_PIN_PULLDOWN_100K / PM_PIN_PULLUP_10K
3. 使能input并禁能output
4. 最后读取电平状态即可
gpio_read(GPIO_PD2)
void user_init()
{
gpio_set_func(GPIO_PC2, AS_GPIO);
/* 将PC2设为输出模式 */
gpio_set_output_en(GPIO_PC2, 1);
gpio_set_input_en(GPIO_PC2, 0);
gpio_set_func(GPIO_PD2, AS_GPIO);
gpio_setup_up_down_resistor(GPIO_PD2, PM_PIN_PULLUP_10K);
gpio_set_output_en(GPIO_PD2, 0);
gpio_set_input_en(GPIO_PD2, 1);
}
4.2 点灯逻辑分析
AT例程主要分为两种模式,一个是BLE未连接时的AT模式,和BLE连接上后的透传模式。
由于我们需要实现的是小程序点灯,即小程序与TC32是通过BLE联系的,所以我们只需要在起机时对led灯的GPIO进行初始化后,使用小程序连接上TC32,最后在透传模式的代码新增对来自小程序的数据进行解析的功能即可。
源码内是直接将小程序的数据通过串口直接打印,我们只需要将收到的字符串进行解析,当满足某种人为规定的条件时,将led灯打开或关闭。
4.3 TC32_SDK分析
既然找到了修改的地方,那就顺藤摸瓜反向整理一下整个系统流吧
int main (void)
1. blc_pm_select_internal_32k_crystal(); //确定唤醒源是否为内部32k RC
2. cpu_wakeup_init(); //初始化MCU
3. int deepRetWakeUp = pm_is_MCU_deepRetentionWakeup(); //获取MCU深度保留唤醒
4. rf_drv_init(RF_MODE_BLE_1M); //启动射频模式
5. gpio_init( !deepRetWakeUp ); //初始化GPIO口(非初始化具体GPIO的模式)
6. clock_init(SYS_CLK_16/24/32M_Crystal); //时钟初始化
7. blc_app_loadCustomizedParameters(); //加载自定义频率偏移上限值
8. tinyFlash_Init(0x70000,0x4000); //初始化KV存储系统
9. 若非深度睡眠模式
tinyFlash_Read(STORAGE_BAUD, baud_buf, &len); //读取波特率
tinyFlash_Read(STORAGE_ATE, &ATE, &len); //读取ATE
tinyFlash_Read(STORAGE_MODE, &device_mode, &len);//读取ATE
/**************************************/
/* 此处开始为可根据实际情况进行修改的部分 */
10. app_uart_init(baud_buf[0]); //初始化串口
11. my_gpio_init(); //初始化GPIO
12. blt_soft_timer_init(); // 初始化定时器
13. 若非深度睡眠模式
判断从步骤9获得的设备模式device_mode
若为主机模式(1)
ble_master_init_normal();
若为从机模式(0)
ble_slave_init_normal();
13.1 初始化随机数生成器
random_generator_init();
13.2 BLE协议栈初始化
13.2.1 根据传入的flash地址获取公共mac地址与随机静态地址
blc_initMacAddress(CFG_ADR_MAC, mac_public, mac_random_static);
app_own_address_type
13.2.2 Controller初始化
blc_ll_initBasicMCU(); //强制性的
blc_ll_initStandby_module(mac_public); //强制性的
blc_ll_initAdvertising_module(mac_public); //adv模块:BLE从机必须安装,
blc_ll_initConnection_module(); //连接模块:BLE从/主设备必须安装
blc_ll_initSlaveRole_module(); //从机模块:BLE从机必须,
13.2.3 Host初始化
gap(通用访问控制配置文件)初始化
blc_gap_peripheral_init();
gatt(通用属性配置文件)初始化(这个函数非常重要!!!!!!!!!!)
my_att_init();
设置MTU为247
blc_att_setRxMtuSize(247);
l2cap(链路控制和适配层)初始化
blc_l2cap_register_handler(blc_l2cap_packet_receive);
SMP(安全管理)初始化
(Smp初始化可能涉及闪存写入/擦除,因此必须在电池检查后进行)
(当一个扇区存储太多信息,即将超过扇区阈值时,必须擦除该扇区,并重新存储所有有用信息)
#if (BLE_REMOTE_SECURITY_ENABLE)
blc_smp_peripheral_init();
#else
blc_smp_setSecurityLevel(No_Security);
#endif
13.3 用户应用层初始化
...
14. irq_enable(); //使能中断
15. while (1) //主循环
15.1 若使能了看门狗,则清除看门狗
wd_clear();
15.2 sdk主循环?仅对外提供了一个接口,没描述实现
blt_sdk_main_loop();
15.3 若当前为主机模式,则进入主机主循环
ble_master_mainloop();
15.4 串口循环,即用户层UART循环收发数据
app_uart_loop();
若此时fifo中存在数据,获取并处理数据
data = my_fifo_get(&uart_rx_fifo)
若此时蓝牙未连接 或 PC5为低电平时需响应AT指令
device_in_connection_state == 0 || gpio_read(CONTROL_GPIO) == 0)
解析处理并响应fifo中的AT命令
at_data_process((char*)(p->data), p->dma_len);
a. 过滤 \r \n
b. 解析AT命令对应的模式(查询/设置/帮助)
mode = data_process_cmd_mode(pbuf);
c. AT命令分析与执行
data_process_parse(pbuf + 3, mode, len-3)
result = cmd_ptr->cmd_handle(ps, mode, dataLen);
否则认为当前蓝牙已连接,进入透传模式
将数据经由BLE发送出去
bls_att_pushNotifyData(SPP_SERVER_TO_CLIENT_DP_H, p->data, p->dma_len);
fifo读写时钟同步
my_fifo_pop(&uart_rx_fifo);
f->rptr++;
rptr:要同步到读时钟域的写指针(写时钟)
15.5 软件定时器进程
blt_soft_timer_process(MAINLOOP_ENTRY);
步骤13的BLE协议栈部分放在之后的博客上单独拎出来分析吧。。这部分就是整个BLE的核心内容,可以结合这个图进行理解,目前还不太懂。。