就跟我自己承诺的一样,我会发一篇关于zigbee串口通信的。 虽然这个是我五月份就做的东西,但是现在看来,还是有那么一群人对这个纠缠不清。但是,这个其实很简单。 事实上zigbee协议栈2006是有自己集成好了串口函数的, 就在MT层的SPIMgr.c文件里面。这里是一部分的源码: /*************************************************************************************************** * LOCAL FUNCTIONS ***************************************************************************************************/
/*************************************************************************************************** * @fn SPIMgr_Init * * @brief * * @param None * * @return None ***************************************************************************************************/ void SPIMgr_Init () { halUARTCfg_t uartConfig;
/* Initialize APP ID */ App_TaskID = 0;
/* UART Configuration */ uartConfig.configured = TRUE; uartConfig.baudRate = SPI_MGR_DEFAULT_BAUDRATE; uartConfig.flowControl = SPI_MGR_DEFAULT_OVERFLOW; uartConfig.flowControlThreshold = SPI_MGR_DEFAULT_THRESHOLD; uartConfig.rx.maxBufSize = SPI_MGR_DEFAULT_MAX_RX_BUFF; uartConfig.tx.maxBufSize = SPI_MGR_DEFAULT_MAX_TX_BUFF; uartConfig.idleTimeout = SPI_MGR_DEFAULT_IDLE_TIMEOUT; uartConfig.intEnable = TRUE; #if defined (ZTOOL_P1) || defined (ZTOOL_P2) uartConfig.callBackFunc = SPIMgr_ProcessZToolData; #elif defined (ZAPP_P1) || defined (ZAPP_P2) uartConfig.callBackFunc = SPIMgr_ProcessZAppData; #else uartConfig.callBackFunc = NULL; #endif
/* Start UART */ #if defined (SPI_MGR_DEFAULT_PORT) HalUARTOpen (SPI_MGR_DEFAULT_PORT, &uartConfig); #else /* Silence IAR compiler warning */ (void)uartConfig; #endif
/* Initialize for ZApp */ #if defined (ZAPP_P1) || defined (ZAPP_P2) /* Default max bytes that ZAPP can take */ SPIMgr_MaxZAppBufLen = 1; SPIMgr_ZAppRxStatus = SPI_MGR_ZAPP_RX_READY; #endif
}
/*************************************************************************************************** * @fn MT_SerialRegisterTaskID * * @brief * * This function registers the taskID of the application so it knows * where to send the messages whent they come in. * * @param void * * @return void ***************************************************************************************************/ void SPIMgr_RegisterTaskID( byte taskID ) { App_TaskID = taskID; }
/*************************************************************************************************** * @fn SPIMgr_CalcFCS * * @brief * * Calculate the FCS of a message buffer by XOR'ing each byte. * Remember to NOT include SOP and FCS fields, so start at the CMD * field. * * @param byte *msg_ptr - message pointer * @param byte len - length (in bytes) of message * * @return result byte ***************************************************************************************************/ byte SPIMgr_CalcFCS( uint8 *msg_ptr, uint8 len ) { byte x; byte xorResult;
xorResult = 0;
for ( x = 0; x < len; x++, msg_ptr++ ) xorResult = xorResult ^ *msg_ptr;
return ( xorResult ); }
#if defined (ZTOOL_P1) || defined (ZTOOL_P2) /*************************************************************************************************** * @fn SPIMgr_ProcessZToolRxData * * @brief | SOP | CMD | Data Length | FSC | * | 1 | 2 | 1 | 1 | * * Parses the data and determine either is SPI or just simply serial data * then send the data to correct place (MT or APP) * * @param pBuffer - pointer to the buffer that contains the data * length - length of the buffer * * * @return None ***************************************************************************************************/ void SPIMgr_ProcessZToolData ( uint8 port, uint8 event ) { uint8 ch;
/* Verify events */ if (event == HAL_UART_TX_FULL) { // Do something when TX if full return; }
if (event & (HAL_UART_RX_FULL | HAL_UART_RX_ABOUT_FULL | HAL_UART_RX_TIMEOUT)) { while (Hal_UART_RxBufLen(SPI_MGR_DEFAULT_PORT)) { HalUARTRead (SPI_MGR_DEFAULT_PORT, &ch, 1);
switch (state) { case SOP_STATE: if (ch == SOP_VALUE) state = CMD_STATE1; break;
case CMD_STATE1: CMD_Token[0] = ch; state = CMD_STATE2; break;
case CMD_STATE2: CMD_Token[1] = ch; state = LEN_STATE; break;
case LEN_STATE: LEN_Token = ch; if (ch == 0) state = FCS_STATE; else state = DATA_STATE;
tempDataLen = 0;
/* Allocate memory for the data */ SPI_Msg = (mtOSALSerialData_t *)osal_msg_allocate( sizeof ( mtOSALSerialData_t ) + 2+1+LEN_Token );
if (SPI_Msg) { /* Fill up what we can */ SPI_Msg->hdr.event = CMD_SERIAL_MSG; SPI_Msg->msg = (uint8*)(SPI_Msg+1); SPI_Msg->msg[0] = CMD_Token[0]; SPI_Msg->msg[1] = CMD_Token[1]; SPI_Msg->msg[2] = LEN_Token; } else { state = SOP_STATE; return; }
break;
case DATA_STATE: SPI_Msg->msg[3 + tempDataLen++] = ch; if ( tempDataLen == LEN_Token ) state = FCS_STATE; break;
case FCS_STATE:
FSC_Token = ch;
/* Make sure it's correct */ if ((SPIMgr_CalcFCS ((uint8*)&SPI_Msg->msg[0], 2 + 1 + LEN_Token) == FSC_Token)) { osal_msg_send( MT_TaskID, (byte *)SPI_Msg ); } else { /* deallocate the msg */ osal_msg_deallocate ( (uint8 *)SPI_Msg); }
/* Reset the state, send or discard the buffers at this point */ state = SOP_STATE;
break;
default: break; }
} } } #endif //ZTOOL
#if defined (ZAPP_P1) || defined (ZAPP_P2) /*************************************************************************************************** * @fn SPIMgr_ProcessZAppRxData * * @brief | SOP | CMD | Data Length | FSC | * | 1 | 2 | 1 | 1 | * * Parses the data and determine either is SPI or just simply serial data * then send the data to correct place (MT or APP) * * @param pBuffer - pointer to the buffer that contains the data * length - length of the buffer * * * @return None ***************************************************************************************************/ void SPIMgr_ProcessZAppData ( uint8 port, uint8 event ) {
osal_event_hdr_t *msg_ptr; uint16 length = 0; uint16 rxBufLen = Hal_UART_RxBufLen(SPI_MGR_DEFAULT_PORT);
/* If maxZAppBufferLength is 0 or larger than current length the entire length of the current buffer is returned. */ if ((SPIMgr_MaxZAppBufLen != 0) && (SPIMgr_MaxZAppBufLen <= rxBufLen)) { length = SPIMgr_MaxZAppBufLen; } else { length = rxBufLen; }
/* Verify events */ if (event == HAL_UART_TX_FULL) { // Do something when TX if full return; }
if (event & ( HAL_UART_RX_FULL | HAL_UART_RX_ABOUT_FULL | HAL_UART_RX_TIMEOUT)) { if ( App_TaskID ) { /* If Application is ready to receive and there is something in the Rx buffer then send it up */ if ((SPIMgr_ZAppRxStatus == SPI_MGR_ZAPP_RX_READY ) && (length != 0)) { /* Disable App flow control until it processes the current data */ SPIMgr_AppFlowControl ( SPI_MGR_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 = SPI_INCOMING_ZAPP_DATA; msg_ptr->status = length;
/* Read the data of Rx buffer */ HalUARTRead( SPI_MGR_DEFAULT_PORT, (uint8 *)(msg_ptr + 1), length );
/* Send the raw data to application...or where ever */ osal_msg_send( App_TaskID, (uint8 *)msg_ptr ); } } } } }
/*************************************************************************************************** * @fn SPIMgr_ZAppBufferLengthRegister * * @brief * * @param maxLen - Max Length that the application wants at a time * * @return None * ***************************************************************************************************/ void SPIMgr_ZAppBufferLengthRegister ( uint16 maxLen ) { /* If the maxLen is larger than the RX buff, something is not right */ if (maxLen <= SPI_MGR_DEFAULT_MAX_RX_BUFF) SPIMgr_MaxZAppBufLen = maxLen; else SPIMgr_MaxZAppBufLen = 1; /* default is 1 byte */ }
/*************************************************************************************************** * @fn SPIMgr_AppFlowControl * * @brief * * @param status - ready to send or not * * @return None * ***************************************************************************************************/ void SPIMgr_AppFlowControl ( bool status ) {
/* Make sure only update if needed */ if (status != SPIMgr_ZAppRxStatus ) { SPIMgr_ZAppRxStatus = status; }
/* App is ready to read again, ProcessZAppData have to be triggered too */ if (status == SPI_MGR_ZAPP_RX_READY) { SPIMgr_ProcessZAppData ( SPI_MGR_DEFAULT_PORT, HAL_UART_RX_TIMEOUT ); }
}
#endif //ZAPP
这些意思很明显,特别注意下有色彩背景的代码。这个其实就是C语言的宏定义。在zigbee协议栈,这个是用得很多的。当然,本人自己也很喜欢用这个方法定义,因为简单,而且直观,更重要的是很方便, 你可以随便定义你要的部分进行编译。 呵呵,有点跑题了。接下来就解释下把,: /* UART Configuration */ uartConfig.configured = TRUE; uartConfig.baudRate = SPI_MGR_DEFAULT_BAUDRATE; uartConfig.flowControl = SPI_MGR_DEFAULT_OVERFLOW; uartConfig.flowControlThreshold = SPI_MGR_DEFAULT_THRESHOLD; uartConfig.rx.maxBufSize = SPI_MGR_DEFAULT_MAX_RX_BUFF; uartConfig.tx.maxBufSize = SPI_MGR_DEFAULT_MAX_TX_BUFF; uartConfig.idleTimeout = SPI_MGR_DEFAULT_IDLE_TIMEOUT; uartConfig.intEnable = TRUE; #if defined (ZTOOL_P1) || defined (ZTOOL_P2) uartConfig.callBackFunc = SPIMgr_ProcessZToolData; #elif defined (ZAPP_P1) || defined (ZAPP_P2) uartConfig.callBackFunc = SPIMgr_ProcessZAppData; #else uartConfig.callBackFunc = NULL; #endif
这个就是串口的初始化部分,注意了, 上面 uartConfig.callBackFunc是一个函数指针,后面的就是这个串口的调用函数。协议栈默认编了两个固化的,这两个是用于与zibgee的上位机通信的, 有特定的协议,是由TI自己定的。 就是一位内TI定义了这个协议,使得如果我们自己编写的话就使用了。
这样。有一种办法,就是跟着它的协议,一下是我得到的TI的串口通信协议:
'*********************************************************************************************** '* 协议数据单元的相关说明 * '*********************************************************************************************** ' ' ARMSKY-ZLocation无线定位开发系统使用TI公司的ZigBee协议栈Z-Stack v1.4.2。为了方便用户与使用 'Z-Stack v1.4.2的目标硬件进行数据交换,Z-Stack v1.4.2中定义了串口通信数据格式。 ' ' 串口属性设置如下: ' ' 波 特 率:38400bps ' 数 据 位:8个 ' 停 止 位:1个 ' 奇偶校验:无 ' ' Z-Stack v1.4.2中串口通信数据格式如下: ' ' **************************************************** ' * SOP * CMD * LEN * Data * FCS * ' **************************************************** ' ' 数据包由多个字段构成,每个字段由1个或多个字节构成。多字节字段的高位字节首先被发送。 ' ' SOP(包起始):该字段长度为1字节,值为0x02,表示数据包开始。 ' CMD(命令ID):该字段长度为2字节,表示数据包的作用。 ' LEN(长度) :该字段长度为1字节,表示Data字段的长度。 ' Data(数据) :该字段包含要被传输的实际数据,该字段的长度由LEN字段指定。 ' FCS(帧校验序列):该字段长度为1字节,确保数据包的完整性。FCS字段值的计算方法是: ' 从CMD字段开始到Data字段结束,逐个字节进行XOR运算,结果即为FCS字段值。 ' 接收方收到数据包后,从Data字段开始到FCS字段结束,逐个字节进行XOR运算, ' 结果为0表示接收正确,否则表示错误。 ' ' Z-Stack v1.4.2中定义了很多串口通信数据包,此处只描述定位应用中所需使用的串口通信数据包。 ' 其他串口通信数据包格式定义请参看Serial Port Interface_F8W-2003-0001_.pdf。 ' ' ' 下面给出4个本定位应用中需要用到的串口通信命令数据包的格式定义: ' ' SYS_PING:发送该命令给目标设备以检查设备的状态及能力。格式定义如下: ' ' ***************************** ' * CMD=0x0007 * LEN=0x00 * ' ***************************** ' ' SYS_PING_RESPONSE:该命令是对SYS_PING命令的响应。格式定义如下: ' ' ********************************************** ' * CMD=0x1007 * LEN=0x02 * Capabilities * ' ********************************************** ' ' Capabilities:该字段长度为2字节。该字段值表示目标设备可以处理的接口。位掩码如下: ' ' MT_CAP_MAC 0x0001 ' MT_CAP_NWK 0x0002 ' MT_CAP_AF 0x0004 ' MT_CAP_ZDO 0x0008 ' MT_CAP_USER_TEST 0x0010 ' MT_CAP_SEQ 0x0020 ' MT_CAP_BOOTLOAD 0 x 8000 ' ' SYS_GET_DEVICE_INFO:发送该命令给目标设备以获得设备的信息。格式定义如下: ' ' ***************************** ' * CMD=0x0014 * LEN=0x00 * ' ***************************** ' ' SYS_GET_DEVICE_INFO_RESPONSE:该命令是对SYS_GET_DEVICE_INFO命令的响应。格式定义如下: ' ' ******************************************************************************************************************************* ' * CMD=0x1014 * LEN=0x03 * Status * IEEEAddress * ShortAddress * DeviceType * DeviceState * NumAssocDevices * AssocDevicesList * ' ******************************************************************************************************************************* ' ' LEN=0x03 Serial Port Interface_F8W-2003-0001_.pdf中第16页中有定义,但存在疑问,不过不影响本应用。 ' Status:该字段长度为1字节。0表示成功,1表示失败。如果IEEEAddress或/和ShortAddress不在有效范围内,则该字段值为1。 ' IEEEAddress:该字段长度为8字节。 ' ShortAddress:该字段长度为2字节。 ' DeviceType:该字段长度为1字节,用来表示设备类型。位0到位2用来指示设备运行为协调器、路由器还是终端设备。 ' DeviceState:该字段长度为1字节,用来表示设备状态。可能的设备状态请参看Serial Port Interface_F8W-2003-0001_.pdf中第16页中的定义。 ' NumAssocDevices:该字段长度为1字节,表示关联到该目标设备的设备数量。 ' AssocDevicesList:该字段长度可变,它是一个每个数据元素为16bit的数组。表示关联到该目标设备的设备的网络地址。
'*********************************************************************************************** '* Z-Stack定位规范中规定的报文格式 * '*********************************************************************************************** ' ' 在Z-Stack定位规范中规定了如下9个报文: ' ' XY-RSSI请求报文(簇ID:0x0011) ' XY-RSSI响应报文(簇ID:0x0012) ' 盲节点查找请求报文(簇ID:0x0013) ' 盲节点查找响应报文(簇ID:0x0014) ' 参考节点配置报文(簇ID:0x0015) ' 盲节点配置报文(簇ID:0x0016) ' 参考节点配置请求报文(簇ID:0x0017) ' 盲节点配置请求报文(簇ID:0x0018) ' RSSIBlast报文(簇ID:0x0019) ' ' ' XY-RSSI请求报文(簇ID:0x0011) ' ' 发送该请求报文来触发一个XY-RSSI响应报文。在发送一系列RSSI Blast报文后该请求报文应被 ' 立即发送以取回在“1跳”射频范围内的参考节点的坐标和与它们每一个的平均RSSI射频链接强度。 ' 注意:如果该报文被发送大于“1跳”半径,那么RSSI射频链接强度将不可用,只有XY坐标可用。 ' 该报文除了一个簇ID没有其他内容。 ' ' XY-RSSI响应报文(簇ID:0x0012) ' ' 该报文被发送以响应XY-RSSI请求报文。RSSI平均值包含了XY-RSSI请求报文本身的RSSI值,然后 ' RSSI平均值被归零以便为另一个一系列RSSI Blast报文做准备。因此,如果RSSI Blast报文从未被发 ' 送,那么RSSI平均值就是XY-RSSI请求报文的RSSI值。 ' ' 字节索引 描 述 值 ' ================================================================================== ' 0和1 参考节点的X位置。 bit[15:2] 整米 ' bit[1:0] 0.25米 ' 如果该字段为0xFFFF, ' 表明参考节点没有被配置。 ' ' 2和3 参考节点的Y位置。 bit[15:2] 整米 ' bit[1:0] 0.25米 ' 如果该字段为0xFFFF, ' 表明参考节点没有被配置。 ' ' 4 任何一系列RSSI Blast广播报文并且包含XY-RSSI 0~255 ' 请求报文本身RSSI值的RSSI平均值。 ' ' 盲节点查找请求报文(簇ID:0x0013) ' ' 发送该报文给一个盲节点以迫使其执行一个位置查找。当位置查找完成后,该报文的响应报文被 ' 盲节点发回。位置查找所需要的时间取决于网络的总流量。该报文除了一个簇ID没有其他内容。 ' ' 盲节点查找响应报文(簇ID:0x0014) ' ' 该报文被盲节点发送以响应盲节点查找请求报文。 ' ' 字节索引 描 述 值 ' ================================================================================== ' 0 状态。 0 — 成功 ' 1 — 没有足够的参考节点响应。 ' ' 1和2 盲节点的(被CC2431内部定位引擎计算出)的X位置。 bit[15:2] 整米 ' bit[1:0] 0.25米 ' ' ' 3和4 盲节点的(被CC2431内部定位引擎计算出)的Y位置。 bit[15:2] 整米 ' bit[1:0] 0.25米 ' ' 5 被用来参与计算位置的参考节点数量。 0~8 ' ' 6和7 最近的(基于RSSI)参考节点的短地址。 0x0000~0xFFFA,0xFFFF无效。 ' ' 8和9 最近的参考节点的X位置。 bit[15:2] 整米 ' bit[1:0] 0.25米 ' ' ' 10和11 最近的参考节点的Y位置。 bit[15:2] 整米 ' bit[1:0] 0.25米 ' ' 12 最近的参考节点的RSSI。 ' ' ' 参考节点配置报文(簇ID:0x0015) ' ' 发送该报文给一个参考节点来设置它的配置项目。该报文也从参考节点被发送以响应参考节点 ' 配置报文。 ' ' 字节索引 描 述 值 ' ================================================================================== ' 0和1 参考节点的X位置。 bit[15:2] 整米 ' bit[1:0] 0.25米 ' ' 2和3 参考节点的Y位置。 bit[15:2] 整米 ' ' bit[1:0] 0.25米 ' 盲节点配置报文(簇ID:0x0016) ' ' 发送该报文给一个盲节点来设置它的配置项目。该报文也从盲节点被发送以响应盲节点配置报文。 ' ' 字节索引 描 述 值 ' ================================================================================== ' 0 盲节点的A参数。A被定义为在离发射机1米的参考距 ' 离上接收到的平均功率的绝对值(以dBm为单位)。 ' ' 1 盲节点的N参数。N是路径损耗指数,用来描述来自 ' 发射机的信号功率随着距离的增大而衰减的速率。 ' ' 2 运行模式。 0 — 被查询模式 ' 1 — 自动模式。 ' ' 3和4 采集时间。在发送XY-RSSI请求报文后要等待参考 以100毫秒为单位增加。 ' 节点响应的毫秒数。 ' ' 5和6 循环时间。低字节首先发送。在开始一个计算周期 以100毫秒为单位增加。 ' 之前要等待的毫秒数。只用于自动模式。 ' ' 7和8 报告短地址。低字节首先发送。在自动模式下,该 0x0000~0xFFFF ' 地址为盲节点响应报文的目的地址;在查询模式下, ' 响应被返回给请求者的地址。 ' ' 9 报告端点。在自动模式下,盲节点响应报文的目的 ' 端点。 ' ' 10 被用来参与位置计算的参考节点的最小数量。 1~16 ' ' ' 参考节点配置请求报文(簇ID:0x0017) ' ' 发送该报文给一个参考节点以请求它的配置。该请求报文的响应报文是参考节点配置报文。 ' 该报文除了一个簇ID没有其他内容。 ' ' ' 盲节点配置请求报文(簇ID:0x0018) ' ' 发送该报文给一个盲节点以请求它的配置。该请求报文的响应报文是盲节点配置报文。 ' 该报文除了一个簇ID没有其他内容。 ' ' RSSI Blast报文(簇ID:0x0019) ' ' 以“1跳”半径广播该报文,在相对短的时间多次发送该报文来触发射频范围内的参考节点计算 ' 它们收到的RSSI Blast广播报文的平均RSSI值。该报文除了一个簇ID没有其他内容。 ' ' ' 用户PC端软件应用可以通过Z-Stack中规定的系统应用报文(SYS_APP_MSG)来与Location Dongle进行通信。 ' ' PC可以通过使用系统应用报文(SYS_APP_MSG)来发送OTA(over the air)报文,输出报文格式为: ' ' 字节索引 描 述 值 ' ================================================================================== ' 0和1 目的地址 — 低字节在前。输出报文的目的地址。 0x0000~0xFFFF ' 2 输出报文的目的端点。 0x00~0xFF ' 3和4 簇ID — 低字节在前。输出报文的簇ID。 0x0000~0xFFFF ' 5 输出报文(下一字段)长度。 0x00~0xFF ' 6~n 输出报文(Z-Stack定位规范中规定的那9个报文) ' ' ' ' PC可以通过使用系统应用报文(SYS_APP_MSG)来输入OTA(over the air)报文,输入报文格式为: ' ' 字节索引 描 述 值 ' ================================================================================== ' 0 应用端点。 对于本应用,应为203 ' 1和2 源地址 — 低字节在前。输入报文的源地址。 0x0000~0xFFFF ' 3 输入报文的源端点。 0x00~0xFF ' 4和5 簇ID — 低字节在前。输入报文的簇ID。 0x0000~0xFFFF ' 6 输入报文的长度。 0x00~0xFF ' 7~n 输入报文(Z-Stack定位规范中规定的那9个报文) ' ' ' ' 系统应用报文SYS_APP_MSG被用来给应用发送原始数据。该请求报文可以或不能获得一个响应报文。 '该请求报文可能获得多个异步响应报文。 ' ' 系统应用报文SYS_APP_MSG的格式如下: ' ' ***************************************************************************** ' * CMD = 0x0018 * LEN = 0x01 +Data字段长度 * Endpoint * Data * ' ***************************************************************************** ' ' Endpoint:该字段长度为1字节。该字段指定数据将被发送给的应用端点。不要使用该字段 ' 来发送ZDO报文(端点0)。 ' Data:该字段长度可变。该字段包含来自应用端点的原始数据包。 ' ' ' SYS_APP_MSG_RESPONSE报文是系统应用报文SYS_APP_MSG的响应报文,格式如下: ' ' *************************************************************** ' * CMD = 0x1018 * LEN = 可变 * Endpoint * Data * ' *************************************************************** ' ' Endpoint:该字段长度为1字节。该字段指明数据是来自哪个应用端点。 ' Data:该字段长度可变。该字段包含来自应用端点的原始数据包。 '
如果想用它默认的通讯协议,就只能这样。当然,市面上的zigbee开发套件基本都是用的这个协议。 但是,还有另外一种方法,就是禁掉这些函数,自己编写函数。 这就是我弄出来的东西。 首先你想禁掉这些很简单,注意到#if 这个后面的内容没, 这个是宏定义判断语句, 只要后面的值有定义(有时候还必须为1)的时候,就生效,所以最直接的方法救治把宏定义禁掉(不要很傻的说把整个注释掉,这个是最白痴的做法,协议栈的文件是所有工程通用的,最好保证完整性。这也就是为什么这个协议栈用那么多宏定义的原因,人家是很聪明的。) 但是涉及到怎么禁,这个我估计会难倒很多人。因为很多人注重代码,却从来忽视了一个东西,那就是编译器。 zigbee的这些宏定义你在代码里面是找不到的,为了修改方便,它们都被设置成有编译器设定。 其它拐弯磨脚的我就不说了,直接方法把。 在IAR下打开一个工程, 从左边workspace里面工程名字点右键->option进入工程设定,这里点左边的C/C++ Complier,然后直接左边上面点Preprossor。 这个界面就是用编译器的宏定义页面, 里面有文件的默认库地址,还有宏定义,在下面那个。可以看到很多宏定义,其中会有一项ZTOOL_P1(或者是ZTOOL_P2,ZAPP_P1,ZAPP_P2)这个是定义串口调用函数的宏定义, 如果你不想用这些函数, 这几个你就必须注释掉。怎么注释?删除?可以,这个是最简单的,但是如果以后你还要用到呢?所以最好的方法就是给它前面随便价格数字或者小写字母就是了,因为宏定义习惯上都是用大写字母(只是习惯,小写也没事),可以很大成都避免跟其它定义冲突的。
好了, 注释掉后,就得自己编写调用函数,这是必须的,要不你一样用不了。 首先是自己编写一个初始化函数: halUARTCfg_t uartConfig; //定义串口初始化结构
/* UART Configuration */ uartConfig.configured = TRUE; uartConfig.baudRate = HAL_UART_BR_115200;//波特率115200 uartConfig.flowControl = FALSE; uartConfig.flowControlThreshold = 48; uartConfig.rx.maxBufSize = 128; uartConfig.tx.maxBufSize = 128; uartConfig.idleTimeout = 6; uartConfig.intEnable = TRUE; uartConfig.callBackFunc = rxCB; //自己编写的接收处理函数 HalUARTOpen(HAL_UART_PORT_0,&uartConfig); //启动串口 HalUARTWrite( HAL_UART_PORT_0,"The CC2430 is initial finished!/n",sizeof("The CC2430 is initial finished!/n"));//只是为了测试下是否串口初始化完成了. 接下来就是自己编写才串口接收处理函数了: static void rxCB( uint8 port, uint8 event ) { uint8 *buf, len;
/* While awaiting retries/response, only buffer 1 next buffer: otaBuf2. * If allow the DMA Rx to continue to run, allocating Rx buffers, the heap * will become so depleted that an incoming OTA response cannot be received. * When the Rx data available is not read, the DMA Rx Machine automatically * sets flow control off - it is automatically re-enabled upon Rx data read. * When the back-logged otaBuf2 is sent OTA, an Rx data read is scheduled. */ if ( otaBuf2 ) { return; }
if ( !(buf = osal_mem_alloc( SERIAL_APP_RX_CNT )) ) { return; }
/* HAL UART Manager will turn flow control back on if it can after read. * Reserve 1 byte for the 'sequence number'. */ len = HalUARTRead( port, buf+1, SERIAL_APP_RX_CNT-1 );
if ( !len ) // Length is not expected to ever be zero. { osal_mem_free( buf ); return; }
/* If the local global otaBuf is in use, then either the response handshake * is being awaited or retries are being attempted. When the wait/retries * process has been exhausted, the next OTA msg will be attempted from * otaBuf2, if it is not NULL. */ if ( otaBuf ) { otaBuf2 = buf; otaLen2 = len; } else { otaBuf = buf; otaLen = len; /* Don't call SerialApp_SendData() from here in the callback function. * Set the event so SerialApp_SendData() runs during this task's time slot. */
osal_set_event( LocDongle_TaskID, 0x0004 ); //通知任务串口有数据 } } 这个我坦白,不是我自己编写的处理程序,是从栈里面抽出来的的, 但是有什么所谓?主要是自己能用,而且摆脱了串口栈束缚。
接下就是自己用任务处理串口数据了, 上面这个只是先把串口数据保存起来而已。有点类似于队列的原理。
到了这也就没我的事了呵。很简单的东西。不好的请见谅。
|