串口,按键,消息,定时器

更新时间:2024-04-24 22:12:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

zigbee3-zstack 串口,按键,消息,定时器

协议栈中的串口接收流程

串口在底层使用的是中断,轮询还是DMA呢??答案从下面这个文件定义的宏可以得知 在C:\\Texas

Instruments\\ZStack-CC2530-2.3.0-1.4.0\\Components\\hal\\target\\CC2530EB\\hal_board_cfg.h

[cpp] view plaincopy

1. //默认开启DMA 2. #ifndef HAL_DMA

3. #define HAL_DMA TRUE 4. #endif 5.

6. //只要定义了以下4个宏,就相当于需要使用串口 7. #ifndef HAL_UART

8. #if (defined ZAPP_P1) || (defined ZAPP_P2) || (defined ZTOOL_P1) || (def

ined ZTOOL_P2)

9. #define HAL_UART TRUE 10. #else

11. #define HAL_UART FALSE 12. #endif 13. #endif 14.

15. // HAL_UART和HAL_DMA都已经定义过了,所以协议栈里的串口默认使用的是DMA,而不是中

16. #if HAL_UART

17. // Always prefer to use DMA over ISR. 18. #if HAL_DMA

19. #ifndef HAL_UART_DMA

20. #if (defined ZAPP_P1) || (defined ZTOOL_P1) 21. #define HAL_UART_DMA 1

22. #elif (defined ZAPP_P2) || (defined ZTOOL_P2) 23. #define HAL_UART_DMA 2 24. #else

25. #define HAL_UART_DMA 1 26. #endif 27. #endif

28. #define HAL_UART_ISR 0 29. #else

30. #ifndef HAL_UART_ISR

31. #if (defined ZAPP_P1) || (defined ZTOOL_P1) 32. #define HAL_UART_ISR 1

33. #elif (defined ZAPP_P2) || (defined ZTOOL_P2) 34. #define HAL_UART_ISR 2 35. #else

36. #define HAL_UART_ISR 1 37. #endif 38. #endif

39. #define HAL_UART_DMA 0 40. #endif 41.

42. // Used to set P2 priority - USART0 over USART1 if both are defined. 43. #if ((HAL_UART_DMA == 1) || (HAL_UART_ISR == 1)) 44. #define HAL_UART_PRIPO 0x00 45. #else

46. #define HAL_UART_PRIPO 0x40 47. #endif 48.

49. #else//否则

50. #define HAL_UART_DMA 0 51. #define HAL_UART_ISR 0 52. #endif

在某个应用的初始化函数中顺序执行下面两个函数,比如在SampleApp_Init函数中, MT_UartInit();

MT_UartRegisterTaskID(task_id);

MT_UartRegisterTaskID//用于给SampleApp注册串口,这样当串口在

MT_UartProcessZToolData(mt_uart.c)发数据到上层时,会发到SampleApp。如果多个app都执行了MT_UartRegisterTaskID,则最后一个注册的有效,因为前面的被覆盖掉了。 void MT_UartRegisterTaskID( byte taskID ) {

App_TaskID = taskID; }

比如,在osalInitTasks函数中

[cpp] view plaincopy

1. void osalInitTasks( void ) 2. {

3. uint8 taskID = 0; 4.

5. tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);

6. osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt)); 7.

8. macTaskInit( taskID++ ); 9. nwk_init( taskID++ ); 10. Hal_Init( taskID++ ); 11. #if defined( MT_TASK )

12. MT_TaskInit( taskID++ );//会执行MT_UartRegisterTaskID函数 13. #endif

14. APS_Init( taskID++ );

15. #if defined ( ZIGBEE_FRAGMENTATION ) 16. APSF_Init( taskID++ ); 17. #endif

18. ZDApp_Init( taskID++ );

19. #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT ) 20. ZDNwkMgr_Init( taskID++ ); 21. #endif

22. SampleApp_Init( taskID );//会执行MT_UartRegisterTaskID函数,把MT_TaskInit函

数注册的串口覆盖掉了。串口有数据发给上层时,SampleApp会收到消息。 23. }

MT_UartInit将会指定串口有数据到来时,调用哪个callback函数来处理。如果在option的preprocessor中定义了ZTOOL_P1即串口0(cc2530有2个串口,ZTOOL_P2或ZAPP_P2代表串口1),则调用的是MT_UartProcessZToolData,见下面

[cpp] view plaincopy

1. /***************************************************************************

************************ 2. * @fn MT_UartInit 3. *

4. * @brief Initialize MT with UART support 5. *

6. * @param None 7. *

8. * @return None

9. ****************************************************************************

***********************/ 10. void MT_UartInit () 11. {

12. halUARTCfg_t uartConfig; 13.

14. /* Initialize APP ID */ 15. App_TaskID = 0; 16.

17. /* UART Configuration */

18. uartConfig.configured = TRUE;

19. uartConfig.baudRate = MT_UART_DEFAULT_BAUDRATE; 20. uartConfig.flowControl = MT_UART_DEFAULT_OVERFLOW; 21. uartConfig.flowControlThreshold = MT_UART_DEFAULT_THRESHOLD; 22. uartConfig.rx.maxBufSize = MT_UART_DEFAULT_MAX_RX_BUFF; 23. uartConfig.tx.maxBufSize = MT_UART_DEFAULT_MAX_TX_BUFF; 24. uartConfig.idleTimeout = MT_UART_DEFAULT_IDLE_TIMEOUT; 25. uartConfig.intEnable = TRUE; 26. #if defined (ZTOOL_P1) || defined (ZTOOL_P2)

27. uartConfig.callBackFunc = MT_UartProcessZToolData; 28. #elif defined (ZAPP_P1) || defined (ZAPP_P2)

29. uartConfig.callBackFunc = MT_UartProcessZAppData; 30. #else

31. uartConfig.callBackFunc = NULL; 32. #endif 33.

34. /* Start UART */

35. #if defined (MT_UART_DEFAULT_PORT)//默认串口,如果定义了ZTOOL_P1则是串口0,

ZTOOL_P2则是串口1

36. HalUARTOpen (MT_UART_DEFAULT_PORT, &uartConfig); 37. #else

38. /* Silence IAR compiler warning */ 39. (void)uartConfig; 40. #endif 41.

42. /* Initialize for ZApp */

43. #if defined (ZAPP_P1) || defined (ZAPP_P2) 44. /* Default max bytes that ZAPP can take */ 45. MT_UartMaxZAppBufLen = 1;

46. MT_UartZAppRxStatus = MT_UART_ZAPP_RX_READY; 47. #endif 48. 49. }

MT_UartProcessZToolData用于处理串口接收缓冲区的数据,pMsg->msg的结构体的数据

如下

[cpp] view plaincopy

1. /***************************************************************************

************************

2. * @fn MT_UartProcessZToolData 3. *

4. * @brief | SOP | Data Length | CMD | Data | FCS | 5. * | 1 | 1 | 2 | 0-Len | 1 | 6. *

7. * Parses the data and determine either is SPI or just simply seria

l data

8. * then send the data to correct place (MT or APP) 9. *

10. * @param port - UART port

11. * event - Event that causes the callback 12. * 13. *

14. * @return None

15. ***************************************************************************

************************/

16. void MT_UartProcessZToolData ( uint8 port, uint8 event ) 17. {

18. uint8 ch;

19. uint8 bytesInRxBuffer; 20.

21. (void)event; // Intentionally unreferenced parameter 22.

23. while (Hal_UART_RxBufLen(port)) 24. {

25. HalUARTRead (port, &ch, 1);//每次读一个字节 26.

27. switch (state) 28. {

29. case SOP_STATE://0

30. if (ch == MT_UART_SOF)// 如果读到的字符时Start-of-frame即0xFE,则进入

LEN_STAT状态,进行读LEN

31. state = LEN_STATE; 32. break; 33.

34. case LEN_STATE://1

35. LEN_Token = ch;//消息的长度 36.

37. tempDataLen = 0; 38.

39. /* Allocate memory for the data */

40. pMsg = (mtOSALSerialData_t *)osal_msg_allocate( sizeof ( mtOSALSeria

lData_t ) +

41. MT_RPC_FRAME_HDR_SZ

+ LEN_Token ); 42.

43. if (pMsg) 44. {

45. /* Fill up what we can */

46. pMsg->hdr.event = CMD_SERIAL_MSG; 47. pMsg->msg = (uint8*)(pMsg+1);

48. pMsg->msg[MT_RPC_POS_LEN] = LEN_Token;//pMsg->msg[0]=len 49. state = CMD_STATE1;//读完长度,就进入CMD_STATE1状态,进行读命令 50. } 51. else 52. {

53. state = SOP_STATE; 54. return; 55. } 56. break; 57.

58. case CMD_STATE1:

59. pMsg->msg[MT_RPC_POS_CMD0] = ch;//pMsg->msg[1]=命令低字节 60. state = CMD_STATE2; 61. break; 62.

63. case CMD_STATE2:

64. pMsg->msg[MT_RPC_POS_CMD1] = ch;//pMsg->msg[2]=命令高字节 65. /* If there is no data, skip to FCS state */ 66. if (LEN_Token) 67. {

68. state = DATA_STATE;//读完命令,如果数据长度不为0,就进入DATA_STATE状

态,进行读数据 69. } 70. else 71. {

72. state = FCS_STATE;//否则进入FCS_STATE状态,进行校验 73. } 74. break; 75.

76. case DATA_STATE: 77.

78. /* Fill in the buffer the first byte of the data */ 79. pMsg->msg[MT_RPC_FRAME_HDR_SZ + tempDataLen++] = ch; 80.

81. /* Check number of bytes left in the Rx buffer */ 82. bytesInRxBuffer = Hal_UART_RxBufLen(port); 83.

84. /* If the remain of the data is there, read them all, otherwise, jus

t read enough,读数量较小的数据 */

85. if (bytesInRxBuffer <= LEN_Token - tempDataLen)//如果剩余数据<=len-已

读长度,全部读出 86. {

87. HalUARTRead (port, &pMsg->msg[MT_RPC_FRAME_HDR_SZ + tempDataLen],

bytesInRxBuffer);

88. tempDataLen += bytesInRxBuffer; 89. }

90. else//否则只读出(len-已读长度)的数据 91. {

92. HalUARTRead (port, &pMsg->msg[MT_RPC_FRAME_HDR_SZ + tempDataLen],

LEN_Token - tempDataLen);

93. tempDataLen += (LEN_Token - tempDataLen); 94. } 95.

96. /* If number of bytes read is equal to data length, time to move on

to FCS */

97. if ( tempDataLen == LEN_Token ) 98. state = FCS_STATE; 99.

100. break; 101.

102. case FCS_STATE: 103.

104. FSC_Token = ch; 105.

106. /* Make sure it's correct */

107. if ((MT_UartCalcFCS ((uint8*)&pMsg->msg[0], MT_RPC_FRAME_HDR_SZ + L

EN_Token) == FSC_Token))//计算fcs 108. {

109. osal_msg_send( App_TaskID, (byte *)pMsg );

110. } 111. else 112. {

113. /* deallocate the msg */

114. osal_msg_deallocate ( (uint8 *)pMsg ); 115. } 116.

117. /* Reset the state, send or discard the buffers at this point */ 118. state = SOP_STATE; 119.

120. break; 121.

122. default: 123. break; 124. } 125. } 126. }

所以如果PC发数据给zigbee串口,需要先发送FE...或者修改这个MT_UartProcessZToolData函数以适应自己的应用

协议栈中的串口发送流程

在某个app_init()中初始化和注册串口(如果此app不需要接收数据,可以不用注册) 直接使用如下代码发送数据即可

HalUARTWrite(0,\

如果在opention中定义了MT_TASK,则在发送实际的数据之前会发送一个11字节的数据头(下行红色数据),在PC接收到如下形式的数据:

FE 06 41 80 01 02 00 02 03 00 C5 48 65 6C 6C 6F 20 57 6F 72 6C 64 0A 后面黑色字体的12个字节才是真正的数据

将MT_TASK取消定义则直接发送真实的数据

协议栈中的按键流程

以其为例C:\\Texas

Instruments\\ZStack-CC2530-2.3.0-1.4.0\\Projects\\zstack\\Samples\\SampleApp

1.在main函数中会执行InitBoard(),用于初始化led和按键 OnBoard.c

[cpp] view plaincopy

1. void InitBoard( uint8 level ) 2. {

3. if ( level == OB_COLD ) 4. {

5. // Interrupts off

6. osal_int_disable( INTS_ALL ); 7. // Turn all LEDs off

8. HalLedSet( HAL_LED_ALL, HAL_LED_MODE_OFF ); 9. // Check for Brown-Out reset 10. ChkReset(); 11. }

12. else // !OB_COLD 13. {

14. /* Initialize Key stuff */

15. OnboardKeyIntEnable = HAL_KEY_INTERRUPT_ENABLE;//此处需要使能按键中断 16. HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);//配置按键终端产生

之后,触发OnBoard_KeyCallback函数 17. } 18. }

配置函数HalKeyConfig,用于配置哪个按键(哪个端口)

回调函数OnBoard_KeyCallback,此函数执行OnBoard_SendKeys,将按键事件发给上层注册按键的应用

2.在SampleApp_Init()函数中注册按键,这样以后有按键事件发生时,才会将消息发送到SampleApp应用

RegisterForKeys( SampleApp_TaskID ); 如果按键已被注册,则后来注册的就会失败。 uint8 RegisterForKeys( uint8 task_id ) {

// Allow only the first task

if ( registeredKeysTaskID == NO_TASK_ID ) {

registeredKeysTaskID = task_id; return ( true ); } else

return ( false ); }

类似于注册串口,但串口刚好相反。

协议栈中的消息流程

3个不得不知道的结构体

[cpp] view plaincopy

1. typedef struct 2. {

3. void *next; 4. uint16 len; 5. uint8 dest_id; 6. } osal_msg_hdr_t; 7.

8. typedef struct 9. {

10. uint8 event; 11. uint8 status; 12. } osal_event_hdr_t; 13.

14. typedef void * osal_msg_q_t;

[cpp] view plaincopy

1. //无线收到数据向上层发送的消息 2. typedef struct 3. {

4. osal_event_hdr_t hdr; /* OSAL Message header */

5. uint16 groupId; /* Message's group ID - 0 if not set */ 6. uint16 clusterId; /* Message's cluster ID */

7. afAddrType_t srcAddr; /* Source Address, if endpoint is STUBAPS_INTER_

PAN_EP,

8. it's an InterPAN message */

9. uint16 macDestAddr; /* MAC header destination short address */ 10. uint8 endPoint; /* destination endpoint */

11. uint8 wasBroadcast; /* TRUE if network destination was a broadcast a

ddress */

12. uint8 LinkQuality; /* The link quality of the received data frame *

/

13. uint8 correlation; /* The raw correlation value of the received dat

a frame */

14. int8 rssi; /* The received RF power in units dBm */ 15. uint8 SecurityUse; /* deprecated */

16. uint32 timestamp; /* receipt timestamp from MAC */ 17. afMSGCommandFormat_t cmd; /* Application Data */ 18. } afIncomingMSGPacket_t; 19.

20. //按键按下时向上层发送的消息格式 21. typedef struct 22. {

23. osal_event_hdr_t hdr;

24. uint8 state; // shift 25. uint8 keys; // keys 26. } keyChange_t; 27.

28. //串口接到数据向上层发送的消息 29. typedef struct 30. {

31. osal_event_hdr_t hdr; 32. uint8 *msg; 33. } mtOSALSerialData_t;

13. uint8 correlation; /* The raw correlation value of the received dat

a frame */

14. int8 rssi; /* The received RF power in units dBm */ 15. uint8 SecurityUse; /* deprecated */

16. uint32 timestamp; /* receipt timestamp from MAC */ 17. afMSGCommandFormat_t cmd; /* Application Data */ 18. } afIncomingMSGPacket_t; 19.

20. //按键按下时向上层发送的消息格式 21. typedef struct 22. {

23. osal_event_hdr_t hdr;

24. uint8 state; // shift 25. uint8 keys; // keys 26. } keyChange_t; 27.

28. //串口接到数据向上层发送的消息 29. typedef struct 30. {

31. osal_event_hdr_t hdr; 32. uint8 *msg; 33. } mtOSALSerialData_t;

本文来源:https://www.bwwdw.com/article/hsgp.html

Top