Кто никогда не совершал ошибок, тот никогда не пробовал что-то новое.
Альберт Эйнштейн

Меню навигации для мобильных

Последние сообщения

#1
Цифровая техника / Re: АЦП в AVR
Последний ответ от Slabovik - 16 Июль, 2022, 20:49
1. Это логическое следствие схемотехники на транзисторах (и лампах тоже). И сделано оно так не `зачем', а 'потому что'
2. По причине, что так организовано схемотехнически. А за логическим объяснением смысла - это лучше к производителю.
#2
Цифровая техника / Re: АЦП в AVR
Последний ответ от Shaman - 16 Июль, 2022, 04:38
Всё, ушел в долгое переваривание полученной информации и отпуск во время которого расстояние от меня до макетки буде около 3000 км поэтому проверить в железе пока не вариант.  :)
Резюмирую то что понял.
1. 1 регистр всегда равно 2 независимых ячейки памяти на чтение и запись (если есть где инфа на русском зачем так сделано буду признателен если поделитесь)

2. Непонятно по какой причине запись 1 в ячейку/регистр? (даже не знаю как это назвать) записи приводит к установке 0 в ячейке чтения. Опять же непонятно как и зачем так сделано. Если знаете, расскажите, пожалуйста.

А тем кто так пишет документацию, желаю самим же её и читать до конца дней.  :)
#3
Цифровая техника / Re: АЦП в AVR
Последний ответ от Slabovik - 15 Июль, 2022, 22:42
Просто хотя бы совмести первые восемь слов с картинкой, которую я уже показывал. Даташит - это всё-таки цельный документ, а не просто обрывки фраз...  :-\  Плюсом надо помнить правила логики, что если об инверсии флага нигде не упоминается, следовательно прочитанное состояние "1" означает "Set", а "0" ~ "Clear". Об это говорит любой фрагмент текста, где описывается его работа, и также диаграммы.

зы: можно было уже с полдюжины раз попробовать на макете ( я же знаю, он у тебя есть), чем впустую перепихиваться по поводу "а вот там этого не написано"...
#4
Цифровая техника / Re: АЦП в AVR
Последний ответ от Shaman - 15 Июль, 2022, 20:49
Цитата: Shaman от 14 Июль, 2022, 14:38This bit is set when an ADC conversion completes and the Data Registers are updated. The ADC Conversion Complete Interrupt is executed if the ADIE bit and the I-bit in SREG are set.
ADIF is cleared by hardware when executing the corresponding interrupt Handling Vector. Alter-natively, ADIF is cleared by writing a logical one to the flag. Beware that if doing a Read-Modify-Write on ADCSRA, a pending interrupt can be disabled. This also applies if the SBI and CBI
instructions are used.

Этот бит устанавливается, когда преобразование АЦП завершается и регистры данных обновляются. Прерывание завершения преобразования АЦП выполняется, если установлены бит ADIE и бит I в SREG. ADIF сбрасывается аппаратно при выполнении соответствующего вектора обработки прерывания. В качестве альтернативы ADIF очищается путем записи логической единицы во флаг. Имейте в виду, что при выполнении чтения-модификации-записи на ADCSRA ожидающее прерывание может быть отключено. Это также применяется, если SBI и CBI используются инструкции.

Господи, да где!?  :o З десь сказано, что он очищается записью 1, но где написано, что очищенное состояние это 0
#5
Цифровая техника / Re: АЦП в AVR
Последний ответ от Slabovik - 15 Июль, 2022, 18:58
Цитата: Shaman от 15 Июль, 2022, 17:27выдержки из мануала. Я пока не нашел.
Как это не нашёл, если мне же эту фразу и цитировал?  :o Описание флага ADIF...  :-\
Цитата: Shaman от 15 Июль, 2022, 17:27А сигнал RD/WR чисто хардверный или может управляться тем кто пишет программу?
Это сигнал арбитража шины, и он хардверный (и не единственный). Но косвенно программист на него влияет, например, когда пишет ReadPort или ReadRAM (команды чисто условные). Формируется же непосредственно шинным контроллером, который у ATmega спрятан где-то внутри, как и сама шина. Вообще, хорошо бы поизучать построение вычислительных систем, начиная с i8080 или с той же Моторолы (правда, у нас она мало распространена, зато i8080 как грязи), там шинный контроллер - устройство частично внешнее (частично всё-таки в чипе CPU, который и задаёт правила его работы), но зато сама шина полностью открыта для фантазий конструктора. Другое дело, что по скорости та же Mega кроет его как... но это другой вопрос.

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

Тут, как говорится, твой ход - реализовать изменения в тестовой программе и посмотреть, как оно отзовётся. Ну не расчехлять же мне свой макетатор...  ::)

зы: Кстати, вот здесь интересная ситуация разбирается. Может пригодится...

#6
Цифровая техника / Re: АЦП в AVR
Последний ответ от Shaman - 15 Июль, 2022, 17:27
Ёкарный бабай  :)  Благодарю за потраченное на ответ время.
Помимо понимания он породил ещё больше вопросов. Попробую разложить комментарии и новые вопросы по степени важности относительно изначального поста.

1.
Цитата: Slabovik от 14 Июль, 2022, 18:21В даташите чётко написано, что сброшенное состояние "0", но для получения "0" при чтении записать надо "1".

Если не сложно киньте, пожалуйста, выдержки из мануала. Я пока не нашел.

2.
Цитата: Slabovik от 14 Июль, 2022, 18:21Вот это: if (ADCSRA & (1<<4))

Я тоже склоняюсь к тому, что компилятор gcc может это неверно интерпретировать в примере сработало скорее всего потому, что использовалась среда разработки для атмеги.

3.
Цитата: Slabovik от 14 Июль, 2022, 18:21ADTS не вижу, где задан...
Пример писался для Атмеги8, в ней нет регистра ADCSRB а соответственно и бита ADTS. А также 5 бит в регистре ADCSRА называется ADFR вместо ADATE и просто включает режим FreeRunning. Комментарий остался от кода для 328-й, забыл исправить  :)

4.
Цитата: Slabovik от 14 Июль, 2022, 18:21И всегда (подчеркну: ВСЕГДА) это разные наборы.
Ок, очень ценная информация. А сигнал RD/WR чисто хардверный или может управляться тем кто пишет программу? Если нет, то тогда интересно зачем сделана такая реализация?

5.
Цитата: Slabovik от 14 Июль, 2022, 18:21PortB используется для контрольки?
В основной программе для отладки, потом удалю, а в примере из видео для вывода индикации.

6.
Цитата: Slabovik от 14 Июль, 2022, 18:21Для некоторого ускорения работы программы,
Да, благодарю, я потом так и делаю просто в СИ я новичок и так мне проще запустить незнакомый код и отследить где он не работает и уж потом упрощать.

Я знаю что контроллер не понимает. Просто так короче писать чем: "С помощью какого набора логических элементов и связей между ними происходит определение как, когда и в какой регистр записывать?"  :)
#7
Цифровая техника / Re: АЦП в AVR
Последний ответ от Slabovik - 14 Июль, 2022, 18:21
А контроллер не понимает, контроллер - это суть набор логических элементов. И вот этот набо логических элементов работает так, что хардверный сигнал "RD/WR" выбирает, к какому набору элементов идёт обращение. И всегда (подчеркну: ВСЕГДА) это разные наборы. Их схемотехнически можно организовать так, что вход регистра, который для чтения, будет подключён к выходу регистра, который на запись, и тогда результат чтения будет идентичен записанному результату, это удобно в ряде случаев (например: память), но в общем случае это не так и по одному и тому же адресу, определяемому хардверными линиями адреса, чтение и запись производится в/из разных наборов логических ячеек, а арбитражем для этого как раз служит сигнал "RD/WR".
Следовательно вот это утверждение
ЦитатаЕсли написано что для сброса состояния нужно записать 1 значит в регистре это бит выставится в 1. А значит сброшенное состояние 1
не является верным. В даташите чётко написано, что сброшенное состояние "0", но для получения "0" при чтении записать надо "1". Это не только у Mega такой прикол, это и у Tiny аналогично, и на форумах тоже часть народ недопонимает это место. Но ещё раз скажу: лучше проверить, поскольку у меня, не часто практикующего последнее время, в голове набор приёмов для кучки разных процессоров и ядер, поэтому где-то могу и ошибиться. Но документация - наше всё, я её и толкую. Ладно, поехали дальше.

Настоятельно рекомендую вписывать в условия более явные признаки.
Вот это: if (ADCSRA & (1<<4)) хорошо бы писать хотя бы так: if ((ADCSRA & (1<<ADIF))>0) потому что компилятор бывает игнорирует такие неявно заданные условия, либо интерпретирует их не так, как видит человек (уже ведь были примеры из практики).

Далее, сразу, как только вошли в это условие (бит=1), надо сделать две вещи. Порядок не особо принципиален, т.к. это произойдёт быстро.
Первое: сбросить бит: ADCSRA=ADCSRA |(1<<ADIF)
Второе: прочитать один раз регистры ADC в двубайтную переменную, с которой дальше и работать.
Если такого чтения не сделать, программа каждый раз, когда у ней будет появляться ADC, будет читать эти регистры, а по прошествии некоторого времени они могут стать неактуальными (часики-то тикают, несмотря на то, что 13 тактов при 125 кГц - это довольно много, но это и не много, когда начинают выполняться какие-либо действия).

Да, в конфигурации обозначен запуск от триггера. А что служит триггером? ADTS не вижу, где задан... По-идее для FreeRunning надо его в 0 поставить (там три бита). Считаем, что FreeRunning стоит.

PortB используется для контрольки?

Для некоторого ускорения работы программы, IF'ы, которые проверяют прочитанные данные с ADC (пусть это будет переменная ADCresult), лучше вложить друг в друга. Будучи записанными просто последовательно, они каждый раз выполняются все. Будучи вложенными, внутренние будут выполняться только при совпадении условий. Например
if (ADCresult <= LowLevel) { Signal = Warning_LOW; }
  else { if (ADCresult >= NormLevel) { Signal = Warning_OK;}
            else { Signal = Warning_NearLOW;}
        }

Ну и здесь, записать в PortB состояние Signal (да, меня практика научила меньше порты дёргать)
Думаю, мелочи, которые я не конкретизировал, вполне понятны и реализация их не составит большого труда. :)

И, да... Надо помнить, что резистор - это очень-очень шумный элемент. Поэтому после резистора надо бы сигнал пофильтровать. Между средним выводом и ногой входа АЦП воткнуть, скажем, 10 кОм, а между входом АЦП и землёй какой-нибудь конденсатор на микрофарад (с SMD керамикой нынче нет проблем, их как грязи). И ещё... Дроссель в питании секции АЦП на этапе макета - элемент вовсе не обязательный. без него всё будет работать не хуже. На этапе реализации можно уже и поставить.
#8
Цифровая техника / Re: АЦП в AVR
Последний ответ от Shaman - 14 Июль, 2022, 17:05
А вот тут я перестаю что-то понимать. Для меня это одно и тоже. Если написано что для сброса состояния нужно записать 1 значит в регистре это бит выставится в 1. А значит сброшенное состояние 1. И вот этот автор говорит то же самое.

Цитата: Slabovik от 14 Июль, 2022, 15:13зы: подозреваю, что есть некоторое заблуждение относительно того, что в реальности из регистра вовсе не обязано читаться то, что туда было записано. Ибо регистр записи и регистр чтения - это разные устройства.

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

А проверить в живую пока не получается, код не работает в протеусе. Даже напрямую скопированный из видео выше.

Видео длинное, поэтому вот код
#define F_CPU 1000000UL
#include <avr/io.h>
int main(void)
{
    DDRB |= (1<<2) | (1<<1) | (1<<0);
    PORTB &= ~((1<<2) | (1<<1) | (1<<0));
    DDRC &= ~(1<<1);

    //Настраиваем АЦП
    ADCSRA |= (1<<ADEN);        //разрешаем работу АЦП,
    ADCSRA |= (1<<ADFR);       //разрешаем работу АЦП с тригера
    ADCSRA &= ~(1<<ADPS2);       
    ADCSRA |= (1<<ADPS1) | (1<<ADPS0); //частота дискретизации 125 кГц
    ADMUX |= (1<<REFS1) | (1<<REFS0); //используем внутреннее опорное напряжение
    ADMUX |= (1<<ADLAR);              //правостороннее выравнивание
    ADMUX &= ~((1<<MUX3) | (1<<MUX2) | (1<<MUX1)); //выставляем в качестве входа АЦП порт PC0
    ADMUX |= (1<<MUX0);
    ADCSRA |= (1<<ADSC);       //запускаем АЦП

    while (1)
    {
         if (ADCSRA & (1<<4))
             {
                if (ADC >= 600)     //в место 600 нужно подставить необходимое заначение для опорного напряжения 1,1 V
                {
                        PORTB |= (1<<0);
                        PORTB &= ~(1<<1);
                        PORTB &= ~(1<<2);
                }
                if (ADC >= 560 && ADC < 600)     //в место 600 нужно подставить необходимое заначение для опорного напряжения 1,1 V
                {
                        PORTB &= ~(1<<0);
                        PORTB |= (1<<1);
                        PORTB &= ~(1<<2);
                }
                if (ADC < 560)     //в место 600 нужно подставить необходимое заначение для опорного напряжения 1,1 V
                {
                        PORTB &= ~(1<<0);
                        PORTB &= ~(1<<1);
                        PORTB |= (1<<2);
                }
                
                ADCSRA |= (1<<4);
                
             }
    }
}
[свернуть]

У меня он почему-то работает как выключатель, т.е. если резистор стоит в минимуме то горит красный, стоит только повернуть сразу зелёный. И для кода из видео я естественно нарисовал схему с Атмега8 и компилил под неё. В живую собрать пока не могу, нет в наличии дросселя на 10uH, а купить не позволяет время.
#9
Цифровая техника / Re: АЦП в AVR
Последний ответ от Slabovik - 14 Июль, 2022, 15:13
Погоди-погоди.... Ты только что утверждал, что в даташите написано, что
Цитата: Slabovik от 14 Июль, 2022, 10:03сброшенное состояние ADIF это 1
а из даташита цитируешь, что "для сброса ADIF запишите в него "1". Разве это одно и то же? Это совершенно разные вещи. Первое - это состояние. Второе - действие для изменения состояния.

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

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

зы: подозреваю, что есть некоторое заблуждение относительно того, что в реальности из регистра вовсе не обязано читаться то, что туда было записано. Ибо регистр записи и регистр чтения - это разные устройства.
#10
Цифровая техника / Re: АЦП в AVR
Последний ответ от Shaman - 14 Июль, 2022, 14:38
This bit is set when an ADC conversion completes and the Data Registers are updated. The ADC Conversion Complete Interrupt is executed if the ADIE bit and the I-bit in SREG are set.
ADIF is cleared by hardware when executing the corresponding interrupt Handling Vector. Alter-natively, ADIF is cleared by writing a logical one to the flag. Beware that if doing a Read-Modify-Write on ADCSRA, a pending interrupt can be disabled. This also applies if the SBI and CBI
instructions are used.

Этот бит устанавливается, когда преобразование АЦП завершается и регистры данных обновляются. Прерывание завершения преобразования АЦП выполняется, если установлены бит ADIE и бит I в SREG. ADIF сбрасывается аппаратно при выполнении соответствующего вектора обработки прерывания. В качестве альтернативы ADIF очищается путем записи логической единицы во флаг. Имейте в виду, что при выполнении чтения-модификации-записи на ADCSRA ожидающее прерывание может быть отключено. Это также применяется, если SBI и CBI используются инструкции.