Семисегментный индикатор и динамическая индикация на AVR микроконтроллере ATmega8

В разных конструкциях бывает оправдано использовать семисегментные светодиодные индикаторы, дешево и сердито по сравнению с символьными ЖКИ. Светодиодный индикатор представляет собой восемь светодиодов (7 для представления цифры и 1 для точки) расположенные в виде слегка наклоненной цифры:
В разных конструкциях бывает оправдано использовать семисегментные светодиодные индикаторы, дешево и сердито по сравнению с символьными ЖКИ. Светодиодный индикатор представляет собой восемь светодиодов (7 для представления цифры и 1 для точки) расположенные в виде слегка наклоненной цифры:
семисегментный светодиодный индикатор
Светодиоды внутри имеют общий анод (ОА) или общий катод (ОК). То есть, для управления одной цифрой нужно 8 выводов микроконтроллера. А что же делать, когда нужно управлять, например, четырьмя цифрами? Использовать микроконтроллер с 4*8=32 выводами? Не экономично.

Для такого случая придумали динамическую индикацию. Для этого соединяем выводы, которые отвечают за включение сегментов в общую шину, а общими анодами (катодами) будем управлять через транзисторы. В отдельный момент времени горит только одна цифра. Таким образом быстро перебирая цифры на дисплее (как кадры в фильме) мы получим эффект постоянно горящего изображения. В замедленном варианте, как это происходит, можно посмотреть на картинке:
анимация динамической индикации
А вот ускоренная в 25 раз картинка, уже начинают вырисовываться контуры «12.34»:
анимация динамической индикации
Используя принцип динамической индикации мы сможем управлять четырьмя цифрами при помощи 8+4=12 выводов. Использование же 2-х сдвиговых регистров HC595 может сократить это число до 4. Рассмотрим схему подключения к микроконтроллеру:

Управлять же индикатором будем с помощью микроконтроллера ATmega8. Резисторы R5-R13 – ограничительные на 470 Ом. R1-R4 – по 1кОм. Транзисторы Q1-Q4 – любые PNP типа, я использовал BC807 в планарном исполнении. Конденсаторы С5,С7 – электролиты по 100 и 200мкф соответственно, С4,С6 – керамика по 0,1мкф. Так как индикатор с общим анодом, то соответственно включение разряда/сегмента производиться низким уровнем.

Для индикаторов с общим катодом схема аналогична, только транзисторы следует взять NPN структуры, и управляться индикатор будет высоким уровнем.
Продемонстрируем сказанное, напишем программу, которая будет перебирать числа от 0 до 9999 и выводить их на семисегментный индикатор.

  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3. // 0 1 2 3 4 5 6 7 8 9
  4. const unsigned char codes[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
  5.  
  6. unsigned char data[4]={0x00,0x00,0x00,0x00};
  7. unsigned char counter=0;
  8.  
  9. void pause (unsigned int a)
  10. { unsigned int i; for (i=a;i>0;i--); }
  11.  
  12. void init_timer (void)
  13. { TIMSK=(1<<TOIE0); //Enable timer overflow interrupt
  14. TCCR0=(0<<CS00)|(1<<CS01)|(0<<CS02); //Prescaller = /1
  15. }
  16.  
  17. void convert_data (unsigned int x)
  18. {unsigned int temp,res;
  19. temp=x;
  20. res=temp/1000; //Calculate 1000-s
  21. data[3]=codes[res];
  22. temp=temp-res*1000;
  23.  
  24. res=temp/100; //Calculate 100-s
  25. data[2]=codes[res];
  26. temp=temp-res*100;
  27.  
  28. res=temp/10; //Calculaate 10-s
  29. data[1]=codes[res];
  30. temp=temp-res*10;
  31.  
  32. data[0]=codes[temp]; //Calculate 1-s
  33. }
  34.  
  35. ISR (TIMER0_OVF_vect)
  36. {PORTD=0xff;
  37. PORTB=~_BV(counter); //Enable digit
  38. PORTD=~data[counter]; //Write code
  39. counter=(counter+1)%4; //Increment digit counter
  40.  
  41. TCNT0=0x00; //Clear timer
  42. }
  43.  
  44. int main(void)
  45. { unsigned int x=0;
  46. DDRD=0xff;
  47. PORTD=0x00;
  48. DDRB=0x0f;
  49. PORTB=0x0f;
  50.  
  51. pause(1000); //Settle pause
  52. init_timer(); //Init timer
  53. sei(); //Interrupt enable
  54. while(1)
  55. {convert_data(x); //Conver data to codes
  56. if (x<9999) x=x+1; //Increment data
  57. else x=0;
  58. pause(30000);
  59. }
  60. return 1;
  61. }

Код очень простой. В массиве codes находятся коды, которые следует выводить на порт, чтобы получить желаемую цифру. Смена активной цифры производиться по прерыванию от переполнения таймера 0. А функция convert_data(int x) раскладывает число х по разрядам, и записывает соответствующие коды в массив data, данные из которого выводятся непосредственно на индикатор, при срабатывание прерывания.
Что из этого вышло, можно глянуть на рисунках:
фото динамической индикации
фото динамической индикации

Исходный код можно скачать в виде проекта под AVR Studio 4
Также, может кому пригодиться, платка для моего табло в формате .lay для программы Sprint Layout 5

Не удаётся открыть

Не удаётся открыть прикреплённый файл к данной статье программой Sprint Layot 5
Выдаёт ошибка "led7_sch.dch" ist keine Sprint-Layout Datei.

Вопроскак открыть этот файл? Какой всё-таки программой?
Заранее Вам спасибо за ответ!

Это программа DipTrace

Это программа DipTrace

Версия Sprint Layout 5 не

Версия Sprint Layout 5 не подходит значит. Попробуй более новую скачать.

Нашёл в сети, скачал и

Нашёл в сети, скачал и установил Sprint-Layout 6.0.
Но файл в архиве не открывается.
Ибо файл этот имеет расширение "*.dch", НО НЕ расширение "*.lay", которое как раз для этой программы.
Т.о. вопрос мой остаётся открытым до сих пор.
Какой программой открыть этот файл в архиве можно?

А это часом не макрос?

А это часом не макрос? Попробуй зайди в спринте в раздел макросы и добавь тот файл как макрос!
Или подожди пока автор статьи отпишется.

Автор статьи ошибся с файлами

Автор статьи ошибся с файлами при архивации!
Автор перепутал положив в архив файл редактора принципиальных схем пакета DipTrace (Не зря когда-то я спрашивал на этом сайте какую программу используете для принципиалок-диптрейс ответили мне).Я этот факт вспомнил. Открыл файл в архиве сначала редактором печаток (т.к. сказано было то в архиве печатка - вылезли ошибки, но открылся), а потом уже в редакторе принципиальных схем открыл (DipTrace Schematic). И я увидел ту же картинку полезной принципиальной схемы, которая была приведена в статье.

В принципе разводку для неё мне будет сделать без особых проблем, но к сожалению времени сейчас на это нет(Современем сделаю всёраввно - могу потом выслать почтой, чтобы выложили для народа!).
По этому (на основании всего выше сказанного) осмелюсь потребовать у автора выложить/добавить/исправить архив с печаткой для Sprint-Layout 5.0 (Раз она существует в природе и чтобы не пылится лишнее время файлу разводки).
Заранее спасибо!

У макросов расширение файла

У макросов расширение файла "*.LMK"
а в архиве dch

приделать USB?

а насколько сложно превратить эту штуку в usb индикатор? (с виртуальным ком-портом), с минимумом обвязки (без 232)
видел где-то, если не ошибаюсь, на tiny45, но без особых объяснений и исходников...

горят все сегменты

Собрал эту схемку, при подаче питания загораются нули и сразу загораются все сегменты, перебор чисел вроде идет, но те сегменты которые должны тухнуть, то они горят в половину яркости(((
что это может быть?
контроллер ATmega8A-PU, транзисторы КТ3107А, ограничивающие резисторы 510 Ом, R1-R4 – по 1.5кОм

поставь pull-up резисторы на

поставь pull-up резисторы на базу и этот эффект пропадёт.

Какая стоит частота

Какая стоит частота тактирования МК? Оптимизация стоит О0? (в свойствах проекта)

Еще попробуй поиграться с делителем на таймере (биты CS00-CS02).

Также есть вариант вывести в статике и посмотреть что твориться. Может какие траблы с включением цифр.

Фьюзы не менял, по этому

Фьюзы не менял, по этому частота получается 1МГц? А по поводу остального можно подробней? я только начал изучать микроконтроллеры и не совсем понимаю)

Смотря какой контроллер, по

Смотря какой контроллер, по памяти скажу что у tiny2313 1МГц, а у Mega8 - 4МГц.

Про оптимизацию - идешь в Project->Configuration options, там есть 5 уровней оптимизации, из них выбираеш О0 (это влияет на корректность задержек в программе).

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

Также попробуй просто вывести по одной цифре все. В случае с вышеописаной схемы:

cli();
DDRD=0xff;
PORTD=0x3f;

DDRB=0xff;
PORTB=0xfe;

Это поможет выявить ошибки подключения.

по-моему, ни то, ни другое,

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

По моему такой эффект

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

тот же эфект

нашёл несколько ошибок в монтаже, исправил, но ничего не изменилось((( цифры бегут, но сегменты не тухнут полностью. питал от юсб и пробовал отдельно 5в через L7805CV, то же самое.. есть еще какие идеи?

код модифицировал, или

код модифицировал, или скопировал как есть?

Код скачал в виде проекта для

Код скачал в виде проекта для AVR Studio 4, что выложен выше..
Может по напряжениям в каких-то точках можно найти причину?

нутк модифицировал, или нет? )

насколько я понимаю, обычный вольтметр там тебе ничего не покажет - общую температуру по больнице, не более, тебе же нужен логический анализатор))
думаЙ, в чем может быть дело. соответствует ли тип транзисторов типу индикатора, правильно ли подключены транзисторы. смотри, правильно ли подключены пины - те ли порты используешь, теми ли пинами ты управляешь в прерывании.
несколько ламерское утверждение (знающие товарищи должны поправить) - наверное,напряжение на аноде индикатора должно быть выше напряжения на катоде... (хотя судя по тому что светится - так оно и есть)
напряжения там должны быть не болье 5В,
можно попробовать отключить изменения цифр - попробовать выводить статику.
плюс проверить работоспособность самого индикатора...

Логический анализатор это

Логический анализатор это перебор))) у меня его нет..
поставил я вместо кт3107 для одной цифры кт816, вроде нормально перебирает, но очень тускло горит, почти ничего не видно(при этом поменял резисторы R1-R4 на 750 Ом), ставлю кт361 и получается тот же эффект как и с кт3107..
почему такая разница, ведь все 3 транзистора p-n-p типа?

а это уже читать спецификации

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

покритикуйте, плиз

завтра на плате поменяю местами portb и portd, постраюсь не запутаться с подключением кнопки и оптрона
программа скомпилировалась, и даже без ошибок и предупреждений - 1175 байт

кнопку вешаю на pd3 и на землю, оптрон: диод на +5 и землю, транзистор – на pd2 (int0) и землю. не напортачить бы с сопротивлениями...

наверное, можно было все это безобразие внутри while перенести в обработчик int1 - пока не дошло, как правильнее.

  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3. #define nop() {asm("nop");}
  4.  
  5. //0 1 2 3 4 5 6 7 8 9 0 П А _ вниз вверх
  6. const unsigned char codes[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
  7. 0x07,0x7f,0x6f,0x3f,0x37,0x77,0x00, 0x5D, 0x6b};
  8. unsigned char data[4]={0x00,0x00,0x00,0x00};
  9. unsigned char counter=0; //this counter is needed to iterate through data array
  10. signed char rotcounter=0; //rotations counter
  11. unsigned char rotdir=0; //direction
  12.  
  13. void pause (unsigned int a)
  14. { unsigned int i;
  15. for (i=a;i>0;i--); //а зачем есть nop();?
  16. }
  17.  
  18. void init_timer (void)
  19. { TIMSK=(1<<TOIE0); //Enable timer overflow interrupt
  20. TCCR0A=0;
  21. TCCR0B=1; //setting the prescaler
  22. }
  23.  
  24. ISR(SIG_INTERRUPT0)//обработка прерываний INT0
  25. {if (rotdir==1)
  26. { // clockwise
  27. if (rotcounter<7) {//на всякий случай, чтобы лишнего не посчитал
  28. rotcounter++;
  29. data[0]=codes[rotcounter]; //меняю количество оборотов в правом разряде
  30. }
  31. }
  32. else { if (rotcounter>0) {//опять же,чтобы глубоко в минус не ушел :-)
  33. rotcounter--;
  34. data[0]=codes[rotcounter]; //меняю количество оборотов в правом разряде
  35. }
  36. }
  37. }
  38.  
  39. ISR (TIMER0_OVF_vect)
  40. {PORTB=0xff; // cathodes - ON, digits OFF
  41. PORTD=~_BV(counter); //Enable digit
  42. PORTB=~data[counter]; //Write code
  43. counter=(counter+1)%4; //Increment digit counter
  44.  
  45. TCNT0=0x00; //Clear timer
  46. }
  47.  
  48. int main(void)
  49. {DDRD=0xF3; // set PORTD as OOOOIIOO
  50. PORTD=0x00; //validly?
  51. DDRB=0xff; // set the whole PORTB for OUTPUT
  52. PORTB=0xff; //what for?
  53.  
  54. pause(1000); //Settle pause
  55.  
  56. init_timer(); //Init timer
  57.  
  58. GIMSK=0b11000000; //разрешаем прерывание int0 и int1 - кнопка
  59. MCUCR=0b00001111;// int by rising front - для кнопки 1 и 2
  60.  
  61. sei(); //Interrupt enable
  62.  
  63. while (1)
  64. {
  65. if ( (PIND & (1<<PIND3)) ) {//при замыкании pd3 на землю, ведь так?
  66. rotdir=!rotdir; //меняем направление движения (компиллятор проглотил)
  67. if (rotdir) { //если по часовой стрелке
  68. data[3]=codes[16]; //рисую символ по часовой стрелке
  69. //на индикаторе - начинаем ожидание оптрона
  70. while (rotcounter<=7){ //пока не сделали нужных нам семь оборотов
  71. asm("nop"); //ждем прерывания от оптрона
  72. }
  73. data[3]=codes[14]; //гасим левый индикатор или выключаем лебедку
  74. }
  75. else
  76. {
  77. data[3]=codes[15]; //рисую символ против часовой стрелки или включаю второе реле
  78. while (rotcounter>=0){ //пока не сделали нужных нам семь оборотов в обратную сторону
  79. nop(); //ждем прерывания от оптрона
  80. }
  81. data[3]=codes[14]; //гасим левый индикатор или типа выключаем нагрузку
  82. }
  83. }
  84. }
  85. return 1;
  86. }

урааа!!! кажется, получилось!

осталось только оптрон поправить! пока импульсы имитирую закорачиванием int0 :-((

короче, asm("nop") никуда не годится - не получалось выходить из двух последних циклов while в основном коде, очень долго не мог понять где затык...
как заменил на pause(100) - все стало работать как и было запланировано :-)

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

апдейт

все напутал.
короче, цифры отображаются нормально везде (задавал массив data в начале - все светится)
с проверкой перед while - похоже пытался зажечь 0x00 - ошибся с устным счетом))
сейчас будем смотреть, как входит в if по нажатию кнопки)))
с подключением оптрона - все равно косяк, как привести его в чувство - не понимаю. объясните, люди добрые, куда смотреть в даташите при подборе сопротивлений на его включение.

поменял 61 строчку

поменял 61 строчку на
PORTD=0x0C; // как я понял, включаем подтягивающие резисторы на pd2 и pd3

теперь при нажатии на кнопку я вижу падение напряжение на порте до нуля, как положено.

оптрон нифига не работает (то ли спалил его, то ли подключил неправильно, то ли сопротивления не те подобрал...
на светодиодных выходах PD - 3,8-3,9В, на базах транзисторов 4,9В, на выходах с управляющих транзисторов - 1,80-1,90, причем при отпускании кнопки - кратковременно повышается на 0,02-0,15В

но самая главная загвоздка - почему все пины PB выдают +5, даже после нажатия кнопки ничего не меняется.

ведь при нажатии кнопки я либо в 83, либо в 92 строчках меняю конфигурацию сегментов в левом разряде и по идее это должно отразиться на пинах PB, разве нет? Получается, я в if не попадаю?

вставил перед while вставил

вставил перед while вставил строчку
data[2]=codes[13]; //проверяем работоспособность буквой А,
но второй слева разряд так и не загорелся... стало быть, что-то не то нахимичил с конфигурацией портов?

Если честно я так и не понял

Если честно я так и не понял что ты хочешь получить.

на самом деле не так

на самом деле не так много
хочу поменять в исходном коде порты, чтобы высвободить int0 и int1

на освободившийся int0 повесить оптрон, который будет считать испульсы

плюс на pd3 повесить кнопку.
по нажатию кнопки я включаю условную стрелку вверх на левом разряде, а в правом - отображаю количество импульсов с оптрона.
по достижении семи импульсов стрелку в левом разряде - гашу

по повторному нажатию - то же самое, но рисую условную стрелку вниз, и считаю до 0, по достижении нуля - гашу левый разряд.

но у меня какой-то затык - вообще ничего не отображается на экране (даже до захода в while), хотя во втром слева разряде по моему разумению должно бы что-то отображаться...

забыл про прерывание

пришлосьпеределать обработчик следующим образом:

  1. ISR (TIMER0_OVF_vect)
  2. { PORTB=0xff; // cathodes - ON, digits OFF
  3. if ((counter==0) || (counter==1)){
  4. PORTD=~_BV(counter);} //pd1,pd2
  5. else {
  6. PORTD=~_BV(counter+2); //pd4,pd5
  7. }
  8. PORTB=~data[counter];
  9. counter=(counter+1)%4;
  10. TCNT0=0x00; //Clear timer
  11. }

но все равно не помогло - ничего не горит и не моргает. куда смотреть? :-)

Семисегментный индикатор и динамическая индикация на AVR микрок

аффтар Ты сам этот код проверял???
Вот рабочий:

  1. #define F_CPU 1000000UL
  2. #include <avr/io.h>
  3. #include <avr/interrupt.h>
  4.  
  5. const unsigned char seg[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
  6. unsigned char data[] = {0x00,0x00,0x00,0x00};
  7. int x = 0;
  8.  
  9. void pause (unsigned int a)
  10. {unsigned int i; for (i=a;i>0;i--);}
  11. void init_timer (void)
  12. {TIMSK = (1<<TOIE0); // Таймер по переполнению
  13. TCCR0 = (1<<CS00)|(0<<CS01)|(0<<CS02); //prescaller
  14. }
  15.  
  16. void convert_data (int x)
  17. {unsigned int temp; temp = x;
  18. data[3] = seg[temp % 10 / 1];
  19. data[2] = seg[temp % 100 / 10];
  20. data[1] = seg[temp % 1000 / 100];
  21. data[0] = seg[temp % 10000 / 1000];
  22. }
  23.  
  24. ISR (TIMER0_OVF_vect)
  25. { PORTC = ~_BV(x);
  26. PORTD = data[x];
  27. x = (x + 1) % 4;
  28. }
  29.  
  30. int main(void)
  31. { unsigned int x = 0;
  32. DDRD = 0xFF;
  33. DDRC = 0xFF;
  34. pause(1000);
  35. init_timer();
  36. sei();
  37.  
  38. while(1)
  39. { convert_data(x);
  40. x++;
  41. if (x >= 9999) x = 0;
  42. pause(10);
  43. }
  44. }

Что именно не работает, внизу

Что именно не работает, внизу есть проект в AVR Studio скачай уже готовый проект и проверь.

два разных вопроса

1. увидеть бы осцилограмму (или как это называется) 5 вольт от элементов питания и от разных зарядок - со стабилизирующими конденсаторами, со схемой на LM7805 и без - просто любопытно насколько мои представления совпадают с реальностью и что принято называть помехами.

2. про модернизацию программы. на моем аттини2313, насколько я понял, доступно 18 пинов. из них 11 пинов у меня занято (7 сегментов и четыре разряда). в данный проект хочу повесить еще температурные датчики 1-wire (1 пин), две кнопки (2 пина) и оптрон (1 пин, а лучше 2 пина).
хочу, чтобы по нажатию на первую кнопку менялась рабочая программа: вместо опа-попа, которая по работает при включении устройства, запускался термометр (в идеале вторая кнопка меняет датчики), а при повторном нажатии на первую кнопку - на чтение включался оптрон а на индикаторе, скажем, до 7 считались его импульсы (при нажатии на вторую кнопку опять считаются импульсы, но меняется направление счета от 0 до 7 и от 7 до 0)

если с портами вроде бы все должно получиться, то с прерываниями и таймерами я пока не очень понимаю, насколько реализуема эта затея: если один таймер используется для отлова нажатия на кнопку, а второй - для отображения информации, то для отлова нажатия третьей кнопки и подсчета импульсов на оптроне счетчиков уже не хватает? то есть на attiny2313 с его двумя таймерами реализовать такую задумку в принципе не получится? или существуют какие-то решения?
или я вообще фигню несу полную? :-)

1) bp.xsp.ru/rules.php

1) bp.xsp.ru/rules.php

noname - с хреновыми кондерами.

От батареек - получиш ровную прямую.
От LM7805 - тоже прямая, только хзхз влияние импульсных нагрузок на просадку напряжения.

2) Не советую отключать пин Reset. При этом теряется возможность программирования по SPI и помочь сможет разве что высоковольтный программатор.

Для считывания фототранзистора лучше использовать внешнее прерывание int0. (1 пин)
Для слежения за клавиатурой - таймер (3 пина для 3-х клавиш)
Для датчика температуры - 1 пин, итого 11+1+3+1=16 пинов, вкладываешся.

спасибо!

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

про вывод на SPI как-то не подумал)) тогда доступно всего 17.

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

про пины - вроде бы тоже посчитал, что будет достаточно (тем более что клавиш хотел всего две). а вот со счетчиками как быть? По даташыту их у меня всего два (один на 8 и один на 16 бит). для подсчета импульсов фототранзистора нужен? (или просто во внешнем прерывании оперировать с обычной глобальной переменной?) для семисегментного индикатора нужен. для слежения за клавиатурой нужен один, или по одному на каждую клавишу (там же всякий дребезг)? и разве там не внешнее прерывание? (у меня есть int1, и я так понимаю ему можно назначить отдельный пин, но кнопок две)
хотя сейчас смотрю на статью про матричную клавиатуру, пытаюсь вникнуть - похоже, можно использовать один таймер и одно прерывание по таймеру сразу для чтения кнопок и для вывода значений, обойтись без внешнего?...
кстати, почему для фототранзистора лучше использовать int0, а не опрашивать по таймеру? просто удобнее смотреть по fall или rise, а не по переполнению таймера? а для клавиш как раз чтобы избежать дребезга - удобнее с таймером?

Да, компьютерные БП в

Да, компьютерные БП в подавляющем большинстве импульсные. Трансформаторы используются как в импульсных, так и в обычных БП. Что ты подразумеваешь под трансформаторным БП?

Да, задержки для шины 1-wire важны и они там привязаны к частоте МК.

Для фототранзистора проще сделать связку: внешнее прерывание по фронту=инкремент глобальной переменной типа long int, чем задействовать счетчик, который втихаря может переполниться. Т.е. надо еще отслеживать переполнение. Счетчик удобен для определения временных интервалов и ШИМа.

Опрос всей клавы можно сделать по таймеру. Дребезг убрать кондером на 0,1мкФ.

Назначить пин прерыванию int0(1) нельзя. Они жестко привязаны к конкретной ноге.

трансформаторным я называю

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

про внешние прерывания - понятно. не пойму, откуда взялась такая конвенция: прерывания по таймеру обрабтывать в ISR (TIMER0_OVF_vect), а внешние - в SIGNAL(SIG_INTERRUPT1) - где это определяется?

и еще, задумался, как правильнее организовать цикл, если устройство начинает работу с ожидания нажатия кнопки? вечный цикл с паузой в 100 мс, а в нем - если пин, заданный на вход, принимает логический ноль, то делаем дело?

SIGNAL - устаревший

SIGNAL - устаревший синтаксис, он тоже работает, но лучше пиши все через ISR.

Проще так:

do {
;
} while (кнопка не была нажата);

Будет выполняться до тех пор, пока условие "кнопка не была нажата" выполняется.

но тогда он отработает до

но тогда он отработает до нажатия кнопки - и стоп-машина, разве нет? мне надо, чтобы он постоянно крутился, что-то типа

  1. unsigned char rotcounter=0; //счетчик оборотов, менется в прерывании int0 от оптрона
  2. ...
  3. ...
  4. while (1) do {
  5. if (!pind1) //при нажатии кнопки
  6. {
  7. rotdir=!rotdir; //меняем направление движения
  8. //(в си, кажется, нет булевских - придется с 0 и 1 заморачиваться и с if конструкцией
  9. if rotdir { //если по часовой стрелке
  10. data[3]=codes[16]; //рисую символ по часовой стрелке на индикаторе,
  11. // потом вместо индикатора просто буду управлять нагрузкой через реле
  12. while (rotcount<=7){ //пока не сделали нужных нам семь оборотов
  13. asm("nop"); //ждем прерывания от оптрона
  14. }
  15. data[3]=codes[14]; //гасим левый индикатор или выключаем лебедку
  16. }
  17. else
  18. {
  19. data[3]=codes[15]; //рисую символ против часовой стрелки
  20. //или включаю второе реле
  21. while (rotcount>=0){ //пока не сделали нужных нам семь
  22. //оборотов в обратную сторону
  23. asm("nop"); //ждем прерывания от оптрона
  24. }
  25. data[3]=codes[14]; //гасим левый индикатор или типа выключаем нагрузку
  26. }
  27. }
  28. }

в прерывании таймера управляем индикацией (левый разряд
//- направление движения, правый - счетчик оборотов)
во внешнем прерывании - в зависимости от направления
//(rotdir) делаем инкремент или декремент rotcount

как думаете, будет работать?
завтра придется на бредборде переделывать все это безобразие... и опять, с подбором сопротивлений к тому оптрону не ошибиться. они должны быть и на диоде, и на входе транзистора. и на выходе транзистора - тоже, как я понял?

кнопку я приделываю к оставшемуся выводу pd6 и замыкаю
//ее через конденсатор на землю, правильно?

попробовал использовать концепцию ISP

в смысле не вынимая микроконтроллера - хрен там, программатор поругался при чтении фьюзов.
пришлось вынимать индикатор - тогда нормально прошилось.
у меня теперь проблема другого плана - фигня какая-то выводится на циферблате (первые 10 - стандартные цифры)
объяснять сложно, вставляю видео:

это что, сгоревший порт?

Ты просто сегмент G перепутал

Ты просто сегмент G перепутал местом с сегментом D

похоже, перепутал, но не G и

похоже, перепутал, но не G и D, а B и C

Значит в схеме используются

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

Не, порт не сгорел, иначе бы какой-то сегмент или цифра вовсе не горели бы, или постоянно горели и не тухли. Скорее трабла в подключении, попробуй поиграться с массивом codes, чтобы добиться корректного отображения цифр.

вот этого не понял

кнопка ресета (1 пин) у меня не задействована в устройстве.
речь о SPI программировании микроконтроллера? вроде бы нет, но завтра проверю. странно, что последние три цифры показывает как и было задумано.
то есть получается, в определенных ситуациях на выходе можно получать совсем не то, что ожидаешь?
кстати, попутно еще вопросы: можно ли считать, что от ножек микроконтроллера до земли идут отдельные цепи?
и еще, какое значение имеет пин, если это порт входа? ноль?

Да, сейчас пытаюсь тебе

Да, сейчас пытаюсь тебе объяснить, почему у тебя не работает ISP.
При программировании, программатор садит Reset на землю, и начинает писать по SPI данные в МК. Если в этот момент что-то ему мешает это сделать - то вылазит ошибка.

На выходах всегда получаешь то, что ты запрограммировал.

Да, когда ножка МК работает на выход и на ней лог. 0 - тогда внутренний транз. замкнут на землю в открытом состоянии, т.е. сопротивление ножка МК-землю равно нулю.

Смотря какой порт входа, там есть 2 режима. В одном пин болтается в воздухе и на него приходит туча наводок. А второй - когда пин входа подтянут на + питания. Если его не трогают, то на нем лог. единица, если его посадят на землю - на нем лог. 0.

собрал на макетке, проверил -

собрал на макетке, проверил - не работает. а как отлаживать?
может, неправильные фьюзы?
у меня были вот такие. дальше вниз - все чисто. я их только прочитал. а потом взял hex файл и прошил во флеш
нужен осциллограф? или есть методы попроще?

Какой hex файл? Из

Какой hex файл? Из статьи?

Какой контроллер используешь?

Может все-таки послушаешь совета и скачаешь AVR Studio с эмулятором для отладки??

Фьюзы выставь на Int RC 1MHz. Если нету 1МГц - выставь на Int RC 128khz.

значит так

хех. забыл эмиттер подключить к питанию. :-)
вроде бы заработало!
но!
у меня почему-то сегмент Е (вертикальный левый нижний) горит ярче остальных, во всех дигитах, в чем может быть дело?
перед полгулкой - чуть не обкакался, показалось(или не показалось),что перепутал местами питание на микроконтроллер. но ничего, вроде что-то похожее, что должен выдавать - выдает. если не считать что один сегмент ярче остальных.

отсутствие питания на эмиттере обнаружил при замерах напряжения, а они казались такими:
на транзисторах (на базе):
3.88 (реже 3.89)
3.86 (реже 3.87)
3.84
3.90
после подключения эмиттера - стало 4,9(4,8)

hex - код из статьи, файл сам

hex - код из статьи, файл сам собрал с минимальными правками под себя.

контроллер - микроконтроллер? attiny2313

от фьюза зависит насколько быстро будут моргать и меняться цифры. у меня они вообще не загораются пока))
буду пробовать смотреть напряжение на ногах микросхемы, на базе транзистора

и еще у меня все на макетке и без конденсаторов, источником питания была сборка из трех элементов питания. когда собирал - вольтметр показывал 3,8 Вольта, после подключения - перестал показывать, может, батареи были в плохом состоянии.

попробую сейчас подключить источник питания импульсный, 5,6Вх0,5А (хорошо что взял вчера lm7805)

в этом случае номиналы конденсатора должны быть другими? (еслина входе не 12, а5,6Вольта?)

Работу с таймером

Работу с таймером переделал?

На МК обязательно став конденсатор, у меня было пару случаев, когда не работало.

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

заработало - в одном месте

заработало - в одном месте ярче светилось из-за неконтакта - поправил проводок - все заработало.
ну и я где-то напутал (похоже, и в самой программе, и в проводках на плате) - и у меня не совсем то, что я хотел выводить выводится..
про конденсатор - я так и не понял, куда и как его ставить.
и что будет, если в своей простой поделке (без всяких АЦП вещей) я буду использовать обычный пятивольтовый блок питания от длинка дир320, без конденсаторов и без всяких L7805