修改协议栈内容来同时使用两个串口

方法一

 

 

协议栈版本:ZStack-2007(ZStack-CC2530-2.5.1a)。

芯片型号:CC2530。

 

 

我们在使用ZigBee时通常只用到一个串口,但是在某些情况下希望同时使用两个串口。ZStack默认只能使用一个串口。不过我们可以通过修改协议栈内容来同时使用两个串口。

 

首先来看一下为什么ZStack只能使用一个串口():

MT_UART.h头文件中:

#if defined (MT_UART_DEFAULT_PORT)

 HalUARTOpen (MT_UART_DEFAULT_PORT, &uartConfig);

#else

  /*Silence IAR compiler warning */

 (void)uartConfig;

#endif

 

//定义了ZTOOL_P1

#if defined (ZTOOL_P1) || defined(ZTOOL_P2)      //DMA方式

 #define MT_UART_DEFAULT_PORT          ZTOOL_PORT

#elif defined (ZAPP_P1) || defined(ZAPP_P2) //ISR方式

 #define MT_UART_DEFAULT_PORT          ZAPP_PORT

#endif

 

 

#if defined (ZTOOL_P1)

 #define ZTOOL_PORT  HAL_UART_PORT_0//串口0

#elif defined (ZTOOL_P2)

 #define ZTOOL_PORT HAL_UART_PORT_1//串口1

#else

 #undef ZTOOL_PORT

#endif

 

该头文件中定义了一个默认UART串口端口,从第二段  #if defined (ZTOOL_P1) ||defined (ZTOOL_P2)      //DMA方式

开始,由于使用了if-else结构,如果定义了ZTOOL_P1或者ZTOOL_P2,那么默认端口为ZTOOL_PORT,在这种情况下ISR方式就不会再出现了。如果没有使用DMA方式,并且定义了ZAPP_P1或者ZAPP_P2,则采用ISR方式。

接下来看第三段:如果定义了ZTOOL_P1,则ZTOOL_PORT为HAL_UART_PORT_0串口0,否则如果定义了ZTOOL_P2,则为串口1。该结构仍采用了if-else结构,也就是说使用了串口0就不会再用到串口1。

那么我们可以得出这样的结论,使用了DMA方式就不能再用ISR方式,使用了串口0就不能再用串口1。当然这只是默认串口,默认串口只能有一个。这个似乎和使用两个串口没什么关系,只是使用两个串口就不能再采用默认串口这一说了。

 

下面再看hal_board_cfg.h中的这样一段:

//如果在没有定义HAL_UART且定义了ZAPP_P、ZAPP_P2、ZTOOL_P1、ZTOOL_P2那么定义HAL_UARTTRUE;否则定义HAL_UART FALSE

#ifndef HAL_UART

#if (defined ZAPP_P1) || (defined ZAPP_P2) || (defined ZTOOL_P1) ||(defined ZTOOL_P2)

#define HAL_UART TRUE

#else

#define HAL_UART FALSE

#endif

#endif

 

 

//如果HAL_UART为真并且没有定义HAL_UART_DMA,并且HAL_DMA为真并且定义了ZAPP_P2、 ZTOOL_P2那么 定义HAL_UART_DMA  2否则定义HAL_UART_DMA  1

#if HAL_UART

#ifndef HAL_UART_DMA

#if HAL_DMA

#if (defined ZAPP_P2) || (defined ZTOOL_P2)

#define HAL_UART_DMA  2

#else

#define HAL_UART_DMA  1

#endif

#else

#define HAL_UART_DMA  0

#endif

#endif

 

 

#ifndef HAL_UART_ISR

#if HAL_UART_DMA        //Default preference for DMA over ISR.

#define HAL_UART_ISR  0

#elif (defined ZAPP_P2) || (defined ZTOOL_P2)

#define HAL_UART_ISR  2

#else

#define HAL_UART_ISR  1

#endif

#endif

 

第一段的意思是如果定义了ZTOOL_P1等四个当中的一个,那么就HAL_UART即为真。即串口可用。

在该头文件上仔细找可以找到该句:

#ifndef HAL_DMA

#define HAL_DMA TRUE

#endif

那么对于第二段,我们可以得出这样的结论:只要是定义了ZTOOL_P1等四个当中的一个,那么HAL_UART_DMA的逻辑值就为1否则为0。

 

而对于第三段只要HAL_UART_DMA的逻辑值为1,则ISR不可用,注释意为默认DMA优先级高于ISR。

所以对于ZStack来说默认只能使用一个串口。那么想要使用两个串口该怎么办呢?当然是要修改上面的代码了。

 

ZigBee使用两个串口的方法:

 

修改hal_board_cfg.h中的第二三段代码如下:

 

#if HAL_UART

//Always prefer to use DMA over ISR.

#if HAL_DMA

#ifndef HAL_UART_DMA

#if (defined ZAPP_P1)||(defined ZTOOL_P1)

#define HAL_UART_DMA 1

#elif(defined ZAPP_P2)||(defined ZTOOL_P2)

#define HAL_UART_DMA 2

#else

#define HAL_UART_DMA 1

#endif

#endif

#define HAL_UART_ISR 2

#else

#ifndef HAL_UART_ISR

#if(defined ZAPP_P1)||(defined ZTOOL_P1)

#define HAL_UART_ISR 1

#elif(defined ZAPP_P2)||(defined ZTOOL_P2)

#define HAL_UART_ISR 2

#else

#define HAL_UART_ISR 1

#endif

#endif

#define HAL_UART_DMA 0

#endif

(该段代码摘录自网上,使用时定义ZATOOL_P1即可,这样选择了串口0DMA方式,串口1中断方式,如果定义ZAPP_P2可能会产生逻辑问题)

修改后意为如果使用了DMA,则定义相应的通道为DMA方式,同时定义串口1采用中断方式,如果没有定义DMA,则使用中断方式。

修改完以后协议栈已支持同时使用两个串口,但是想要使用还得对串口进行初始化。自带的串口初始化不作改动,默认串口0采用DMA方式,另外需要写一个串口1的初始化函数。函数如下:

void MT_Uart1Init ()

{

 halUARTCfg_t uartConfig1;

 

  /*Initialize APP ID */

 App_TaskID = 0;

 

  /*UART Configuration */

 uartConfig1.configured           =TRUE;

 uartConfig1.baudRate             =MT_UART_DEFAULT_BAUDRATE;

 uartConfig1.flowControl          =MT_UART_DEFAULT_OVERFLOW;

 uartConfig1.flowControlThreshold = 32;

 uartConfig1.rx.maxBufSize        =32;

 uartConfig1.tx.maxBufSize        =32;

 uartConfig1.idleTimeout          =6;

 uartConfig1.intEnable            =TRUE;

 uartConfig1.callBackFunc         =MT_UartProcessZToolData;

 

  /*Start UART */

 HalUARTOpen (HAL_UART_PORT_1, &uartConfig1);

  /*Silence IAR compiler warning */

 

  /*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

 

}

注意红色字体部分:  HalUARTOpen(HAL_UART_PORT_1, &uartConfig1);

初始化打开串口为HAL_UART_PORT_1,其他参数有结构体uartConfig1传给回调函数。当然还需要将该初始化注册到用户应用层。即在用户应用层初始化函数中(例:void SampleApp_Init( uint8 task_id )注:不同的程序应用层初始化函数不同)调用该函数即可。

 

当然还需要回调函数。两个串口初始化均采用同样的回调函数,测试显示只能使用一个回调函数。所以对于串口事件均指定一个处理事件,如果想要两个串口分别对应不同的串口事件,则做如下修改:

 

       if (pMsg)

       {

         /* Fill up what we can */

         if(port == HAL_UART_PORT_0)

         {

           pMsg->hdr.event = CMD_SERIAL_MSG;

         }

         else

         {

           pMsg->hdr.event = CMD_SERIAL1_MSG;

         }

         pMsg->msg = (uint8*)(pMsg+1);

         pMsg->msg[MT_RPC_POS_LEN] = LEN_Token;

         state = CMD_STATE1;

       }

 

在用户应用层加上相应的触发事件及处理函数即可。

由于板子还没有出来,还没有进行测试。

板子测试成功。

 

 

 

 

 

 

 

 

方法二

 

 

前两天因为做东西需要在zstack协议栈下同时使用两个串口,通过参考网上的一些资料,经过一段时间的折腾,算是搞定了,现在把详细的配置方法贴出来跟大家分享,如果有问题的话也希望大家指出来共同进步。

 

 

 

1、在hal_board_cfg.h中,更改#define HAL_UART_ISR  0为#define HAL_UART_ISR 2,使用uart1为中断方式,在P1口,因此,全局来看,串口0为DMA方式,在P0口,串口1为ISR方式,在P1口。

 

 

 

 

 

2、更改MT_UARTInit函数中开启串口程序部分如下:

 

 

 

#if defined(MT_UART_DEFAULT_PORT)

 

  HalUARTOpen (MT_UART_DEFAULT_PORT,&uartConfig);

 

  HalUARTOpen (HAL_UART_PORT_1,&uartConfig);

 

#else

 

 

 

 

 

3、关于分别处理两个串口的数据问题:

 

在MT_UART.c中加入串口区分,在MT_UartProcessZToolData函数中登记串口事件时加入串口区分,如下:

 

if(port==0)

 

    pMsg->hdr.event = CMD_SERIAL_MSG_0;

 

  else if(port==1)

 

    pMsg->hdr.event = CMD_SERIAL_MSG_1;

 

CMD_SERIAL_MSG_0为串口0数据处理,CMD_SERIAL_MSG_1为串口1数据处理,需要更改相应的宏定义,在MT.h中更改

 

/* Message CommandIDs */

 

#defineCMD_SERIAL_MSG_0                  0x01

 

#defineCMD_SERIAL_MSG_1                  0x07

 

 

 

 

 

 

 

4、更改MT_TASK.c中MT_ProcessIncomingCommand函数在switch语句中加入串口区分,如下

 

switch (msg->hdr.event )

 

  {

 

    case CMD_SERIAL_MSG_0:

 

      MT_ProcessIncoming(msg->msg);

 

      break;

 

     

 

    case CMD_SERIAL_MSG_1:

 

      MT_ProcessIncoming(msg->msg);

 

      break;

 

 

 

 

 

 

 

 

 

5、用户可以通过修改SampleApp.c中的SampleApp_ProcessEvent函数来实现处理两个不同串口的数据,如下:

 

switch (MSGpkt->hdr.event )

 

      {

 

        case CMD_SERIAL_MSG_0:  

 

        SampleApp_SerialCMD((mtOSALSerialData_t *)MSGpkt);

 

         break;

 

        case CMD_SERIAL_MSG_1: 

 

         SampleApp_SerialCMD((mtOSALSerialData_t*)MSGpkt);

 

         break;

 

串口处理函数可根据网蜂教程自行编写实现相应的功能。

 

 

 

 

 

 

 

好啦,到这里就配置完成了,希望能改需要的朋友一些帮助,同时如果有问题的话还请各位不吝赐教,批评指正,共同进步。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
课程背景Modbus 协议是工业自动化控制系统中常见的通信协议,协议的全面理解是个痛点。本课程主讲老师集10多年在Modbus协议学习、使用中的经验心得,结合当前物联网浪潮下Modbus协议开发的痛点,推出这套面向Modbus 协议初学者的课程。本课程不同于以往市面课程只是协议讲解无实现代码,而是采用讲解与实践并重的方式,结合STM32F103ZET6开发板进行手把手编程实践,十分有利于初学者学习。涵盖了学习者在Modbus协议方面会遇到的方方面面的问题,是目前全网首个对Modbus协议进行全面总结的课程。课程名称   协议讲解及实现>>课程内容1、Modbus 协议的基础。2、Modbus协议栈函数编程实现。3、Modbus协议在串行链路编程实现。4、Modbus协议在以太网链路编程实现。5、常见问题的解决方法。带给您的价值通过学习本课程,您可以做到如下:1、全面彻底的理解Modbus协议。2、理解在串行链路,以太网链路的实现。3、掌握Modbus协议解析的函数编程方法,调试工具的使用。4、掌握多个串口,网口同时运行同一个Modbus协议栈的方法。5、掌握Modbus协议下,负数,浮点数等处理方法。讲师简介许孝刚,山东大学工程硕士,副高职称,技术总监。10多年丰富嵌入式系统开发经验,国家软考“嵌入式系统设计师”。2017年获得“华为开发者社区杰出贡献者”奖励。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值