简体   繁体   English

如何仅从8051一次串行发送字符串?

[英]How can I send a string serially from an 8051 only ONCE?

I am making an 8051 microcontroller communicate wirelessly with a computer. 我正在使8051微控制器与计算机进行无线通信。 The microcontroller will send a string to its serial port (DB9) and the computer will receive this string and manipulate it. 微控制器将一个字符串发送到其串行端口(DB9),计算机将接收该字符串并对其进行操作。

My problem is that I do not know how to make the 8051 transmit the string just once. 我的问题是我不知道如何使8051仅发送一次字符串。 Since I need to manipulate the string at the PC end it has to be received only one time. 由于我需要在PC端处理字符串,因此只能接收一次。 Currently, even though in the C code I am sending the string once, on my computer I am receiving the same string continuously. 当前,即使在C代码中,我只发送一次字符串,但在我的计算机上,我仍在连续接收相同的字符串。 I assume this is because whatever is in the SBUF is continuously transmitted. 我认为这是因为SBUF中的任何内容都是连续传输的。 Is there any way that I can send my string only once? 有什么办法只能将我的字符串发送一次? Is there a way to empty the SBUF? 有没有办法清空SBUF?

I tried to use the RTS (Request to Send) pin (7th pin) on the DB9 because I read somewhere that if I negated the voltage on that pin it would stop the flow of data to the serial port. 我尝试在DB9上使用RTS(请求发送)引脚(第7引脚),因为我读到某处的内容,如果否定该引脚上的电压,将阻止数据流向串行端口。 So what I did was programmed my microcontroller to send the string and then sent logic level 0 to an output pin that was connected to my DB9 RTS pin. 因此,我对微控制器进行了编程,以发送字符串,然后将逻辑电平0发送到连接到DB9 RTS引脚的输出引脚。 However, that didn't work. 但是,那没有用。

Does anyone have any suggestions? 有没有人有什么建议? I'd really appreciate them. 我真的很感激他们。

EDIT 编辑

The software that I'm using on the PC is X-CTU for Xbee modules. 我在PC上使用的软件是Xbee模块的X-CTU。 This is the code on my microcontroller: 这是我的微控制器上的代码:

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;   
}  

Could someone please verify that it is in fact only sending the string once? 有人可以验证它实际上只发送一次字符串吗?

EDIT 编辑

Looks like Steve, brookesmoses and Neil hit the nail on the head when they said that it was what was happening AFTER my main function that was causing the problem. 当史蒂夫(Steve),布鲁克斯莫斯(Brookesmoses)和尼尔(Neil)说我的主要功能导致问题发生的原因时,他们的想法就打在了头上。 I just tried the suggested code Steve put up (more specifically the for(;;); and defining serTX outside of main) and it worked perfectly. 我只是尝试了Steve提出的建议代码(更具体地说,是for(;;);并在main之外定义serTX),所以它运行良好。 The controller is probably rebooted and hence the same code keeps repeating itself. 控制器可能已重新启动,因此相同的代码不断重复。

Thanks so much for the help! 非常感谢你的帮忙! :) :)

Can you confirm that the 8051 really is sending the data only once? 您能确认8051实际上仅发送一次数据吗? One way to check would be to use a scope to see what is happening on the UART's TX pin. 一种检查方法是使用示波器查看UART TX引脚上发生的情况。

What software are you using on the PC? 您在PC上使用什么软件? I'd suggest using simple communications software like HyperTerminal or PuTTY . 我建议使用简单的通讯软件,例如HyperTerminal或PuTTY If they are showing the string being sent to the PC multiple times, then chances are the fault is in the software running on the 8051. 如果他们显示字符串多次发送到PC,则很可能是8051上运行的软件出现故障。

EDIT: To be honest, this sounds like the kind of debugging that engineers have to face on a regular basis, and so it's a good opportunity for you to practise good old-fashioned methodical problem-solving. 编辑:老实说,这听起来像是工程师必须定期进行的调试,因此这是您练习良好的老式的,有条理的方法来解决问题的好机会。

If I may be very blunt, I suggest you do the following: 如果我可能很直率,建议您执行以下操作:

  1. Debug. 调试 Try things out, but don't guess . 试试看,但是不要猜测 Experiment. 实验。 Make small changes in your code and see what happens. 在代码中进行一些小的更改,然后看看会发生什么。 Try everything you can think of. 尝试所有您能想到的。 Search the web for more information. 在网上搜索更多信息。
  2. If that doesn't produce a solution, then return here, and provide us with all the information we need. 如果仍然无法解决,请返回此处,并向我们提供所需的所有信息。 That includes relevant pieces of the code, full details of the hardware you're using, and information about what you tried in step 1. 其中包括相关的代码片段,所用硬件的完整详细信息以及有关在第1步中尝试过的内容的信息。

EDIT: I don't have the rep to edit the question, so here's the code posted by the OP in the comment to her question: 编辑:我没有代表来编辑问题,所以这是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; } 
}

As Neil and Brooksmoses mention in their answers, in an embedded system, the main function is never allowed to terminate. 正如Neil和Brooksmoses在回答中提到的那样,在嵌入式系统中,永远不允许终止主要功能。 So you either need to put your code in an infinite loop (which may be what is inadvertently happening), or add an infinite loop at the end, so the program effectively halts. 因此,您要么需要将代码置于无限循环中(这可能是无意中发生的事情),要么在末尾添加无限循环,以便程序有效地停止。

Also, the function SerTx should be defined outside main. 同样,功能SerTx应该在main外部定义。 This may be syntatically correct, but it keeps things simple not declaring functions within other functions. 从语法上讲这可能是正确的,但它使事情简单而不在其他函数中声明函数。

So try this (I've also added some comments in an attempt to make the code easier to understand): 因此,请尝试这样做(我也添加了一些注释,以使代码更易于理解):

#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;
} 

The code you posted has no loop in main(), so you need to determine what your compiler's C runtime does when main() returns after sending 'Y'. 您发布的代码在main()中没有循环,因此您需要确定在发送“ Y”后main()返回时编译器的C运行时将执行什么操作。 Given your problem, I imagine the compiler generates some code to do some cleanup then restart the micro (maybe a hardware reset, maybe just be restarting the C runtime). 考虑到您的问题,我想编译器会生成一些代码来进行一些清理,然后重新启动Micro(也许是硬件重置,也许只是重新启动C运行时)。 It looks like your program works exactly as you've written it, but you've ignored what happens before and after main() is called. 看起来您的程序完全按照编写的方式工作,但是您忽略了在调用main()之前和之后发生的事情。

If you want your string sent once and only once, ever, then you need something like while(1) {} added after the last character is sent. 如果您希望一次只发送一次字符串,那么在发送最后一个字符之后,需要添加while(1) {} But, then your program is doing nothing -- it will just execute an empty loop forever. 但是,那么您的程序什么都不做-它将永远执行一个空循环。 A reset (such as power cycling) is needed to start again, and send the string. 需要重设(例如关机后再开机)才能重新开始并发送字符串。

Note that if your micro has a watchdog timer, it might intervene and force an unexpected reset. 请注意,如果您的微型计算机具有看门狗定时器,则它可能会干预并强制执行意外的复位。 If this happens, your string will be sent once for each watchdog reset (which could be something like once each second, with the rate depending on your hardware). 如果发生这种情况,您的字符串将在每次看门狗重置时发送一次(可能每秒发送一次,其速率取决于您的硬件)。

Also, having serTx() defined nested inside main() is probably not what you want. 另外,将serTx()定义嵌套在main()内部可能不是您想要的。

It's hard to say what the problem is without seeing any of the 8051 code. 如果不查看任何8051代码,很难说出问题是什么。 For example, a logic error on that side could lead to the data being sent multiple times, or the 8051 software might be waiting for an ACK which is never received, etc. 例如,该侧的逻辑错误可能导致多次发送数据,或者8051软件可能正在等待从未收到的ACK等。

Normally on an 8051 code has to explicitly send each character, but I assume this is taken care of for you by the C run-time. 通常,在8051代码上必须显式发送每个字符,但是我认为C运行时会为您解决这一问题。

Use of the RTS/CTS (Request To Send/Clear To Send) is for flow control (ie to prevent buffer overruns - the buffers are usually pretty small on these microcontrollers) and not to stop transmission altogether. 使用RTS / CTS(请求发送/清除发送)是为了进行流控制(即,防止缓冲区溢出-这些微控制器上的缓冲区通常很小),而不是完全停止传输。

Echoing Neil's answer (in a reply, since I don't yet have the rep to comment): In a typical microcontroller situation without an OS, it's not immediately clear what the exit() function that gets implicitly called at the end of main() should do -- or, more accurately, it can't do the usual "end the program and return to the OS", because there's no OS to return to. 回应Neil的回答(在答复中,因为我还没有回复要评论):在没有操作系统的典型微控制器情况下,尚不清楚立即在main()的末尾隐式调用的exit()函数是什么)应该-或更准确地说,它不能执行通常的“结束程序并返回操作系统”,因为没有操作系统可以返回。

Moreover, in a real application, you almost never want the program to just stop, unless you turn off the system. 而且,在实际的应用程序中,除非关闭系统,否则您几乎永远不会希望程序停止运行。 So one thing that the exit() implementation should definitely not do is take up a lot of code space. 因此exit()实现绝对不应该做的一件事是占用大量代码空间。

In some systems I've worked on, exit() is not actually implemented at all -- if you're not going to use it, don't even waste a byte on it! 在我研究过的某些系统中,exit()实际上根本没有实现-如果您不打算使用它,甚至不要在上面浪费一个字节! The result is that when the execution path gets to the end of main(), the chip just wanders off into a lala land of executing whatever happens to be in the next bit of memory, and typically quickly ends up either stuck in a loop or faulting with an illegal opcode. 结果是,当执行路径到达main()的末尾时,芯片便陷入了执行下一个内存中发生的事情的混乱境地,并且通常很快陷入循环或循环中。错误的非法操作码。 And the usual result of a fault with an illegal opcode is ... rebooting the chip. 错误操作码错误的通常结果是...重新启动芯片。

That seems like a plausable theory for what's happening here. 对于这里发生的事情,这似乎是一个合理的理论。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM