А зачем такие сложности? Почему нельзя просто UCSR0C = 0x06; Там же нет битов, которые меняются в процессе работы, и которые можно испортить. Я как понял, это никакая не битовая операция, а как записать байт в регистр идиотским способом.
Eто целый стиль прогр. кода для AVR. Например, мне всегда удивляет DATA = ... | (0 << NNN). Кто пишет так, как привык. Важен результат, а к чужому стилю привыкаешь быстро.
А зачем такие сложности? Почему нельзя просто UCSR0C = 0x06;
можно. и иногда я так делаю, если пишу для себя и предполагаю, что никогда не вернусь к этому. И если придется возвращаться, то вспомнить, что такое 0x06 мне невозможно, и будет потеря времени на проверку, что здесь включено, есть четность или нет, 7 или 8 бит и т.д.
я делаю как ненормальные... но указываю все биты в т.ч. и 0е, и обычно дефайню значения для удобочитаемости (получается вроде таблицы алгоритм-билдера) но! небольшая проблема возникает когда один параметр растянут на 2 регистра (напрямую писать уже не получится, но дефайн при этом использовать по прежнему можно, правда конструкции выходят витиеватые - пример регистр WGM1 в tiny2313)Спойлер
Код:
// Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 1200,000 kHz #define _CS1 1 // Mode: CTC top=OCR1A #define _WGM1 4 // OC1A output: Disconnected #define _COM1A 0 // OC1B output: Disconnected #define _COM1B 0 // Noise Canceler: Off #define _ICNC1 0 // Input Capture on Falling Edge #define _ICES1 0 // Timer1 Overflow Interrupt: Off #define _TOIE1 0 // Input Capture Interrupt: Off #define _ICIE1 0 // Compare A Match Interrupt: Off #define _OCIE1A 0 // Compare B Match Interrupt: Off #define _OCIE1B 0
а можно пойти ещё дальше и, добавив условную компиляцию, исключать из сборки содержащие нули регистры неподключаемой периферии... пожалуй, как время появится, этим и займусь...
Добавлено after 7 hours 77 minutes 77 seconds: Получится что-то такое, вынесенное в отдельный файл...Спойлер
_________________ Просто не учи физику в школе, и вся твоя жизнь будет наполнена чудесами и волшебством Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
нет, этот код пользователь не увидит, для него настройка будет выглядеть так:Спойлер
Код:
// Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 1200,000 kHz #define _CS1 1 // Mode: CTC top=OCR1A #define _WGM1 4 // OC1A output: Disconnected #define _COM1A 0 // OC1B output: Disconnected #define _COM1B 0 // Noise Canceler: Off #define _ICNC1 0 // Input Capture on Falling Edge #define _ICES1 0 // Timer1 Overflow Interrupt: Off #define _TOIE1 0 // Input Capture Interrupt: Off #define _ICIE1 0 // Compare A Match Interrupt: Off #define _OCIE1A 0 // Compare B Match Interrupt: Off #define _OCIE1B 0
#include <tiny2313_peripheral_init.c>
я хотел упростить эту тавтологию, (хоть она не очень то и мешает) но внутри дефайна не получилось применить условную компиляцию
Добавлено after 6 minutes 43 seconds: оно, конечно, можно ещё приблизить к пользователю, если применять команды вида: #define _NoiseCancellerOnTimer1Enabled вместо #define _ICNC1 1 но это и печатать больше и ещё кучу команд учить...
Добавлено after 1 minute 7 seconds: Да и какой-то уж слишком ардуинообразный код получится...
_________________ Просто не учи физику в школе, и вся твоя жизнь будет наполнена чудесами и волшебством Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
Добавлено: Ср июл 12, 2023 09:29:39
Встал на лапы
Зарегистрирован: Пт мар 19, 2021 08:58:45 Сообщений: 118
Рейтинг сообщения:0
Всем привет! Собрал я для своей дачи контроллер для озонирования воды, т.к. в воде много двухвалентного железа, его как то надо окислять, чтобы применять воду для бытовых нужд, озон лучше всего для этого подходит еще попутно очень хорошо обеззараживает воду. Вся система состоит из двух бочек, алгоритм таков: первую бочку скважный насос накачивает воду, после наполнения бочки включается циркуляционный насос и гоняет воду по кругу в первой бочке через эжектор Вентури, тем самым смешивает воду с озоном из озонатора 1 час(по таймеру), далее отстаивание воды 6 часов(по таймеру), далее перелив воды через электромагнитный клапан во вторую расходную бочку, откуда после наполения второй бочки третий насос с гидроаккамулятром подает воду в дом на разбор. Всем этим действием и управляет контроллер на atmega8. Решил прикрутить еще "собаку", ну мало ли завис, сбросит. Но тут же возникает вопрос из за незнания применения "собаки", к примеру зависло во время одного из действия когда считает таймер, "собака" сбросила, т.е. все сначало, весь счет таймера потерялся... как с этим быть, писать в энергонезависимую память раз в секунду/минуту какая часть программы выполнялась, счет таймера, ресурс быстро израсходую? писать все тоже самое отдельную память?
к примеру зависло во время одного из действия когда считает таймер, "собака" сбросила, т.е. все сначало, весь счет таймера потерялся... как с этим быть, писать в энергонезависимую память раз в секунду/минуту какая часть программы выполнялась, счет таймера, ресурс быстро израсходую? писать все тоже самое отдельную память?
В самом дешёвом модуле RTC для ардуинки, в чипе DS1307 есть ещё и SRAM с питанием от батареи, 56 байт. Можно туда заливать текущее состояние, дублируя трижды, с учётом того, что МК может зависнуть во время записи. А при старте сравнивать все три сохранённых блока, если два идущих подряд совпали - можно их использовать для восстановления состояния. Либо просто использовать время из RTC, типа "если сейчас от 01 до 06 часов утра - гонять воду в первом баке".
считать таймер в переменных, не очищаемых при сбросе МК
Подскажите пожалуйста, скажем после сброса сторожевым таймером, мне скорее всего нужно в регистре управления MCUCSR два бита WDRF(Флаг индикации сброса сторожевым таймером) и PORF(Флаг Сброса включении питания), чтобы понимать МК как он именно сбросился. Потом, поняли что сторожевым таймером, биты сбросить в 0. Далее самое интересно, где это делаетcя int main? нацарапал приблизительный пример:
int main(void) { if (MCUCSR & (1 << PORF)) // вероятность этого сброса выше всех, пусть идет первым { MCUCSR&=(unsigned char)(~(1 << PORF)); // делаем что должно при сбросе "вкл-выкл питания" } else if (MCUCSR & (1 << WDRF)) { MCUCSR&=(unsigned char)(~(1 << WDRF)); // делаем что должно при сбросе "собакой" } else { // делаем что должно при ином сбросе }
Я тоже так подумал вначале. Но потом пришел к выводу, что сбрасывая сразу все биты в конце мы увеличим длину кода до их сброса (особенно если большая обработка причины сброса), а значит и вероятность сброса во время выполнения этого участка. И последующее определение причины сброса может оказаться неверным.
на сколько я помню, минимальное время WDT - около 15 мс, за это время можно столько кода выполнить... другое дело, что лучше проверять причину сброса в секции .init3, т.е. после инициализации внутренних регистров и стека, но до очистки статических переменных... вот тогда время будет минимальным. хотя, имхо, и так страху нет
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
Добавлено: Ср июл 19, 2023 07:51:14
Сверлит текстолит когтями
Карма: 12
Рейтинг сообщений: 38
Зарегистрирован: Вс май 21, 2006 16:07:59 Сообщений: 1225 Откуда: Алтай
Рейтинг сообщения:0
Вопрос знатокам, есть две восьмибитных переменных А и В Как просто младший полубайт переменной А сохранить (перенести) в младший полубайт переменной В, не изменяя значение старшего полубайта переменной В?
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения