ZIGBEE2007的串口通信(转)
此篇文章为转载,谢谢原著者分享
就跟我自己承诺的一样,我会发一篇关于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 ); //通知任务串口有数据
}
}
这个我坦白,不是我自己编写的处理程序,是从栈里面抽出来的的, 但是有什么所谓?主要是自己能用,而且摆脱了串口栈束缚。
接下就是自己用任务处理串口数据了, 上面这个只是先把串口数据保存起来而已。有点类似于队列的原理。
到了这也就没我的事了呵。很简单的东西。不好的请见谅。
这个给力了,赞一个,辛苦,楼主
楼主 如何驱动双串口啊