12 在ZStack里实现uart数据接收功能

在上一篇已经实现uart数据输出功能了,但接收数据时尚未搞好的。
在MT任务里已实现当有uart数据需接收时,自动调用函数MT_UartProcessZToolData来处理数据的接收,接收数据后通过发出消息的方法把数据传递到用户任务里去。

void MT_UartProcessZToolData ( uint8 port, uint8 event ) //
{
  uint8  ch;
  uint8  bytesInRxBuffer;

  (void)event;  // Intentionally unreferenced parameter

  while (Hal_UART_RxBufLen(port)) //判断是否已经有数据接收
  {
    HalUARTRead (port, &ch, 1); //接收数据
    ...

   osal_msg_send( App_TaskID, (byte *)pMsg ); //通过给用户任务发消息的方式传递串口接收到的数据
  }
  ...
}


但MT_UartProcessZToolData会对接收到数据进行加工处理的,MT层有自己的一套协议。为了省事,我们自己改造下函数好了。

typedef struct
{
  osal_event_hdr_t  hdr; //都是这种头部
  uint8             *msg;
} mtOSALSerialData_t; //串口数据消息的类型

void MT_UartProcessZToolData ( uint8 port, uint8 event )
{

  uint8 ch, *p;

  uint8 len = Hal_UART_RxBufLen(port); //先获取需要接收的数据长度

  if (len <= 0) //如果没有数据接收则直接返回
    return;


  pMsg = (mtOSALSerialData_t *)osal_msg_allocate(sizeof(mtOSALSerialData_t)+len+1); 
  //准备消息的缓冲区,len表示串口数据长度, 多加的一个字节用于存放此次接收的数据长度。 
  pMsg->msg = (uint8 *)(pMsg+1); //msg指向数据的开始存放位置
  p = &(pMsg->msg[1]); //保留一个字节位置用于存放接收的数据长度
  len = HalUARTRead (port, p, len); //接收数据

  pMsg->msg[0] = len;  //记录数据长度。 存放的格式: "消息结构体内容" + "长度" + "接收到的数据内容"
  pMsg->hdr.event = CMD_SERIAL_MSG; //设置消息类型
  osal_msg_send( App_TaskID, (byte *)pMsg ); //发出消息
}


实现接收到串口数据后, 重新发回去的功能.
MyApp.c

#include "OnBoard.h"
#include "MyApp.h"
#include "hal_led.h"
#include "hal_key.h"
#include "MT_UART.h"
#include "hal_uart.h"
#include "MT.h"


#define TIME_OUT_EVENT 0x4
#define TIME_LEN       2000

uint8  mytask_id; //用于存放本身的任务号


void MyApp_Init(uint8 task_id )
{
   mytask_id = task_id; 

   RegisterForKeys(mytask_id); //设置当前任务接收按键消息
   MT_UartRegisterTaskID(mytask_id);//指定当MT任务接收到串口数据时,传递到本任务来
}



uint16 MyApp_ProcessEvent(uint8 task_id, uint16 events )
{
  keyChange_t *key_evt;

  if ( events & SYS_EVENT_MSG ) //当有按键消息时,任务的事件会是SYS_EVENT_MSG
  {
    key_evt = (keyChange_t *)osal_msg_receive(mytask_id);

    while (key_evt)
    {
      if (key_evt->hdr.event == KEY_CHANGE) //按键事件
      {                
          if (key_evt->keys  &  HAL_KEY_SW_1)
              HalUARTWrite(HAL_UART_PORT_0, "btn1\n\r", 6);
          if (key_evt->keys  &  HAL_KEY_SW_2)
              HalUARTWrite(HAL_UART_PORT_0, "btn2\n\r", 6);
      }
      if (key_evt->hdr.event == CMD_SERIAL_MSG) //串口接收数据事件
      {
           mtOSALSerialData_t *p = (mtOSALSerialData_t *)key_evt;
           HalUARTWrite(HAL_UART_PORT_0, &p->msg[1], p->msg[0]); //把接收到的数据重新发回去      
      }

      osal_msg_deallocate( (uint8 *)key_evt ); //回收消息的空间
      key_evt = (keyChange_t *)osal_msg_receive(mytask_id); //再次接收本任务的消息
    }
  }    

  if (events & TIME_OUT_EVENT) //定时器的事件
  {
     ;
  }

  return 0;
}


注意如需实现像接收到”leds on\n”这样的命令后操作硬件的功能,则需在串口接收数据事件里先把接收到数据暂存起来,直到接收到’\r’符号(window上传过来的是’\n’)为止.

MyApp.c

#include "OnBoard.h"
#include "MyApp.h"
#include "hal_led.h"
#include "hal_key.h"
#include "MT_UART.h"
#include "hal_uart.h"
#include "MT.h"
#include "stdio.h"
#include "string.h"


#define TIME_OUT_EVENT 0x4
#define TIME_LEN       2000
#define LEN            100

uint8  mytask_id; //用于存放本身的任务号
uint8 *line;
uint8 len_rcv;

void MyApp_Init(uint8 task_id )
{
   mytask_id = task_id; 

   RegisterForKeys(mytask_id); //设置当前任务接收按键消息
   MT_UartRegisterTaskID(mytask_id);//指定当MT任务接收到串口数据时,传递到本任务来

   line = osal_msg_allocate(LEN);
   len_rcv = 0;
}



uint16 MyApp_ProcessEvent(uint8 task_id, uint16 events )
{
  keyChange_t *key_evt;

  if ( events & SYS_EVENT_MSG ) //当有按键消息时,任务的事件会是SYS_EVENT_MSG
  {
    key_evt = (keyChange_t *)osal_msg_receive(mytask_id);

    while (key_evt)
    {
      if (key_evt->hdr.event == KEY_CHANGE) //按键事件
      {                
          if (key_evt->keys  &  HAL_KEY_SW_1)
              HalUARTWrite(HAL_UART_PORT_0, "btn1\n\r", 6);
          if (key_evt->keys  &  HAL_KEY_SW_2)
              HalUARTWrite(HAL_UART_PORT_0, "btn2\n\r", 6);
      }
      if (key_evt->hdr.event == CMD_SERIAL_MSG) //串口接收数据事件
      {
           mtOSALSerialData_t *p = (mtOSALSerialData_t *)key_evt;
           uint8 *d = &p->msg[1];
           if (d[p->msg[0] - 1] != '\r') //接收到'\r'为止
           {
              memcpy(line + len_rcv, d, p->msg[0]);
              len_rcv += p->msg[0];
           }
           else //接收到'\r'符号后输出内容
           {
              HalUARTWrite(HAL_UART_PORT_0, line, len_rcv); //把接收到的数据发回去
              HalUARTWrite(HAL_UART_PORT_0, "\n\r", 2); 
              len_rcv = 0;
           }
      }

      osal_msg_deallocate( (uint8 *)key_evt ); //回收消息的空间
      key_evt = (keyChange_t *)osal_msg_receive(mytask_id); //再次接收本任务的消息
    }
  }    

  if (events & TIME_OUT_EVENT) //定时器的事件
  {
     ;
  }

  return 0;
}
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值