Страница 49 из 421

Добавлено: Пн авг 31, 2009 22:23:18
dm211
Вот так сделал-

Код: Выделить всё

char s[]="RING"; 
if(!strcmp(rx_buffer,s)) putsf("ATA\r");

Добавлено: Вт сен 01, 2009 17:04:51
dm211
Но это работает только один раз, это понятно-нужно очистить массив,чтобы следующая приходящая строка вводилась на чистый массив. Как это можно сделать ?

Код: Выделить всё

memset(rx_buffer,0,100);
не помогает.

Добавлено: Вт сен 01, 2009 18:00:09
alexsey163
здравствуйте а есть у кого нибудь старая версия code vision avr или дайте ссылку. :lol:

Добавлено: Вт сен 01, 2009 18:17:24
dm211
http://www.hardlock.org.ua/soft/cvavr/index.html
Мне бы кто ответил..

Добавлено: Вт сен 01, 2009 18:38:34
alexsey163
спасибо вам но там она не работает. :( .Не знаете ли ещё откуда можно скачать старую версию.

Добавлено: Вт сен 01, 2009 18:43:16
Yellow Tiger
dm211 писал(а):http://www.hardlock.org.ua/soft/cvavr/index.html
Мне бы кто ответил..
Работать напрямую с rx_buffer - не следует, ведь он хранит не строку, а данные циклического буфера - начало строки в нем не по адресу rx_buffer[0], а где угодно внутри. :)))
Я советовал использовать gets() - что-то не подошло в таком варианте? Слишком простой, так как не нужно пользоваться memset'ом? :)))

Добавлено: Вт сен 01, 2009 18:55:49
dm211
gets() у меня ошибку выдает.

Добавлено: Вт сен 01, 2009 19:35:25
Yellow Tiger
И что теперь - отказаться от неё? :)))

Добавлено: Ср сен 02, 2009 08:58:25
dm211
Допустим,без gets(), а с помощью getchar() собираю приходящие символы в массив m, внутри прерывания по приходящему символу:

Код: Выделить всё

char s[]="RING";
char m[5];
// Прерывание по приему символа в регистр  UDR
interrupt [USART_RXC] void usart_rx_isr(void)
{
......
 m[i]=getchar();
  i++; if(i==5)i=0;    
  if(!strcmp(m,s)){putsf("ATA\r");}
}
Тоже работает только один раз, пробовал так-

Код: Выделить всё

if(!strcmp(m,s)){putsf("ATA\r");m[0]='0';} // также m[0]='\0'; , m[0]=' ';
-толку нет. Перерыл весь инет-с такой проблемой вопросы есть,но ответа толкового нет.
Вот проект с Протеусом-

Добавлено: Ср сен 02, 2009 19:20:14
Yellow Tiger
То, что ваша программа вообще работает - чистая случайность.

Общие замечания:

1. Я вам уже говорил - использовать приемный буфер, как строку нельзя - это только в первый раз символы укладываются в него с начала, а дальше - начало строки и её конец циклически ползают по буферу. Правда, ваше "работает только в первый раз" имеет другой объяснение - о нем чуть позже.

2. Участок кода от getchar() до putsf() должен быть вынесен за пределы обработчика прерываний - во-первых, потому, что работа со входным потоком и обработкой команд - это синхронная часть кода, а не асинхронная; а во-вторых потому, что тело обработчика прерываний должно исполняться за наикратчайшее время. Выносите всё в main() (пока нет других, вложенных функций).

3. глобальные переменные (i, m[]) объявляйте как volatile, иначе компилятор, видя, что к ним ни один оператор функции main и вызываемых ею, не обращается, может соптимизировать все "до нуля". :)))

Теперь о поведении программы.
Символьный массив m[] - статический, а значит - инициируется нулями. Что произойдет в первый раз, после приема символа 'G'??? ... подумали? Ответ нашли? ... Показываю - в буфере (еще до прихода символа '\r'!!!), будет строка 'RING\0' - и сравнение с помощью strcmp() пройдет правильно, но(!!!) - признак конца строки, после четырех символов RING - находится там случайно - он остался от нулей, внесенных во время инициализации статических данных, и больше его туда никто не поместит, а значит - strcmp() уже никогда не найдет там какую-либо строку, даже если вы приложите усилия к тому, чтобы прерывание всякий раз укладывало новую строку, начиная с первого символа.

В общем, в первый раз срабатывает правило четности ошибок, и программа срабатывает "верно", но потом количество ошибок становится нечетным,и программа перестает создавать видимость правильной работы. :)))

Удачи! :)

Добавлено: Ср сен 02, 2009 19:51:38
dm211
Спасибо за подробные разьяснения.

Добавлено: Ср сен 02, 2009 20:13:49
Yellow Tiger
Что, уже заработало? :)

Добавлено: Ср сен 02, 2009 20:28:37
ARV
мне вообще непонятна страсть начинающих к кольцевым буферам и прерываниям... ну если опыта маловато, ну поступайте примитивно - работайте по ожиданию символа! 99% ваших потребностей реализуются так, что пока не пришло что-то - ничего не делается! тут никаких асинхронных приемов с буфферизацией не нужно...

Добавлено: Ср сен 02, 2009 20:48:24
Yellow Tiger
Так ведь, такой пример попался... с кольцевым буфером. :(

Добавлено: Ср сен 02, 2009 21:15:59
dm211
Да у меня давно все работает по приходу символа, иногда не хватает-например- узнать заряженность аккумулятора модема, чтоб снаружи включить зарядку

Добавлено: Ср сен 02, 2009 21:16:57
dm211
Ну я же спрашиваю тех,у кого большой опыт...

Добавлено: Чт сен 03, 2009 06:11:17
dm211
Тогда мне надо сделать по другому-не сравнивать строки полностью, а сделать реакцию, если в приходящих символах есть например одна за другой цифры 7,0, тогда и переполнение буфера не страшно. Буду думать над этим.

Добавлено: Чт сен 03, 2009 13:25:36
ARV
даже и не знаю... захотелось пособветовать один алгоритм, но не окажу ли я медвежью услугу? вы тут с буфером разобраться не можете, а тут я со своими идеями... но рискну.

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

поясню алгоритм поиска.
вы определяете структуру типа

Код: Выделить всё

typedef struct{
   char flag; // признак "активности"
   char cmd[]; // строка-команда
}t_search
и потом создаете массив таких структур с заданием каждому элементу массива flag=1 и cmd = "вашей строке".

Код: Выделить всё

t_search array[3] = {
   {1,"RE"}, {1,"RU"}, {1,"ST"} // для команд RESET, RUN и STOP хватит анализа первых 2 символов
};
затем начинаете ждать символ. когда пришел символ - вы его сравниваете с первым символом команд во всем массиве, и устанавливаете flag=1 для тех элементов, в которых символы совпали.

Код: Выделить всё

array[i].flag = array[i].str[1] == ch;
затем ждете следующий символ и сравниваете его со вторым символом тех команд, у которых flag==1. если оказалось, что второй символ не совпал в некоторых элементах массива - вы делаете для них flag=0.

Код: Выделить всё

array[i].flag = array[i].flag && (array[i].str[2] == ch);
и так повторяете до тех пор, пока не будут приняты N символов, по которым 100% будет определена единственная команда в массиве - только у нее останется flag==1.

если синтаксис ваших команд таков, что принимается более длинаая команда, чем из N символов, или в команде имеются параметры, которые тоже надо обрабатывать, то это вы делаете уже после определения команды: "хвост" символов сверх N просто отбрасываете (ведь к этому моменту уже ясно, сколько там осталось символов), а параметры выделяете традиционным методом.

естественно, после всего этого надо сделать flag = 1;во всех элементах массива.

алгоритм можно усовершенствовать - это лишь общий план, набросок. надеюсь, вам это поможет...

Добавлено: Чт сен 03, 2009 14:15:26
dm211
Спасибо, буду разбираться со структурами теперь.

Добавлено: Чт сен 03, 2009 16:33:27
klok
Yellow Tiger писал(а): Прерывание помещает приходящие символы в буфер, getch() - достает их оттуда, а gets() - вызывает getch() (помещая результат в строку) пока не получит из неё символ конца строки. И всех делов.
Приветствую мастеров Си... У меня задача, сходная с задачей dm211 - есть набор запросов, на которые надо отвечать... УАРТ должен работать по прерыванию... Сразу скажу, на асме я это делал не напрягаясь, подозреваю что на Си это еще проще, только вот не вштырило меня еще Си :(
Подскажите как мне эту gets вызвать, и что она мне даст в ответ...

Лучше пример кода, дальше разберусь :)