6

我正在制作一个 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;   
}  

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

编辑

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

非常感谢你的帮忙!:)

4

4 回答 4

6

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

你在电脑上用什么软件?我建议使用像 HyperTerminal 或PuTTY这样的简单通信软件。如果他们多次显示正在发送到 PC 的字符串,那么很可能故障出在 8051 上运行的软件中。

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

如果我可能很直率,我建议您执行以下操作:

  1. 调试。尝试一下,但不要猜测。实验。对你的代码做一些小的改动,看看会发生什么。尝试一切你能想到的。在网上搜索更多信息。
  2. 如果这不能产生解决方案,请返回此处,并向我们提供我们需要的所有信息。这包括相关的代码片段、您正在使用的硬件的完整详细信息以及您在步骤 1 中尝试的内容的信息。

编辑:我没有代表来编辑问题,所以这是 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;
} 
于 2009-08-01T14:25:42.303 回答
6

您发布的代码在 main() 中没有循环,因此您需要确定当 main() 在发送“Y”后返回时,编译器的 C 运行时会做什么。鉴于您的问题,我想编译器会生成一些代码来进行一些清理,然后重新启动 micro(可能是硬件重置,可能只是重新启动 C 运行时)。看起来您的程序与您编写的程序完全一样,但是您忽略了调用 main() 之前和之后发生的情况。

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

请注意,如果您的微控制器有看门狗定时器,它可能会进行干预并强制进行意外重置。如果发生这种情况,您的字符串将在每次看门狗重置时发送一次(可能是每秒一次,速率取决于您的硬件)。

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

于 2009-08-01T23:03:02.237 回答
2

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

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

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

于 2009-08-01T11:26:56.660 回答
2

回应尼尔的回答(在回复中,因为我还没有代表发表评论):在没有操作系统的典型微控制器情况下,目前尚不清楚在 main( ) 应该做——或者更准确地说,它不能做通常的“结束程序并返回操作系统”,因为没有操作系统可以返回。

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

在我工作过的一些系统中,exit() 根本没有真正实现——如果你不打算使用它,甚至不要在它上面浪费一个字节!结果是,当执行路径到达 main() 的末尾时,芯片只是徘徊在执行下一位内存中的任何内容的 lala 土地上,并且通常很快就会陷入循环或陷入困境错误的操作码非法。非法操作码故障的通常结果是……重新启动芯片。

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

于 2009-08-02T00:16:20.230 回答