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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • rsyslog配置日志服务器_linux开启rsyslog

    rsyslog配置日志服务器_linux开启rsyslogRsyslog是一个开源软件实用程序,用于UNIX和类Unix计算机系统,用于在IP网络中转发日志消息,收集日志。它实现了基本的syslog协议,通过基于内容的过滤,丰富的过滤功能,灵活的配置选项扩展了它,并添加了诸如使用TCP进行传输等功能。一、配置环境系统:Debian二、Rsyslog配置基本上Linux系统都安装Rsyslog服务但没有开启,只需要修改配置文件即可使用。首先,如…

  • CSS 边框 阴影 效果

    CSS 边框 阴影 效果

  • java从入门到精通_学习Java最好的10本书,从入门到精通

    java从入门到精通_学习Java最好的10本书,从入门到精通在当代,学习Java等编程课程的主要方式是视频资源。如果你想学,在网上五分钟之内就可以找到一堆学习视频,瞬间将你的硬盘填满。但是这些课程质量良莠不齐,对于小白来说,的确让人头痛不已。但是,书籍不同。对于书籍而言,它们都是出自业内大牛和资深的大学教授的精心编写,内容好坏与否,有很多同领域的网友都能帮你把关。所以说,如果你选对了学习的书籍,就可以不用担心自己在编程中,埋下错误的种子,同时还可以更深入的…

  • MySQL八股文连环45问,你能坚持第几问?「建议收藏」

    MySQL八股文连环45问,你能坚持第几问?「建议收藏」文人从事多年面试工作,将MySQL面试分享给大家,希望大家顺利拿下offer

  • 十进制的ascii码转化为十六进制_16进制对照表

    十进制的ascii码转化为十六进制_16进制对照表源地址:https://www.baidu.com/link?url=3bScEOF5BVXt7ptGDjBV5JmynXHqEh5lyut1vUx6vEM7qqPY1vtbO22Vvy7xUoFd&

  • python字符串比较大小[通俗易懂]

    python字符串比较大小[通俗易懂]理解原理和相关知识字符串按位比较,两个字符串第一位字符的ascii码谁大,字符串就大,不再比较后面的;第一个字符相同就比第二个字符串,以此类推,需要注意的是空格的ascii码是32,空(null)的ascii码是0https://zhidao.baidu.com/question/558202137825309252.htmlord函数接受一个字符print(max([‘1’,’…

发表回复

您的电子邮箱地址不会被公开。

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