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

zigbee协议栈串口收发 From zigbee菜鸟笔记(十 二)一.串口问题关于串口的一些常识欢迎点击进入串口中断二.协议栈串口发送问题

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

一.串口问题

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

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

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

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

#include "hal_uart.h"
#include "MT_UART.h"

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

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

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

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 );
函数作用:注册串口任务
函数原型:

void MT_UartRegisterTaskID( byte taskID )
{ 
   
  App_TaskID = taskID;
}

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

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
函数原型:

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这时候就处于待处理事件
函数原型:

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):添加头文件 :

#include "hal_uart.h"
#include "MT_UART.h"

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

MT_UartInit();
HalUARTWrite(0,"UART_OPEN_SUFFCESS",sizeof("UART_OPEN_SUFFCESS"));

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

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

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

(一).添加头文件:

#include "hal_uart.h"
#include "MT_UART.h"

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

#define SAMPLEAPP_SEND_PERIODIC_MSG_EVT 0x0001

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

#define UART_EVT 0x0002

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

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我们已经绑定在串口了 并且在这里启动第一个串口。
}

(四)事件仿写

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端.串口回调函数

(一).添加头文件:

#include "hal_uart.h"
#include "MT_UART.h"

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

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

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

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.net/141967.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • jdbc如何连接mysql数据库_sqlplus连接远程数据库

    jdbc如何连接mysql数据库_sqlplus连接远程数据库好多朋友遇到了在本地可以连接mysql数据库,而在jsp页面连接远程mysql数据库而连不上的问题,现总结以下:1.配置远程mysql数据库,使其允许远程tcp/ip连接,开放默认端口(3306) 或者设置为3309,2.创建用户,使其具有在任意HOST连接任意database的权限;3.在jdbc连接串中设置端口,如:jdbc:mysql://192.168.0.2:3309/ic

    2022年10月10日
    0
  • nginx最全教程_nginx使用教程

    nginx最全教程_nginx使用教程location[=|~|~*|^~]patt{}中括号可以不写任何参数,此时称为一般匹配也可以写参数因此,大类型可以分为3种location=patt{}[精准匹配]locationpatt{}[一般匹配]location~patt{}[正则匹配]——————————————–如何发挥作用?:首先看有没有精准匹配…

    2025年5月23日
    1
  • cmd从c盘切换到d盘_cmd怎样切换到d盘

    cmd从c盘切换到d盘_cmd怎样切换到d盘1、按WIN+R键打开运行,输入cmd并回车;2、默认路径为用户文档路径,如果想要切换到C盘中的某个文件夹,比如AppData,可以执行命令cdAppData;3、但如果想切换到D盘,输入cd

    2022年8月2日
    14
  • css画圆弧_css圆角样式

    css画圆弧_css圆角样式CSS3是样式表(stylesheet)语言的最新版本,它的一大优点就是支持圆角。网页设计大师NicholasZakas的最新文章,清晰易懂地解释了CSS3圆角的各个方面,非常值得学习。以下就是我翻译的中文版。=========================================CSS3圆角详解作者:NicholasZakas译者:阮一峰发表日期:2010年12月8日一、CSS3…

    2025年7月25日
    0
  • iPhone6分辨率与适配[通俗易懂]

    (via:sunnyxx’sblog) 分辨率和像素经新xcode6模拟器验证(分辨率为pt,像素为真实pixel):1.iPhone5分辨率320×568,像素640×1136,@2×2.iPhone6分辨率375×667,像素750×1334,@2×3.iPhone6Plus分辨率414×736,像素1242×2208,@3x,(注意,在这个

    2022年4月17日
    73
  • 利用键盘钩子捕捉linux键盘动作,利用键盘钩子捕获Windows键盘动作[通俗易懂]

    利用键盘钩子捕捉linux键盘动作,利用键盘钩子捕获Windows键盘动作[通俗易懂]下载本文示例代码引言  在科研生产中对研制、调试操作的记录是非常有必要而且是有很重要价值的。通过对记录信息的分析,可以在事故发生后准确的分析出事故的起因、操作是否存在失误等许多重要线索。通常需要记录的信息是多种多样的,如环境温度记录、软件运行记录、文件访问记录等等。这里将以键盘信息记录为例来讲述类似的实验信息自动记录的一般实现方法。  由于需要记录当前系统下所有应用程序的键盘录入记录,因此必须采取…

    2022年5月2日
    45

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号