前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >zigbee协议栈串口收发 From zigbee菜鸟笔记(十 二)

zigbee协议栈串口收发 From zigbee菜鸟笔记(十 二)

作者头像
全栈程序员站长
发布2022-09-01 15:20:07
8760
发布2022-09-01 15:20:07
举报

大家好,又见面了,我是你们的朋友全栈君。

一.串口问题

有问题发送邮件至468078841@qq.com

关于串口的一些常识欢迎点击进入串口中断

二.协议栈串口需用函数解读

这部分主要讲述串口发送问题在协议栈中

代码语言:javascript
复制
#include "hal_uart.h"
#include "MT_UART.h"

这两个文件中封装着关于串口的API函数

关于串口的日常收发问题我们主要使用以下的几个函数

(一)在#include "MT_UART.h"函数中 函数名:MT_UartInit 函数作用:MT层初始化串口 函数原型:

代码语言:javascript
复制
void MT_UartInit ()
{ 
   
  halUARTCfg_t uartConfig;

  /* Initialize APP ID */
  App_TaskID = 0;

  /* UART Configuration */
  uartConfig.configured           = TRUE;//确定配置
  uartConfig.baudRate             = MT_UART_DEFAULT_BAUDRATE; //这里是波特率
  uartConfig.flowControl          = MT_UART_DEFAULT_OVERFLOW;//流控
  uartConfig.flowControlThreshold = MT_UART_DEFAULT_THRESHOLD;//在RX缓存达到maxRxBufSize之前还有多少字节空余。当到达maxRxBufSize –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;
#elif defined (ZAPP_P1) || defined (ZAPP_P2)
  uartConfig.callBackFunc         = MT_UartProcessZAppData;
#else
  uartConfig.callBackFunc         = NULL;     //回调函数 这个很有用
#endif

  /* Start UART */
#if defined (MT_UART_DEFAULT_PORT)
  HalUARTOpen (MT_UART_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 */
  MT_UartMaxZAppBufLen  = 1;
  MT_UartZAppRxStatus   = MT_UART_ZAPP_RX_READY;
#endif

}

(二)函数名:extern void MT_UartRegisterTaskID( uint8 taskID ); 函数作用:注册串口任务 函数原型:

代码语言:javascript
复制
void MT_UartRegisterTaskID( byte taskID )
{ 
   
  App_TaskID = taskID;
}

(三)在#include "hal_uart.h"文件中 函数名:extern uint16 HalUARTRead ( uint8 port, uint8 *pBuffer, uint16 length ); 函数作用:读取 port 串口 将 length 字节内容读取到 pBuffer 函数原型:

代码语言:javascript
复制
uint16 HalUARTRead(uint8 port, uint8 *buf, uint16 len)
{ 
   
  (void)port;
  (void)buf;
  (void)len;

#if (HAL_UART_DMA == 1)
  if (port == HAL_UART_PORT_0)  return HalUARTReadDMA(buf, len);
#endif
#if (HAL_UART_DMA == 2)
  if (port == HAL_UART_PORT_1)  return HalUARTReadDMA(buf, len);
#endif
#if (HAL_UART_ISR == 1)
  if (port == HAL_UART_PORT_0)  return HalUARTReadISR(buf, len);
#endif
#if (HAL_UART_ISR == 2)
  if (port == HAL_UART_PORT_1)  return HalUARTReadISR(buf, len);
#endif

#if HAL_UART_USB
  return HalUARTRx(buf, len);
#else
  return 0;
#endif
}

(四)函数名:extern uint16 HalUARTWrite ( uint8 port, uint8 *pBuffer, uint16 length ); 函数作用:将 length 字节长度的 pBuffer 发送到串口 port 函数原型:

代码语言:javascript
复制
uint16 HalUARTWrite(uint8 port, uint8 *buf, uint16 len)
{ 
   
  (void)port;
  (void)buf;
  (void)len;
,
,
,

#if (HAL_UART_ISR == 2)
  if (port == HAL_UART_PORT_1)  return HalUARTWriteISR(buf, len);
  HalUARTTx(buf, len);
  return len;
#else
  return 0;
#endif
}

(五)在OSAL.h文件中 函数名:uint8 osal_set_event( uint8 task_id, uint16 event_flag ) 函数作用:将 task_id 事件 event_flag 标志位置1这时候就处于待处理事件 函数原型:

代码语言:javascript
复制
uint8 osal_set_event( uint8 task_id, uint16 event_flag )
{ 
   
  if ( task_id < tasksCnt )
  { 
   
    halIntState_t   intState;
    HAL_ENTER_CRITICAL_SECTION(intState);    // Hold off interrupts
    tasksEvents[task_id] |= event_flag;  // Stuff the event bit(s)
    HAL_EXIT_CRITICAL_SECTION(intState);     // Release interrupts
    return ( SUCCESS );
  }
   else
  { 
   
    return ( INVALID_TASK );
  }
}

三.在协议栈中发送

(1):添加头文件 :

代码语言:javascript
复制
#include "hal_uart.h"
#include "MT_UART.h"

在系统事件初始化函数SampleApp_Init中加上串口初始化函数

代码语言:javascript
复制
MT_UartInit();
HalUARTWrite(0,"UART_OPEN_SUFFCESS",sizeof("UART_OPEN_SUFFCESS"));

关于串口0 串口1的问题可以看这里串口中断 这时将代码烧写进入2530中,每次重启,设备都会发送UART_OPEN_SUFFCESS到上位机,关于串口初始化杂乱消息解决方向会在后续出教程解决。

四.将PC端发送的消息回传PC端.事件监控

在前面一节我们知道了协议栈对于消息的处理是基于事件轮询模式,但是在初始自带中只有按键和RF等并没有串口事件,那我们如何添加自己的事件,让接收到的消息回传呢

(一).添加头文件:

代码语言:javascript
复制
#include "hal_uart.h"
#include "MT_UART.h"

(二)自己定义串口事件 在uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )函数里自带了一个SAMPLEAPP_SEND_PERIODIC_MSG_EVT事件,我们goto一下,可以看到事件定义为

代码语言:javascript
复制
#define SAMPLEAPP_SEND_PERIODIC_MSG_EVT 0x0001

我们仿照自带的类型仿写 在这里我们要介绍一下这里的事件大小是二进制移位然后转16进制进行表示那我我们的接着就是0x0002 0x0004 等等,在这里我们添加自己的串口事件

代码语言:javascript
复制
#define UART_EVT 0x0002

(三).添加自己的初始化函数 在系统事件初始化函数SampleApp_Init中加上串口初始化函数

代码语言:javascript
复制
void SampleApp_Init( uint8 task_id )
{ 
   
  SampleApp_TaskID = task_id;
  SampleApp_NwkState = DEV_INIT;
  SampleApp_TransID = 0;
  .
  .
  .
  .
  .
 
  // Setup for the flash command's destination address - Group 1
  SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;
  SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
  SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;
  
  // Fill out the endpoint description.
  SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
  Samp
#endif
  HalLedSet( HAL_LED_2, HAL_LED_MODE_ON ); 
  
  
  MT_UartInit(); //
  HalUARTWrite(0,"UART_OPEN_SUFFCESS",sizeof("UART_OPEN_SUFFCESS"));
  MT_UartRegisterTaskID(task_id);//注册串口事件
  osal_set_event(task_id,UART_EVT);//调用此函数来设置任务的事件标志为1 UART_EVT我们已经绑定在串口了 并且在这里启动第一个串口。
}

(四)事件仿写

代码语言:javascript
复制
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{ 
   
  afIncomingMSGPacket_t *MSGpkt;
  (void)task_id;  // Intentionally unreferenced parameter
  
  if ( events & SYS_EVENT_MSG )
  { 
   
    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
    while ( MSGpkt )
    { 
   
     。
     。
     。
     。
     。
     。
     
  
  // Send a message out - This event is generated by a timer
  // (setup in SampleApp_Init()).
  if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
  { 
   
    // Send the periodic message
    SampleApp_SendPeriodicMessage();
    
    // Setup to send message again in normal period (+ a little jitter)
    osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
                       (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );
    
    // return unprocessed events
    return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);
  }
  
  if ( events & UART_EVT )//如果UART_EVT被触发 我们就进入这里
  { 
   
    
    UART_len =  Hal_UART_RxBufLen(0); //先读取串口0 监测是否有消息
    if(UART_len)  //有消息进入这里
    { 
   
      osal_memset(UART_RX,'\0',128);   //将UART_RX内容清空
      HalUARTRead(0,UART_RX,UART_len); //读取消息
      HalUARTWrite(0,UART_RX,UART_len);//发送消息
      UART_len = 0; //清空这次的消息
    }
    
    //定时器执行
    osal_set_event(task_id,UART_EVT);//再次置1 进行消息监控
    // return unprocessed events
    return (events ^ UART_EVT); //将这次消息事件清空
  }
  // Discard unknown events
  return 0;
}

通过上述的操作我们就可以完成常见的串口收发,不过这样写有点麻烦,用这种写过GPRS登录的云端服务器的操作,很麻烦,要考虑很多东西,还容易被优化了。

五.将PC端发送的消息回传PC端.串口回调函数

(一).添加头文件:

代码语言:javascript
复制
#include "hal_uart.h"
#include "MT_UART.h"

(二)自己仿写串口初始化函数,这里可以去MT_UartInit();直接复制到void SampleApp_Init( uint8 task_id )改写

代码语言:javascript
复制
void SampleApp_Init( uint8 task_id )
{ 
   
  SampleApp_TaskID = task_id;
  SampleApp_NwkState = DEV_INIT;
  SampleApp_TransID = 0;
  .
  .
  .
  .
  .
 
  // Setup for the flash command's destination address - Group 1
  SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;
  SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
  SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;
  
  // Fill out the endpoint description.
  SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
  Samp
#endif
  HalLedSet( HAL_LED_2, HAL_LED_MODE_ON ); 
  
  
  halUARTCfg_t uartConfig;//定义个串口结构体
  uartConfig.configured             =TRUE;//串口配置为真
  uartConfig.baudRate               =HAL_UART_BR_115200;//波特率为9600
  uartConfig.flowControl            =FALSE;//流控制为假
  uartConfig.callBackFunc       =    Uart_Callback_Function ;//串口回调函数,当接受检测到串口消息,我们就调用这个函数
  HalUARTOpen(HAL_UART_PORT_0,&uartConfig);// 打开串口0
  HalUARTWrite(0,"UART_OPEN_SUFFCESS",sizeof("UART_OPEN_SUFFCESS"));

}

不要忘记声明函数static void Uart_Callback_Function();

(三)实现串口回调函数 在串口初始化的作用域下,自己随便找个地方写

代码语言:javascript
复制
static void Uart_Callback_Function ()
{ 
   
   UART_len =  Hal_UART_RxBufLen(0); //先读取串口0 长度
    if(UART_len)  //有消息进入这里
    { 
   
      osal_memset(UART_RX,'\0',128);   //将UART_RX内容清空
      HalUARTRead(0,UART_RX,UART_len); //读取消息
      HalUARTWrite(0,UART_RX,UART_len);//发送消息
      UART_len = 0; //清空这次的消息
    }

}

通过上述步骤步骤,算是基本掌握了协议栈的串口问题,在后续将会写一些关于双串口调试的问题,有问题也欢迎大家一起讨论,后续忙完会陆续出一些其他的内容,欢迎提要求哈!

有问题请发邮件至468078841@qq.com

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/141967.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022年5月2,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一.串口问题
  • 二.协议栈串口需用函数解读
  • 三.在协议栈中发送
  • 四.将PC端发送的消息回传PC端.事件监控
  • 五.将PC端发送的消息回传PC端.串口回调函数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档