Помогите пожалуйста с таким вопросом. Словил адский глюк на МК, еле отловил его. Суть такая, есть массив определенной размерности и если в строке, которая в него отправляется символов больше чем в массиве то происходит что-то странное. Например некоторые переменные сами по себе меняют свое значение, неправильно работает логика и т. д.
Проблему то я решил, сделав массив больше, но я не совсем понимаю почему так могло происходить. И хотелось бы добавить какую-то проверку чтобы в будущем этого избежать.
buffer_tx_index=0; //эта переменная очищается в нужный момент, перед помещением новой строки в массив
USART_SendStr("какая-то строка");
UPD: кажется я понял. Получается я вылезал за размерность массива и данные писались куда-то в память, а там были значения переменных и на их место писались левые значения. Добавил вот такую проверку
Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
Добавлено: Ср сен 06, 2017 10:14:09
Открыл глаза
Зарегистрирован: Вс сен 30, 2012 15:04:05 Сообщений: 69
Рейтинг сообщения:0
Кто-нибудь подскажет, обязательно ли достижение логического нуля при прерывании по спадающему фронту? И второй вопрос туда же; у меня INT и ADC вместе, ADC подтянут к + через 10 кОм, а к земле через кнопку и 5кОм, соответственно при замыкании кнопки на ADC и INT не ноль, но хочется, чтобы прерывание сработало, что посоветуете?
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
см. логические уровни а даташите. Гарантированно сработает low = (-0.5 ... VCC*0.2), high=(VCC*0.6 ... VCC+0.5). На практике можно считать, что переключение идет примерно по середине питания. Это довольно грубое приближение: в реальности на входах присутствует гистерезис, разброс характеристик и т.п.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
Добавлено: Ср сен 06, 2017 14:11:01
Собутыльник Кота
Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04 Сообщений: 2694 Откуда: г. Чайковский
Рейтинг сообщения:0 Медали: 1
Protosha писал(а):
ADC подтянут к + через 10 кОм, а к земле через кнопку и 5кОм,
Т.е. у Вас всего два возможных состояния уровней напряжения на порте. Посоветую не использовать АЦП и сделать уровни, которые гарантируют четкие логические уровни.
Вопросы Ваши к "о программировании AVR на Си." отношения не имеют.
_________________ Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
Добавлено: Ср сен 06, 2017 14:24:35
Открыл глаза
Зарегистрирован: Вс сен 30, 2012 15:04:05 Сообщений: 69
Рейтинг сообщения:0
У меня 4 таких резистора (разные) с кнопочками, поэтому на ADC. Я тут подумал может существует какая схема, которая дополнительно просадит напряжение на очень короткий промежуток времени (<10ms)? Но такой, чтобы ADC получил не ноль со всех кнопок, а уже восстановившееся значение. Никто не сталкивался? Все используют кнопки без прерываний или занимают 100500 портов?
Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
Добавлено: Ср сен 06, 2017 14:30:00
Собутыльник Кота
Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04 Сообщений: 2694 Откуда: г. Чайковский
Рейтинг сообщения:1 Медали: 1
Компаратор можно использовать или внешний или внутренний. Так то, как правило, кнопки удобно в основном цикле проверять, т.к. обычно это самая медленная периферия.
Добавлено after 2 minutes 45 seconds: Можно использовать прерывание от АЦП. Установить самую низкую частоту для АЦП, чтобы по реже срабатывало, т.к. точность Вам не нужна должно нормально работать.
_________________ Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
задействовал 2 порта и успешно пробуждал МК от сна прерыванием, а затем при помощи АЦП определял, какая кнопка это прерывание вызвала... может, мой вариант вам подойдет?
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
...кнопки удобно в основном цикле проверять, т.к. обычно это самая медленная периферия.
А если в основном цикле что-то работает, прикажете мне стоять с нажатой кнопкой и ждать чуда? А если я хочу не ждать, а прервать все процессы и сделать что-то другое?
Вот хотелось бы пояснений. 1)Когда я нажимаю на кнопки, напряжение на них от 0.39Uп до 0.68Uп (прерывание не срабатывает), на вашей схеме (пусть внутренняя подтяжка 40кОм) при нажатии SB1 на PB4 0.5Uп и прерывание срабатывает?? 2)Зачем для вывода нуля вы использовали PB3, а не землю?
а вы по ссылке ходили? статью читали? я там подробно все описал, зачем и почему.
Добавлено after 3 minutes 57 seconds:
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 МГц.
и, в принципе, все перечисленные функции "на глаз" выполняются мгновенно. во всяком случае, дискомфорта я не испытываю от скорости реакции на внешние воздействия.
что делаете вы, что боитесь не успеть?
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Доброго времени суток адептам Си. Решил потихоньку изучать данный язык, и в качестве учебной задачи взялся написать парсер АТ команд. Как ни странно, за вечер неторопливого чтива инфы по указателям, с перерывами на чаек, родилось что-то рабочее. Но как обычно, я не верю, что мог вот так вот взять, и правильно/красиво написать. Просьба подсказать что где можно подправить/улучшить. В часности меня напрягает "warning: passing argument 1 of 'Parsing_in_UART' discards qualifiers from pointer target type" в обработчике Прерывания по приходу байта в буффер UART. Переводчиком воспользовался, но все равно не осилил И еще, как правильно организовать вываливание из функции ожидания парсинга Parsing по ошибке парсинга? Сейчас у меня обработчик UART возвращает код ошибки 2, но я не могу придумать условия, как по нему быстро вывалиться из цикла ожидания, не тупя там до истечения времени парсинга. И продолжаю там ожидать, как будто парсинг еще продолжаеться Спойлер
char Parsing(char *string, unsigned int parsing_delay); char Parsing_in_UART(char *string);
// Обявляем глобальные переменные volatile char *parsing_pointer; // Указатель на строку, которую будем парсить volatile char parsing_result; // Результат парсинга строки
// Заводим строки AT команд во флеше. Обязательно вне main char AT[] PROGMEM = "AT\r\n"; char OK[] PROGMEM = "OK\r\n";
// Прерывание по приходу байта в буффер UART ISR (USART_RXC_vect) { parsing_result = Parsing_in_UART(parsing_pointer); // Парсим строку посимвольно, после каждого вызова возвращаем состояние парсинга (0-парсинг продолжаеться, 1- парсинг успешно закончен, 2- ошибка парсинга или превышено время парсинга) }
int main(void) { volatile unsigned char i;
// Инициализация периферии UBRRL = LO(bauddivider); UBRRH = HI(bauddivider); UCSRA = 0; UCSRB = 0<<RXCIE|0<<TXCIE|0<<UDRIE|1<<RXEN|1<<TXEN; // Прерывание UDRIE сразу никогда не разрешаем, иначе контроллер сразу входит в это прерывание UCSRC = 1<<URSEL|1<<UCSZ1|1<<UCSZ0;
LED_DDR |= 1<<LED1|1<<LED2; // Светодиоды на вывод
sei();
InitSIMCOM(); // Инициализируем модуль SIMCOM
// Главный цикл while(1) { i++; LED_PORT ^=1<<LED1; _delay_ms(1000);
} }
// Инициализация модуля SIMCOM ========= void InitSIMCOM(void) { while (parsing_result != 1) // Пока нет овета ОК, долбим АТ { SendStr_P(AT); // Шлем АТ parsing_result = Parsing(OK,500); // И после каждого АТ 500 мс ждем ответ. Должен быть "ОК" } }
// Парсинг строки ================== char Parsing(char *string, unsigned int parsing_delay) // На входе указатель на первый символ строки, и время парсинга строки { parsing_pointer=string; // Копируем указатель на 1 сивол строки, которую будем парсить в глобальную переменную UCSRB |= 1<<RXCIE; // Разрешаем прерывание по приходу байта - парсинг начался
while(parsing_result != 1) // Ждем успешного окончания, либо ошибки парсинга { _delay_ms(1); parsing_delay--; if (parsing_delay==0) return 2; // Если время парсинга вышло, вываливаемся из цикла с ошибкой парсинга } return 1; }
// Парсинг символа строки в обработчике UART ========================= char Parsing_in_UART(char *string) // На входе указатель на символ строки { if (UDR == pgm_read_byte(string)) // Сравниваем принятый байт с символом из строки { // Если идентичны string++; // Увеличиваем указатель, выбирая следующий символ строки if (pgm_read_byte(string)=='\0') // Если следующий байт строки 0 (конец строки) { UCSRB &=~(1<<RXCIE); // Запрещаем прерывание по приходу байта - прием закончен return 1; // Возвращаем признак успешного окончания парсинга } else { parsing_pointer=string; // Иначе обновляем глобальный указатель return 0; // И вываливаемся без признака успешного парсинга } } else return 2; // Если не идентичны - возвращаем признак ошибки парсинга. Не 0, чтобы сразу закончить неудачный парсинг }
// Отправка строки из флеша в UART ================= void SendStr_P(char *string) // На входе указатель на символ строки { while (pgm_read_byte(string)!='\0') // Пока байт строки не 0 (конец строки) { SendByte(pgm_read_byte(string)); // Мы продолжаем слать строку string++; // Не забывая увеличивать указатель, выбирая следующий символ строки } }
// Отправка одного символа строки в UART =========== void SendByte(char byte) // На входе байт { while(!(UCSRA & (1<<UDRE))); // Ждем флага готовности UART UDR=byte; // Засылаем байт в UART }
Как-то странно у вас... если работаете по прерываниям, то по прерываниям надо все и делать, без циклов ожидания. Похоже, от автомата состояний вам никуда не деться... Передали строку - перешли в состояние "жду ответа", попутно установили таймер ожидания Таймер истек до прихода ответа - перешли в состояние "ошибка ожидания" Пришел байт - перешли в состояние "прием строки", а если уже в состоянии приема строки, то анализируете байт и по итогам анализа либо остаетесь в этом состоянии (еще не дошла вся строка), либо переходите в состояние "ошибка" или "принят ответ" и т.д. прием байта, таймер - по прерываниям, остальное - функциями.
а в главном цикле смотрите на состояние и делаете нужные операции: если надо ждать - ждете, если надо устранять ошибку - устраняете, если пришла какая-то строка - выполняете, что надо...
И еще: из обработчика прерываний крайне нежелательно вызывать другие функции, тем более с параметрами. Но если уж очень хочется, делайте все эти вызываемые из прерывания функции static, и, по возможности, ниоткуда более их не вызывайте.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
В часности меня напрягает "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 в данном случае выглядит мягко говоря странно. Что во флеше может что-то измениться?
Спасибо за советы, придеться наверно таки делать конечный автомат. Пока, как посоветовал ARV, перенес код парсинга из функции в сам обработчик, и варнинг действительно пропал. Насчет того, зачем указатель обявлять как volatile. Я читал, и везде неоднократно слышал, что этот квалификатор используеться, если переменная может произвольно (асинхронно, в любой момент времени) изменяться действиями извне. У меня она задаеться при вызове функции парсинга, а изменяеться в обработчике по приему байта. Когда придет байт я без понятия, выходит собитие асинхронное, поэтому и поставил этот квалификатор. Я неверно рассуждал ?
Насчет того, зачем указатель обявлять как volatile. Я читал, и везде неоднократно слышал, что этот квалификатор используеться, если переменная может произвольно (асинхронно, в любой момент времени) изменяться действиями извне. У меня она задаеться при вызове функции парсинга, а изменяеться в обработчике по приему байта. Когда придет байт я без понятия, выходит собитие асинхронное, поэтому и поставил этот квалификатор. Я неверно рассуждал ?
volatile char *p; // значение куда указывает p может изменяться (у Вас оно меняться в принципе не может, так как находится во флеше) char * volatile p; // значение самого указателя может изменться
Ну и наконец volatile char * volatile p; // значение указателя может меняться во вне (например, в обработчике) и значение, на которое указывает p тоже может меняться во вне
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 46
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения