Как непрерывно отправлять и получать данные с помощью беспроводного последовательного порта в 8051?

Я пытаюсь заставить микроконтроллер общаться с программой на моем рабочем столе. Я использую соединения последовательного порта с радио 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() просто создает строку на основе входных данных некоторых датчиков. Функции отправки и получения обычно работают нормально, но когда мне нужно, чтобы они непрерывно отправляли и получали, как в приведенной выше функции Configure(), это не работает.

Какие-либо предложения? Я был бы очень признателен им.


person CodeConfused    schedule 24.10.2009    source источник
comment
Быстрый и грязный хак, который сделает ваш код более надежным, состоит в том, чтобы ограничить количество времени, в течение которого вы будете ждать, пока RI будет установлен в true. Установите переменную на 65535 и уменьшите. Если он достигнет 0 до того, как вы получите байт, сдайтесь и попробуйте отправить снова. Если вам действительно нужна версия вашего кода, основанная на прерываниях, я могу вам помочь - в целом они гораздо надежнее.   -  person Tom Leys    schedule 09.11.2009


Ответы (2)


Проблема в том, что ваши функции отправки и получения опрашиваются и блокируются. Когда вы вызываете функцию приема, она вернется только после получения полного сообщения. То же самое для функции отправки, но в случае отправки продолжительность, вероятно, короче (ваша программа, вероятно, будет вызывать функцию отправки только тогда, когда есть сообщение для отправки, в то время как получение может ждать несколько дней, прежде чем сообщение прибудет.

Если вам требуется асинхронная связь, лучше всего использовать связь на основе прерываний; по крайней мере, для получения и в идеале для отправки и получения.

Это также можно реализовать с помощью опроса связи, но тогда вам нужно написать функцию, которая проверяет, доступен ли символ для приема (или если tx-пуст), чтобы читать/записывать следующий символ из/в буфер.

Преимущества связи на основе прерываний:

  • полный дуплекс
  • используется меньше процессорного времени (нет необходимости в циклах ожидания)
  • меньше энергопотребления (это позволяет процессору переходить в режим пониженного энергопотребления/ожидания с пробуждением по прерыванию; для опроса всегда требуется полная мощность)

В качестве первого шага я советую вам реализовать (или получить) прием на основе прерывания; даже когда функция передачи по-прежнему заблокирована, это позволит работать в полнодуплексном режиме с минимальными усилиями. Если у вас нет ОС (rtos/scheduler), вам придется подумать о механизме синхронизации. Простейшая форма для вашего приема - обрабатывать сообщение, если оно доступно, и немедленно возвращаться, если нет (полного) сообщения.

удачи.

Редактировать после комментариев В отношении отдельных сообщений может показаться, что все работает, если рабочий стол реагирует на сообщения, отправленные контроллером. Если ваш контроллер имеет большой буфер FIFO (т.е. 64 байта) на приеме, это может сработать. У большинства контроллеров, которых я знаю, этого нет. Многие имеют только один символьный буфер. Вы можете обнаружить это с помощью бита ПЕРЕПОЛНЕНИЯ в регистрах; если это установлено, то символы терялись при приеме.

Некоторые варианты использования: * вы хотите отправить 2 сообщения за один раз (скажем: init + do_something). ПК отвечает на первое сообщение, но контроллер все еще отправляет и сбрасывает большую часть данных. * ПК начинает отправку до того, как контроллер выполнит функцию Receive(). Данные в начале пакета могут быть потеряны * любое прерывание связи может привести к взаимоблокировке (т.

Итак, для диагностики: проверьте бит переполнения. Если он установлен, вы потеряли данные и вам нужно работать с функциями прерывания. Если возможно, контролируйте обе стороны (по крайней мере, состояние; например, мигание светодиода для отправки и одного для приема).

Вам может помочь монитор rs232 (для этого вам потребуются дополнительные порты. Существует множество (в том числе бесплатных) приложений, которые могут отслеживать несколько портов rs232 и предоставлять временные метки. Таким образом, вы можете наблюдать за порядком обмена данными. Google нашел меня : ссылка; в последние годы я использовал несколько подобных утилит.

person Adriaan    schedule 24.10.2009
comment
Большое спасибо за ваше предложение, Адриан. Но я в замешательстве. У меня было предчувствие, что это может не работать из-за аспекта блокировки, но я полагал, что способ, которым я писал свои программы, мог бы обойти это. Смотрите, я заставляю контроллер отправлять сообщение, пока программа рабочего стола ожидает его с помощью Receive(). Затем программа рабочего стола проверяет сообщение, видит ли оно приемлемое (все это, пока программа контроллера ожидает получения), а затем отправляет сигнал сообщения msg принятие или отклонение сообщения. Receive() в контроллере, который был заблокирован, теперь разблокирован, не так ли? - person CodeConfused; 25.10.2009
comment
Так не следует ли просто продолжить работу с остальной частью кода? То есть проверьте, предназначено ли полученное сообщение для принятия или отклонения (в это время настольный компьютер ожидает с заблокированным получением), а затем снова отправьте сообщение? Я уверен, что асинхронная связь решит эту проблему, как вы сказали, но у меня немного крайний срок с этим проектом, и я никогда не пробовал асинхронную связь. раньше, поэтому я был бы очень признателен, если бы вы помогли решить эту проблему с синхронным! - person CodeConfused; 25.10.2009
comment
Хммм... Я думаю, вполне возможно, что здесь происходит именно это. Хотя я не совсем понимаю, как отправка двух сообщений с контроллера на рабочий стол и двух сообщений обратно с рабочего стола на контроллер может работать за один раз, а не когда я помещаю один и тот же код в цикл, я думаю, что мне просто нужно предположить сообщения теряются при непрерывной отправке и получении, и, в конце концов, оба ожидают в заблокированных функциях приема. :( Я попробую контролировать обе стороны, как вы предложили. Спасибо! - person CodeConfused; 26.10.2009

Ваша программа, как написано, должна отправить 4 байта, а затем прочитать 2 байта (при условии, что регистры, которые у вас есть, верны, но если вы вообще заработали, они, вероятно, верны), затем снова отправьте 4 байта... Вероятно, это не так. висит на отправляющей части, но принимающая сторона всегда будет ждать чтения двух байтов, и если по какой-то причине два байта не поступят во входной регистр, вы будете продолжать ждать вечно.

Может быть, когда вы нагружаете систему (отправляете байт слишком быстро), вы переполняете входной буфер и в конечном итоге теряете байт? таким образом, никогда не получая два байта. и застрянет.

  1. Вы можете отладить, где вы застряли? это на самом деле в цикле приема?
  2. Можете ли вы регулировать передачу с компьютера на микро, чтобы вы могли вручную отправлять по одному байту за раз?
  3. есть ли рукопожатие между интерфейсом micro и xbee? может ли это быть задушено микро?
person simon    schedule 25.10.2009
comment
Да, Саймон, ты прав, он должен отправить 4 байта, затем получить 2 и так далее, пока не будет получен определенный ответ. Я почти уверен, что проблема действительно заключается в части получения, просто потому, что Xbees загораются при отправке или получении. Таким образом, я могу «видеть», что 2 байта из программы рабочего стола покинули рабочий стол, а также «видеть», как они поступают на микроконтроллер. После этого код контроллера просто не обрабатывает его. Я пытался отлаживать, вручную отправляя байты по одному, как вы сказали. Но это все равно не сработало. - person CodeConfused; 25.10.2009
comment
Я не уверен насчет рукопожатия между микро и Xbee. Но я уверен, что нет. - person CodeConfused; 25.10.2009
comment
@CudeConfused, можете ли вы определить, меняется ли бит RI и сколько раз? каким-то образом, когда вы отправляете байт несколько раз, бит RI не устанавливается. Может ли что-то вызвать RI до того, как вы его очистите и, таким образом, пропустите второй байт? - person simon; 26.10.2009
comment
Однако, если бы бит RI не был установлен, он бы не работал и для передачи и приема двух сообщений, не так ли? Хотя это работает. Это не работает только тогда, когда я помещаю тот же код в цикл. - person CodeConfused; 26.10.2009
comment
@CodeConfused (извините за опечатку в последнем комментарии, я не могу редактировать комментарии;)) Я не совсем понимаю рабочие и нерабочие ситуации? Я думаю, вам нужно быть более конкретным. Мне нравится предложение Адриана прочитать бит переполнения в вашем цикле приема. Я думаю, что мигание светодиода для каждого полученного байта подтвердит, что вы прочитали только один байт, а затем ждали вечно. - person simon; 27.10.2009
comment
@CodeConfused Вы также можете изменить свой протокол на рукопожатие по одному байту за раз. Отправить один байт, получить один байт. тогда микро и компьютер могут дросселировать / рукопожатие друг друга, чтобы предотвратить любые перегрузки. Это не лучший способ сделать это в долгосрочной перспективе, но это быстрое и грязное решение. Асинхронный метод прерывания был бы лучшим долгосрочным подходом. - person simon; 27.10.2009