Как я могу отправить строку последовательно с 8051 только ОДИН РАЗ? - PullRequest
6 голосов
/ 01 августа 2009

Я заставляю микроконтроллер 8051 связываться по беспроводной связи с компьютером. Микроконтроллер отправит строку на свой последовательный порт (DB9), и компьютер получит эту строку и будет манипулировать ею.

Моя проблема в том, что я не знаю, как заставить 8051 передавать строку только один раз. Поскольку мне нужно манипулировать строкой на конце ПК, она должна быть получена только один раз. В настоящее время, хотя в коде C я отправляю строку один раз, на моем компьютере я постоянно получаю одну и ту же строку. Я предполагаю, что это потому, что все, что находится в SBUF, непрерывно передается. Есть ли способ, которым я могу отправить свою строку только один раз? Есть ли способ очистить SBUF?

Я попытался использовать вывод RTS (Запрос на отправку) (7-й вывод) на DB9, потому что я где-то читал, что, если я подавлю напряжение на этом выводе, это остановит поток данных в последовательный порт. Поэтому я запрограммировал мой микроконтроллер на отправку строки, а затем отправил логический уровень 0 на выходной вывод, который был подключен к моему выводу DB9 RTS. Однако это не сработало.

У кого-нибудь есть предложения? Я действительно ценю их.

EDIT

Программное обеспечение, которое я использую на ПК, - X-CTU для модулей Xbee. Это код моего микроконтроллера:

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

Может кто-нибудь проверить, действительно ли она отправляет строку только один раз?

EDIT

Похоже, Стив, Бруксмос и Нейл ударили ногтем по голове, когда они сказали, что это было то, что происходило ПОСЛЕ моей основной функции, которая вызывала проблему. Я только что попробовал предложенный код, который поставил Стив (точнее, for (;;) и определил serTX вне main), и он работал отлично. Контроллер, вероятно, перезагружен, и, следовательно, один и тот же код продолжает повторяться.

Большое спасибо за помощь! :)

Ответы [ 5 ]

6 голосов
/ 02 августа 2009

Код, который вы опубликовали, не имеет цикла в main (), поэтому вам нужно определить, что делает среда выполнения C вашего компилятора, когда main () возвращает после отправки 'Y'. Учитывая вашу проблему, я представляю, что компилятор генерирует некоторый код для некоторой очистки, а затем перезапускает микро (возможно, аппаратный сброс, может быть просто перезапуск среды выполнения C). Похоже, ваша программа работает точно так, как вы ее написали, но вы проигнорировали то, что происходит до и после вызова main ().

Если вы хотите, чтобы ваша строка отправлялась один и только один раз, то вам нужно добавить что-то вроде while(1) {} после отправки последнего символа. Но тогда ваша программа ничего не делает - она ​​просто выполнит пустой цикл навсегда. Сброс (например, выключение и включение питания) необходим для повторного запуска и отправки строки.

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

Кроме того, определение serTx (), вложенного в main (), вероятно, не то, что вам нужно.

6 голосов
/ 01 августа 2009

Можете ли вы подтвердить, что 8051 действительно отправляет данные только один раз? Один из способов проверки состоит в том, чтобы использовать прицел, чтобы увидеть, что происходит на выводе TART UART.

Какое программное обеспечение вы используете на ПК? Я бы предложил использовать простые коммуникационные программы, такие как HyperTerminal или PuTTY . Если они показывают строку, отправляемую на ПК несколько раз, скорее всего, ошибка в программном обеспечении, запущенном на 8051.

РЕДАКТИРОВАТЬ: Если честно, это звучит как отладка, с которой инженеры сталкиваются на регулярной основе, и поэтому у вас есть хорошая возможность попрактиковаться в старомодном методическом решении проблем. .

Если я могу быть очень тупым, я предлагаю вам сделать следующее:

  1. Debug. Попробуйте, но не догадывайтесь . Эксперимент. Сделайте небольшие изменения в своем коде и посмотрите, что произойдет. Попробуйте все, что вы можете придумать. Поиск в Интернете для получения дополнительной информации.
  2. Если это не дает решения, вернитесь сюда и предоставьте нам всю необходимую информацию. Сюда входят соответствующие фрагменты кода, полные сведения об используемом оборудовании и информация о том, что вы пытались выполнить на шаге 1.

РЕДАКТИРОВАТЬ: У меня нет представителя для редактирования вопроса, поэтому вот код, опубликованный ОП в комментарии к ее вопросу:

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

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

Также, функция 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;
} 
2 голосов
/ 02 августа 2009

Повторение ответа Нейла (в ответ, поскольку у меня пока нет представителя для комментариев): В типичной ситуации с микроконтроллером без ОС не сразу понятно, что функция exit () вызывается неявно в конце of main () должен делать - или, точнее, он не может выполнить обычное «завершение программы и возврат к ОС», потому что нет ОС, к которой можно вернуться.

Более того, в реальном приложении вы почти никогда не хотите, чтобы программа просто остановилась, если вы не выключите систему. Поэтому одна вещь, которую реализация exit () определенно не должна делать, это занимать много места в коде.

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

Это похоже на правдоподобную теорию того, что здесь происходит.

2 голосов
/ 01 августа 2009

Трудно сказать, в чем проблема, не видя код 8051. Например, логическая ошибка на этой стороне может привести к тому, что данные будут отправлены несколько раз, или программное обеспечение 8051 может ожидать ACK, который никогда не принимается, и т. Д.

Обычно в коде 8051 приходится явно отправлять каждый символ, но я предполагаю, что об этом позаботится за вас среда выполнения C.

Использование RTS / CTS (Запрос на отправку / Очистка для отправки) предназначено для управления потоком (т. Е. Для предотвращения переполнения буфера - буферы на этих микроконтроллерах обычно довольно малы) и не для полной остановки передачи.

0 голосов
/ 01 августа 2009

Эта статья предназначена для сборки, а не для C, но может оказаться полезной: http://www.8052.com/tutser.phtml

...