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

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

Сообщение WiseLord »

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

Сообщение webtime »

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

:)))
Реклама
Родился
Сообщения: 2
Зарегистрирован: Сб апр 27, 2019 10:02:19

Сообщение Prod »

Подскажите в чём косяк может быть? Если кнопка (включаем к питанию) на 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 один фикус.
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

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

Проверяйте либо:

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

if ((PINC & (1<<PC1)) == (1<<PC1))
либо

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

if ((PINC & (1<<PC1))
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Родился
Сообщения: 2
Зарегистрирован: Сб апр 27, 2019 10:02:19

Сообщение Prod »

WiseLord
Спасибо, а как надёжней исходя из опыта?
Или if ((PINC & 0x2) == 0x2) // Если нажата кнопка на PC1
Последний раз редактировалось Prod Сб апр 27, 2019 12:13:08, всего редактировалось 1 раз.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Без разницы
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 819
Зарегистрирован: Вт окт 23, 2012 13:17:25
Откуда: Прокопьевск

Сообщение Oxford »

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

Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 93
Зарегистрирован: Пн окт 31, 2016 06:23:19

Сообщение KorbenDallas »

[uquote="Prod",url="/forum/viewtopic.php?p=3624013#p3624013"]WiseLord
Спасибо, а как надёжней исходя из опыта?[/uquote]

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

Проверка

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

if ((data & MASK) != 0)
применяется для того, чтобы проверить, установлен ли в 1 хотя бы один бит, описываемый маской `MASK`.

Проверка

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

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

Понятно, что когда речь идет о проверке одного-единственного бита, разница между этими вариантами стирается полностью. Используйте тот, который вам больше нравится.
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

Сообщение baron_P »

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

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

/*
МК ATMEGA8
Частота МК = 8 МГц
Fuse High Byte

Fuse Low Byte

*/

//Подключенные файлы
#include <avr/io.h>         // Стандартные функции ввода/вывода для МК
#include <avr/interrupt.h>  // Стандартные функции работы с прерываниями

//Подстановки



//Прототипы функций
//Процедура инициализации входов/выходов
void init_IO(void);
//Процедура инициализации ТС1
void init_TC1(void);


//Глобальные переменные


/********** Главная фунция **********/
void main(void)
{

    //Инициализация входов/выходов
    init_IO();
    //Процедура инициализации ТС1
    init_TC1();
    
    //Инициализация локальных переменных
    //Значение числа с 12-битного входа
    unsigned int data_input = 0;
    //Значения с соотв. входов
    unsigned char data_in_D, data_in_B = 0;
    
    //Разрешение прерываний
    sei();
    
    //Рабочий цикл
    while(1)
    {
        //Читаем значения со входов
        //Порт D без изменений
        data_in_D = PIND;
        //Порт B с очисткой неиспользуемых младших битов
        data_in_B = PINB & ((1 << PB7) | (1 << PB6) | (1 << PB5) | (1 << PB4));

        //Преобразуем их в 10-битное число
        data_input = ((data_in_B << 4) | data_in_D) >> 2;

        //Выдаем заданную скважность ШИМ
        OCR1A = data_input;
    };

}



/********** Функции **********/
//Процедура инициализации входов/выходов
void init_IO(void)
{
    //12-битный вход, собранный из входов портов D и B
    //Младшие биты входа 7-0 (порт D)
    DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4) | (1 << PD3) | (1 << PD2) | (1 << PD1) | (1 << PD0));
    //Старшие биты входа 11-8 (порт B)
    DDRB &= ~((1 << PB7) | (1 << PB6) | (1 << PB5) | (1 << PB4));
    //Подтягиваем входы к единице
    PORTD |= (1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4) | (1 << PD3) | (1 << PD2) | (1 << PD1) | (1 << PD0);
    PORTB |= (1 << PB7) | (1 << PB6) | (1 << PB5) | (1 << PB4);

    //Тестовый выход
    DDRB |= (1 << PB0);
}


//Процедура инициализации ТС1 (формирование выходного аналогового напряжения)
void init_TC1(void)
{
    //Вывод PB1 (OC1A) - выход ШИМ
    DDRB |= (1 << PB1);
    //Сброс в ноль выхода OC1A при совпадении, режим 10-bit FastPWM
    TCCR1A |= (1 << COM1A1) | (1 << WGM11) | (1 << WGM10);
    //Предделитель 1
    TCCR1B |=  (1 << WGM12) | (1 << CS10);
    //Начальное значение скважности ШИМ
    OCR1A = 0;
    //Вкл. прерывания по переполнению ТС
    TIMSK |= (1 << TOIE1);
}


/********** Векторы прерываний **********/
//Вектор прерывания по переполнению ТС1
ISR(TIMER1_OVF_vect)
{
    PORTB ^= (1 << PB0);
}
Собственно, что не так. При задании разных бит на входы порта D проблем нет - ШИМ на выходе выдает сообразную входам скважность. То самое с двумя младшими битами порта B (PB5 и PB4). А вот на изменение старших битов PB6 и PB7, ШИМ реагирует только после того, как я меняю значение на любом другом входе. Т.е. меняю на PB6 0 на 1 - на выходе ничего не изменятся. Потом меняю на PD3 0 на 1 - и тут же ШИМ на выходе становится таким, как и должно быть при выставленных в 1 PB6 и PD3.
Отчего такая муть может происходить? Два часа ковырял сегодня и ничего, идеи кончились.
We do what we must because we can (c) GLaDOS
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

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

И, кстати, не пробовали работать отдельно с OCR1AH и OCR1AL. AVR-libc, конечно, позволяет сразу с 16-битным работать, но кто знает, как это протеус воспринимает... В даташите на ATmega8A (17.3 - Accessing 16-bit Registers) про это немножко написано.
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 19055
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

а зачем 12 бит, если они потом обрезаются до 10 бит?
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

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

Вот это

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

//Преобразуем их в 10-битное число
        data_input = ((data_in_B << 4) | data_in_D) >> 2
Заменить например на это

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

data_input = (uint16_t) какая-то тестовая константа;
Поглядеть на реакцию системы. Сделать какие-то выводы.
Кстати в протеусе можно и точки останова использовать и смотреть значения переменных и по шагам шагать.

Естественно следует избегать неявного преобразования типов.
WiseLord писал(а):AVR-libc, конечно, позволяет сразу с 16-битным работать, но кто знает, как это протеус воспринимает...
А протеус исполняет то, что скомпиллено.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

Сообщение baron_P »

Starichok51 писал(а):а зачем 12 бит, если они потом обрезаются до 10 бит?
Потому что исходный сигнал 12 бит, но точность, пока, особо не нужна - может сделаю и 12-бит ШИМ потом.

[uquote="WiseLord",url="/forum/viewtopic.php?p=3645324#p3645324"]Немножко смущает (data_in_B << 4). Хотя.. обнуляться не должно, ведь 4 - вроде как 16-битная переменная, так что и data_in_B должно привестись к 16бит перед сдвигом.
И, кстати, не пробовали работать отдельно с OCR1AH и OCR1AL. AVR-libc, конечно, позволяет сразу с 16-битным работать, но кто знает, как это протеус воспринимает... В даташите на ATmega8A (17.3 - Accessing 16-bit Registers) про это немножко написано.[/uquote]
Z_h_e писал(а):Варнинги компилятор выдает?
Вот это

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

//Преобразуем их в 10-битное число
        data_input = ((data_in_B << 4) | data_in_D) >> 2
Заменить например на это

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

data_input = (uint16_t) какая-то тестовая константа;
Поглядеть на реакцию системы. Сделать какие-то выводы.
Кстати в протеусе можно и точки останова использовать и смотреть значения переменных и по шагам шагать.
Естественно следует избегать неявного преобразования типов. А протеус исполняет то, что скомпиллено.
Компилятор молчит. Проблема в том, что, если вместо PINB подставить константу, то все выводится как должно. Более того, и с PINB выводится в ШИМ как должно, но происходит это только если изменить какой-либо еще из битов, кроме PB6 и PB7. Т.е. считается то все правильно, а вот с обновлением значений этой пары битов какая-то странь. Завтра посмотрю по шагам.
We do what we must because we can (c) GLaDOS
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Я бы всё-таки попробовал, спокойствия ради:

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

OCR1AH = (data_input >> 8);
OCR1AL = (data_input & 0xFF);
Но всё-таки, скорее всего, очередной глюк Proteus.
Контактная информация:
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

Сообщение baron_P »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3645413#p3645413"]Я бы всё-таки попробовал, спокойствия ради:

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

OCR1AH = (data_input >> 8);
OCR1AL = (data_input & 0xFF);
Но всё-таки, скорее всего, очередной глюк Proteus.[/uquote]
Ничего не изменилось. Взял процедуру из датащита, но она тоже не помогла:

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

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: Спаял на макетке - все работает без проблем. Видимо, это и впрямь баг Протеуса.
We do what we must because we can (c) GLaDOS
Встал на лапы
Аватара пользователя
Сообщения: 93
Зарегистрирован: Пн окт 31, 2016 06:23:19

Сообщение KorbenDallas »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3645324#p3645324"]Немножко смущает (data_in_B << 4). Хотя.. обнуляться не должно, ведь 4 - вроде как 16-битная переменная, так что и data_in_B должно привестись к 16бит перед сдвигом.[/uquote]

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

А вот обыкновенные integral promotions тут никто не отменял, то есть `data_in_B` будет неявно преобразовано к типу `int` само по себе.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

baron_P писал(а):Как посмотреть в Протеусе состояние переменных не разобрался сходу,
Нужно подгружать исполняемый код не hex, а elf. Тогда можно будет видеть переменные в отладке на паузе. И еще желательно кинуть исходники в папку с проектом в протеусе, тогда можно и по шагам шагать будет. Я правда очень давно в протеусе симуляцию не делал, может чего не точно сказал. А так да, модели МК для протеуса не без глюков, что-то там в режиме СТС было не так, например.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

Сообщение baron_P »

[uquote="Z_h_e",url="/forum/viewtopic.php?p=3645877#p3645877"]Нужно подгружать исполняемый код не hex, а elf. Тогда можно будет видеть переменные в отладке на паузе. И еще желательно кинуть исходники в папку с проектом в протеусе, тогда можно и по шагам шагать будет. Я правда очень давно в протеусе симуляцию не делал, может чего не точно сказал. А так да, модели МК для протеуса не без глюков, что-то там в режиме СТС было не так, например.[/uquote]
Спасибо, попробую при случае, пока же необходимость отпала) Вот, что получилось в итоге (входы типа "открытый коллектор", 12-битный ШИМ на выходе):
Спойлер

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

/*
МК ATMEGA8
Частота МК = 8 МГц
Fuse High Byte
BODLEVEL = 0 - нижний порог напряжения питания 4 В
BODEN    = 0 - слежение за напряжением питания вкл.
SUT1     = 0 \ время включения 6СК + 64 ms
SUT0     = 0 /
CKSEL3   = 0 \
CKSEL2   = 1 - встроенный источник тактовых импульсов
CKSEL1   = 0 - с частотой 8 МГц
CKSEL0   = 0 /
Fuse Low Byte
RSTDISBL = 1 - переназначение вывода ~RESET выкл.
WDTON    = 1 - постоянная работа сторожевого таймера выкл.
SPIEN    = 0 - внутрисхемное программирование вкл.
CKOPT    = 1 - опции работы с внешним кварцевым резонатором выкл.
EESAVE   = 1 - защита EEPROM от стирания выкл.
BOOTSZ1  = 0 \ размер загрузочного сектора
BOOTSZ0  = 0 / 1024 слова, начальный адрес $0C00
BOOTRST  = 1 - перенос стартового сектора в область загрузчика выкл.
*/

//Подключенные файлы
#include <avr/io.h>         // Стандартные функции ввода/вывода для МК
#include <avr/interrupt.h>  // Стандартные функции работы с прерываниями
#include <avr/wdt.h>        // Стандартные функции работы cо сторожевым таймером

//Подстановки
#define PWM_MAX 4095    // Максимальное значение скважности для 12-битиного ШИМ (PWM_MAX = 2^12 - 1)
#define N_MAX 3         // Максимальное количесво значений для получения средне арифметичесого (2^N_MAX = 8)
#define U_INT_MAX 65535 // Максимальное значение типа unsigned int


//Прототипы функций
//Процедура инициализации входов/выходов
void init_IO(void);
//Процедура инициализации ТС1
void init_TC1(void);
//Процедура записи в 16-битный регистр OCR1A
void WriteToOCRA1(unsigned int);
//Функция получения среднего значения из N_MAX полученных
unsigned int data_conversation(unsigned int, unsigned int);


/********** Главная фунция **********/
void main(void)
{

    //Инициализация входов/выходов
    init_IO();
    //Инициализация ТС1
    init_TC1();
    
    //Инициализация локальных переменных
    //Значения с входов соотв. портов
    unsigned char data_in_D = 0, data_in_B = 0;
    //Значение числа с 12-битного входа
    unsigned int data_input = 0;
    //Вычисленное средне арифметическое из N_MAX полученных значений
    unsigned int data_reference = 0;
    
    //Разрешение прерываний
    sei();

    //Включение сторожевого таймера с периодом 1с
    wdt_enable(WDTO_1S);
    
    //Рабочий цикл
    while(1)
    {
        //Чтение значений со входов
        //Порт D без изменений
        data_in_D = PIND;
        //Порт B с очисткой неиспользуемых младших битов
        data_in_B = PINB & ((1 << PB7) | (1 << PB6) | (1 << PB5) | (1 << PB4));

        //Преобразование полученных значений в 12-битное число (0b00 4бита PortB 8 битов PortD)
        data_input = (data_in_B << 4) | data_in_D;

        //Получение среднего арифметического из N_MAX значений
        data_reference = data_conversation(data_input, data_reference);

        //Выдача заданния скважности ШИМ в регистр сравнения
        WriteToOCRA1(data_reference);

        //Сброс сторожевого таймера
        wdt_reset();
    };

}



/********** Функции **********/
//Процедура инициализации входов/выходов
void init_IO(void)
{
    //12-битный вход, собранный из входов портов D и B
    //Младшие биты входа 7-0 (порт D)
    DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4) | (1 << PD3) | (1 << PD2) | (1 << PD1) | (1 << PD0));
    //Старшие биты входа 11-8 (порт B)
    DDRB &= ~((1 << PB7) | (1 << PB6) | (1 << PB5) | (1 << PB4));
    //Подтяжка входов к единице
    PORTD |= (1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4) | (1 << PD3) | (1 << PD2) | (1 << PD1) | (1 << PD0);
    PORTB |= (1 << PB7) | (1 << PB6) | (1 << PB5) | (1 << PB4);

    //Неиспользуемые выводы назначаются входами
    DDRB &= ~((1 << PB3) | (1 << PB2) | (1 << PB0));
    DDRC &= ~((1 << PC5) | (1 << PC4) | (1 << PC3) | (1 << PC2) | (1 << PC1) | (1 << PC0));
    //Подтяжка неиспользуемых входов к единице
    PORTB |= (1 << PB3) | (1 << PB2) | (1 << PB0);
    PORTC |= (1 << PC5) | (1 << PC4) | (1 << PC3) | (1 << PC2) | (1 << PC1) | (1 << PC0);
}


//Процедура инициализации ТС1 (формирование выходного аналогового напряжения)
void init_TC1(void)
{
    //Вывод PB1 (OC1A) - выход ШИМ
    DDRB |= (1 << PB1);
    //Сброс в ноль выхода OC1A при совпадении, режим FastPWM (ICR1)
    TCCR1A |= (1 << COM1A1) | (1 << WGM11);
    //Предделитель 1
    TCCR1B |=  (1 << WGM13) | (1 << WGM12) | (1 << CS10);
    //Маскимальное значение скважности
    ICR1 = PWM_MAX;
    //Начальное (нулевое) значение скважности ШИМ
    WriteToOCRA1(0);
}


//Процедура атомарной записи в 16-битный регистр OCR1A (пример из датащита на Atmega8)
void WriteToOCRA1(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;
}


//Функция получения среднего значения из N_MAX полученных
unsigned int data_conversation(unsigned int data_in, unsigned int data_ref)
{
    //Суммарное значение N_MAX полученных
    static unsigned int data_sum;
    //Счетчик количества просуммированых значений
    static unsigned char data_n;
    
    //Если количество просуммированных значений меньше заданного
    if (data_n < (1 << N_MAX))
    {
        //Добавляем полученное значение к сумме предыдущих (предельное значени data_in = PWM_MAX*2^N_MAX = 32670)
        data_sum += data_in;
        //Инкрементируем счетчик полученных значений
        data_n++;
    }
    else
    {
        //Иначе, обновляем предыдущее средне-арифметическое значение
        data_ref = (data_sum >> N_MAX);

        //Обнуляем сумму полученных значений
        data_sum = 0;
        //Обнуляем счетчик полученных значений
        data_n = 0;
    }

    //Возвращаем среднее значение
    return data_ref;
}
We do what we must because we can (c) GLaDOS
Встал на лапы
Аватара пользователя
Сообщения: 93
Зарегистрирован: Пн окт 31, 2016 06:23:19

Сообщение KorbenDallas »

[uquote="baron_P",url="/forum/viewtopic.php?p=3646369#p3646369"]

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

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

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

Во-вторых, вышеприведенная функция возвращает новое среднее только на каждой `2^N_MAX` итерации. На остальных итерациях возвращается последнее вычисленное среднее. Это так и задумано?
Последний раз редактировалось KorbenDallas Чт июн 06, 2019 20:02:46, всего редактировалось 1 раз.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

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

#include <util/atomic.h> /* вот в этом заголовке все нужное */

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

Мой уютный бложик... заходите!
Контактная информация:
Ответить

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