TIMAC 开发随笔二:CC2530的串口操作

来源:互联网 发布:数控车床左牙怎么编程 编辑:程序博客网 时间:2024/05/17 22:51

TIMAC 开发随笔 二 : CC2530的串口操作

引用请注明出处!!我的邮箱qinxiaoyu@163.com

本人身在山西太原,欢迎各位联系哦。。。

        其实说CC2530串口的文章已经很多了,有的文章说的特别的详细。我在一开始调串口的时候也参考了很多网上的文章,他们都给了我很大的帮助!这里我说的串口操作也是走的其中的一条路子,那么就是移植ZStack的部分串口软件来做开发。

        先说说我为什么特别钟情于串口的操作,在一上来弄TIMAC的第一步就是先打通串口部分。

        1.串口基本上是我们最常用的接口了。在后续的开发中,大部分的通讯都是依靠串口来完成的。

        2.串口工具的易取得性。做软件开发的,SPI转USB的不多,UART转USB的小转换板总是特别多的。

        3.方便观察软件流程。其实这里也不一定非要使用串口,要是有其他好的接口也可以使用。有人说过,读懂一段代码最难的就是专业术语。但是我感觉,软件的流程,数据的走向,也都是很重要的部分。

        IAR的IDE并没有提供很好的输出设备(当然,也有可能是我还不知道怎么使用)。当我们的代码运行的时候,我们不可能只依靠一些断点来判断程序的走向,这样效率太低下了。所以,我们必须引入一种更好的调试方式。那么就是输出打印信息!就像linux下的打印信息一样,我们可以随时掌握程序的走向!

         开始说串口的操作了,这里我还会把我的打印管理贴出来供大家参考一下。这套管理方法学自于CSR的蓝牙软件,优点是管理方便;缺点是会占有比较多的code空间。不过我们的软件不是很大,只有50多kb,而flash却有256k,够我们挥霍的了。

       

1.选择uart的读取数据的方式:

         CC2530给我们提供了2种读取串口数据的方式,一种是中断式的(ISR),一种是DMA式的。CC2530的文档上明确的告诉了我们,在使用ISR式并且串口速率在115200时,当RF数据繁忙的时候,可能会有不可预料的问题。我们需要至少115200的串口速率,所以就果断放弃ISR方式。

          在这里,我们需要使能CC2530的DMA.。

/* Set to TRUE enable DMA usage, FALSE disable it */#ifndef HAL_DMA#define HAL_DMA TRUE#endif

        将原来的FALSE改成TRUE就可以了。

2.使能UART:

/* Set to TRUE enable UART usage, FALSE disable it */#ifndef HAL_UART#if (defined ZAPP_P1) || (defined ZAPP_P2) || (defined ZTOOL_P1) || (defined ZTOOL_P2)#define HAL_UART TRUE#else#define HAL_UART FALSE#endif#endif

      在这里,我直接将我的设备设置成了ZAPP_P1设备。在IDE的project->option->C/C++连接器中的宏定义中直接定义宏ZAPP_P1。这样就将HAL_UART设置成了TRUE。

3.设置UART使用DMA模式:

#ifndef HAL_UART_DMA#if HAL_DMA#if (defined ZAPP_P2) || (defined ZTOOL_P2)#define HAL_UART_DMA  2#else#define HAL_UART_DMA  1#endif#else#define HAL_UART_DMA  0#endif#endif
      我们在上一步设置宏的时候定义了ZAPP_P1,这样#define HAL_UART_DMA  2是有效的。我们刚好需要UART1来做串口,定义成了2,刚好对应的就是UART1。
#ifndef HAL_UART_ISR#if HAL_UART_DMA           // Default preference for DMA over ISR.#define HAL_UART_ISR  0#elif (defined ZAPP_P2) || (defined ZTOOL_P2)#define HAL_UART_ISR  2#else#define HAL_UART_ISR  1#endif#endif
      ISR模式被设置成了0,在后续的编译时,ISR方式的函数将不会被编译。

4.设置串口参数(这一段函数我们使用了ZStack的MT_UART中的代码)

#define MT_UART_ZAPP_RX_READY           0x01#define UartDefaultRxLen50#define UartDefaultTxLen30#define UartDefaultIdleTimeOut        200void UartSetNormalConfig(uint8 port){    halUARTCfg_t UartConifg;    UartConifg.configured            = TRUE;    UartConifg.baudRate              = HAL_UART_BR_115200;      //串口波特率    UartConifg.flowControl           = HAL_UART_FLOW_OFF;       //流控开关    UartConifg.flowControlThreshold  = 0;    UartConifg.rx.maxBufSize         = UartDefaultRxLen;        //rxbuf的大小    UartConifg.tx.maxBufSize         = UartDefaultTxLen;        //txbuf的大小    UartConifg.idleTimeout           = UartDefaultIdleTimeOut;  //串口超时时间    UartConifg.intEnable             = TRUE;                    //中断使能    UartConifg.callBackFunc          = MT_UartProcessZAppData;  //串口回调函数    HalUARTOpen(port,&UartConifg);                              //设置串口    MT_UartMaxZAppBufLen  = UartDefaultRxLen;    MT_UartZAppRxStatus   = MT_UART_ZAPP_RX_READY;}     
5.串口回调函数(串口数据就在这个位置被读取出来)

void MT_UartProcessZAppData ( uint8 port, uint8 event ){osal_event_hdr_t  *msg_ptr;uint16 length = 0;uint16 rxBufLen  = Hal_UART_RxBufLen(MT_UART_DEFAULT_PORT);/*If maxZAppBufferLength is 0 or larger than current lengththe entire length of the current buffer is returned.*/if ((MT_UartMaxZAppBufLen != 0) && (MT_UartMaxZAppBufLen <= rxBufLen)){length = MT_UartMaxZAppBufLen;}else{length = rxBufLen;}/* Verify events */if (event == HAL_UART_TX_FULL){// Do something when TX if fullreturn;}if (event & ( HAL_UART_RX_FULL | HAL_UART_RX_ABOUT_FULL | HAL_UART_RX_TIMEOUT)){if ( Hal_TaskID ){/*If Application is ready to receive and there is somethingin the Rx buffer then send it up*/if ((MT_UartZAppRxStatus == MT_UART_ZAPP_RX_READY ) && (length != 0)){/* Disable App flow control until it processes the current data */MT_UartAppFlowControl (MT_UART_ZAPP_RX_NOT_READY);/* 2 more bytes are added, 1 for CMD type, other for length */msg_ptr = (osal_event_hdr_t *)osal_msg_allocate( length + sizeof(osal_event_hdr_t) );if ( msg_ptr ){msg_ptr->event = HAL_UART_PROCESS_EVENT;msg_ptr->status = length;/* Read the data of Rx buffer */                                        /*!!!!!!这里读取串口中的数据!!!!!*/                                        HalUARTRead( MT_UART_DEFAULT_PORT, (uint8 *)(msg_ptr + 1), length );MT_UartZAppRxStatus= MT_UART_ZAPP_RX_READY;}}}}}void MT_UartAppFlowControl ( bool status ){    /* Make sure only update if needed */    if (status != MT_UartZAppRxStatus )    {        MT_UartZAppRxStatus = status;    }    /* App is ready to read again, ProcessZAppData have to be triggered too */    if (status == MT_UART_ZAPP_RX_READY)    {        MT_UartProcessZAppData (MT_UART_DEFAULT_PORT, HAL_UART_RX_TIMEOUT );    }}

6.串口数据发送函数(现在已经写成了多参数的debug函数,等同于printf,zprintf函数等)

新建一个文件,起名为debug.c

void DEBUG(uint8 *fmt ,...){#ifdef DEBUG_ENABLEDva_listarg_ptr;uint8LocalText[64];uint8 cnt;uint8m;for(cnt=0 ; cnt<64 ; cnt++) {LocalText[cnt] = 0x00;}va_start(arg_ptr, fmt);vsprintf(LocalText, fmt, arg_ptr);va_end(arg_ptr);for(m=0 ; m<64 ; m++) {if(LocalText[m]==0x00){break;}}HalUARTWrite(HAL_UART_PORT_1,LocalText,m);#else;#endif}
7.串口debug宏定义

可以新建一个debug.h文件,在debug.h文件中定义下列的宏。以按键debug为例:

#ifdefDEBUG_ENABLED#define DEBUG_HAL_KEY_D   //按键debug#define DEBUG_MSA_D       #define DEBUG_MAC_PIB_D#define DEBUG_MAC_RADIO_D#define DEBUG_MSA_MAIN_D#endif

在hal_key.c中添加如下的语句:

#include “debug.h”#ifdef DEBUG_HAL_KEY_D#define DEBUG_HAL_KEY_STR(X,Y)DEBUG_STRING(X, Y)#define DEBUG_HAL_KEY(X,...) DEBUG(X,##__VA_ARGS__)#else#define DEBUG_HAL_KEY_STR(X,Y)#define DEBUG_HAL_KEY(X,...)#endif
在hal_key.c文件中可以如下使用DEBUG_HAL_KEY()函数,如:

void HalKeyPoll (void){uint8 keys = 0;if ((HAL_KEY_JOY_MOVE_PORT & HAL_KEY_JOY_MOVE_BIT))  /* Key is active HIGH */{keys = halGetJoyKeyInput();DEBUG_HAL_KEY("HAL KEY::halGetJoyKeyInput=%d\r\n",keys);}if (!HAL_PUSH_BUTTON1()){DEBUG_HAL_KEY("HAL KEY::HalKeyPoll HAL_PUSH_BUTTON1\r\n");keys |= HAL_KEY_SW_6;}if (!HAL_PUSH_BUTTON2()){DEBUG_HAL_KEY("HAL KEY::HalKeyPoll HAL_PUSH_BUTTON2\r\n");keys |= HAL_KEY_SW_7;}/* If interrupts are not enabled, previous key status and current key status* are compared to find out if a key has changed status.*/if (!Hal_KeyIntEnable){if (keys == halKeySavedKeys){/* Exit - since no keys have changed */return;}/* Store the current keys for comparation next time */halKeySavedKeys = keys;}else{/* Key interrupt handled here */}/* Invoke Callback if new keys were depressed */if (keys && (pHalKeyProcessFunction)){(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);}}
这样在按键1按下,按键2按下,遥控柄按下的情况下,都会有串口数据从串口1输出。


当我们不想debug文件hal_key.c中的内容时,只要将debug.h中的宏

#define DEBUG_HAL_KEY_D
变成

#define xDEBUG_HAL_KEY_D
就不会输出hal_key..c中的debug内容了。


同理,要想关闭整个软件中的debug内容,则只要将

#define DEBUG_ENABLED
变成

#define xDEBUG_ENABLED
整个工程中,串口1就不会有任何的debug输出了。



小结:串口的debug数据的输出对于调试有着非常直观的作用,使用这种方式debug,将大大的降低软件阅读的难度。用上面的方法管理debug的输出,也更加的合理,更加的便于操作!





0 0
原创粉丝点击