admin

Видеокурс По Avr-Микроконтроллерам Для Начинающих

2 325 сообщений в этой теме

COKPOWEHEU    261

Видеоуроки, разумеется, не смотрел, но могу предположить что ADC - регистровая пара ADCH:ADCL, кои описаны в даташите на контроллер.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Гость Дмитрий   
Гость Дмитрий

Здравствуйте, после просмотра 4 и 5 урока решил сделать свою схему на мк. Программа такова что должна переключать ножки порта при нажатии на одну кнопку в одну сторону, при нажатии на другую в другую. Почему то не работает в другую сторону. нажимаю вторую кнопку и он возвращает во второй разряд а не в предыдущий.

Вот:

#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>

    

void set(){
    DDRB = 0xFF;
    DDRD = 0xFF;
    PORTD = 0x00;
    DDRC = 0x00;
    PORTC = 0x00;
    PORTB = 0b00000001;
}
int main(void)
{
    set();
    int t=0,i=0;
    int e=0b00000001;
   do
    {
        if (PINC&(1<<PC0))
        {
            i=i+1;    
            PORTB=(e << i);
            _delay_ms(100);
        }
        else {
        if (PINC&(1<<PC1))
        {
            e=(e << i);
            i=i-1;
            PORTB=(e >> i);
            _delay_ms(100);
        }
        }
    }
         while(1);
    }
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
COKPOWEHEU    261

Допустим, сразу при включении нажата кнопка PC1. Первая же итерация:

e =(e<<i) = (1<<0) = 1
i = i-1 = 0-1 = -1;
PORTB = (e>>i) = (1>>-1) - что тут произойдет зависит от компилятора. Скорее всего, PORTB = 0;

Как вы вообще такое изобрели? Может проще было завести массив с возможными значениями и перебирать индексы?

const uint8_t values[8] = {(1<<0), (1<<1), (1<<2), (1<<3), (1<<4), (1<<5), (1<<6), (1<<7)};
uint8_t counter=0;
#define BTN_INC C,0,0
#define BTN_DEC C,1,0

while(1){
  if( PIN_ON( BTN_INC ) ){
    counter++;
  }else if( PIN_ON( BTN_DEC ) ){
    counter--;
  }
  if(counter >= 8)counter = 0; //поскольку тип беззнаковый, проверять на отрицательность не надо
  PORTB = values[counter];
  _delay_ms(100);
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
UTSource

Найдите миллионы труднодоступных

электронных компонентов

ARV    463

Всё-таки я всё больше и больше убеждаюсь, что учить надо не операторам Си и регистрам микроконтроллера, а умению разбивать задачу на подзадачи и формальному описанию алгоритма. Без этого никуда. Вот я бы "бегущий огонь по кнопке" делал бы совсем иначе.

1. Сделал бы функцию rotete_left(uint8_t *state); которая двигает огонек на порту влево
2. Сделал бы функцию rotate_right(uint8_t *state); которая двигает огонек на порту вправо
3. Определил бы переменную состояния огонька, адрес которой затем передавал бы в вышеописанные функции
4. Сделал бы функцию get_button(void); которая возвращала бы номер нажатой кнопки
И в итоге получилось бы такое:

uint8_t state = 1;

while(1){
  switch(get_button()){
    case 0 : // не нажато
      	break;
    case 1: // влево
      	rotete_left(&state);
      	break;
    case 2: // вправо
      	rotete_right(&state);
      	break;
  }
}

Гораздо понятнее, чем сразу "сырой" код писать, не так ли? Я умышленно не раскрыл функции, т.к. это уже второстепенное дело. Да и макросами можно заменить их при желании...

Изменено пользователем ARV

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Гость Дмитрий   
Гость Дмитрий

Здравствуйте, вчера сидел до вечера и сегодня утром посидел и понял!

Вот как я сделал: 

#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>

    

void set(){
    DDRB = 0xFF;
    DDRD = 0xFF;
    PORTD = 0x00;
    DDRC = 0x00;
    PORTC = 0x00;
    PORTB = 0b00000001;
}
int main(void)
{
    set();
    int t=0,i=0,g=0;
    int e=PORTB;
   do
    {
        if (PINC&(1<<PC0))
        {
            if (PORTB>=0b00010000)
            {
            PORTB=0b00010000;
            }
                    i=1;
                    PORTB=(PORTB << i);
                    _delay_ms(100);
        }
        if (PINC&(1<<PC1))
        {    
            g=1;
            PORTB=(PORTB >> g);
            _delay_ms(100);    
    
        }
    }
         while(1);
    }

Но все равно спасибо вам за инфу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    463

Не будет работать. Нажмите на любую кнопку больше 7 раз - что будет?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Гость Дмитрий   
Гость Дмитрий

поймите, это еще не готовая программа, а всего лишь блок. Она еще не закончена, да и схему вы не видели. Но я понял о чем вы, вы предлагали мне объявить функции а потом просто вставлять где нужна как с функцией установки портов.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
goodkote    0

Всем привет!

Вопрос по уроку №3.

Поясните по выбору номиналов токоограничивающих резисторов, плиз. Напряжение - 5 вольт. Потребление 1 светодиода примерно 20 мА. Итого, падение напряжения на резисторе 220 Ом будет равняться 4,4 В. Т. е. светодиоду останется 0,6 В. Он от такого напряжения зажжется?

Или не так?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
goodkote    0
2 часа назад, goodkote сказал:

Всем привет!

Вопрос по уроку №3.

Поясните по выбору номиналов токоограничивающих резисторов, плиз. Напряжение - 5 вольт. Потребление 1 светодиода примерно 20 мА. Итого, падение напряжения на резисторе 220 Ом будет равняться 4,4 В. Т. е. светодиоду останется 0,6 В. Он от такого напряжения зажжется?

Или не так?

Разобрался. Ток потребления светодиода в данном случае - 10 мА. Так что все ОК.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
RA3DTI    56

Здравствуйте. Подскажите где найти ПОЛНОЦЕННУЮ версию Avr (Atmel) Studio 6. Два раза устанавливал и оба раза она не запускалась, выдавалось сообщение: не установлены какие-то компоненты.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
DmitryS    28

@RA3DTI  ,  версия студии полноценная , это винда у вас не полноценная , читайте каких компонентов не хватает , устанавливайте с сайта майкрософт . Да зачем вам 6 студия , когда есть 7-ая , практически все один в один .

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
RA3DTI    56
12 часа назад, DmitryS сказал:

@RA3DTI  , ....... Да зачем вам 6 студия , когда есть 7-ая , практически все один в один .

Читал про 7-ю, что она "тяжеловесная", гораздо медленнее 6-й, пишут что она раздражает своей задумчивостью, если комп не супер. Тем  не менее  спасибо за совет, попробую.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
gogaze    4

Жалко, что тема видимо скоро совсем умрет! А как хотелось бы на основе полученных знаний сделать какой-либо блок питания с многофункциональным дисплеем, чтобы он кроме своей точности еще и выглядел стильно!!! Типа такого.

Нашел библиотеку со шрифтами (симпатичными), и пока застопорился с их использованием в моем "показометре". 

Пример.jpg

NokiaDisplay.zip

Изменено пользователем gogaze
Добавление файлов

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Berg    17

Тема то не умрет, главное чтоб у тебя не пропало желание далее изучать мир МК.

А чем тебя не устраивает библиотека, которая использовалась в видеокурсе?

Если тебе нужен как на скрине большой и узкий шрифт(5х14), то в файле n5110.c ищем функцию - byte LcdChr ( LcdFontSize size, byte ch ) и закомментируем пару строчек:

            // Копируем две части в кэш
            LcdCache[tmpIdx++] = b1;
//            LcdCache[tmpIdx++] = b1;
//            LcdCache[tmpIdx + 82] = b2;
            LcdCache[tmpIdx + 83] = b2; 

там же чуть ниже правим так:

        // Обновляем x координату курсора
        LcdCacheIdx = (LcdCacheIdx + 5) % LCD_CACHE_SIZE;// было 11

Симпотичные шрифты и специфичные знаки можно самому рисовать или использовать чужие, при этом не прыгая из библы в библу. Есть проги помогающие в этом.

Вот к примеру знак Ома и Цельсия, как на скрине твоем. В файле n5110.h:

{ 0x5C, 0x62, 0x02, 0x62, 0x5C },   //  0x7B 123 знак Ома вместо "{"
{ 0x01, 0x3C, 0x42, 0x42, 0x42 },   //  0x7D 125 знак Цельсия вместо "}" 

строки с символами: "{" и "}" закомментируем.

Вот мой БП рожденный после просмотра видеокурсов. 9 порогов срабатывания защиты при превышении тока, отключение сработанной защиты ручное или автоматическое. Пока ждал дисплей с алли немного изучил таймер и ШИМ, и прикрутил управление вент. охлаждения через ШИМ 30%, 60% и 100% при определенных температурах с настройкой через меню.

По поводу точности, думаю для БП оно прям суперское и не нужно, для этого существуют специальные приборы. Ну или использовать ОУ типа Rail to Rail MCP604

 

2017-10-13 03.33.33_micro.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
gogaze    4

Огромное спасибо за попытку помочь! Пока наверняка понял только то, что мне еще читать и читать, пробовать и пробовать, чтобы осмыслить и понять! 

Еще раз спасибо!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
gogaze    4

Воспользовался твоими рекомендациями, спасибо за реальную помощь!!! Если я правильно понял мы немного изменили отображение шрифта  FONT_2X?

Поэкспериментировал, в протеусе получилось так, как на скрине.

Пока не до конца разобрался с позиционированием "правого" столбца.

Выводил так: 

  //Вольты
        Lcd_printf (0,1,FONT_2X,(readADC(0)*20.00/1023),1);
        Lcd_prints (5,1,FONT_1X,(unsigned char*)PSTR("V"));
   //Ток стабилизации
        Lcd_printf (0,3,FONT_2X,(readADC(1)*10.00/1023),1);
        Lcd_prints (5,3,FONT_1X,(unsigned char*)PSTR("As"));

  //Текущий ток
        Lcd_printf (0,5,FONT_2X,(readADC(2)*10.00/1023),1);
        Lcd_prints (5,5,FONT_1X,(unsigned char*)PSTR("А"));
  //Омы
        Lcd_printf (9,0,FONT_1X,((readADC(0)*20.00/1023)/(readADC(2)*10.00/1023)),1);
        Lcd_prints (15,0,FONT_1X,(unsigned char*)PSTR("{"));
        Lcd_update();

  

2017-10-18_180326.jpg

Изменено пользователем gogaze
Дополнение к тексту

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Berg    17

Не понел про "правый" столбец.

Если имелось в виду, что при 100Ом затрется знак Ома, то я делал так:

float napryazh, tok, soprotivl; // объявляем глобально (перед функцией main)
...
napryazh =((readADC(1)*2.56*(30/2.56))/1023);
tok =((readADC(2)*2.56*(6/2.56))/1023);
if(tok > 0){
	soprotivl = napryazh / tok;
	if(soprotivl < 1){Lcd_printf(9,1,FONT_1X,soprotivl,2);}
	if(soprotivl >= 1 && soprotivl < 10){Lcd_printf(12,1,FONT_1X,soprotivl,0);}
	if(soprotivl > 9 && soprotivl < 100){Lcd_printf(11,1,FONT_1X,soprotivl,0);}
	if(soprotivl > 99 && soprotivl < 1000){Lcd_printf(10,1,FONT_1X,soprotivl,0);}
	if(soprotivl > 999 && soprotivl < 10000){Lcd_printf(9,1,FONT_1X,soprotivl,0);}
}
else{Lcd_prints(9,1,FONT_1X,(unsigned char*)PSTR("----"));}
Lcd_prints(13,1,FONT_1X,(unsigned char*)PSTR("{"));// знак Ома
...

Еще готовься к тому, что в железе измеренное напряжение будет "плясать" до безобразия, в зависимости от пульсаций БП, сотое значение так вообще "8" будет.

В этом поможет таймер, настраивай на миллисекунд так 60 и по флагу выводи значения на экран каждые 0.5сек. Так же этот таймер пригодится для опроса кнопок, если они планируются.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
gogaze    4
7 часов назад, Berg сказал:

Не понел про "правый" столбец.

С размещением показаний на дисплее немного разобрался (скрин1)

Идею 

7 часов назад, Berg сказал:

то я делал так:

я понял, спасибо, буду иметь ввиду.

7 часов назад, Berg сказал:

в железе измеренное напряжение будет "плясать" до безобразия

Ну там же еще много факторов, которые на это влияют: и конфигурация неиспользуемых портов, и разводка печатной платы, и размещение деталей на ней. С этим я уже сталкивался, когда делал "показометр" для переделанного в лабораторный БП  АТХ.  Только делал в CVAVR на дисплее 1602. Нормально получилось. (скрин2)

7 часов назад, Berg сказал:

В этом поможет таймер, настраивай на миллисекунд так 60 и по флагу выводи значения на экран каждые 0.5сек. Так же этот таймер пригодится для опроса кнопок, если они планируются.

100% согласен! Но до изучения таймеров ни как пока не дойду (со мной внуков трое:4, 6 и 8 лет - особо не разгуляешься).

Еще раз спасибо тебе за полезные советы!  

2017-10-19_090742.jpg

2017-10-19_091611.jpg

Изменено пользователем gogaze
Дополнения к ответу

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
gogaze    4

Уважаемый @Berg! Снова обращаюсь с проблемой. Хотел сделать как у тебя

float napryazh, tok, soprotivl; // объявляем глобально (перед функцией main)

napryazh =((readADC(1)*2.56*(30/2.56))/1023);

tok =((readADC(2)*2.56*(6/2.56))/1023);

Для большего удобства в введении дополнительных функций, но проект не стал компилироваться - ошибки типа "конфликт tok," и

"tok =((readADC(2)*2.56*(6/2.56))/1023);"  не константа. В CVAVR это решалось установкой одной галочки "float, width, precision" в свойствах проекта. А в Atmel studio 7 ни как не получается. Все, что нашел в инете перепробовал - ни в какую!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
COKPOWEHEU    261

@gogaze, старайтесь избегать использования чисел с плавающей точкой. В 90% случаев достаточно фиксированной.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ваша публикация должна быть проверена модератором

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

×   Вставлено в виде отформатированного текста.   Восстановить форматирование

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

Загрузка...

  • Похожие публикации

    • Автор: Alexey104
      Всем привет!
      Возникла следующая проблема:
       
      Есть две ардуины 'Mega2560'. По несчастливому стечению обстоятельств данные платы попали в руки одному чуваку, который, вернув их, заявил, что они перестали работать после того, как он "чисто ради интереса" поковырял на обеих некоторые фьюзы. Есть у меня такой китайский usbasp v2 программатор:
      Подключив данный девайс к ICSP-пинам первой платы, удалось без проблем восстановить на ней загрузчик через стандартную Arduino-IDE, после чего работоспособность платы полностью восстановилась. Но вот при попытке сделать то же самое со второй платой, получаю это:
      Такое же сообщение получаю при попытке зашить загрузчик в неподключенную к программатору ардуину, то есть программатор вообще не видит МК. Плата прекрасно работала до того, как вышеупомянутый товарищ покрутил настройки фьюзов.
       
      Что я пытался предпринять:
      Замыкал пины JP3 программатора, отвечающие за понижение скорости, подключал к ардуине 5V от внешнего источника при прошивке загрузчика, - не помогло.
       
      Поиском пользоваться умею, аналогичную тему тут находил, но там проблема была в том, что парень неверно подключал программатор к контроллеру. В моём же случае всё подключено верно, повторюсь, что загрузчик первой платы этим же программатором был восстановлен успешно.
      Буду рад любым советам касательно того, как восстановить работоспособность платы.
       
       
       
    • Автор: Сергей Скопинцев
      Нужно разработать циклическую программу сбора информации от 10 измерительных источников. Период повторения цикла - одна секунда
      Источники:
       М - тензопреобразователь давления. Мостовая схема питается постоянным напряжением, выходной сигнал от 0 до 100 милливольт
       Т, ТМ, ТА- три канала измерения изменения напряжения в диапазоне от 400 до 600 милливольт (тоже нужен мост?)
       ЛМ - анализатор максимума напряжения (от 0 до 5 Вольт) по 10 точкам более-менее распределённых в измерительном цикле. Найденный максимум потом должен участвовать в анализе, постепенно уменьшаясь на 20% каждый цикл
       ВЛ - измерить напряжение на Малой емкости (50 пФ) с помощью емкостного делителя по алгоритму:
                         Снять Землю со средней точки емкостного делителя, подать на емкостной делитель положительный Импульс
                         Замерить нужное нам напряжение в средней точке делителя
                         Снять положительный Импульс с делителя, посадить на землю среднюю точку делителя
      - остальные каналы К7...К10  служебные
      Разрядность данных - 16 двоичных.

      Результаты писать на MicroSD текстовым файлом, на первом месте в строке текущее время в секундах, остальные каналы разделены пробелами
      Порядок каналов:
      Т - М -ТМ - Вл - ЛМ -...
      Коэффициенты усиления по каждому информационному каналу должен иметь возможность изменить оператор по формуле y = Ax + B
      Прибор автономный, питается от + 5 Вольт.
       
    • Автор: Ru_s
      Здравствуйте. Подскажите пожалуйста, возможно ли на attiny13 реализовать такую штуку. Мне в процессе работы программы нужно поменять режим работы таймера/счетчика с fast PWM на обычный счёт, отсчитать длительный промежуток времени и опять вернутся в режим ШИМ. Т.е. я подаю на ногу сигнал ШИМ и когда он в максимальном значении, я его отключаю, и тупо подаю на ногу высокий лог. уровень. В это время Т/С по идее свободен, и мне надо посчитать время работы выхода на максимальном лог. уровне, при достижении какого-то значения времени нужно перевести т/с обратно в ШИМ. Возможно ли это? И как приблизительно это реализовать
    • Автор: Kiraspbkiev Kira
      День Добрый. Есть два вопроса от новичка: 1) Правильная ли схема сделанная мною? 2) если схема верна то как правильно подключить к atmega328p-mu usb на чипе cp2102-grm?
      На схеме колодка JP1 это AVR ISP а JP2 это UART
      С проектированием столкнулся в первый раз, цель узнать что то новое и сделать своими руками:)