ZStack协议栈为CC2530编写了一套操作系统并规定了数据收发的协议。这个片上系统工作的大致流程是:初始化各种板上硬件资源(LED、按键、串口、其他外设),初始化网络状态,根据设备类型进行组网或加入网络,最后正式开始运行这个系统——进入一个死循环不断轮询各种片上资源和设备,一旦其状态有所改变即在事件处理过程中执行相应的事件回调函数。
而由于我所使用的开发板与TI官方板并不完全兼容,所以必须对协议栈的驱动进行修改,才能顺利移植到我的板子上来。本文主要内容为LED和按键的驱动修改。
CC2530 2.5.1a实现了3个LED,虽然板子上一共有4个LED,LED4的所有驱动都被映射到了LED1。因此在没有进行驱动修改之前,在上层调用HAL层的API操作LED4相当于操作LED1。针对LED的驱动修改,主要是改动HAL\Target\CC2530EB\Config\hal_borad_cfg.h(此为项目Workspace视图下的路径,文件的物理路径并不是它)的第112~135行和310~335行(行号不一定准确,我是以修改后的文件作为基准的,但偏差也不会太大)。
如果你的板子上4个LED使用的IO口都与官方板不同,那么就都需要更改(如果不使用LED4,那么只修改3个)。所幸我的板子上LED1~LED3都与官方板完全兼容。下面以LED4的驱动添加为例,具体展示一下需要修改哪些内容。
#define LED4_BV BV(1) #define LED4_SBIT P0_1 #define LED4_DDR P0DIR #define LED4_POLARITY ACTIVE_HIGH
这几行代码应该添加在hal_board_cfg.h第129行,即LED3的定义后面,LED4_BV是LED4使用的管脚(0~7),可以看到它被定义为BV(1),BV(n)又是另一个宏定义,作用为将数字1左移n位,这正好可以用来操作设备使用的位;LED4_SBIT是LED4使用的IO口,在我的板子上,它使用的是P0_1。LED4_DDR是LED4所在IO口的方向寄存器——P0DIR;LED4_POLARITY是LED4的有效电平,协议栈默认的是高电平有效,所以定义为ACTIVE_HIGH。如果使用的板子是低电平有效,那么这里需要改成ACTIVE_LOW。
前面提到,LED4的操作全部被映射到了LED1上,所以还要修改第310~335行中LED4的各项宏定义。可以看到协议栈定义了LED的4中操作,分别为TURN_ON、TURN_OFF、TOGGLE、STATE,只需要仿照LED3的宏定义,把原来LED4的宏定义替换成LED4的版本就行了。注意我们使用的是2530EB_REV17,所以337行之后关于2530EB_REV13的代码不要去修改,REV13版本的板子上只有1个LED。修改的代码如下:
#define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0); ) #define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1); ) #define HAL_TOGGLE_LED4() st( if (LED4_SBIT) { LED4_SBIT = 0; } else { LED4_SBIT = 1;} ) #define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT))
一般来说,LED的驱动就只需要修改这些,但不幸的是,我的LED4所使用的P0_1在协议栈中被定义为按键S2的端口。所以我还需要进一步修改按键驱动。
按键的驱动代码分布在hal_board_cfg.h和hal_key.c中。hal_board_cfg.h的第147~151行中,虽然PUSH1定义为S1而我的独立按键在板子上标注的是S2,但由于协议栈里面已经写好了S1(HAL_KEY_SW_6)的全部代码,所以不妨把S1的驱动映射到我的S2上。查看板子的电路图可以知道,这个按键使用的是P0_5,所以把PUSH1_BV后面的宏定义改为BV(5),PUSH1_BIT也改为P0_5。而我的板子上按键是低电平有效,所以PUSH1_POLARITY需要改为ACTIVE_LOW。
到此,LED的修改就算是完成了,LED4可以正常的工作,可以在SammpleApp.c中处理周期信息的SampleApp_MessageMSGCB()中进行测试:当接收到周期信息,就切换LED4的状态。
但是,按键驱动还没有修改完。按键的另一部分驱动在hal_key.c的第110~128行。这里看到SW6已经写好了不少代码,我们只需要改一下其中的一些值就可以。如果使用SW7,这些代码需要手动添加。本来按键被定义在P01,但我的板子上按键在P05所以把所有涉及P01的代码全改为P05,分别是:
- HAL_KEY_SW_6_BIT
- HAL_KEY_SW_6_IENBIT
- HAL_KEY_SW_6_ICTLBIT
到此,按键的修改似乎也完成了,但测试发现,按键的操作还是不能正常触发事件。原因在于我们使用的P0_5又跟别的硬件冲突了,这次是UART。官方的板子使用的是4线的UART,可以进行硬件级的流量控制,而我的板子缩水了,只接了2线。查阅数据手册可以发现,P0_4、P0_5被用于流量控制(CTS和RTS)。我这里这两个管脚没有接线,所以需要禁用流量控制。流量控制的使用与否被定义在MT_UART.c,这里直接修改MT_UART.c的第109行:uartConfig.flowControl=MT_UART_DEFAULT_OVERFLOW为FALSE也可以,更为规范地修改应该修改MT_UART_DEFAULT_OVERFLOW的值,在mt_uart.h的第73行。
这样驱动修改就完成了,但测试一下,按键仍然不能正确地触发事件。这个问题卡了我好几天,最后总算是解决了,这是该版本协议栈中的一个BUG。
问题出在hal_key.c的HalKeyPoll()函数中。系统每100ms会轮询一次所有按键,检查是否有按键被按下。在2.5.1a版本的协议栈里面,这个函数:
- 检查摇杆是否被按下,如果按下则读出键值;
- 如果是轮询方式,检查这个读出的键值是否跟全局变量halKeySavedKeys中的值相同,如果相同则表明实际上没有按键按下,直接返回,不进行事件的触发;
- 最后检查独立按键是否被按下,直接调用了一个宏if(HAL_PUSH_BUTTON1())来判定。
不难看出,其逻辑是有问题的:单独按这个按键是永远不会被响应的,因为只检查了摇杆就开始判断有没有按键改变。只有在按摇杆的同时按下独立按键,才会被判定为按下了独立按键,而实验也证明了我的猜想。
因此,要想独立按键被正确地响应,需要交换一下2和3两步的顺序。而在之前版本的协议栈中,独立按键的检查是放在第一步执行的。不知道TI是怎么回事,在这个版本里搞出这么个BUG。
这样就没问题了,LED和按键的驱动修改全部完成。
另外还有一个疑问,轮询方式下没有任何延时去抖的代码,但这个按键却工作得很好。而中断模式下,却有延时去抖的代码。
没有评论:
发表评论