8051如何通过无线串口连续发送和接收?

发布于 2024-08-08 15:27:23 字数 1409 浏览 12 评论 0原文

我正在尝试使微控制器与桌面上的程序进行通信。我使用串行端口连接两端的 Xbee 无线电。

当我从微控制器向桌面发送一些内容,然后桌面上的程序将一些内容发送回微控制器时,通信工作正常。

但是,当我需要将信息从控制器连续发送到桌面程序直到桌面程序发送特定答案时,它不起作用。

以下是我正在讨论的代码:

    unsigned char ans = 'N';
    unsigned int count = 0;

    void main(void)
    {


        while(1)
        {
            if(count == 0)
            {
                Configure();
                count = 1;
            }

                  //there is some more code here but is irrelevant to the serial communication

         }

    }


void Configure()
{


    //Repeat this until the user accepts the sent string as correct
    while(ans == 'N')
    {

        BuildString();
        Send();
        Receive();
    }
}

void Send()
{
    unsigned int i;

    TMOD = 0x20;
    TH1 = 0xFD;
    SCON = 0x50;
    TR1 = 1;

    for(i=0; i<4; i++)
    {
        SBUF = toSend[i];
        while(TI == 0);
        TI = 0;
    }   

}

void Receive()
{
    unsigned int j;

    TMOD = 0x20;
    TH1 = 0xFD;
    SCON = 0x50;
    TR1 = 1;


    for(j=0; j<2; j++)
    {
        while(RI == 0);
        Received[j] = SBUF;
        RI = 0; 
    }


    if(count == 0)
        ans = Received[1];

    else
    {   
        RunType = Received[0];
        Move = Received[1];
    }


}

BuildString() 函数只是根据一些传感器输入构造一个字符串。 发送和接收函数通常工作正常,但当我需要它们连续发送和接收时,就像上面的配置()函数一样,它不起作用。

有什么建议吗?我真的很感激他们。

I'm trying to make a microcontroller communicate with a program on my desktop. I'm using serial port connections with Xbee radios on both ends.

The communication works fine when I send something from the microcontroller to the desktop and the program on the desktop then sends something back to the microcontroller.

However, when I require the information to be sent from the controller to the desktop program continuously until the desktop program sends a particular answer it doesn't work.

Here's the code for what I'm talking about:

    unsigned char ans = 'N';
    unsigned int count = 0;

    void main(void)
    {


        while(1)
        {
            if(count == 0)
            {
                Configure();
                count = 1;
            }

                  //there is some more code here but is irrelevant to the serial communication

         }

    }


void Configure()
{


    //Repeat this until the user accepts the sent string as correct
    while(ans == 'N')
    {

        BuildString();
        Send();
        Receive();
    }
}

void Send()
{
    unsigned int i;

    TMOD = 0x20;
    TH1 = 0xFD;
    SCON = 0x50;
    TR1 = 1;

    for(i=0; i<4; i++)
    {
        SBUF = toSend[i];
        while(TI == 0);
        TI = 0;
    }   

}

void Receive()
{
    unsigned int j;

    TMOD = 0x20;
    TH1 = 0xFD;
    SCON = 0x50;
    TR1 = 1;


    for(j=0; j<2; j++)
    {
        while(RI == 0);
        Received[j] = SBUF;
        RI = 0; 
    }


    if(count == 0)
        ans = Received[1];

    else
    {   
        RunType = Received[0];
        Move = Received[1];
    }


}

The BuildString() function simply constructs a string on the basis of some sensor inputs.
The send and receive functions work fine usually but when I need them to send and receive continuously, like in the Configure() function above, it doesn't work.

Any suggestions? I'd really appreciate them.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

記憶穿過時間隧道 2024-08-15 15:27:23

问题在于您的发送和接收函数都被轮询和阻塞。当你调用receive函数时,只有在接收到完整的消息后才会返回。与发送功能相同,但在发送的情况下,持续时间可能会更短(您的程序可能只会在有消息要发送时调用发送,而接收可能会在消息到达之前等待几天。

如果您需要异步通信,最好是使用基于中断的通信;至少对于接收,理想情况下对于发送和接收

都可以使用轮询通信来实现这一点,但是您需要编写一个函数来检查字符是否可用于接收。 (或者如果 tx-empty),从缓冲区读取/写入下一个字符

基于中断的通信的优点是:

  • 全双工
  • 使用更少的 cpu 时间(不需要等待循环)
  • 更少的功率(它允许 cpu)进入低功耗/待机模式,中断唤醒;轮询始终需要全功率)

作为第一步,我建议您实现(或获取)基于中断的接收;即使传输功能仍然被阻止,它也会允许以最小的努力进行全双工操作。如果您没有操作系统(实时操作系统/调度程序),您将不得不考虑同步机制。最简单的形式是让您的接收器在有可用消息时处理消息,并在没有(完整)消息时立即返回。

祝你好运。

评论后编辑
在逐条消息的基础上,如果桌面对控制器发送的消息做出反应,那么事情似乎会正常进行。如果您的控制器在接收端有一个大的 FIFO 缓冲区(即 64 字节),这可能会起作用。我认识的大多数控制器都没有这个。许多只有一个字符缓冲区。您可以使用寄存器中的溢出位来检测这一点;如果设置了此项,则接收时字符会丢失。

一些用例:
* 你想一次性发送 2 条消息(例如:init + do_something)。电脑响应第一条消息,但控制器仍在发送并丢弃大部分数据。
* PC 在控制器执行 receive() 函数之前开始发送。数据包开头的数据可能会丢失
* 任何通信中断都可能导致死锁(即控制器和桌面都在等待另一端发送某些内容。

因此诊断:检查溢出位。如果设置了该位,则说明已丢失数据,需要处理如果可能的话,监视两侧(至少是状态;例如,一个闪烁的 LED 表示发送,一个闪烁的 LED 表示接收)

(例如,您需要一些额外的端口)。 (包括免费软件)可以监视多个 rs232 端口并提供时间戳的应用程序,因此您可以通过 Google 找到我:link;过去几年我使用过几个类似的实用程序。

The problem is that both your send and receive functions are polled and blocking. When you call the receive function, it will only return after a complete message is received. Dito for the send function, but in case of send the duration is propably shorter (your program will propably only call send when there is a message to be sent, while receive can wait for days before a message arrives.

If you require asynchronous commmunication, the best is to use interrupt based communications; at least for the receive and ideally for both send and receive.

It is also possible to impement this using polled communications, but then you need to write a function which checks if a character is available for receive (or if tx-empty), to read/write the next character from/to the buffer.

The advantages of interrupt based communication are:

  • full duplex
  • less cpu time is used (no wait loops necessary)
  • less power (it allows the cpu to go to a low power/standby mode, with wakeup on interrupt; polling always requires full power)

As a first step I advise you to implement (or get) a interrupt based receive; even when the transmit function is still blocked, it will allow full duplex operation with minimal effort. If you haven't got a os (rtos/scheduler) you'll have to think of a synchronisation mechanism. The simplest form is for your receive to handle a message if there is one available, and to return immediately if there isn't a (complete) message.

good luck.

Edit after comments
On a message-by-message basis, things may seem to work if the desktop is reacting on messages sent by the controller. If your controller has a large FIFO buffer (i.e. 64 bytes) on the receive, this may work. Most controllers I know haven't got this. Many have only a single character buffer. You can detect this using an OVERFLOW bit in the registers; if this is set, then characters were lost on receive.

Some usecases:
* you want to send 2 messages in one go (say: init + do_something). The pc responds to the first msg, but the controller is still sending and drops most of the data.
* PC starts sending before controller is executing the receive() function. Data at the beginning of the packet may get lost
* any drop in communication may cause a deadlock (i.e. controller and desktop are both waiting for the other end to send something.

So to diagnose: check the overflow bit. If it is set, you have lost data and you need to work on the interrupt functions. If possible, monitor both sides (at least the state; a blink a led for send, and one for receive for instance).

A rs232 monitor may help you (you'll need some additional ports for this. There are many (including freeware) applications which can monitor multiple rs232 ports and provide timestamps. So you can observe the order of communications. Google found me : link; I've used several similar utilities in the past years.

我只土不豪 2024-08-15 15:27:23

你编写的程序应该发送 4 个字节,然后读取 2 个字节。(假设你拥有的寄存器是正确的,但如果你让它正常工作,它们可能是正确的)然后再次发送 4 个字节......它可能不是挂在发送部分但接收端,因为它将始终等待读取两个字节,如果由于某种原因两个字节没有到达输入寄存器,您将继续等待。

也许当您对系统施加压力(发送字节太快)时,您会溢出输入缓冲区并最终丢失一个字节?因此永远不会得到两个字节。并会被卡住。

  1. 你能调试你卡住的地方吗?它实际上是在接收循环中吗?
  2. 您可以限制从 PC 到微型计算机的传输,以便您可以一次手动发送一个字节吗?
  3. micro和xbee接口之间有握手吗?可以通过微型节流吗?

Your program as written should send 4 bytes and then read 2 bytes.(assuming the registers you have are correct, but if you got it to work at all they are probably correct) then send 4 bytes again... It probably isn't hanging on the send part but the receiving side as it will always be waiting to read two bytes, and if for some reason two bytes don't arrive at the input register you will continue to wait for ever.

It maybe when you stress the system(send byte too quickly) you are overflowing the input buffer and end up loosing a byte? thus never getting two bytes. and will get stuck.

  1. can you debug where you are getting stuck? is it in fact in the receive loop?
  2. can you throttle the transmission from the pc to the micro so you can manually send one byte at a time?
  3. is there any handshaking between the micro and xbee interface? can that be throttled by the micro?
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文