Zigbee 网络支持星状、树(簇)状,网状三种网络拓扑结构;
第1个字节 | 第2个字节 | 第3个字节 | 第4个字节 | 第5~Len+4字节 | 第 n+1 字节 |
---|---|---|---|---|---|
数据枕头SOP | 数据长度(Len) | 命令低字节(CMD) | 命令高字节(CMD) | 数据(Len字节) | 校验码 |
0XFE | 按位XOR |
void MT_UartProcessZToolData ( uint8 port, uint8 event )
{
uint8 ch;
uint8 bytesInRxBuffer;
(void)event; // 有意未引用的参数
while (Hal_UART_RxBufLen(port)) // 计算Rx缓冲区长度-缓冲区中的字节数。
{
HalUARTRead (port, &ch, 1); // 读取一个数据
switch (state) // 串口接收状态机
{
case SOP_STATE: // SOP_STATE - 数据针头 0x00
if (ch == MT_UART_SOF) // 收到第一个数据,MT_UART_SOF 为 0xFE
state = LEN_STATE; // 确认后跳转状态 LEN_STATE - 数据长度
break;
case LEN_STATE: // LEN_STATE - 数据长度 0x03
LEN_Token = ch; // 接收数据长度
tempDataLen = 0; // 临时数据长度
/* 为数据分配内存空间 */
pMsg = (mtOSALSerialData_t *)osal_msg_allocate( sizeof ( mtOSALSerialData_t ) +
MT_RPC_FRAME_HDR_SZ + LEN_Token );
if (pMsg) // 如果分配成功
{
/* 尽我们所能 */
pMsg->hdr.event = CMD_SERIAL_MSG; // 注册事件号 CMD_SERA_MSG
pMsg->msg = (uint8*)(pMsg+1); // 把数据定位到结构体数据部分
pMsg->msg[MT_RPC_POS_LEN] = LEN_Token;// 存数据长度第一位数据
state = CMD_STATE1; // 跳转状态 命令低字节
}
else
{
state = SOP_STATE;
return;
}
break;
case CMD_STATE1: // 接收第三个数据
pMsg->msg[MT_RPC_POS_CMD0] = ch; //
state = CMD_STATE2; // 命令高字节
break;
case CMD_STATE2:
pMsg->msg[MT_RPC_POS_CMD1] = ch; // 命令高字节
/* 如果没有数据,跳到FCS状态 */
if (LEN_Token)
{
state = DATA_STATE;
}
else
{
state = FCS_STATE;
}
break;
case DATA_STATE:
/* 在缓冲区中填充数据的第一个字节 */
pMsg->msg[MT_RPC_FRAME_HDR_SZ + tempDataLen++] = ch;
/* 检查Rx缓冲区中剩余的字节数 */
bytesInRxBuffer = Hal_UART_RxBufLen(port);
/* 如果剩下的数据在那里,把它们全部读出来,否则,只要读够就行了 */
if (bytesInRxBuffer <= LEN_Token - tempDataLen)
{
HalUARTRead (port, &pMsg->msg[MT_RPC_FRAME_HDR_SZ + tempDataLen], bytesInRxBuffer);
tempDataLen += bytesInRxBuffer;
}
else
{
HalUARTRead (port, &pMsg->msg[MT_RPC_FRAME_HDR_SZ + tempDataLen], LEN_Token - tempDataLen);
tempDataLen += (LEN_Token - tempDataLen);
}
/* 如果读取的字节数等于数据长度,则跳转到FCS的状态 */
if ( tempDataLen == LEN_Token )
state = FCS_STATE;
break;
case FCS_STATE:
FSC_Token = ch;
/* 确保它是正确的 */
if ((MT_UartCalcFCS ((uint8*)&pMsg->msg[0], MT_RPC_FRAME_HDR_SZ + LEN_Token) == FSC_Token))
{
osal_msg_send( App_TaskID, (byte *)pMsg );
}
else
{
/* 释放消息内存 */
osal_msg_deallocate ( (uint8 *)pMsg );
}
/* 重置状态,此时发送或放弃缓冲区 */
state = SOP_STATE;
break;
default:
break;
}
}
}
MT_UartCalcFCS - 通过对每个字节进行异或运算来计算消息缓冲区的FCS。记住不要包含SOP和FCS字段,从CMD字段开始。
SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
void SampleApp_SerialMSG( mtOSALSerialData_t *SeMsg );
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
/* 收到串口数据 */
case CMD_SERIAL_MSG:
SampleApp_SerialMSG( (mtOSALSerialData_t *)MSGpkt );
break;
...
}
...
}
/*********************************************************************
* @fn SampleApp_SerialMSG
*
* @brief 处理串口数据
*
* @param mtOSALSerialData_t *SeMsg - 串口数据
*
* @return none
*/
void SampleApp_SerialMSG( mtOSALSerialData_t *SeMsg )
{
# HalUARTWrite ( 0, "有消息!\r\n", osal_strlen( "有消息!\r\n" ) );
HalUARTWrite ( 0, SeMsg->msg + 1, *(SeMsg->msg) + 2 ); // 加上2个命令字节
HalUARTWrite ( 0, "\r\n", 3 );
}
void SampleApp_SerialMSG( mtOSALSerialData_t *SeMsg )
{
/* 接收到串口消息 LED2 闪烁 */
HalLedBlink (HAL_LED_2, 3, HAL_LED_DEFAULT_DUTY_CYCLE, HAL_LED_DEFAULT_FLASH_TIME);
HalUARTWrite ( 0, "接收串口消息!\t", osal_strlen( "接收串口消息!\t" ) );
HalUARTWrite ( 0, SeMsg->msg + 1, *(SeMsg->msg) + 2 ); // 加上2个命令字节
HalUARTWrite ( 0, "\r\n", osal_strlen("\r\n") );
/* MT传输协议中的CMD */
uint16 cmd;
cmd = *(SeMsg->msg + 1);
cmd |= *(SeMsg->msg + 2) << 8;
switch ( *(SeMsg->msg + 1) )
{
/* TOGGLE */
case 0x0030:
HalLedSet( HAL_LED_1,HAL_LED_MODE_TOGGLE );
break;
/* 开灯 */
case 0x0031:
HalLedSet( HAL_LED_1,HAL_LED_MODE_ON );
break;
/* 关灯 */
case 0x0032:
HalLedSet( HAL_LED_1,HAL_LED_MODE_OFF );
break;
default:
break;
}
}
我修改了协议栈的 LED4
在 hal_board_cfg.h,总添加代码:
/* 4 - NewLand */
#define LED4_BV BV(3)
#define LED4_SBIT P1_3
#define LED4_DDR P1DIR
#define LED4_POLARITY ACTIVE_HIGH
HAL_TURN_OFF_LED4(); \
LED4_DDR |= LED4_BV; \
#define HAL_LED_DEFAULT_MAX_LEDS 4
LED4 宏定义与其他 LED 的一致即可。
晚安,情人节快乐……
修改串口回调函数
void MT_UartProcessZToolData ( uint8 port, uint8 event )
{
uint8 ch, len = 0;
uint8 uartData[128];//定义一个数组暂存数据
uint8 i;
(void)event;//Intentionally unreferenced parameter
while(Hal_UART_RxBufLen(port))//只要检测到串口缓存区有数据
{
HalUARTRead (port,&ch,1);//就把数据一个一个的传给ch变量
uartData[len+1] = ch;//再把ch的数据传给数组
len ++;
}
if(len)
{
uartData[0] = len;//第一个元素呢设为数据长度
pMsg = (mtOSALSerialData_t *)osal_msg_allocate( sizeof(mtOSALSerialData_t ) + len + 1 );//为串口数据包分配内存
if (pMsg)
{
/* Fill up what we can */
pMsg->hdr.event = CMD_SERIAL_MSG;//设置串口数据到达事件
pMsg->msg = (uint8*)(pMsg+1);//把数据定位到结构体数据部分
for(i=0; i<=len; i++)
{
pMsg->msg[i] = uartData[i];//再把暂存区数据放入串口数据包中
}
osal_msg_send( App_TaskID, (byte *)pMsg );//将数据包发往消息队列
}
osal_msg_deallocate ((uint8 *)pMsg );//分起的内存用完后记得开除,以免内存溢出。
}
}