Обсуждаем контроллеры компании Atmel.
Ответить

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт авг 18, 2017 13:18:48

Помогите пожалуйста с таким вопросом. Словил адский глюк на МК, еле отловил его.
Суть такая, есть массив определенной размерности и если в строке, которая в него отправляется символов больше чем в массиве то происходит что-то странное. Например некоторые переменные сами по себе меняют свое значение, неправильно работает логика и т. д.

Проблему то я решил, сделав массив больше, но я не совсем понимаю почему так могло происходить.
И хотелось бы добавить какую-то проверку чтобы в будущем этого избежать.
Код:
unsigned char usartTxBuf[15]; //передающий буфер
buffer_tx_index = 0;

void USART_PutChar(unsigned char sym)
{
    usartTxBuf[buffer_tx_index] = sym; //помещаем символы в буфер
   buffer_tx_index++;
}


//функция отправки строки
void USART_SendStr(char * data)
{
  unsigned char sym;
  while(*data){
    sym = *data++;
    USART_PutChar(sym);
  }
}

buffer_tx_index=0; //эта переменная очищается в нужный момент, перед помещением новой строки в массив

USART_SendStr("какая-то строка");

UPD:
кажется я понял. Получается я вылезал за размерность массива и данные писались куда-то в память, а там были значения переменных и на их место писались левые значения. Добавил вот такую проверку
Код:
void USART_PutChar(unsigned char sym)
{
    usartTxBuf[buffer_tx_index] = sym; //помещаем символы в буфер
        if(buffer_tx_index < 15-1)
        {
   buffer_tx_index++;
        }
}

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн сен 04, 2017 18:48:47

Как вот это культурно написать?
Код:
if(m[0]<x && m[1]<x && m[2]<x && ......m[50]<x) y=0;

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн сен 04, 2017 19:10:08

Как вот это культурно написать?
Код:
if(m[0]<x && m[1]<x && m[2]<x && ......m[50]<x) y=0;

например, так
Код:
int i;
for(i = 0; (i < 51) && (m[i] < x); i++);
if(i >= 51) y = 0;

Re: Нескольно простых вопросов о программировании AVR на Си.

Ср сен 06, 2017 10:14:09

Кто-нибудь подскажет, обязательно ли достижение логического нуля при прерывании по спадающему фронту?
И второй вопрос туда же; у меня INT и ADC вместе, ADC подтянут к + через 10 кОм, а к земле через кнопку и 5кОм, соответственно при замыкании кнопки на ADC и INT не ноль, но хочется, чтобы прерывание сработало, что посоветуете?

Re: Нескольно простых вопросов о программировании AVR на Си.

Ср сен 06, 2017 13:59:55

см. логические уровни а даташите. Гарантированно сработает low = (-0.5 ... VCC*0.2), high=(VCC*0.6 ... VCC+0.5). На практике можно считать, что переключение идет примерно по середине питания.
Это довольно грубое приближение: в реальности на входах присутствует гистерезис, разброс характеристик и т.п.

Re: Нескольно простых вопросов о программировании AVR на Си.

Ср сен 06, 2017 14:11:01

Protosha писал(а):ADC подтянут к + через 10 кОм, а к земле через кнопку и 5кОм,
Т.е. у Вас всего два возможных состояния уровней напряжения на порте. Посоветую не использовать АЦП и сделать уровни, которые гарантируют четкие логические уровни.

Вопросы Ваши к "о программировании AVR на Си." отношения не имеют.

Re: Нескольно простых вопросов о программировании AVR на Си.

Ср сен 06, 2017 14:24:35

У меня 4 таких резистора (разные) с кнопочками, поэтому на ADC.
Я тут подумал может существует какая схема, которая дополнительно просадит напряжение на очень короткий промежуток времени (<10ms)? Но такой, чтобы ADC получил не ноль со всех кнопок, а уже восстановившееся значение. Никто не сталкивался? Все используют кнопки без прерываний или занимают 100500 портов?

Re: Нескольно простых вопросов о программировании AVR на Си.

Ср сен 06, 2017 14:30:00

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

Добавлено after 2 minutes 45 seconds:
Можно использовать прерывание от АЦП. Установить самую низкую частоту для АЦП, чтобы по реже срабатывало, т.к. точность Вам не нужна должно нормально работать.

Re: Нескольно простых вопросов о программировании AVR на Си.

Ср сен 06, 2017 14:48:36

А что у вас за задача, что надо кнопочки "аналоговые" и прерывание на один порт вешать?

вот у меня был проект с такой схемой:
Изображение
задействовал 2 порта и успешно пробуждал МК от сна прерыванием, а затем при помощи АЦП определял, какая кнопка это прерывание вызвала... может, мой вариант вам подойдет?

Re: Нескольно простых вопросов о программировании AVR на Си.

Ср сен 06, 2017 16:18:23

...кнопки удобно в основном цикле проверять, т.к. обычно это самая медленная периферия.

А если в основном цикле что-то работает, прикажете мне стоять с нажатой кнопкой и ждать чуда? А если я хочу не ждать, а прервать все процессы и сделать что-то другое?
Можно использовать прерывание от АЦП.

А это хорошая мысль, упустил, спасибо.
А что у вас за задача, что надо кнопочки "аналоговые" и прерывание на один порт вешать?

Да ничего особенного, хочется по нажатию понять, какая кнопка нажата и выполнить соответствующее действие.
...вот у меня был проект с такой схемой...

Вот хотелось бы пояснений.
1)Когда я нажимаю на кнопки, напряжение на них от 0.39Uп до 0.68Uп (прерывание не срабатывает), на вашей схеме (пусть внутренняя подтяжка 40кОм) при нажатии SB1 на PB4 0.5Uп и прерывание срабатывает??
2)Зачем для вывода нуля вы использовали PB3, а не землю?

Re: Нескольно простых вопросов о программировании AVR на Си.

Ср сен 06, 2017 17:40:23

Protosha писал(а):Вот хотелось бы пояснений.
а вы по ссылке ходили? статью читали? я там подробно все описал, зачем и почему.

Добавлено after 3 minutes 57 seconds:
Protosha писал(а):А если в основном цикле что-то работает, прикажете мне стоять с нажатой кнопкой и ждать чуда? А если я хочу не ждать, а прервать все процессы и сделать что-то другое?
если у вас все нормально организовано в основном цикле - не будет никаких проблем! ничего ждать не придется.

Re: Нескольно простых вопросов о программировании AVR на Си.

Ср сен 06, 2017 18:26:16

...я там подробно все описал, зачем и почему.

"..после чего на делитель подается питание.."
Вот этими словами вы имели ввиду выдача "1" с порта PB3?

...если у вас все нормально организовано в основном цикле - не будет никаких проблем!

А если организовано нормально, прям высчитано время, которое будет тратиться на те или иные функции и заход в них осуществляется не всегда, а по таймеру и с определёнными событиями, чтобы вообще очень сильно экономить время, но сами функции могут быть увесистыми, но их нужно прервать экстренным методом, то тоже не будет никаких проблем от кнопок без прерываний?

Re: Нескольно простых вопросов о программировании AVR на Си.

Ср сен 06, 2017 18:57:22

Protosha писал(а):А если организовано нормально
Маловероятно, что при нормальном алгоритме нет времени на кнопки в основном цикле.

Re: Нескольно простых вопросов о программировании AVR на Си.

Ср сен 06, 2017 19:14:27

Protosha писал(а):Вот этими словами вы имели ввиду выдача "1" с порта PB3?
разумеется
Protosha писал(а):А если организовано нормально, прям высчитано время, которое...
я не знаю, что именно вы там мастерите, и не могу дать советов. поделитесь, что за задачу вы решаете? я не единожды сталкивался с тем, что простые вещи пытаются сделать слишком сложно, загоняя себя в тупик искусственно завышенных требований. например, многие считают, что реакция на кнопки должна быть мгновенной, но не дают себе труда задуматься, что такое "мгновенно" с точки зрения микроконтроллера и человека-пользователя.

с точки зрения микроконтроллера "мгновенно" - это как раз пара-тройка тактов.
а с точки зрения человека, то 0,1 секунды - это уже мгновенно. знаменитый Брюс Ли имел мышечную реакцию чуть быстрее, чем 0,1 секунды, а простой человек и 0,25 будет за счастье почитать... и даже если вашим девайсом будет пользоваться Брюс Ли, то за 0,1 секунды микроконтроллер сможет выполнить до 2 миллионов (!!!) команд. это ж какая такая увесистость функции у вас должна быть, чтобы она за это время не отработала?!

простой пример: у меня в проекте "цветомузыки" 100 раз в секунду (т.е. период цикличности 10 мс) делается цикл, состоящий из:
- сбора данных с АЦП с заданной периодичностью (64 семпла)
- FFT обработки этих семплов
- обсчета разных "видеоэффектов" (используются вычисления с float-переменными, т.е. "очень медленные")
- обновления информации для 128 светодиодов типа WS2812
- вывода на ЖКИ 16х2 текста и/или "псевдографического спектра" сигнала
- опроса энкодера с кнопкой и выполнение соответствующих команд
- приема IR-сигналов управления

и при всем этом в цикле у меня остается еще от 30 мкс до 6 мс ожидания, т.е. эта работа занимает не 10 мс, а меньше. микроконтроллер работает при этом на частоте 16 МГц.

и, в принципе, все перечисленные функции "на глаз" выполняются мгновенно. во всяком случае, дискомфорта я не испытываю от скорости реакции на внешние воздействия.

что делаете вы, что боитесь не успеть?

Re: Нескольно простых вопросов о программировании AVR на Си.

Чт сен 07, 2017 21:53:39

Удалено

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн окт 16, 2017 08:47:22

Доброго времени суток адептам Си. Решил потихоньку изучать данный язык, и в качестве учебной задачи взялся написать парсер АТ команд. Как ни странно, за вечер неторопливого чтива инфы по указателям, с перерывами на чаек, родилось что-то рабочее. Но как обычно, я не верю, что мог вот так вот взять, и правильно/красиво написать. Просьба подсказать что где можно подправить/улучшить. В часности меня напрягает "warning: passing argument 1 of 'Parsing_in_UART' discards qualifiers from pointer target type" в обработчике Прерывания по приходу байта в буффер UART. Переводчиком воспользовался, но все равно не осилил :)))
И еще, как правильно организовать вываливание из функции ожидания парсинга Parsing по ошибке парсинга? Сейчас у меня обработчик UART возвращает код ошибки 2, но я не могу придумать условия, как по нему быстро вывалиться из цикла ожидания, не тупя там до истечения времени парсинга. И продолжаю там ожидать, как будто парсинг еще продолжаеться :dont_know:

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн окт 16, 2017 09:01:20

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

а в главном цикле смотрите на состояние и делаете нужные операции: если надо ждать - ждете, если надо устранять ошибку - устраняете, если пришла какая-то строка - выполняете, что надо...

И еще: из обработчика прерываний крайне нежелательно вызывать другие функции, тем более с параметрами. Но если уж очень хочется, делайте все эти вызываемые из прерывания функции static, и, по возможности, ниоткуда более их не вызывайте.

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн окт 16, 2017 13:41:45

В часности меня напрягает "warning: passing argument 1 of 'Parsing_in_UART' discards qualifiers from pointer target type" в обработчике Прерывания по приходу байта в буффер UART. Переводчиком воспользовался, но все равно не осилил :)))


char Parsing_in_UART(char *string); // параметр char*, а передаете в эту функцию volatile char*
Вот и варнингует, что в Parsing_in_UART() квалификатор volatile отброшен.

Ну и объявление volatile в данном случае выглядит мягко говоря странно. Что во флеше может что-то измениться?

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн окт 16, 2017 20:02:38

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

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн окт 16, 2017 20:10:51

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


volatile char *p; // значение куда указывает p может изменяться (у Вас оно меняться в принципе не может, так как находится во флеше)
char * volatile p; // значение самого указателя может изменться

Ну и наконец :-)
volatile char * volatile p; // значение указателя может меняться во вне (например, в обработчике) и значение, на которое указывает p тоже может меняться во вне
Ответить