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

Обсуждаем контроллеры компании Atmel.
Ответить
Встал на лапы
Аватара пользователя
Сообщения: 93
Зарегистрирован: Пн окт 31, 2016 06:23:19

Сообщение KorbenDallas »

[uquote="PombI4",url="/forum/viewtopic.php?p=3606162#p3606162"]Простой вопрос - могу ли я сдвинуть регистр (допустим порта вывода) какой то одной командой сдвига?

Или я сначала должен прочесть содержимое регистра, потом произвести модификацию содержимого, а потом записать регистр обратно?

PORTB=PORTB<<1;[/uquote]

Если ваш вопрос о том, можно ли записать это через составное присваивание `PORTB <<= 1`, то ответ - да можно. В собственных заголовочных файлах Arduino IDE синтаксис составного присваивания широко используется. Avr-gcc сам разберется, в какую последовательность машинных команд необходимо странслировать такое присваивание для того, чтобы оно работало правильно.
Реклама
Открыл глаза
Сообщения: 79
Зарегистрирован: Пн дек 19, 2016 10:20:28

Сообщение PombI4 »

Нет, вопрос у меня был про то, можно ли сдвиг регистра порта вывода осуществить одной командой типа LSL. Но, похоже это невозможно.
Реклама
Опытный кот
Аватара пользователя
Сообщения: 844
Зарегистрирован: Пт авг 31, 2018 21:53:52
Откуда: ул. Островидова, общага напротив

Сообщение webtime »

Для дальнейшего сравнения в eeprom записывается значение переменной.

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

// Atmel Studio 6
#define F_CPU 8000000UL // 8MHz
uint16_t foo_prev EEMEM;
while(1){
		int foo_current;
//...
		//запись текущего давления в eeprom
		eeprom_update_word(&foo_prev, foo_current);
		_delay_ms(2000);
	}
	return(0);
}
Как записывать в eeprom значение переменной не при каждом изменении переменной, а каждые 6 часов?
Последний раз редактировалось webtime Чт апр 18, 2019 13:28:45, всего редактировалось 2 раза.
Варкалось. Хливкие шорьки
Пырялись по нове,
И хрюкотали зелюки,
Как мюмзики в мове.

:)))
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Ну так надо и делать это не чаще 6 часов.

Завести, например таймер, в прерывании которого декрементировать некую переменную. При достижении ею нуля - разрешать обновление переменной в eeprom, а при обновлении - снова сбрасывать эту переменную в начальное значение, обеспечивающее 6 часов декремента до 0.
Спойлер

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

static uint16_t update_timer;

ISR ... { // every 1 second
  if (update_timer) {
    update_timer--;
  }
}

uint16_t foo_prev EEMEM;
while(1){
      int foo_current;
//...
      //запись текущего давления в eeprom
      if (!update_timer) {
        eeprom_update_word(&foo_prev, foo_current);
        update_timer = 21600; // 6 hours
        _delay_ms(2000);
      }
   }
   return(0);
}
Последний раз редактировалось WiseLord Чт апр 18, 2019 13:30:46, всего редактировалось 1 раз.
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Опытный кот
Аватара пользователя
Сообщения: 844
Зарегистрирован: Пт авг 31, 2018 21:53:52
Откуда: ул. Островидова, общага напротив

Сообщение webtime »

Поиск находит только timer с выводом в порт, в данном случае это не надо, только отсчет времени и запись значения переменной.
Нуждаюсь в примере кода :) .
Варкалось. Хливкие шорьки
Пырялись по нове,
И хрюкотали зелюки,
Как мюмзики в мове.

:)))
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Пример см. выше. Возможно, понадобится завести "теневую" (shadow) копию переменной foo_prev. То есть, обновлять её всегда, а значение в eeprom - только раз в 6 часов. При старте программы считывать в эту теневую переменную ячейку eeprom и пользоваться именно ею в качестве _prev значения.
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 844
Зарегистрирован: Пт авг 31, 2018 21:53:52
Откуда: ул. Островидова, общага напротив

Сообщение webtime »

Спасибо.
Как завести "теневую" (shadow) копию переменной foo_prev и сделать остальное?
И как задать время 2 минуты, для моделирования в протеусе?
Извините за глупые вопросы.
Варкалось. Хливкие шорьки
Пырялись по нове,
И хрюкотали зелюки,
Как мюмзики в мове.

:)))
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

uint16_t foo_prev_shadow;

И использовать именно её там, где сейчас, возможно, используется foo_prev. То есть это "как бы" переменная в eeprom, но на самом деле - нет. То, что в eeprom, обновляется раз в 6 часов.

Или как-то так:
Спойлер

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

static uint16_t update_timer;

ISR ... { // every 1 second
  if (update_timer) {
    update_timer--;
  }
}

uint16_t foo_prev;
uint16_t foo_prev_ee EEMEM;

void init(void)
{
  foo_prev = foo_prev_ee;
  //.. init timer to interrupt every 1 sec
}

int main {
  init();

  while(1) {
    int foo_current;

    //...

    //запись текущего давления в eeprom
    foo_prev = foo_current;
    if (!update_timer) {
      eeprom_update_word(&foo_prev_ee, foo_prev);
      update_timer = 21600; // 6 hours
    }
  }

  return 0;
}
Последний раз редактировалось WiseLord Чт апр 18, 2019 13:57:30, всего редактировалось 2 раза.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 844
Зарегистрирован: Пт авг 31, 2018 21:53:52
Откуда: ул. Островидова, общага напротив

Сообщение webtime »

Спасибо.

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

ISR ... { // every 1 second
// Error	2	expected '=', ',', ';', 'asm' or '__attribute__' before '...' token
Вместо троеточия должно быть некоторое значение?
1 минута - 21600/360 ?
Последний раз редактировалось webtime Чт апр 18, 2019 14:35:09, всего редактировалось 1 раз.
Варкалось. Хливкие шорьки
Пырялись по нове,
И хрюкотали зелюки,
Как мюмзики в мове.

:)))
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Там должно быть правильное описание прерывания выбранного Вами таймера, настроенного на, например, 1 секунду.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 844
Зарегистрирован: Пт авг 31, 2018 21:53:52
Откуда: ул. Островидова, общага напротив

Сообщение webtime »

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

ISR(TIMER0_OVF_vect) { // every 1 second
	if (update_timer) {
		update_timer--;
	}
}
?
Варкалось. Хливкие шорьки
Пырялись по нове,
И хрюкотали зелюки,
Как мюмзики в мове.

:)))
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Ну да. Настраиваете его на то, чтобы срабатывал раз в секунду (зависит от делителей и частоты МК) и всё будет работать как задумано. Не получается ровно раз в секунду - подойдёт любое другое значение, просто пересчитать 6 часов в нужное значение (для 1 сек интервала 6 часов - это 21600 срабатываний, для другой частоты прерываний будет другое значение)
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 844
Зарегистрирован: Пт авг 31, 2018 21:53:52
Откуда: ул. Островидова, общага напротив

Сообщение webtime »

Не подскажете в коде, как настроить? Atmega8, частота 8MHz, остальные фюзы заводские (HIGH - D9, LOW - E4).

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

#define F_CPU 8000000UL // 
Варкалось. Хливкие шорьки
Пырялись по нове,
И хрюкотали зелюки,
Как мюмзики в мове.

:)))
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Пример с делителем 64:
https://github.com/WiseLord/pcm2705/blo ... .c#L66-L67
Прерывание (срабатывает 8000000 / 64 / 256 = 488 раз в секунду) - чуть ниже
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 844
Зарегистрирован: Пт авг 31, 2018 21:53:52
Откуда: ул. Островидова, общага напротив

Сообщение webtime »

:shock: и как это применить в нашем случае?
Варкалось. Хливкие шорьки
Пырялись по нове,
И хрюкотали зелюки,
Как мюмзики в мове.

:)))
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Я уже ВСЁ выше написал.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 844
Зарегистрирован: Пт авг 31, 2018 21:53:52
Откуда: ул. Островидова, общага напротив

Сообщение webtime »

Спасибо :( .

Добавлено after 1 hour 15 minutes 49 seconds:
Поискал, почитал, понятнее не стало.
Варкалось. Хливкие шорьки
Пырялись по нове,
И хрюкотали зелюки,
Как мюмзики в мове.

:)))
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

:facepalm: вот у тебя была переменная "Х", она быля объявлена в еепром, ты её объяви в ОЗУ, как обычную переменную
а в еепром объяви для хранения значения ещё одну переменную "У".
1) при включении питания (в начале MAIN) делай Х=У; (забираем из еепром значение переменной для дальнейшей с ним работы)
2) при работе программы взаимодействуй с переменной Х (как и раньше)
3) возьми любой периодический процесс или (при отсутствии такогО сделай) подойдет прерывание от любого таймера, посчитай, сколько раз оно вызовется за требуемые 6 часов, вот до стольки и считай, как досчитал - запускай счет сначала и обновляй значение в еепром У=Х...
всё...
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Опытный кот
Аватара пользователя
Сообщения: 844
Зарегистрирован: Пт авг 31, 2018 21:53:52
Откуда: ул. Островидова, общага напротив

Сообщение webtime »

Понятнее не стало не то, как оно должно работать, оно работает в железе именно так, как вы излагаете. Я никогда не писал для мк, поэтому затруднение вызывает именно реализация инициализация таймера в коде.

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

void init(void)
{
	foo_prev = foo_prev_ee;
	//.. init timer to interrupt every 1 sec
	TCCR0 |= (0<<CS02) | (1<<CS01) | (1<<CS00);	/* Prescaler = 64, 125kHz */
	TIMSK |= (1<<TOIE0);							/* Enable timer compare match interrupt */
}
Варкалось. Хливкие шорьки
Пырялись по нове,
И хрюкотали зелюки,
Как мюмзики в мове.

:)))
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

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

скачай алгоритм билдер - из него получается хорошая шпаргалка по периферии АВРок.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Ответить

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