概述
需要测试代码的可以留下邮箱,或者关注微信公众号 小白技术栈 后台回复【cc2530串口回调函数】获取。
CC2530使用MT层实现串口读操作,在MT_UART.c文件定义回调函数:
#if defined (ZTOOL_P1) || defined (ZTOOL_P2)
uartConfig.callBackFunc = MT_UartProcessZToolData;
在串口接收回调函数MT_UartProcessZToolData()中,Zstack采用状态机接收的方式对串口接收数据进行处理,看似比较复杂,但其实这样接收数据还能校验数据的准确性,而且还有osal_msg_send( App_TaskID, (byte *)pMsg )发送机制,处理数据比较方便。
其接收数据格式为 0xFE + 数据长度(仅是data的长度)+ 命令字段 + data[] + 校验和
代码注释如下:
/***************************************************************************************************
* @fn MT_UartProcessZToolData
*
* @brief | SOP | Data Length | CMD | Data | FCS |
* | 1 | 1 | 2 | 0-Len | 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 port - UART port
* event - Event that causes the callback
*
*
* @return None
***************************************************************************************************/
void MT_UartProcessZToolData ( uint8 port, uint8 event )
{
uint8 ch;
uint8 bytesInRxBuffer;
(void)event; // Intentionally unreferenced parameter
while (Hal_UART_RxBufLen(port)) //判断是否有数据
{
HalUARTRead (port, &ch, 1); //每次接收一个数据
switch (state)
{
case SOP_STATE: //初始状态state = 0,判断帧头是否为SOP_STATE(0xFE)
if (ch == MT_UART_SOF)
state = LEN_STATE; //若帧头正确,状态机状态改为LEN_STATE
break;
case LEN_STATE: //接收第二字节时,进入LEN_STATE
LEN_Token = ch; //将第二字节(传输数据data[]的长度)赋值给LEN_Token
tempDataLen = 0; //初始化临时数据计数器tempDataLen为零
/* Allocate memory for the data */
pMsg = (mtOSALSerialData_t *)osal_msg_allocate( sizeof ( mtOSALSerialData_t ) +
MT_RPC_FRAME_HDR_SZ + LEN_Token ); //分配存放消息的空间,由3字节(1字节数据长度位+2字节CMD字段)+ data[]长度
if (pMsg) //若有消息接收
{
/* Fill up what we can */
pMsg->hdr.event = CMD_SERIAL_MSG; //事件ID,供应用层查询使用
pMsg->msg = (uint8*)(pMsg+1); //加1的目的是为了分配存放数据末尾的1字节校验和
pMsg->msg[MT_RPC_POS_LEN] = LEN_Token; //将数据长度存放到msg[0]
state = CMD_STATE1; //修改状态机状态为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; //第四字节为命令字段二
/* If there is no data, skip to FCS state */
if (LEN_Token) //如果有数据接收,则状态机改为DATA_STATE
{
state = DATA_STATE;
}
else //如果无数据接收,则状态机改为FCS_STATE校验模式
{
state = FCS_STATE;
}
break;
case DATA_STATE:
/* Fill in the buffer the first byte of the data */
pMsg->msg[MT_RPC_FRAME_HDR_SZ + tempDataLen++] = ch; //开始存放data[]
/* Check number of bytes left in the Rx buffer */
bytesInRxBuffer = Hal_UART_RxBufLen(port);
/* If the remain of the data is there, read them all, otherwise, just read enough */
if (bytesInRxBuffer <= LEN_Token - tempDataLen) //如果缓冲区剩余字节数不大于分配 的空间,则将剩余字节全部存放到msg
{
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);
}
/* If number of bytes read is equal to data length, time to move on to FCS */
if ( tempDataLen == LEN_Token )
state = FCS_STATE; //修改状态为校验状态
break;
case FCS_STATE:
FSC_Token = ch; //将最后一个字节(校验和)赋值给FSC_Token
/* Make sure it's correct */
if ((MT_UartCalcFCS ((uint8*)&pMsg->msg[0], MT_RPC_FRAME_HDR_SZ + LEN_Token) == FSC_Token)) //校验成功,则将消息发送出去
{
osal_msg_send( App_TaskID, (byte *)pMsg ); //将消息发送到应用层
}
else
{
/* deallocate the msg */
osal_msg_deallocate ( (uint8 *)pMsg ); //此函数用于释放消息缓冲区。此函数由任务(或处理元素)在处理完接收到的消息后调用
}
/* Reset the state, send or discard the buffers at this point */
state = SOP_STATE; //恢复到初始化状态,等待下次接收
break;
default:
break;
}
}
}
然后在SampleApp.c文件uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )函数状态机中添加如下:
mtOSALSerialData_t *UartMsg;
.
.
.
case CMD_SERIAL_MSG:
UartMsg = (mtOSALSerialData_t *)MSGpkt;
memcpy(uartRecvBuf, UartMsg->msg, UartMsg->msg[0] + 3);
SampleApp_Send_P2P_Message();
memset(uartRecvBuf, 0, UartMsg->msg[0] + 3);
将串口接收到的消息发送到协调器,通过协调器打印出来。
cc2530串口接收数据由stm32发送测试,其测试代码为:
uint8_t MT_UartCalcFCS( uint8_t *msg_ptr, uint8_t len )
{
uint8_t x;
uint8_t xorResult;
xorResult = 0;
for ( x = 0; x < len; x++, msg_ptr++ )
xorResult = xorResult ^ *msg_ptr;
return ( xorResult );
}
/*********************************************************************
* @fn led_entry
*
* @brief Led run.
*
* @param parameter - none
*
* @return none
*/
void led_entry(void *parameter)
{
uint8_t led_state = LED_ON;
uint8_t test_buf[13] = {0xFE, 0x08, 0x03, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00};
test_buf[11] = 0xff;
while(1)
{
LED(led_state);
led_state = ~led_state;
test_buf[12] = MT_UartCalcFCS((uint8_t*)&test_buf[1], 11);
HAL_UART_Transmit(&huart1, test_buf, 13, 0xFF);
test_buf[4]++;
rt_thread_mdelay(1000);
}
}
最后
以上就是靓丽蜡烛为你收集整理的CC2530之串口接收回调函数MT_UartProcessZToolData()的全部内容,希望文章能够帮你解决CC2530之串口接收回调函数MT_UartProcessZToolData()所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复