UART ISR的Tx RX架构 [英] UART ISR Tx Rx Architecture

查看:428
本文介绍了UART ISR的Tx RX架构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是复杂的东西呢?

我在我的架构code从8051微过UART跟外围设备。外围响应从主机到命令,只能在一个时间到一个命令作出响应。这是一个简单的发送和接收协议。 (TX1,RX1,TX2,RX2,TX3,RX3)每个TX消息端接一个CR,每个响应>端接一个。直到我收到的最后一个响应我不能发送新邮件。答复还可以呼应在开始打印原稿TX消息,如果我启用该选项(而这将导致更多的流量)

I'm architecting my code to talk from a 8051 micro to a peripheral device over UART. The peripheral responds to commands from the host and can only respond to one command at a time. It's a simple send and receive protocol. (tx1, rx1, tx2, rx2, tx3, rx3) Each TX message is terminated with a CR, each response is terminated with a >. I can't send a new message until I receive the response to the last one. Responses can also echo print the original TX message in the beginning if I enable that option (but this causes more traffic)

这是示例消息是:


  • TX:你好

  • RX:世界>

或用回声选项...


  • TX:你好

  • RX:您好!\\ rWorld>

选项A
如getHello函数将包括双方的发送和接收。并行ISR例程将收集输入的数据,并在接收到'>'字符时,抛出一个标志。

Option A A function such as getHello would consist of both the send and receive. A parallel ISR routine would gather the incoming bytes and throw a flag when the '>' character is received.

char* getHello(char * buf){
    sendMsg("Hello\r");
    delay(10ms); //wait a little bit

    //wait for receive to come in or timeout to occur
    while(!receiveFlag || !timeoutFlag);  //thrown by ISR
    receiveMsg(buf);
    //parse the message and do some other stuff
    return buf;
}

优点:


  • 一切都包含在一个函数中。

  • 易于调试

缺点:


  • 此功能是阻塞,如果外围从未如此回应超时必须实现都挺。

  • 邮件无法接收失灵,必须在系列(即TX1,RX1,TX2,RX2,TX3,RX3)

选项B
并行的方法是采取。两个单独的函数会创建。一个用于发送该消息,并且一个将vertexed在接收到来自在ISR的响应。

Option B A parallel approach is taken. Two separate functions would created. one to send the message, and one that would vertexed upon receiving a response from the ISR.

void sendHello(){
    sendMsg("Hello\r");
    //do some other stuff if needed
}

char* receiveMsg(char * buf){
    //figure out from echo print what the tx message was
    //use a switch statement to decide which response parser to call
    switch(txMessage){ //pseudo code
    case "Hello":
        receiveMsg(buf);
        //parse the message and do some other stuff
        break;
    }
    return buf;
}

优点:


  • 可以处理并行的消息回来了乱序,因为它依赖于TX消息的回声印刷弄清楚如何解析它。 (即,TX1,TX2,TX3,RX1,RX2,RX3)

缺点:


  • 相当困难的调试

  • 派生多个线程

  • 许多额外的code

  • 不值得的,因为消息一定会回来的,以

现在,我在做选择B,但我继续这个项目,我开始喜欢这种感觉越来越过于复杂。我很好奇你们的想法。

Right now, I'm doing Option B, but as I continue on with the project, I begin to feel like this is getting overly complex. I'm curious what you guys think.

谢谢!

推荐答案

我倾向于做这样的东西,不过,身份证往往有一个独立的串行端口下课(结构+功能)和住的协议类通过串行端口的顶部。我用这些都在我的嵌入式系统的时间。这给你两全其美,阻塞同步调用和异步调用,所以你可以伪多任务。

I tend to do this kind of stuff, though, Id tend to have a separate serial port "class" ( struct + functions ) and a protocol class that lives over the top of serial port. I used these all the time in my embedded systems. This gives you the best of both worlds, a blocking synchronous call and an async call so you can pseudo multitask.

typedef struct serial_port_s serial_port;
typedef void (*serial_on_recived_proc)(serial_port* p);
typedef struct serial_port_s{
    bool timeoutFlag;
    bool receiveFlag;
    void* context;
    serial_on_recived_proc response_handler;
};

void send_serial(serial_port* p, char* message)
{
    //SendMsg?
}
void receive_serial(serial_port* p, char* response)
{
    //receiveMsg?
}

bool has_data(serial_port* p)
{
    return p->receiveFlag;
}

bool has_timed_out(serial_port* p)
{
    return p->timeoutFlag;
}
bool is_serial_finished(serial_port* p)
{
    return has_data(p) || has_timed_out(p); 
}

bool serial_check(serial_port* p)
{
    if(is_serial_finished(p) && p->response_handler != NULL)
    {
       p->response_handler(p)
       p-> response_handler = NULL;
       return true;
    }
    return false;
}

void send(serial_port* p, char* message, char* response)
{
    p->response_handler=NULL;
    send_serial(p, message);
    while(!is_serial_finished(p));
    receive_serial(p, response);
}

void sendAsync(serial_port* p, char* message, serial_on_recived_proc handler, void* context)
{
    p->response_handler = handler;
    p->context = context;
    send_serial(p, message);
}

void pow_response(serial_port* p)
{
    // could pass a pointer to a struct, or anything depending on what you want to do
    char* r = (char*)p->context;  
    receive_serial(p, r);
    // do stuff with the pow response
}

typedef struct
{
   char text[100];       
   int x;
   bool has_result;
} bang_t;

void bang_parse(bang_t* bang)
{
   bang->x = atoi(bang->text);
}

void bang_response(serial_port* p)
{
    bang_t* bang = (bang_t*)p->context;  
    receive_serial(p, bang->text);
    bang_parse(bang);
    bang->has_result=true;
}

void myFunc();
{
    char response[100];
    char pow[100];
    bang_t bang1;
    bang_t bang2;
    serial_port p; //
    int state = 1;
    // whatever you need to do to set the serial port

    // sends and blocks till a response/timeout
    send(&p, "Hello", response);
    // do what you like with the response

    // alternately, lets do an async send...
    sendAsync(&p, "Pow", pow_response, pow);       

    while(true)
    {
        // non block check, will process the response when it arrives               
        if(serial_check(p))
            {
              // it has responded to something, we can send something else...

              // using a very simple state machine, work out what to send next.
              // in practice I'd use enum for states, and functions for managing state
              // transitions, but for this example I'm just using an int which
              // I just increment to move to the next state
              switch(state)
              {
              case 1: 
                 // bang1 is the context, and will receive the data
                 sendAsync(&p, "Bang1", bang_response, &bang1);
                 state++; 
                 break;
              case 2:
                 // now bang2 is the context and will get the data...
                 sendAsync(&p, "Bang2", bang_response, &bang2);
                 state++; 
                 break;
              default:
                 //nothing more to send....
                 break;
              }
            }
        // do other stuff you want to do in parallel
    }
};

这篇关于UART ISR的Tx RX架构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆