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,'
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;
}
'
,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,'
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; //清空这次的消息
}
}
'
,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)


相关推荐

  • HTTP常见的状态码

    HTTP常见的状态码状态码解释200一切正常301永久重定向302临时重定向401用户名或密码错误403禁止访问(客户端IP地址被拒绝404文件不存在414请求URI头部过长500服务器内部错误502BadGateway(错误网关)…

  • docker部署redis哨兵集群_redis部署安装

    docker部署redis哨兵集群_redis部署安装Docker安装Docker部署redis在dockerhub上可以看到有redis的官方镜像不去网站,也可以通过如下命令查看有那些镜像可用Dockersearch命令dockersearchredis拉取redis镜像Dockerpull命令这里我们拉取官方的最新版本的镜像:dockerpullredis:latest查看本地镜像Dockerimages命令有redis和hello-world运行容器Dockerrun命令d

    2022年10月18日
  • 永恒之蓝病毒win7解决方法_win10永恒之蓝漏洞补丁

    永恒之蓝病毒win7解决方法_win10永恒之蓝漏洞补丁简介:NSA武器库的公开被称为是网络世界“核弹危机”,其中有十款影响Windows个人用户的黑客工具,包括永恒之蓝、永恒王者、永恒浪漫、永恒协作、翡翠纤维、古怪地鼠、爱斯基摩卷、文雅学者、日食之翼和尊重审查。这些工具能够远程攻破全球约70%的Windows系统,无需用户任何操作,只要联网就可以入侵电脑,就像冲击波、震荡波等著名蠕虫一样可以瞬间血洗互联网,木马黑产很可能改造NSA的武器…

    2022年10月16日
  • 借助栈来实现单链表的逆置运算_中缀后缀表达式互相转换

    借助栈来实现单链表的逆置运算_中缀后缀表达式互相转换原题链接算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。输入格式:输入在一行中给出不含空格的中缀表达式,可包含+、-、*、\以及左右括号(),表达式不超过20个字符。输出格式:在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。输入样例:2+3*(7-4)+8/4输出样例:2 3 7 4 – * + 8 4 / +注意

  • StringBuffer与StringBuilder的区别_String

    StringBuffer与StringBuilder的区别_String1:StringBuffer、StringBuilder和String一样,也用来代表字符串。String类是不可变类,任何对String的改变都会引发新的String对象的生成;StringBuffer则是可变类,任何对它所指代的字符串的改变都不会产生新的对象。2:HashTable是线程安全的,很多方法都是synchronized方法,而HashMap不是线程安全的,但其在单线程程序中的性能比HashTable要高。3:StringBuffer和StringBuilder类的区..

  • TCP连接异常终止(RST包)场景分析

    TCP连接异常终止(RST包)场景分析一、TCP异常终止(reset报文)TCP的异常终止是相对于正常释放TCP连接的过程而言的,我们都知道,TCP连接的建立是通过三次握手完成的,而TCP正常释放连接是通过四次挥手来完成。但是有些情况下,TCP在交互的过程中会出现一些意想不到的情况,导致TCP无法按照正常的三次握手建立连接或四次挥手来释放连接。如果此时不通过其他的方式来释放TCP连接的话,这个TCP连接将会一直存在,占用系统的资源。在这种情况下,我们就需要有一种能够释放TCP连接的机制,这种机制就是TCP的reset报文。reset报文是指

发表回复

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

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