2009-08-01 6 views
6

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

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

Я попытался использовать контакт RTS (Request to Send) (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

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

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

+0

Программное обеспечение, которое я использую на ПК, это X-CTU для модулей Xbee. Это код моего микроконтроллера: #include void SerTx (unsigned char); void main (void) { \t TMOD = 0x20; \t TH1 = 0xFD; \t SCON = 0x50; \t TR1 = 1; \t \t \t SerTx ('O'); \t SerTx ('N'); \t SerTx ('L'); \t SerTx ('Y'); \t void SerTx (unsigned char x) { \t SBUF = x; \t while (TI == 0); \t TI = 0; } } Возможно, кто-то подтвердит, что он фактически отправляет только одну строку? – CodeConfused

+0

Пожалуйста, отредактируйте свой вопрос и вставьте код, отформатированный как код, чтобы его было легче читать. –

+0

@CodeConfused: Я рад, что все мы нашли решение! У меня есть еще два запроса. (1) По этому вопросу и всем остальным вопросам о переполнении стека, пожалуйста, отметьте ответ как «принятый», нажав на большой галочку тем, который, по вашему мнению, дает лучший ответ на ваш вопрос. Это полезно для других людей, у которых может быть один и тот же вопрос в будущем, так как они могут сразу увидеть лучший ответ. (2) В этом вопросе, пожалуйста, отформатируйте код как код. Для этого отредактируйте вопрос, выберите код и нажмите кнопку кода (это кнопка с 1 и 0 на ней). Благодарю. –

ответ

6

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

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

EDIT: Честно говоря, это звучит как вид отладку, что инженеры должны столкнуться на регулярной основе, и поэтому это хорошая возможность для Вас, чтобы практиковать хорошие старомодные методические решение проблем.

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

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

EDIT: У меня нет респ редактировать вопрос, так вот код отправленный ОП в комментарии к ней вопрос:

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

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

Кроме того, функция SerTx должна быть определена вне основного. Это может быть синтаксически корректным, но в нем все упрощается, не объявляя функции в рамках других функций.

Так что попробуйте это (я также добавил некоторые комментарии в попытке сделать проще код, чтобы понять):

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

Я использую модули Xbee, Стив, поэтому программное обеспечение на ПК - X-CTU. Тем не менее, я попытался устранить проблему, используя Hyperterminal. То же самое происходит и с этим, т. Е. Строка принимается непрерывно. – CodeConfused

+0

Абсолютно ты можешь быть очень тупым, Стив! :) Все, что помогает! Ваш код сделал трюк, спасибо большое. P.S. TI = 0 не является точно отключением передатчика. TI должен быть принудительно равен нулю, потому что после передачи одного символа 8051 поднимает флаг TI, чтобы сигнализировать, что он готов к большей передаче. – CodeConfused

2

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

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

Использование RTS/CTS (запрос на отправку/очистку для отправки) предназначено для управления потоком (то есть для предотвращения переполнения буфера), на таких микроконтроллерах, как правило, довольно мало), а вовсе не останавливать передачу.

6

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

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

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

Кроме того, определение serTx(), вложенного в main(), возможно, не то, что вы хотите.

+0

Спасибо Нейлу, ты был абсолютно прав. Но есть ли способ выйти из пустой петли без использования аппаратного обеспечения? – CodeConfused

+0

P.S. Я не думаю, что у моего микроконтроллера есть сторожевой таймер. – CodeConfused

+0

Я предполагаю, что простой ответ: сделать петлю что-то сделать. Встроенная прошивка обычно имеет основной цикл, который работает вечно. Этот цикл будет проверять аппаратное обеспечение, чтобы увидеть, есть ли какая-то работа, например новые данные из последовательного порта или измененный цифровой вход, а затем вызвать соответствующую функцию для работы с этим событием. – Neil

2

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

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

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

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

+0

Спасибо brooksmoses. Вы объяснили это очень хорошо!И я думаю, что это именно то, что происходило здесь. – CodeConfused