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

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

Чт апр 18, 2019 23:08:12

Зачем тупо копипастить куски кода? Зачем Вам мой делитель 64? Почему не 1024, лучше подходящий для задачи? Для шестичасовых интервалов - чем больше делитель, тем реже прерывания, тем лучше для Вас. Откройте даташит на МК, почитайте про таймера, про их регистры. Сделайте осознанный выбор таймера - возможно, 16-битный Timer1 с соответственно подобранным делителем будет дучшим выбором.
Я Вам потому и давал общее описание решения, чтобы понимание сути появилось. А Вы просто пытаетесь куски кода без малейших правок утащить, даже в документацию не заглянув.

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

Пт апр 19, 2019 04:32:49

Для осознанного выбора хорошо иметь понимание. Присматриваюсь, отсюда и куски кода, как обозначение проблемы, а не ее решение. Направление Вы указали, спасибо, но перейти с основательно подзабытых пятнадцатилетней давности "плюсов" на си для мк за несколько часов мне не удалось. Засим, мечтаю о подарке в виде рабочего актуального кода :) .

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

Сб апр 27, 2019 10:04:44

Подскажите в чём косяк может быть? Если кнопка (включаем к питанию) на PC0, то отлично всё выполняется, но если на PC1 и старше хрена лысого ..

Код:
/*
 * GccApplication1.c
 * ATMEGA48
 
#define F_CPU 8000000UL    // 8 MHz
#include <avr/io.h>
#include <util/delay.h>
 
int main(void)
{
   DDRB = 0xFF;   // все выводы порта B сконфигурировать как выходы
   DDRD = 0xFF;   // все выводы порта D сконфигурировать как выходы
   DDRC = 0x00;   // все выводы порта C сконфигурировать как входы
   
   while (1)
   
   if ((PINC &(1<<PC1))==1) // Если нажата кнопка
   {
      while((PINC &(1<<PC1))==1){} // Ждем отпускания кнопки
 
      PORTB =0xFF; PORTD =0xFF; _delay_ms(500); // Включение группы портов B и D
   }
}
 

Компилирую с помощью Atmel Studio 7, и визуализирую на Proteus 8.6/8.8 один фикус.

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

Сб апр 27, 2019 11:07:33

Prod писал(а):if ((PINC &(1<<PC1))==1) // Если нажата кнопка
Неверное условие. PINC & (1<<PC1) никогда не будет равно 1. Либо 0, либо 2

Проверяйте либо:
Код:
if ((PINC & (1<<PC1)) == (1<<PC1))

либо
Код:
if ((PINC & (1<<PC1))

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

Сб апр 27, 2019 11:52:14

WiseLord
Спасибо, а как надёжней исходя из опыта?
Или if ((PINC & 0x2) == 0x2) // Если нажата кнопка на PC1
Последний раз редактировалось Prod Сб апр 27, 2019 12:13:08, всего редактировалось 1 раз.

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

Сб апр 27, 2019 12:01:50

Без разницы

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

Вс апр 28, 2019 15:23:38

Prod, надежно тогда, когда знаешь как работает код.

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

Ср май 01, 2019 00:39:17

WiseLord
Спасибо, а как надёжней исходя из опыта?


Никакой разницы в "надежности" тут нет.

Проверка

Код:
if ((data & MASK) != 0)


применяется для того, чтобы проверить, установлен ли в 1 хотя бы один бит, описываемый маской `MASK`.

Проверка

Код:
if ((data & MASK) == BITS)


применяется для того, чтобы проверить, установлены ли биты, описываемый маской `MASK`, именно в значения, указанные в наборе `BITS`.

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

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

Вт июн 04, 2019 19:19:21

Доброго времени суток
Делаю преобразователь из 12-битнго параллельного интерфейса в аналоговый на Atmega8. Вроде, просто: собираю со входов число, выдаю его как задание скважности ШИМ. Использую 10-битный FastPWM в Таймер/Счетчеке 1. ШИМ работает, задание отрабатывается, число со входов собирается. Только вот Протеус выдает что-то очень странное.
Тестовая схема:
Изображение
Фьюзы:
Изображение
Код:

Собственно, что не так. При задании разных бит на входы порта D проблем нет - ШИМ на выходе выдает сообразную входам скважность. То самое с двумя младшими битами порта B (PB5 и PB4). А вот на изменение старших битов PB6 и PB7, ШИМ реагирует только после того, как я меняю значение на любом другом входе. Т.е. меняю на PB6 0 на 1 - на выходе ничего не изменятся. Потом меняю на PD3 0 на 1 - и тут же ШИМ на выходе становится таким, как и должно быть при выставленных в 1 PB6 и PD3.
Отчего такая муть может происходить? Два часа ковырял сегодня и ничего, идеи кончились.

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

Вт июн 04, 2019 19:46:29

Немножко смущает (data_in_B << 4). Хотя.. обнуляться не должно, ведь 4 - вроде как 16-битная переменная, так что и data_in_B должно привестись к 16бит перед сдвигом.

И, кстати, не пробовали работать отдельно с OCR1AH и OCR1AL. AVR-libc, конечно, позволяет сразу с 16-битным работать, но кто знает, как это протеус воспринимает... В даташите на ATmega8A (17.3 - Accessing 16-bit Registers) про это немножко написано.

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

Вт июн 04, 2019 21:00:05

а зачем 12 бит, если они потом обрезаются до 10 бит?

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

Вт июн 04, 2019 21:29:27

baron_P писал(а):Два часа ковырял сегодня и ничего, идеи кончились.
Варнинги компилятор выдает?

Вот это
Код:
//Преобразуем их в 10-битное число
        data_input = ((data_in_B << 4) | data_in_D) >> 2
Заменить например на это
Код:
data_input = (uint16_t) какая-то тестовая константа;
Поглядеть на реакцию системы. Сделать какие-то выводы.
Кстати в протеусе можно и точки останова использовать и смотреть значения переменных и по шагам шагать.

Естественно следует избегать неявного преобразования типов.
WiseLord писал(а):AVR-libc, конечно, позволяет сразу с 16-битным работать, но кто знает, как это протеус воспринимает...
А протеус исполняет то, что скомпиллено.

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

Вт июн 04, 2019 21:55:08

Starichok51 писал(а):а зачем 12 бит, если они потом обрезаются до 10 бит?

Потому что исходный сигнал 12 бит, но точность, пока, особо не нужна - может сделаю и 12-бит ШИМ потом.

Немножко смущает (data_in_B << 4). Хотя.. обнуляться не должно, ведь 4 - вроде как 16-битная переменная, так что и data_in_B должно привестись к 16бит перед сдвигом.
И, кстати, не пробовали работать отдельно с OCR1AH и OCR1AL. AVR-libc, конечно, позволяет сразу с 16-битным работать, но кто знает, как это протеус воспринимает... В даташите на ATmega8A (17.3 - Accessing 16-bit Registers) про это немножко написано.


Z_h_e писал(а):Варнинги компилятор выдает?
Вот это
Код:
//Преобразуем их в 10-битное число
        data_input = ((data_in_B << 4) | data_in_D) >> 2
Заменить например на это
Код:
data_input = (uint16_t) какая-то тестовая константа;
Поглядеть на реакцию системы. Сделать какие-то выводы.
Кстати в протеусе можно и точки останова использовать и смотреть значения переменных и по шагам шагать.
Естественно следует избегать неявного преобразования типов. А протеус исполняет то, что скомпиллено.


Компилятор молчит. Проблема в том, что, если вместо PINB подставить константу, то все выводится как должно. Более того, и с PINB выводится в ШИМ как должно, но происходит это только если изменить какой-либо еще из битов, кроме PB6 и PB7. Т.е. считается то все правильно, а вот с обновлением значений этой пары битов какая-то странь. Завтра посмотрю по шагам.

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

Вт июн 04, 2019 22:26:42

Я бы всё-таки попробовал, спокойствия ради:
Код:
OCR1AH = (data_input >> 8);
OCR1AL = (data_input & 0xFF);

Но всё-таки, скорее всего, очередной глюк Proteus.

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

Ср июн 05, 2019 08:42:22

Я бы всё-таки попробовал, спокойствия ради:
Код:
OCR1AH = (data_input >> 8);
OCR1AL = (data_input & 0xFF);

Но всё-таки, скорее всего, очередной глюк Proteus.

Ничего не изменилось. Взял процедуру из датащита, но она тоже не помогла:
Код:
void TIM16_WriteOCRA1(unsigned int i)
{
    unsigned char sreg;
    /* Save Global Interrupt Flag*/
    sreg = SREG;
    /* Disable interrupts*/
    cli();
    /* Set OCR1A to i */
    OCR1A= i;
    /* Restore Global Interrupt Flag*/
    SREG = sreg;
}

Как посмотреть в Протеусе состояние переменных не разобрался сходу, но поигрался с константами и выяснил, что входы портов не причем. Описанный глюк проявляется при трех значениях в OCR1A:
0b0100000000 - 256
0b1000000000 - 512
0b1100000000 - 768
Но любые другие значения - без проблем ( 255 и 257, 511 и 513, 767 и 769). Не понимаю, как состояние младших битов может влиять на старшие.

UPD: Спаял на макетке - все работает без проблем. Видимо, это и впрямь баг Протеуса.

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

Ср июн 05, 2019 16:36:24

Немножко смущает (data_in_B << 4). Хотя.. обнуляться не должно, ведь 4 - вроде как 16-битная переменная, так что и data_in_B должно привестись к 16бит перед сдвигом.


Нет, это так не работает. В операторах побитового сдвига тип второго операнда никак не влияет на преобразования первого операнда. Так что не имеет никакого значения, какой тип имеет `4`.

А вот обыкновенные integral promotions тут никто не отменял, то есть `data_in_B` будет неявно преобразовано к типу `int` само по себе.

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

Ср июн 05, 2019 18:36:11

baron_P писал(а):Как посмотреть в Протеусе состояние переменных не разобрался сходу,
Нужно подгружать исполняемый код не hex, а elf. Тогда можно будет видеть переменные в отладке на паузе. И еще желательно кинуть исходники в папку с проектом в протеусе, тогда можно и по шагам шагать будет. Я правда очень давно в протеусе симуляцию не делал, может чего не точно сказал. А так да, модели МК для протеуса не без глюков, что-то там в режиме СТС было не так, например.

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

Чт июн 06, 2019 14:09:41

Нужно подгружать исполняемый код не hex, а elf. Тогда можно будет видеть переменные в отладке на паузе. И еще желательно кинуть исходники в папку с проектом в протеусе, тогда можно и по шагам шагать будет. Я правда очень давно в протеусе симуляцию не делал, может чего не точно сказал. А так да, модели МК для протеуса не без глюков, что-то там в режиме СТС было не так, например.

Спасибо, попробую при случае, пока же необходимость отпала) Вот, что получилось в итоге (входы типа "открытый коллектор", 12-битный ШИМ на выходе):

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

Чт июн 06, 2019 19:40:33

Код:
//Функция получения среднего значения из N_MAX полученных
unsigned int data_conversation(unsigned int data_in, unsigned int data_ref)


Во-первых, среднее у вас вычисляется не из `N_MAX` значений, как написано в комментарии, а из `2^N_MAX` значений.

Во-вторых, вышеприведенная функция возвращает новое среднее только на каждой `2^N_MAX` итерации. На остальных итерациях возвращается последнее вычисленное среднее. Это так и задумано?
Последний раз редактировалось KorbenDallas Чт июн 06, 2019 20:02:46, всего редактировалось 1 раз.

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

Чт июн 06, 2019 19:53:28

baron_P писал(а)://Процедура атомарной записи в 16-битный регистр OCR1A (пример из датащита на Atmega8)

атомарные операции в AVR-GCC делаются не так
Код:
#include <util/atomic.h> /* вот в этом заголовке все нужное */

void WriteToOCRA1(unsigned int i){
   ATOMIC_BLOCK(ATOMIC_RESTORSETATE){
      OCR1A= i;
   }
}
хотя я так и не понял, зачем в этом коде атомарность для доступа к OCR1A...
Ответить