當前位置:編程學習大全網 - 源碼下載 - 如何在Zstack中使用串口CC2530不錯

如何在Zstack中使用串口CC2530不錯

網上和論壇裏面很多帖子都把精力集中到分析協議棧的串口工作機制上,比如分析DMA

工作原理,中斷工作原理,然後分析輸入和輸出Buffer的處理等內容,學習者跟著協議棧的

串口底層壹直到頂層轉圈、轉圈、再轉圈,蒙圈了。

實際上,從應用角度講,我們根本就沒有必要去深入的追究Zstack中串口的工作機制,

也沒有必要去搞清楚到底是怎麽DMA和Interrupt的,我們只要調用幾個簡單函數就可以正

常使用串口了。其實協議棧已經把使用串口的條件準備好了,我們何必再糾結硬件底層實現

呢?應用者應該把協議棧看作壹個平臺,平臺之上的應用才是我們的目標。下面我就講壹下

如何利用協議棧現有平臺來實現自己的串口應用。這裏我所提及的現有平臺即是Zstack自帶

的MT包,其實Zstack中的這個MT包功能相當強大,通過TI提供的ZTOOL工具可以用串

口的方式同整個協議棧進行交互,在我們編寫Zigbee應用程序的過程中,很多不知道該如何

調用的函數都能在MT中找到參考!這個不多說了,有興趣的同學可以去專門研究壹下MT

包。

二、使用方法

在MT包中,已經有了串口初始化即串口數據處理函數可用,關鍵的幾個函數出現在

MT_Uart.c文件中。我們拿出來幾個關鍵函數說明壹下(我撿重要語句註釋):

第壹個函數

void MT_UartInit ()

{ // 這個是MT中的壹個串口初始化函數,主要作用是初始化串口工作的壹些規矩

halUARTCfg_t uartConfig;

App_TaskID = 0; //處理串口數據的任務ID,可以先不管

uartConfig.configured = TRUE;

uartConfig.baudRate = MT_UART_DEFAULT_BAUDRATE;

//默認38400波特率;可以更改,但是可能有新問題,具體解釋內容比較多,我不說;

uartConfig.flowControl = FALSE;//MT_UART_DEFAULT_OVERFLOW;

//禁止硬件流控,如果妳的串口只有RXD,TXD和GND三條線,必須這麽做;

uartConfig.flowControlThreshold= MT_UART_DEFAULT_THRESHOLD;

uartConfig.rx.maxBufSize = MT_UART_DEFAULT_MAX_RX_BUFF;

uartConfig.tx.maxBufSize = MT_UART_DEFAULT_MAX_TX_BUFF;

uartConfig.idleTimeout = MT_UART_DEFAULT_IDLE_TIMEOUT;

uartConfig.intEnable = TRUE;

#if defined (ZTOOL_P1) || defined (ZTOOL_P2)

uartConfig.callBackFunc = MT_UartProcessZToolData;

//如果編譯的時候選擇使用ZTOOL,那麽MT_UartProcessZtoolData將會處理串口接到的數

//據串

#elif defined (ZAPP_P1) || defined (ZAPP_P2)

uartConfig.callBackFunc = MT_UartProcessZAppData;

//如果編譯的時候沒有選擇ZTOOL,而是選擇使用了ZAPP,則由MT_UartProcessZAppData

//函數來處理串口數據串

(*如果是用CC2530的P0口那兩根串口引腳,妳就要define ZTOOL_P1,如果是P1口的那

兩根串口引腳,妳就要define ZTOOL_P2,對於ZAPP_P1和ZAPP_P2也是壹個情況*)

#else

uartConfig.callBackFunc = NULL;

//這個地方,如果妳有興趣自己寫壹個串口處理函數,那麽妳實現壹個My_UartProcessData

//函數,然後填到這裏,替換NULL。

#endif

#if defined (MT_UART_DEFAULT_PORT)

HalUARTOpen (MT_UART_DEFAULT_PORT, &uartConfig);

//如果定義了默認串口,(0或者1),打開串口,這個HalUartOpen函數會做壹大堆工作,具

//體說來就是初始化唄。。。,我沒有必要展開。需要註意的是這個函數把前面哪壹堆初始化

//的uartConfig做為參數傳進去了噢!

#else

(void)uartConfig;

#endif

#if defined (ZAPP_P1) || defined (ZAPP_P2)

MT_UartMaxZAppBufLen = 1;

MT_UartZAppRxStatus = MT_UART_ZAPP_RX_READY;

//這兩句,如果是不想使用MT_UartProcessZToolData來處理串口數據,就。。。。

//再說就要深入串口機制了,網上講解文章太多了,自己看吧,我壹會兒使用

//MT_UartProcessZToolData。

#endif

}

第二個函數

void MT_UartRegisterTaskID( byte taskID )

{

App_TaskID = taskID;

}

第三個函數

void MT_UartProcessZToolData ( uint8 port, uint8 event )

osal_msg_deallocate ( (uint8 *)pMsg );

}

我們往上看看這個Message是什麽?MT_UartProcessZToolData函數開始不遠的地方有以下程

序段:

if (pMsg)

{

pMsg->hdr.event = CMD_SERIAL_MSG;

pMsg->msg = (uint8*)(pMsg+1);

pMsg->msg[MT_RPC_POS_LEN] = LEN_Token;

state = CMD_STATE1;

}

從這裏看到,這個函數建立了壹個消息頭,用CMD_SERIAL_MSG做為消息,那麽

osal_msg_send給任務的那個消息將會以CMD_SERIAL_MSG出現。。。。。。。

好了,以上三個函數看完,我們試著使用壹下:

以GenericApp例子為例:

void GenericApp_Init( byte task_id )

XXXXXXXXXXXXX

XXXXXXXXXXXXX

(這個函數的最後,其實放在這個函數的哪裏都行)

MT_UartInit(); //added by kennan

MT_UartRegisterTaskID(GenericApp_TaskID);

再看壹下MT_UartRegisterTaskID(GenericApp_TaskID):

void MT_UartRegisterTaskID( byte taskID )

{

App_TaskID = taskID;

}

好了,這樣,我們順利地把串口發來的數據用MT_UartProcessZToolData來處理,並且把處理

後的數據打包發給了任務GenericApp_TaskID。

接下來,我們看壹下在GenericApp_TaskID中如何處理吧。

在GenericApp的主處理函數中:

UINT16 GenericApp_ProcessEvent( byte task_id, UINT16 events )

if ( events & SYS_EVENT_MSG )

{

MSGpkt = (afIncomingMSGPacket_t*)osal_msg_receive( GenericApp_TaskID );

while ( MSGpkt )

{

switch ( MSGpkt->hdr.event )

{

case ZDO_CB_MSG:

GenericApp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );

break;

case KEY_CHANGE:

GenericApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t

*)MSGpkt)->keys );

break;

//增加

Case CMD_SERIAL_MSG:

ProcessUartData((mtOSALSerialData_t *)MSGpkt);

//這個函數妳自己實現吧,想做啥呢?想做啥就做啥。如果想把接

//到的數據發回串口,調用HalUARTWrite就行了。

如果妳不知道如何提取串口消息並處理,我就好人做到底,幫妳實現壹個ProcessUartData()

函數吧。這個函數的作用是把接收到的數據從CM0開始壹直到payload的最後壹個字節發送

給串口回顯,不包括校驗字節噢。

ProcessUartCommand((mtOSALSerialData_t *)MSGpkt)

{ //為了正確地進行下面工作,用mtOSALSerialData_t類型來指向整個zigbee數據包(不是串

//口數據包)

uint8 *pMsg;

pMsg = MSGpkt->msg;

//定義壹個指針,指向真正的串口接收數據存放位置,MSGptk裏面還有壹些別的Header噢。

switch ( MSGpkt->hdr.event )

{

case CMD_SERIAL_MSG://如果是串口消息。。。。

HalLedSet( HAL_LED_RED, HAL_LED_MODE_FLASH );

//用LED燈指示壹下收到數據啦

uint8 *pBuffer;

uint8 datalength;

uint8 i;

//定義幾個變量,為從接收到的串口包裏面提取數據以及寫回串口做準備

datalength = *pMsg++;

//串口包中第壹個字節是數據長度噢

pBuffer = osal_mem_alloc(datalength);

//分配壹塊內存準備把串口消息數據拿出來

if(pBuffer != NULL)

{

for(i = 0;i < datalength; i++)

*pBuffer++ = *pMsg++;

//把消息中的串口數據按照datalength數量挨個撈出來放血(放血啥意思?把池子

//裏面那東西撈出來放血,明白不?

HalUARTWrite(0,pBuffer,datalength);

//撈出來放血的串口數據再寫回串口,也就是送到串口助手顯示

Osal_memfree(pBuffer);

//動態申請的內存記得用完了free壹下噢

}

break;

default:

break;

}

}

說明:因為ZTOOL發過來的數據是有格式的,所以如果妳用串口助手來測試,那麽發的數

據要按照格式來,如果妳不想按那個格式,妳可以自己去修改MT_UartProcessZToolData裏面

的相關程序。這種方法對於想要通過PC來控制zigbee的應用場合非常實用,因為妳PC發過

來的壹般也會有命令和數據,如果不用MT的格式,妳自己也要規範壹個格式,既然MT已

經有了,我們就借用就好。

對於MT_UartProcessZAppData這個處理方法,也就是妳define了ZAPP_P1或ZAPP_P2

的情況,其機制也是類似的,只不過沒有規定格式,妳更自由,這裏我就不多說了。

再有,如果妳真的在測試的時候不知道那麽壹長串數據的xor 結果是多少,也可以去

MT_UartProcessZToolData函數中,找到:

//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 );

//}

把我標紅的幾個位置註釋掉,就不會校驗了,妳也不用算xor結果了,不過發數據的時候

這個位置還是要的,妳隨便填個0好了。

  • 上一篇:元宵燈籠手工制作方法 元宵燈籠手工制作方法介紹
  • 下一篇:喝喜酒紅包封面怎麽寫 紅包封面寫法詳細攻略
  • copyright 2024編程學習大全網