如何从仅8011的ONCE串行发送字符串?

时间:2009-08-01 10:58:11

标签: c embedded serial-port microcontroller 8051

我正在使8051微控制器与计算机进行无线通信。微控制器将字符串发送到其串行端口(DB9),计算机将接收该字符串并对其进行操作。

我的问题是我不知道如何让8051只传输一次字符串。由于我需要在PC端操作字符串,因此必须只接收一次。目前,即使在C代码中我发送一次字符串,在我的计算机上我连续收到相同的字符串。 我认为这是因为SBUF中的任何内容都是连续传输的。有什么方法可以只发送一次我的字符串吗?有没有办法清空SBUF?

我尝试在DB9上使用RTS(请求发送)引脚(第7个引脚),因为我读到某个地方,如果我否定了该引脚上的电压,它将阻止数据流到串行端口。所以我所做的是编程我的微控制器发送字符串,然后将逻辑电平0发送到连接到我的DB9 RTS引脚的输出引脚。但是,这没有用。

有没有人有任何建议?我真的很感激他们。

修改

我在PC上使用的软件是Xbee模块的X-CTU。这是我的微控制器上的代码:

include reg51.h 
void SerTx(unsigned char);  
void main(void)  
{  
  TMOD = 0x20;  
  TH1 = 0xFD;  
  SCON = 0x50;  
  TR1 = 1;   

  SerTx('O');  
  SerTx('N');  
  SerTx('L');  
  SerTx('Y'); 

}

void SerTx(unsigned char x)  
{  
  SBUF = x;  
  while(TI==0);   
  TI = 0;   
}  

有人可以确认它实际上只发送一次字符串吗?

修改

看起来像史蒂夫,布鲁克斯和尼尔在他们说这是我的主要功能导致问题之后发生的事情时头上钉了一针。我刚刚尝试了Steve提出的建议代码(更具体地说是for(;;);并在main之外定义了serTX)并且它工作得很好。控制器可能重新启动,因此相同的代码不断重复。

非常感谢你的帮助! :)

5 个答案:

答案 0 :(得分:6)

您能否确认8051确实只发送一次数据?一种检查方法是使用示波器来查看UART TX引脚上发生的情况。

您在PC上使用的是哪些软件?我建议使用HyperTerminal或PuTTY之类的简单通讯软件。如果他们多次显示发送到PC的字符串,则可能是8051上运行的软件出现故障。

编辑:说实话,这听起来像是工程师必须经常面对的那种调试,所以这是一个很好的机会让你练习好的老式有条不紊的问题 - 解决。

如果我可能非常生硬,我建议你做以下事情:

  1. 调试。尝试一下,但不要猜测。实验。对代码进行细微更改,看看会发生什么。尝试你能想到的一切。在网上搜索更多信息。
  2. 如果这不能产生解决方案,请返回此处,并向我们提供我们需要的所有信息。这包括代码的相关部分,您正在使用的硬件的完整详细信息,以及您在步骤1中尝试的内容的信息。
  3. 编辑:我没有代表编辑问题,所以这是OP在她的问题评论中发布的代码:

    #include<reg51.h>
    
    void SerTx(unsigned char);
    
    void main(void)
    {
        TMOD = 0x20; TH1 = 0xFD; SCON = 0x50; TR1 = 1;
        SerTx('O'); SerTx('N'); SerTx('L'); SerTx('Y');
    
        void SerTx(unsigned char x)
            { SBUF = x; while(TI==0); TI = 0; } 
    }
    

    正如Neil和Brooksmoses在他们的答案中提到的,在嵌入式系统中,主要功能永远不会被终止。因此,您需要将代码置于无限循环中(这可能是无意中发生的事情),或者在末尾添加无限循环,因此程序会有效停止。

    此外,函数SerTx应该在main之外定义。这可能在语法上是正确的,但它使事情变得简单,而不是在其他函数中声明函数。

    所以试试这个(我还添加了一些注释,试图让代码更容易理解):

    #include<reg51.h>
    
    void SerTx(unsigned char);
    
    void main(void)
    {
        /* Initialise (need to add more explanation as to what
            each line means, perhaps by replacing these "magic
            numbers" with some #defines) */
        TMOD = 0x20;
        TH1  = 0xFD;
        SCON = 0x50;
        TR1  = 1;
    
        /* Transmit data */
        SerTx('O'); SerTx('N'); SerTx('L'); SerTx('Y');
    
        /* Stay here forever */
        for(;;) {}
    
    }
    
    void SerTx(unsigned char x)
    {
        /* Transmit byte */
        SBUF = x;
    
        /* Wait for byte to be transmitted */
        while(TI==0) {}
    
        /* Clear transmit interrupt flag */
        TI = 0;
    } 
    

答案 1 :(得分:6)

您发布的代码在main()中没有循环,因此您需要确定在发送'Y'后main()返回时编译器的C运行时所执行的操作。鉴于你的问题,我想编译器生成一些代码来做一些清理,然后重启微(可能是硬件复位,也许只是重新启动C运行时)。看起来你的程序与你编写的程序完全一样,但是你忽略了调用main()之前和之后发生的事情。

如果您希望您的字符串只发送一次,那么您需要在发送最后一个字符后添加while(1) {}之类的内容。但是,那么你的程序什么都不做 - 它将永远执行一个空循环。需要重置(例如电源循环)才能再次启动,并发送字符串。

请注意,如果您的micro具有看门狗定时器,它可能会介入并强制意外重置。如果发生这种情况,您的字符串将在每次看门狗复位时发送一次(可能类似于每秒一次,速率取决于您的硬件)。

另外,将serTx()定义为嵌套在main()中可能不是你想要的。

答案 2 :(得分:2)

如果没有看到任何8051代码,很难说出问题是什么。例如,该方面的逻辑错误可能导致数据被多次发送,或者8051软件可能正在等待从未收到的ACK等等。

通常在8051代码上必须显式发送每个字符,但我认为这是由C运行时为你处理的。

使用RTS / CTS(请求发送/清除发送)用于流量控制(即防止缓冲区溢出 - 这些微控制器上的缓冲区通常非常小),而不是完全停止传输。

答案 3 :(得分:2)

回应Neil的回答(在回复中,因为我还没有代表发表评论):在没有操作系统的典型微控制器情况下,不能立即清楚在最后隐式调用的exit()函数是什么main()应该做 - 或者更确切地说,它不能做通常的“结束程序并返回到OS”,因为没有操作系统可以返回。

此外,在实际应用程序中,除非关闭系统,否则几乎不需要程序停止。因此,exit()实现绝对不应该做的一件事就是占用大量的代码空间。

在我曾经使用的一些系统中,exit()实际上根本没有实现 - 如果你不打算使用它,甚至不要在它上面浪费一个字节!结果是当执行路径到达main()的末尾时,芯片只是徘徊在执行下一位存储器中的任何事件的lala land中,并且通常很快就会陷入循环或者发生非法操作错误。非法操作码出错的通常结果是......重新启动芯片。

对于这里发生的事情,这似乎是一个可信的理论。

答案 4 :(得分:-1)

这篇特别的文章是用于汇编而不是C,但它可能有用: http://www.8052.com/tutser.phtml