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#endifISR模式被设置成了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的输出,也更加的合理,更加的便于操作!
- TIMAC 开发随笔二:CC2530的串口操作
- TIMAC 开发随笔 一:CC2530的flash在线读写
- CC2530串口
- CC2530串口
- CC2530的ZigBee应用层加入串口
- CC2530--串口实验的回显
- cc2530-Contiki系统的串口输入问题
- Android驱动(二)串口操作之tiny4412开发板实现串口通讯的两种方法
- Beaglebone Black 串口的操作(二)
- 开发随笔二
- html开发随笔二
- CC2530 串口驱动
- CC2530 串口实验
- CC2530串口接收总结
- CC2530串口中断
- CC2530串口通讯2
- CC2530 串口驱动
- CC2530串口实验
- sierra wireless公司产品漏洞公告更新
- 内核对象--可等待计时器WaitableTimer(二)
- C#学习之类
- java学习笔记24——String类不可变性
- 1194. Message Flood
- TIMAC 开发随笔二:CC2530的串口操作
- phalcon tag
- Lattice paths——格子路径
- 字体加阴影效果
- window下如何配置apache Http服务器使其能运行python cgi脚本
- centOS无线网卡驱动
- 三层 实例理解
- 基于Hadoop1.0.4的分布式云网盘(转载)
- POJ 2585 拓扑排序