1.文章背景
此篇文章以ac696n_soundbox_sdk_v1.7.0版本进行入门讲解:
写这篇文章的目的是因为自己在尝试入门杰理微的时候遇到了好多的问题点,想尝试用买到的开发板来驱动一颗LED闪烁却一直没有按自己想象的逻辑成功跑出效果,在网上到处翻找手册教程以及B站上看了许多教学视频后都感觉没有一个能很好一步步带我上手的教程,最后还是自己通过串口打印日志一步步对SDK的架构渐渐清晰,也可能是因为自己比较惯性思维,想以学习一款MCU跑裸机的方式,一直在main函数的while(1) 主循环里面尝试IO口点灯,导致卡在这里很久;但我还是希望以学习一款MCU的方式来攥写这篇杰理微蓝牙入门的文章,这样对有MCU基础的人会比较好理解,可以更快上手。
MCU开发入门流程一般就是:
1.了解对应MCU的最简外围电路及相关引脚外设功能;
2.下载MCU对应开发编译环境与工具链并熟悉;
3.熟悉对应程序框架及其启动流程;
4.掌握其程序烧录及调试方法;
5.通过MCU的IO口进行点灯操作;
2.正式学习
1.以AC6969D蓝牙芯片搭建的一个最简蓝牙音箱为例进行了解(无使用电池供电):

这颗IC只需要1颗24MHz外部晶振以及几颗电容就可以搭建起最简外围电路进行程序烧录了,由于杰理微这款芯片本身就是以soundbox产品为定位,所以其供电引脚定义也不是VCC或VDD了,而是VBAT,支持2.2V~5.5V电压供电,VDDIO为其内部LDO给内部IO进行供电的引脚,当VBAT为5V供电时实测VDDIO为3.3V,当外部有较小负载需要3.3V供电时也可以从这里取电,手册建议最好不超100mA,至于每个管脚对应的硬件外设功能这里就不列出了,网上到处可以找到对应芯片手册。
2.下载对应开发编译环境及工具链及对应版本SDK:

较常用的开发环境有三种,Code::blocks、VScode、Makefile,官网文档推荐使用Code::blocks,我也就用了这种,直接在杰理微官网的文档中心下载即可,网址:
https://doc.zh-jieli.com/Tools/zh-cn/dev_tools/dev_env/index.html
至于AC696X系列的SDK,由于官方并没有释放该资源,所以我也不方便在这里提供资源了,有需要的可以自己GitHub或码云上翻找一下,还是能找到的。得到对应的SDK后解压后得到以下目录文件,


此文件即为对应的工程文件。
3.熟悉SDK的程序框架及其启动流程:
首先我们找到该目录下的board_config.h,我们在该文件里面选择我们开启哪个模板来进行开发(一般根据所使用的芯片来选择对应模板):


我用的是AC6969D芯片,所以我就使能了对应的DEMO,其他DEMO都注释掉了。
使能该板级配置后,我们就找到对应的DEMO头文件,去里面使能我们需要用到的功能或者根据我们的实际硬件电路更改对应的配置参数,关闭不需要用到的功能等:

然后我们要使用芯片的各种外设比如定时器timer、uart、spi、iic这些的话,SDK也提供了对应的c文件程序模板,其对应在该目录下:

我们可以新建一个.c文件定义我们自己要使用的函数,也可以在SDK给出的.c文件里面直接定义或者更改其模板函数进行使用也行; 像MCU开发一样,我们的外设初始化函数一般也是在main函数里面while(1)主循环之前进行调用,我们找到目录下的app_main.c文件,程序在经过一系列启动流程之后就会跑到该文件下的app_main()函数里面了:
启动流程图:


同时可以看到我们的主循环是在app_task_loop()这个函数里面:

这个函数会通过循环判断app_curr_task的值然后进入不同的任务去执行,这个时候肯定会有人想着把要循环扫描的功能,比如LED闪烁、按键检测这些放在这里,是不是就轻松实现IO点灯功能和按键切换了,一开始我也是这么想,不过实际操作发现是不可行的,因为app配置里面的任务比如蓝牙初始化过程中其是具有阻塞性的,就是程序会卡在那里直到满足某个条件后才会继续进行或者退出然后再进入到这个while循环,但是我们可以通过创建一个新的任务或开启一个触发中断的定时器,来实现我们需要进行扫描的东西,这里以开启一个定时器为例,定时器相关封装函数位于timer.h文件里面:


通过在app_main()函数里面初始化开启一个定时器,定时时间到达后就会触发中断执行中断回调函数rgb_led_timer_callback里面的内容:


对应timer.h里面的系统定时器开启函数:

此定时器开启后将一直存在,不会因为进入一次中断就消失,但是其无法阻止系统进入低功耗,当我们的app配置里面无开启任何使能时,系统就会因为判断为没有任务执行而自动进入低功耗,那这个定时器里面要执行的内容也将无法执行了。
下面这个用户定时器开启函数所开启的定时器就可以阻止系统进入低功耗,同时其还可以设置中断优先级:

但是其每次开启后仅会触发进入一次中断,需在中断回调函数中删除上次开启的定时器,否则会造成内存堆积直到溢出报错,然后再次开启该定时器,:

这是我尝试不删除上一个定时器后串口输出的报错结果:

通过上述开启定时器的方式并在中断中进行扫描判断处理,就可以完成我们大部分想要实现的功能了。
4.掌握其程序烧录及调试方法:
杰理微烧录器原理为 USB通信+强制进入ISD下载模式+上电时序控制,实际烧录时当芯片的VBAT脚如果接了大滤波电容的情况下由于会破坏上电时序,所以基本很难识别到芯片,所以建议最好采用空片烧录而不是带板子烧录,或者在板子上预留跳接口,当程序调试好后再把跳接口短接上。
程序的编译和下载在Code::blocks是一体的,按下F9后程序编译完识别到芯片后就会自动将程序下载进芯片,要看到有显示正在write才是有在烧录程序进芯片:

在程序编译后如果没更改,想要快速烧录,也可以找到download.bat这个文件进行直接烧录:

调试方法一般采用串口打印数据观察程序动向,要使用串口调试只需要做这两步就可以实现:
1).在app_config.h文件中使能lib总开关:


2).根据自己硬件uart的TX脚及通讯波特率,在对应的demo.h文件里面修改uart配置参数:

像我之前串口打印发现程序跑到board_init()函数里面后串口就不输出数据了,导致程序都没跑到app_main()函数里面,我想要实现的功能全部没跑起来,然后我就在board_init()函数里面每一句执行函数后面都进行数据打印:

最后发现开启了TCFG_UI_ENABLE后应该是里面重新定义使用了我的串口,导致我的串口不输出数据了,将这里disable之后就正常了:

5.使用IO口进行点灯操作:
这一步后面我让整个程序跑起来进入app_main()和学会定时器的创建使用之后就没有去尝试了,而是直接尝试我想要的功能:蓝牙连接播放音乐+驱动RGB灯+通过串口接收数据改变RGB的显示模式,同时回传特定数据给外部MCU,后面我会再写一篇文章记录一下我的实现方式和程序,这里先给大家看看效果:

