Содержание
Урок 1. Первый проект
Урок 2. Управление кнопками
Урок 3. Подключение LCD
Урок 4. Использование ШИМ
Урок 5. Таймеры
Урок 6.1. Статическая индикация
Урок 6.2. Динамическая индикация
Урок 7.1. Генерация звука
Урок 7.2. Генерация звука. Продолжение
Урок 8.1. Передача данных через UART
Урок 8.2. Передача данных через UART. Продолжение»
Урок 9. Передача данных через SPI
Урок 10. Изучение АЦП. Простой вольтметр
Урок 11. Получение синуса при помощи ШИМ
Урок 12. Измерение температуры
Урок 13. Внешние прерывания.
Урок 14. Использование отладчика
Урок 15.1. Управление инкрементальным энкодером
Урок 15.2. Управление громкостью, при помощи энкодера
Урок 16. Управление RGB светодиодом
Урок 17. Использование ИК
Урок 18.1. Знакомство с графическим дисплеем
Урок 18.2 Вывод изображения на графический дисплей
Урок 18.3 Вывод русскоязычного текста
Урок 19. Формирование сигнала, при помощи ЦАП (R2R)
Урок 20. Опрос матричной клавиатуры
Урок 21. Сторожевой таймер
Урок 22.1 Воспроизведение wav. Введение.
Урок 22.2 Воспроизведение wav. Продолжение.
Урок 23.1 Работа с внешней памятью
Урок 23.2 Работа с файловой системой Fat

seglogoВ продолжение урока, рассмотрим динамическую индикацию. Если вы внимательно изучили статическую индикацию, то знаете, что сегментный индикатор это набор светодиодов. Для того, чтобы подключить индикатор, нужно 7 ножек микроконтроллера. Но, вдруг нам понадобилось использовать несколько индикаторов, например 2, 3, 4…

Тогда нам понадобится уже 14, 21, 28 ножек, а ножек итак мало… Тут нам на помощь приходит динамическая индикация. Основная задача динамической индикации — снизить количество используемых ножек микроконтроллера. Обратите внимание на схеме задействовано 9, а не 14 ножек. Ножки управления все подключены параллельно.
sch2

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

Более детально. В первый момент времени все выключено PORTB=0x00; PORTD=0xFF; так как схема с общим «+», анодом. Далее на PORTD посылается конфигурация первого числа, например «0». Из статической индикации мы помним:

case 0:
{
  PORTD=0xC0; 
  break;
}

Но обратите внимание, «+» подключен к PORTB.1, т.е. чтобы зажечь сегмент нужно включить ножку PORTB.1=1; 

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

При высоких частотах, человеческий глаз не способен разглядеть эти переключения, и кажется что индикатор горит постоянно. Рекомендуется не использовать частоты кратные 50Гц. В своем тестовом проекте я использовал 120Гц. Таймер настроен на частоту 1МГц. Код обрабатывается в прерывании таймера1. Прерывание вызывается 240 раз в секунду, потому что индикаторов два, поэтому 1000 000/240=4166 или 0x1046 пихаем в регистр сравнения. Протеус подружить с динамическим индикатором не удалось, зато на железе заработало сразу.

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

Для схемы с общим анодом

sch4

Для схемы с общим катодом

sch3

В качестве тестовой прошивки использовал таймер из предыдущего проекта.

Видео работы прошивки

101 комментарий: Урок 6.2 Динамическая индикация в AVR микроконтроллерах

  • Какова частота мерцания в данном проекте? Помогите пожалуйста посчитать и разобраться с таймерами, а то в уроке про таймеры совершенно не понятно что откуда берётся.

  • Обновлено

  • Большое спасибо :razz:

  • Подскажите пожалуйста какие транзисторы лучше использовать в схеме (крайне желательно в корпусе TO92 или подобном) или какие параметры у них должны быть.

  • нужно грубо прикинуть ток, например у SA56-11G один сегмент потребляет максимум 25ма, всего сегментов 8, значит максимальный ток будет 200ма. При динамической индикации, ток конечно будет меньше, да и вряд ли все сегменты будут гореть одновременно, но лучше всегда брать с запасом, по току более 200ма, как вариант BC337-25.

  • Добавьте пожалуйста код для четырех семисегментников

  • Код практически не изменится, нужно добавить в прерывании условие включения 3 и 4 индикатора, аналогично 1 и 2. И пересчитать прерывание

  • interrupt [TIM1_COMPA] void timer1_compa_isr(void)
    {
    PORTB=0x00;

    if(i==0){n=n1;PORTB.0=1;i++;}
    if(i==1){n=n2;PORTB.1=1;i++;}
    if(i==2){n=n3;PORTB.2=1;i++;}
    else{n=n4;PORTB.3=1;i=0;}
    switch(n)
    {
    case 0:{PORTD=0b10001000;break;}
    case 1:{PORTD=0b11101011;break;}
    case 2:{PORTD=0b01001100;break;}
    case 3:{PORTD=0b01001001;break;}
    case 4:{PORTD=0b00101011;break;}
    case 5:{PORTD=0b00011001;break;}
    case 6:{PORTD=0b00011000;break;}
    case 7:{PORTD=0b11001011;break;}
    case 8:{PORTD=0b00001000;break;}
    case 9:{PORTD=0b00001001;break;}
    }
    }
    правильный ли это код для 4-ёх семисегментников? У меня не робит почему-то, горят только 2 разряда, а ещё 2 последних не откликаются и даже при то, что задано чтобы они показывали 0123, они показывают 22 тупо и всё… Помогите начинающему прогерру

  • в выборе свитч писал сам под свои индикаторы и на таймере всё работало, этот блок можно не проверять все цифирки правильные. Если надо, то схему могу прислать.

  • Попробуйте так:
    interrupt [TIM1_COMPA] void timer1_compa_isr(void)
    {
    PORTB=0×00;
    switch(i)
    {
    case 0: n=n1;PORTB.0=1;i++; break;
    case 1: n=n2;PORTB.1=1;i++; break;
    case 2: n=n3;PORTB.2=1;i++; break;
    case 3: n=n4;PORTB.3=1;i=0; break;
    }
    switch(n)
    {
    case 0:{PORTD=0b10001000;break;}
    case 1:{PORTD=0b11101011;break;}
    case 2:{PORTD=0b01001100;break;}
    case 3:{PORTD=0b01001001;break;}
    case 4:{PORTD=0b00101011;break;}
    case 5:{PORTD=0b00011001;break;}
    case 6:{PORTD=0b00011000;break;}
    case 7:{PORTD=0b11001011;break;}
    case 8:{PORTD=0b00001000;break;}
    case 9:{PORTD=0b00001001;break;}
    }
    }

  • Всё равно не работает, лучше, но не работает… последние два разряда всё равно не горят…

  • тогда схему и прошивку целиком нужно смотреть, можете выложить на форуме, или на почту мне прислать

  • Роман, а у Вас 2й и 3й пины порта В объевлены, как выходы? Т.е. DDRB = 00001111, или DDRB = 0x0F, что-то такое есть? :-)

  • Ether, спасибо, попался я на простом :razz: :razz: :razz:

  • Нужна ещё помощь. На 4-ёх индикаторах мерцает на таких вот настройках таймера:// Timer/Counter 1 initialization
    // Clock source: System Clock
    // Clock value: 8000,000 kHz
    // Mode: Normal top=0xFFFF
    // OC1A output: Disconnected
    // OC1B output: Disconnected
    // Noise Canceler: Off
    // Input Capture on Falling Edge
    // Timer Period: 8,192 ms
    // Timer1 Overflow Interrupt: Off
    // Input Capture Interrupt: Off
    // Compare A Match Interrupt: On
    // Compare B Match Interrupt: Off
    TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
    TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
    TCNT1H=0x00;
    TCNT1L=0x00;
    ICR1H=0x00;
    ICR1L=0x00;
    OCR1AH=0x01;
    OCR1AL=0x04;
    OCR1BH=0x00;
    OCR1BL=0x00;
    Подскажите настройки чтобы пошустрее мигало(незаметно т.е.)

  • В генераторе кода поменяйте Mode: Normal top=0xFFFF на Mode: CTC top=OCR1A,

  • здравствуйте,подскажите пожалуйста…
    у меня такой вопрос — как вывести информацию на LCD и 7seg …
    точнее сказать так: хочу чтоб в схеме были два индикатора — один lcd другой 7seg,но чтоб информация выводилась (я делаю спидометр)скорость на 7seg ,а одометр и всякая другая информация на lcd(т.е. одометр)….
    я запутался и что то вообще не могу разобраться помогите с трудностями пожалуйста….

  • здравствуйте,подскажите пожалуйста…
    у меня такой вопрос — как вывести информацию на LCD и 7seg …
    точнее сказать так: хочу чтоб в схеме были два индикатора — один lcd другой 7seg,но чтоб информация выводилась (я делаю спидометр)скорость на 7seg ,а одометр и всякая другая информация на lcd(т.е. одометр)….
    я запутался и что то вообще не могу разобраться помогите с трудностями пожалуйста….буду длягодарен если скинете исходный код по этому делу…

  • какие проблемы, 3 урок вывод на LCD, урок 6.1 вывод на семисегментник статической индикацией. там и исходники и объяснение.

  • Спасибо разобрался,там я сам напутал в переменных…спасибо за ответ…

  • Добрый день,у меня такой вопрос как подключить и7seg индикатор к AVR через регистр сдвига и как им управлять…помогите разобрать…

  • про это будет статья в ближайшее время

  • спасибо за ответ,жду с нетерпением,уж сильно нужно так как ног порой маловато бывает…

  • Здравствуйте. Хочу собрать частотомер с динамической индикацией. Подскажите пожалуйста, как полученный результат разложить на разряды, чтобы потом его поочередно вывести на семисегментные индикаторы? Хотя бы просто подскажите в каком направлении двигаться… Заранее спасибо

  • i[0]= freq/1000; //тысячи
    i[1]= freq/100; //сотни
    i[2]= freq/10; //десятки
    i[3]= freq%10; //единицы

  • Подскажите, если в коде прерывания написать #asm(«sei») другие виды прерываний могут сработать в любой момент независимо прерывание завершилось или нет. Необходимо что бы одно прерывание не приоритетное не мешало другому более приоритетному.

  • Другие виды прерываний не сработают если они не настроены, если прерывания мешают друг другу, можно при входе в не приоритетное прерывание отключать остальные #asm(«cli»)

  • Подскажите, как разбить float на разряды(13,85 например)?
    Int разбиваю кодом ниже, а на float ругается.

    chislo = 5931; // это int
    ....
    number1=chislo%10; // 1ый разряд
    number2=(chislo%100)/10; // 2ой разряд
    number3=(chislo%1000)/100; // 3ий разряд
    number4=(chislo%10000)/1000; // 4ий разряд

    Спасибо!

  • num1 = result/10; //десятки
    num2 = result%10; //единицы
    num3 = ((float)result — (char)result)*10; //дробная часть, будет с небольшой погрешностью

  • а не подскажете. какие резисторы лучше всего использовать в данной схеме?

  • зависит от тока сегмента и питающего напряжения, если питание 5в и ток сегмента 20ма, то резистор нужен 5/0.02=250 ом, т.е 300 ом будет нормально

  • Здравствуйте
    Подскажите как посчитать переменную скажем за 5 секунд,и вывести среднее значение в другую переменную.
    Нужно создать задержку при которой выводилось на экран среденее значение а не бегали цифры хаотично.
    Спасибо

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

  • наверное не так написал,как подсчитать переменную за 5 секунд,и вывести среднее значение х+х+х+х+х/5

  • думаю я вас понял правильно, так что см. пред. ответ

  • а как написать этот код,или где посмотреть пример

  • таймеры вам в помощь http://avr-start.ru/?p=414

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

  • ….interrupt ….. // по прерыванию раз в секунду
    {
    if(sek < 5)
    {
    i[sek] = result;
    sek++;
    }
    else
    {
    mid = (i[0]+i[1]+i[2]+i[3]+i[4])/5;
    sek = 0;
    }
    }

  • Доброго времени суток.
    Все получилось, все работает… НО !

    У меня задача немного интересней: считать данные с АЦП. Взял ваш урок для примера по АЦП, но не смог вписаться в код…. Почти сутки просидел…

    Где вставить строку запроса с АЦП, чтоб потом она автоматом отработало..

    num=((5.00*adc_data[0])/1024.00);

  • там же в прерывании

  • ….interrupt ….. // по прерыванию раз в секунду
    {
    if(sek < 5)
    {
    i[sek] = result;
    sek++;
    }
    else
    {
    mid = (i[0]+i[1]+i[2]+i[3]+i[4])/5;
    sek = 0;
    }
    }

    что означает i и mid :sad:

  • i это временная переменная ,которая хранит значение результатов за 1,2,3 секунду, сделано в виде массива. mid — среднее

  • Здравствуйте, так а а где прошивка к данному проекту

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

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

  • Ув. Автор,
    В коде прошивки на Си есть директива #asm(sei). Я раньше писал на ассемблере под 8086, и там, насколько я помню, эта инструкция была sti (от англ. reSTore Interrupts). Это опечатка, или же язык ассемблера для микроконтроллеров AVR от такового для 8086?
    Заранее спасибо за ответ

  • Простите, язык отличается. Пропустил слово, с кем не бывает.

  • Отличается, можно в даташите посмотреть набор команд

  • Спасибо

  • Мне нужно написать программу для этой схемы
    http://vk.com/photo274168004_360830925
    Смысл в том, что я должен нажатием кнопок +- уменьшать и увеличивать значения показываемые на индикаторе. Но эти значения фиксированные.
    Вы не могли бы сказать мне правильно ли сделана схема.
    И, если не тяжело пример программы для нее.

  • Здравствуйте уважаемый админ)Простой вопрос. А можно ли в протеусе увидеть прерывание?(в виде изменения на осцилоскопе состояния порта ,если например в прерывании поставить порт на единицу?).Буду рад если вы ответите))

  • можно

  • Огромное спасибо за ваш сайт с обучением.
    По теме в Протеусе нужно использовать 2-х сегментный, или 4-х сегментный индикатор, тогда все заработает.

  • Здравствуйте, возникла такая ситуация, реализовал динамическую индикацию на PORTB как в первом уроке, применяя для переключения PORTC.0, PORTC.1 в протеусе работает замечательно , а на железе нет, подаю питание, коротко мерцают разряды и потухают, тактировал от внутреннего на 8МГц, от чего это может быть? Заранее благодарен.

  • Вот листинг:

    #include
    #include
    #asm
    .equ __w1_port=0x12 ;PORTD
    .equ __w1_bit=0
    #endasm
    #include
    #include

    int temper;
    int number = 0;
    int number1 = 0;
    int number2 = 0;
    int i=0;
    eeprom int final=0;

    interrupt [EXT_INT0] void ext_int0_isr(void)
    {

    }

    interrupt [EXT_INT1] void ext_int1_isr(void)
    {

    }

    // Timer 1 output compare A interrupt service routine
    interrupt [TIM1_COMPA] void timer1_compa_isr(void)
    {
    PORTC.0=0;
    PORTC.1=0;
    if(i==0)
    {
    number=number1;
    PORTC.1=1;
    i++;
    }
    else
    {
    number=number2;
    PORTC.0=1;
    i=0;
    }

    switch(number)
    {
    case 0:{PORTB=0xC0; break;}
    case 1:{PORTB=0xF9; break;}
    case 2:{PORTB=0xA4; break;}
    case 3:{PORTB=0xB0; break;}
    case 4:{PORTB=0x99; break;}
    case 5:{PORTB=0x92; break;}
    case 6:{PORTB=0x82; break;}
    case 7:{PORTB=0xF8; break;}
    case 8:{PORTB=0x80; break;}
    case 9:{PORTB=0x90; break;}
    }
    }

    void main(void)
    {
    float dT = 1.2;
    PORTB=0xC0;
    DDRB=0xFF;

    PORTC=0xFF;
    DDRC=0xFF;

    PORTD = 0x0C;
    DDRD = 0x80;

    TCCR1A=0x00;
    TCCR1B=0x0A;
    TCNT1H=0x00;
    TCNT1L=0x00;
    ICR1H=0x00;
    ICR1L=0x00;
    OCR1AH=0x10;
    OCR1AL=0x46;

    GICR|=0xC0;
    MCUCR=0x00;
    GIFR=0xC0;
    TIMSK=0x10;

    w1_init();
    // Global enable interrupts
    #asm(«sei»)

    while (1)
    {
    temper=ds18b20_temperature(0);
    if (temper>1000)
    {
    temper=4096.0-temper;
    temper=-temper;
    }

    number1= temper/10;
    number2= temper%10;
    delay_ms(1500);

    };
    }

  • это из за датчика температуры

  • Большое спасибо, буду разбираться…

  • Доброго дня ! Подскажите пожалуйста как быть с регистром сравнения если у меня задействовано 3 сегмента. С двумя по выше сказанным параметрам работает отлично, после добавления третьего индикаторы вообще не светятся, разве что в протеусе. Спасибо.

    третий сегмент добавил так :
    switch (i){
    case 0: number = n1; PORTC.0 = 1;i++;break;
    case 1: number = n2; PORTC.1 = 1;i++;break;
    case 2: number = n3; PORTC.2 = 1;i=0;break;
    }
    n1 = temper/100;
    n2 = (temper%100)/10;
    n3 = (temper%100)%10;

  • посчитайте частоту может недостаточно чтобы светилось, пройдитесь отладчиком

  • Здравствуйте! Вот решил попробывать себя в микроконторолерах. Решил собрать устройтво которое считает количество нажатий кнопок, одна кнопка инкрементирует другая декрементирует. вывожу на симесигментник. проблема вот в чем: как связать внешнее прерывание по нажатию кнопки и вывод на симесигментик с моей програмой?
    код:
    #include
    #include // for putsf
    #include
    #define ISC10 2
    #define ISC11 3
    #define INT1 7
    unsigned char int1 = 0;

    int i=0;
    int k=0;
    int l=0;
    int m=0;
    int rezUHH=0;
    int rezUH=0;
    int rezUL=0;
    int rezULL=0;

    //##########################################################
    //# Подпрограммы
    //##########################################################

    void display(int ind_tabl, int point)
    {
    if (point==0)
    {
    switch (ind_tabl)
    {
    case 0 : PORTD = 0b11111010; break;
    case 1 : PORTD = 0b10000010; break;
    case 2 : PORTD = 0b10111001; break;
    case 3 : PORTD = 0b10101011; break;
    case 4 : PORTD = 0b11000011; break;
    case 5 : PORTD = 0b01101011; break;
    case 6 : PORTD = 0b01111011; break;
    case 7 : PORTD = 0b10100010; break;
    case 8 : PORTD = 0b11111011; break;
    case 9 : PORTD = 0b11101011; break;
    }
    }
    if (point==1)
    {
    switch (ind_tabl)
    {
    case 0 : PORTD = 0b11111110; break;
    case 1 : PORTD = 0b10000110; break;
    case 2 : PORTD = 0b10111101; break;
    case 3 : PORTD = 0b10101111; break;
    case 4 : PORTD = 0b11000111; break;
    case 5 : PORTD = 0b01101111; break;
    case 6 : PORTD = 0b01111111; break;
    case 7 : PORTD = 0b10100110; break;
    case 8 : PORTD = 0b11111111; break;
    case 9 : PORTD = 0b11101111; break;
    }
    }
    }

    //##########################################################
    //# Обработка прерываний
    //##########################################################

    // Прерывание по совпадению T1 с OCR1A f=300 Hz (75 Hz)
    interrupt [TIM1_COMPA] void T1_CompareA (void)
    { int rez=0;
    i++;
    if (i==1)
    {
    PORTB.7 = 0;
    PORTB.2 = 1;
    display(rezUHH, 0);
    }
    if (i==2)
    {
    PORTB.2 = 0;
    PORTB.1 = 1;
    display(rezUH, 1);
    }
    if (i==3)
    {
    PORTB.1 = 0;
    PORTB.0 = 1;
    display(rezUL, 0);
    }
    if (i==4)
    {
    PORTB.0 = 0;
    PORTB.7 = 1;
    display(rezULL, 0);
    i = 0;
    }

    {}
    rez = (ADCW*5)/2;

    rezUHH = rez/1000;
    rezUH = (rez/100)%10;
    rezUL = (rez/10)%10;
    rezULL = rez%10;
    }

    //##########################################################
    //# Инициализация
    //##########################################################

    void initialization(void)
    {

    // Ин-ция таймеров
    TCNT0=0x00;
    // T1:
    TCCR1A=0b00000000; // Включаем перывй тамер с предделителем на
    TCCR1B=0b00001010; // 8 (f T1 = 8 000 000 / 8 = 1 000 000 Hz)
    TCNT1H=0x00; // Обнуляем содержимое таймера
    TCNT1L=0x00; // Обнуляем содержимое таймера
    OCR1AH=0x0D; // Устанавливаем OCR1A в 0x0D04 (2 222 — 1)
    OCR1AL=0x04;
    OCR1BH=0x00;
    OCR1BL=0x00;
    TIMSK=0b00010000;
    // T3:
    ASSR=0x00;
    //определяем биты регистров
    // Внешие прерывания
    //INT0;
    //INT1;
    MCUCR=0x00;

    // Ин-ция портов
    DDRB=0xFF; // Порт В — выход
    PORTB=0x00;
    DDRC=0b11111110; // Порт С — выход
    PORTC=0x00;
    DDRD=0xFF; // Порт D — выход
    PORTD=0x00;

    #asm(«sei»)
    }

    //##########################################################
    //# Тело основной программы
    //##########################################################

    void main (void)
    {

    initialization();
    sei();//устанавливаем бит глобального разрешения прерывани
    // Бесконечный цикл
    Идея в том что: при нажатии одной кнопки ждем вторую кнопку и потом инкрементируем а при нажатии второй ждем первую и декриментируем. Часть кода в вайл(ниже) просто как пример идеи вместо портов должны каак я понимаю быть внешние прерывания. Но блин! Я ничего стоящего не нашел по инфе .как это все обьединить . Помогите новичку! Извиняюсь если вопрос уж шибко большой.
    while (1){
    M1:
    if (PORTB.3==1)

    { while(1)

    if(PORTB.4==1)

    {k++;
    goto M1; }
    if(l=2000){l=0; goto M1;}}}
    if (PORTB.4==1)
    { while(1)
    {m++;
    if(PORTB.3==1)

    {k++;
    m=0; goto M1; }
    if(m=2000){m=0; goto M1;}}}}

  • не увидел обработчика внешнего прерывания

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

    /*****************************************************
    Автор программы :

    Project : Реализация шины I2C (TWI)_Master
    Version :
    Date :
    Author :
    Company :
    Comments:

    Chip type : ATmega8
    Program type : Application
    AVR Core Clock frequency: 8,000000 MHz
    Memory model : Small
    External RAM size : 0
    Program size : x bytes
    *****************************************************/

    #include
    #include // for putsf
    #include
    #include

    unsigned int i=0;
    unsigned int k=0;
    unsigned int l=0;
    unsigned int m=0;

    //##########################################################
    //# Подпрограммы
    //##########################################################

    void display(unsigned int ind_tabl)
    {
    switch (ind_tabl)
    {
    case 0 : PORTD = 0b11111010; break;
    case 1 : PORTD = 0b10000010; break;
    case 2 : PORTD = 0b10111001; break;
    case 3 : PORTD = 0b10101011; break;
    case 4 : PORTD = 0b11000011; break;
    case 5 : PORTD = 0b01101011; break;
    case 6 : PORTD = 0b01111011; break;
    case 7 : PORTD = 0b10100010; break;
    case 8 : PORTD = 0b11111011; break;
    case 9 : PORTD = 0b11101011; break;
    }
    }

    //##########################################################
    //# Обработка прерываний
    //##########################################################

    // Прерывание по совпадению T1 с OCR1A f=300 Hz (75 Hz)
    interrupt [TIM1_COMPA] void T1_CompareA (void)
    { unsigned int rez=0;
    i++;
    if (i==1)
    {
    PORTB.0 = 0;
    PORTB.2 = 1;
    display(0);
    }
    if (i==2)
    {
    PORTB.2 = 0;
    PORTB.1 = 1;
    rez = k/10;
    display(rez);
    }
    if (i==3)
    {
    PORTB.1 = 0;
    PORTB.0 = 1;
    rez = k%10;
    display(rez);
    i = 0;
    }

    }

    //##########################################################
    //# Инициализация
    //##########################################################

    void initialization(void)
    {

    // Ин-ция таймеров
    TCNT0=0x00;
    // T1:
    TCCR1A=0b00000000; // Включаем перывй тамер с предделителем на
    TCCR1B=0b00001010; // 8 (f T1 = 8 000 000 / 8 = 1 000 000 Hz)
    TCNT1H=0x00; // Обнуляем содержимое таймера
    TCNT1L=0x00; // Обнуляем содержимое таймера
    OCR1AH=0x0D; // Устанавливаем OCR1A в 0x0D04 (2 222 — 1)
    OCR1AL=0x04;
    OCR1BH=0x00;
    OCR1BL=0x00;
    TIMSK=0b00010000;
    // T3:
    ASSR=0x00;
    //определяем биты регистров

    // Внешие прерывания
    //INT0;
    //INT1;
    MCUCR=0x00;

    // Ин-ция портов
    DDRB=0xFF; // Порт В — выход
    PORTB=0x00;
    DDRC=0b11111001; // Порт С — выход
    PORTC=0x00;
    DDRD=0xFF; // Порт D — выход
    PORTD=0x00;

    #asm(«sei»)
    }

    //##########################################################
    //# Тело основной программы
    //##########################################################

    void main (void)
    {

    initialization();

    while (1)
    {
    M1:
    if (PINC.1==1)
    {while(1)
    {
    if(PINC.2==1)
    {
    if (k0) k—;
    goto M1;
    }
    //if(m=2000) { m=0; goto M1;}
    }
    }
    }

    извиняюсь если забиваю коменты) :oops:

  • void main (void)
    {

    initialization();

    while (1)
    {
    M1:
    if (PINC.1==1)
    {while(1)
    {
    if(PINC.2==1)
    {
    if (k0) k—;
    goto M1;
    }
    //if(m=2000) { m=0; goto M1;}
    }
    }
    }

    обрезало)

  • https://drive.google.com/file/d/0B6Jn0dae8wjbd1pHRTZuMmR2V0U/view?usp=sharing

    извиняюсь раньше не додумался :oops: в коментах режет последнею часть

  • Я не понял вообще логики, по идее есть 2 датчика, логично разместить их один у самого выхода, другой чуть вглубь кухни. Тогда появится 2 основных возможных варианта: вначале размыкается датчик 1, потом датчик 2 — это когда кто то вошел в кухню. Вариант 2 сначала размыкается датчик 2, а потом датчик 1 — значит кто то ушел. Собственно остается обработать эти 2 состояния. Для этого нужно 2 флага, для каждого датчика и одна переменная, которая по этим флагам изменяется.

  • описано выше вами правильно, но есть одно но ! я сколько не мучился , ничего не получается как вы сказали 2 состояния не обрабатываются, обрабатывается только одно: когда ктото вошел он считает все впорядке + , а на выход тобишь -минус 1, шишь ! уж как хочешь я этот код переделывал с флагами без флагов . Если есть пример похожий или где почитать о подобном, буду благодарен , я сам только начал изучать си. Вот и спрашиваю. Примеров просто не нашел, сам по логике пытаюсь докумекать(

  • Первое что в голову пришло

    ext_interrupt1()
    {
    if(flag2 == 1)
    {
    peoples++;
    flag1 = 0;
    flag2 = 0;
    }
    else
    flag1 = 1;
    }

    ext_interrupt2()
    {
    if(flag1 == 1)
    {
    peoples--;
    flag1 = 0;
    flag2 = 0;
    }
    else
    flag2 = 1;
    }

  • спасибо :wink:

  • Здравствуйте! При написании программы для вольтметра-амперметра, столкнулся с тем, что не отображаются единицы ампер на втором дисплее, Скриншот в Proteus.
    Быть может таймер в этом виноват?

  • лучше проект целиком с протеусом

  • как увеличиваете ток?

  • Изменяя сопротивление лампочки.

  • посмотрел Ваш проект, у Вас подцеплен внешний кварц к ноге PB6 и эта же нога пытается управлять индикацией. Ставишь на внутренний генератор и все ок.

  • Таки проглядел) Благодарю!

  • админ подскажите что не так,к тини2313 подключил 4 семисег. индикатора, частототу для них выбрал 120гц, таймер работает на 4мгц, 4.000.000/480=8333 или 208D, записал в регистр OCR1BH=0x20
    OCR1BL=0x8D
    фьюзы стоят
    CKSEL0, CKSEL2,CKSEL3, SUT0, но они все равно очень сильно мерцают, как можно исправить?

  • OCR1BH=0x02

  • Здравствуйте, помогите пожалуйста советом, если можно хоть как-то предположить от чего так происходит и в каком направлении мыслить, при включении датчик прерывисто возвращает не те значения, показания скачут то 999 то вообще сбрасывается в 0 потом текущая температура, и так по кругу, помех шины никаких нет.Поменял 2 датчика, разницы никакой. Всю голову «сломал». :neutral:

  • Извиняюсь, если не в ту тему написал (индикация динамическая, датчик DS18b20)

  • сделайте разрешение датчика меньше

  • Не помогло :sad:

  • К тому же еще обнаружил, что протеус выдает тоже самое, сделал вывод, что что-то с кодом, но не пойму где ошибка ..

  • проблема в том, что прерывание останавливает измерения датчика.

  • А как можно реализовать, чтобы этого не происходило ?

  • Может измерять как-то в прерывании ?

  • В CVAVR есть такая бяка. Когда работает библа датчика, то она запрещает прерывания на период отцифровки температуры. Я смотрел в недрах ее функций и нашел там паузу в 750 мс. Отсюда возникают мерцания при динамической индикации. А вот если приходят кривые параметры, то скорее всего это железо. Либо не правильно собрана схема, либо повесили датчик на ногу с кокой-то периферией. Внимательно осмотрите схему. А и вот еще. Данная шина очень требовательна к временным задержкам. Проверьте правильность выбора частоты тактования с реальными значениями. Есть подозрения что собака порыта именно тут.

  • Алексей, большое спасибо за ответ !
    В общем удалил все ненужное, добавил задержку в цикле на 500 ms, при этом данные исправно отображаются, нашел косяк — нужно при некоторой температуре выставлять на ножке лог 1 ( подключено реле ). Так вот при добавлении проверки сразу возникает «мерцание». Не пойму… :cry:

    temper = ds18b20_temperature(0);

    n1 = (temper%100)%10;
    n2 = (temper%100)/10;
    n3 = temper/100;
    delay_ms(500);

    if (temper >= (float)final){PORTD.7 = 0;}
    else if (temper <= ((float)final)-dT){PORTD.7 = 1;}

  • Скорее всего приведение к float влияет, попробуйте убрать и посмотреть на результат

  • А зачем вообще в float приводить? Функция температуру возвращает в int. Ее нужно делить на 10.

  • Без перевода тоже также никаких изменений

  • тогда смотрите что у вас там по схеме на PD7, проблема очевидно в железе

  • Всем огромнейшее спасибо ! Проблема оказалась на порту, впаял светодиод вместо ключа работает как часики :smile: буду мудрить дальше )

  • ULN2003 в помощь. :razz:

  • Здравствуйте. А как выводить точку???

  • хоть отдельной ногой, хоть динамически

  • а подробней можно? пример какой-то

  • так что на счет примера? как организовать вывод точки на порту PORTD.7?

  • не понимаю вашей проблемы, точка тот же светодиод, PORTD.7=1, вам такой нужен пример? или в чем вопрос?

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

  • не ленимся читаем самый первый урок

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Свежие записи
Последние комментарии
  • Загрузка...
Архивы
Счетчик
Яндекс.Метрика