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

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
Shuspano
Грызет канифоль
Сообщения: 270
Зарегистрирован: Вс окт 20, 2019 13:03:56

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

Сообщение Shuspano »

А зачем такие сложности? Почему нельзя просто UCSR0C = 0x06;
Там же нет битов, которые меняются в процессе работы, и которые можно испортить. Я как понял, это никакая не битовая операция, а как записать байт в регистр идиотским способом.
Реклама
veso74
Поставщик валерьянки для Кота
Сообщения: 1907
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

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

Сообщение veso74 »

Eто целый стиль прогр. кода для AVR. Например, мне всегда удивляет DATA = ... | (0 << NNN). Кто пишет так, как привык. Важен результат, а к чужому стилю привыкаешь быстро.

Пример из TinyI2C:

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

USICR = 0<<USISIE | 0<<USIOIE | 1<<USIWM1 | 0<<USIWM0 | 1<<USICS1 | 0<<USICS0 | 1<<USICLK | 0<<USITC;
Реклама
OKF
Это не хвост, это антенна
Сообщения: 1392
Зарегистрирован: Вт июн 07, 2011 08:03:18

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

Сообщение OKF »

Плюс. Перед глазами все биты USICR, которые можно изменить одним движением, при необходимости.
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

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

Сообщение Martian »

[uquote="Shuspano",url="/forum/viewtopic.php?p=4426173#p4426173"]А зачем такие сложности? Почему нельзя просто UCSR0C = 0x06;[/uquote]можно. и иногда я так делаю, если пишу для себя и предполагаю, что никогда не вернусь к этому. И если придется возвращаться, то вспомнить, что такое 0x06 мне невозможно, и будет потеря времени на проверку, что здесь включено, есть четность или нет, 7 или 8 бит и т.д.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

Сообщение Ivanoff-iv »

я делаю как ненормальные... но указываю все биты в т.ч. и 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



// Timer/Counter 1 initialization
TCCR1A=(_COM1A<<COM1A0) | (_COM1B<<COM1B0) | ((_WGM1&3)<<WGM10);
TCCR1B=(_ICNC1<<ICNC1) | (_ICES1<<ICES1) | ((_WGM1>>2)<<WGM12) | (_CS1<<CS10);
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(_TOIE1<<TOIE1) | (_OCIE1A<<OCIE1A) | (_OCIE1B<<OCIE1B) | (_ICIE1<<ICIE1) | (_OCIE0B<<OCIE0B) | (_TOIE0<<TOIE0) | (_OCIE0A<<OCIE0A);
а можно пойти ещё дальше и, добавив условную компиляцию, исключать из сборки содержащие нули регистры неподключаемой периферии...
пожалуй, как время появится, этим и займусь...

Добавлено after 7 hours 77 minutes 77 seconds:
Получится что-то такое, вынесенное в отдельный файл...
Спойлер

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

// Timer/Counter 1 initialization
#if defined(_COM1A) || defined(_COM1B) || defined(_WGM1)
    TCCR1A=0
    #ifdef _COM1A
        | (_COM1A<<COM1A0)
    #endif
    #ifdef _COM1B
        | (_COM1B<<COM1B0)
    #endif
    #ifdef _WGM1 
        | ((_WGM1&0b11)<<WGM10)
    #endif
    ;  
#endif
#if defined(_ICNC1) || defined(_ICES1) || defined(_WGM1) || defined(_CS1)
    TCCR1B=0
    #ifdef _ICNC1
        | (_ICNC1<<ICNC1) 
    #endif
    #ifdef _ICES1
        | (_ICES1<<ICES1)  
    #endif
    #ifdef _WGM1
        | ((WGM1>>2)<<WGM12) 
    #endif
    #ifdef _CS1
        | (_CS1<<CS10)
    #endif
    ;  
#endif
останется проинициировать нужные биты и следом приинклюдить файл настройки периферии...

правда плохо то, что так у меня выйдет сделать только начальную настройку... :(
Вложения
1686022463926.jpg
(29.72 КБ) 306 скачиваний
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Реклама
veso74
Поставщик валерьянки для Кота
Сообщения: 1907
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

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

Сообщение veso74 »

В последних выражениях много тавтологии - не упрощаем пользователю, а усложняем :P.

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

TCCR1B=(_ICNC1<<ICNC1) | (_ICES1<<ICES1) | ((_WGM1>>2)<<WGM12) | (_CS1<<CS10);
...
#ifdef _WGM1
  | ((WGM1>>2)<<WGM12)
#endif
Если бы у меня был выбор редактировать, я бы пропустил код даже для понимания :).
А если придется: следует полная замена/переписывание.
Реклама
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

Сообщение Ivanoff-iv »

нет, этот код пользователь не увидит, для него настройка будет выглядеть так:
Спойлер

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

// 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
но это и печатать больше и ещё кучу команд учить... :roll:

Добавлено after 1 minute 7 seconds:
Да и какой-то уж слишком ардуинообразный код получится... :kill:
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
kote52
Встал на лапы
Сообщения: 120
Зарегистрирован: Пт мар 19, 2021 08:58:45

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

Сообщение kote52 »

Всем привет! Собрал я для своей дачи контроллер для озонирования воды, т.к. в воде много двухвалентного железа, его как то надо окислять, чтобы применять воду для бытовых нужд, озон лучше всего для этого подходит еще попутно очень хорошо обеззараживает воду. Вся система состоит из двух бочек, алгоритм таков: первую бочку скважный насос накачивает воду, после наполнения бочки включается циркуляционный насос и гоняет воду по кругу в первой бочке через эжектор Вентури, тем самым смешивает воду с озоном из озонатора 1 час(по таймеру), далее отстаивание воды 6 часов(по таймеру), далее перелив воды через электромагнитный клапан во вторую расходную бочку, откуда после наполения второй бочки третий насос с гидроаккамулятром подает воду в дом на разбор. Всем этим действием и управляет контроллер на atmega8. Решил прикрутить еще "собаку", ну мало ли завис, сбросит. Но тут же возникает вопрос из за незнания применения "собаки", к примеру зависло во время одного из действия когда считает таймер, "собака" сбросила, т.е. все сначало, весь счет таймера потерялся... как с этим быть, писать в энергонезависимую память раз в секунду/минуту какая часть программы выполнялась, счет таймера, ресурс быстро израсходую? писать все тоже самое отдельную память?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

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

Мой уютный бложик... заходите!
kote52
Встал на лапы
Сообщения: 120
Зарегистрирован: Пт мар 19, 2021 08:58:45

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

Сообщение kote52 »

[uquote="ARV",url="/forum/viewtopic.php?p=4444882#p4444882"]считать таймер в переменных, не очищаемых при сбросе МК[/uquote]
это каких? static?
veso74
Поставщик валерьянки для Кота
Сообщения: 1907
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

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

Сообщение veso74 »

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

uint8_t count __attribute__ ((section (".noinit")));
kote52
Встал на лапы
Сообщения: 120
Зарегистрирован: Пт мар 19, 2021 08:58:45

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

Сообщение kote52 »

[uquote="veso74",url="/forum/viewtopic.php?p=4444941#p4444941"]

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

uint8_t count __attribute__ ((section (".noinit")));
[/uquote]
Спсибо, пойду подтягивать теорию! :beer:
mont-oriol
Мучитель микросхем
Сообщения: 437
Зарегистрирован: Пн май 27, 2019 07:18:28
Откуда: ВВХ-ск

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

Сообщение mont-oriol »

[uquote="kote52",url="/forum/viewtopic.php?p=4444850#p4444850"]к примеру зависло во время одного из действия когда считает таймер, "собака" сбросила, т.е. все сначало, весь счет таймера потерялся... как с этим быть, писать в энергонезависимую память раз в секунду/минуту какая часть программы выполнялась, счет таймера, ресурс быстро израсходую? писать все тоже самое отдельную память?[/uquote]
В самом дешёвом модуле RTC для ардуинки, в чипе DS1307 есть ещё и SRAM с питанием от батареи, 56 байт. Можно туда заливать текущее состояние, дублируя трижды, с учётом того, что МК может зависнуть во время записи. А при старте сравнивать все три сохранённых блока, если два идущих подряд совпали - можно их использовать для восстановления состояния.
Либо просто использовать время из RTC, типа "если сейчас от 01 до 06 часов утра - гонять воду в первом баке".
kote52
Встал на лапы
Сообщения: 120
Зарегистрирован: Пт мар 19, 2021 08:58:45

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

Сообщение kote52 »

[uquote="veso74",url="/forum/viewtopic.php?p=4444941#p4444941"]

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

uint8_t count __attribute__ ((section (".noinit")));
[/uquote]
и
ARV писал(а):считать таймер в переменных, не очищаемых при сбросе МК
Подскажите пожалуйста, скажем после сброса сторожевым таймером, мне скорее всего нужно в регистре управления MCUCSR два бита WDRF(Флаг индикации сброса сторожевым таймером) и PORF(Флаг Сброса включении питания), чтобы понимать МК как он именно сбросился. Потом, поняли что сторожевым таймером, биты сбросить в 0. Далее самое интересно, где это делаетcя int main?
нацарапал приблизительный пример:

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

#include "main.h"
#define F_CPU 8000000UL 

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/wdt.h>

uint8_t state_error __attribute__ ((section (".noinit")));
uint8_t state_status __attribute__ ((section (".noinit")));
uint8_t state_status_2 __attribute__ ((section (".noinit")));

void sensor(void);

int main(void)
{
	if(MCUCSR&(1<<WDRF)){ MCUCSR&=~(1<<WDRF);}
	if(MCUCSR&(1<<PORF)) {MCUCSR&=~(1<<PORF);}

	Port_Init();
	Timer_Init();

	sei();
	
	wdt_enable(WDTO_1S);
while (1) {
	wdt_reset();
	sensor(); //опрос датчиков уровня воды
	if(state_status == 1){
		PORTD |= (1<<RELAY_PUMP);   //вкл насос
	}else{
		PORTD &=~ (1<<RELAY_PUMP);  //выкл насос
	}
    }
}
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

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

Сообщение Martian »

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

int main(void)
{
  if (MCUCSR & (1 << PORF)) // вероятность этого сброса выше всех, пусть идет первым
  {
        MCUCSR&=(unsigned char)(~(1 << PORF));
       // делаем что должно при сбросе  "вкл-выкл питания" 
  }
  else if (MCUCSR & (1 << WDRF))
  {
      MCUCSR&=(unsigned char)(~(1 << WDRF));
      // делаем что должно при сбросе "собакой" 
  }
  else
  {
      // делаем что должно при ином сбросе
  }
    
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

единственная поправка: нет необходимости всякий раз сбрасывать только один бит в MCUSR, достаточно после всех проверок просто записать туда ноль.

разумеется, при установленном PORF надо инициализировать все .noinit переменные, т.к. в ином месте это делать нельзя.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

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

Сообщение Martian »

Я тоже так подумал вначале. Но потом пришел к выводу, что сбрасывая сразу все биты в конце мы увеличим длину кода до их сброса (особенно если большая обработка причины сброса), а значит и вероятность сброса во время выполнения этого участка. И последующее определение причины сброса может оказаться неверным.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

на сколько я помню, минимальное время WDT - около 15 мс, за это время можно столько кода выполнить... другое дело, что лучше проверять причину сброса в секции .init3, т.е. после инициализации внутренних регистров и стека, но до очистки статических переменных... вот тогда время будет минимальным. хотя, имхо, и так страху нет
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

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

Сообщение Martian »

но сброситься может и не от только от внутреннего ватчдога же, может, внешний сбросил

Добавлено after 3 minutes 19 seconds:
[uquote="ARV",url="/forum/viewtopic.php?p=4447610#p4447610"]хотя, имхо, и так страху нет[/uquote] согласен.
Аватара пользователя
wws63
Сверлит текстолит когтями
Сообщения: 1231
Зарегистрирован: Вс май 21, 2006 16:07:59
Откуда: Алтай

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

Сообщение wws63 »

Вопрос знатокам, есть две восьмибитных переменных А и В
Как просто младший полубайт переменной А сохранить (перенести) в младший полубайт переменной В, не изменяя значение старшего полубайта переменной В?
Ответить

Вернуться в «AVR»