Обявления

Для полноценной работы рекомендуется пройти регистрацию.

Рекламные сообщения будут удаляться вместе с пользователем. Что есть реклама - буду решать я.

Динамическая индикация

Обсуждение проектов, не вошедших в предыдущие категории

Динамическая индикация

Сообщение Denis_K » 05 окт 2018 13:14

Пытаюсь написать код для таймера под свои нужды, но никак не выходит с индикацией... Разряды не перебираются по одному, а меняются сразу три цифры...
Например: пишу на вывод число 123, а выводится сначала 1, затем 2 и потом 3 на трех разрядах(111 >> 222 >> 333), все это зациклено. Хотя по задумке :) должно быть 1 в первом разряде, 2 во втором и 3 в третьем с числом на выходе 123. Что я делаю не так?

Добавлено спустя 3 часа 16 минут 17 секунд:
Вот код без скачивания...


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

#define F_CPU 8000000L

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

unsigned int i;
unsigned int R1=0, R2=0, R3=0;

void segchar (unsigned int seg)
{
   switch(seg)
   {
      case 1: PORTC = 0b11011111;                                       //PC1
              PORTB = 0b11110111;
      break;
      case 2: PORTC = 0b11011101;
              PORTB = 0b11011100;
      break;                                           //PC2                           //PC5
      case 3: PORTC = 0b11011101;
              PORTB = 0b11010101;
      break;
      case 4: PORTC = 0b11011011;
              PORTB = 0b11010111;
      break;                                                         //PB5
      case 5: PORTC = 0b11111001;
              PORTB = 0b11010101;
      break;
      case 6: PORTC = 0b11111001;
              PORTB = 0b11010100;
      break;                                        //PB0                           //PB3
      case 7: PORTC = 0b11011101;
              PORTB = 0b11110111;
      break;
      case 8: PORTC = 0b11011001;
              PORTB = 0b11010100;
      break;                                                      //PB1
      case 9: PORTC = 0b11011001;
              PORTB = 0b11010101;
      break;
      case 0: PORTC = 0b11011001;
              PORTB = 0b11110101;
      break;
   }   
}

void timer_ini(void)
{   
   TCCR1B |= (1<<WGM12);
   TIMSK1 |= (1<<OCIE1A);   
   OCR1AH = 0b00001111;
   OCR1AL = 0b00001010;
   TCCR1B |= (1<<CS12);
}

unsigned int n_count=0;

ISR (TIMER1_COMPA_vect)
{   
    if(n_count==0) {PORTC|=(1<<PORTC0);PORTC&=~(1<<PORTC3);PORTC&=~(1<<PORTC4);segchar(R1);}      
   if(n_count==1) {PORTC|=(1<<PORTC3);PORTC&=~(1<<PORTC4);PORTC&=~(1<<PORTC0);segchar(R2);}      
   if(n_count==2) {PORTC|=(1<<PORTC4);PORTC&=~(1<<PORTC0);PORTC&=~(1<<PORTC3);segchar(R3);}
      
   n_count++;
   if (n_count>2) n_count=0;
}

void ledprint(unsigned int number)
{   
   R1=number/100;         
   R2=(number%100)/10;     
   R3=(number%100)%10;    
}

int main(void)
{
   unsigned int butcount=0, butstate=0;
   timer_ini();
   DDRD = 0b00010000;
   DDRB = 0b11111111;
   DDRC = 0b11111111;
   PORTD = 0b00100000;
   PORTC = 0b11100110;
   PORTB = 0b11111111;
   i=0;
   sei();
   ledprint(123);
   
   while(1)
   {      
   }
   }
Вложения
main.rar
(935 байт) Скачиваний: 15
Denis_K
Частенько бываю
 
Сообщения: 81
Зарегистрирован: 16 июн 2017 13:48
Откуда: Краснодарский край

Re: Динамическая индикация

Сообщение IYra » 06 окт 2018 13:23

Denis_K писал(а): Вот код без скачивания...

1. В коде желательно больше комментариев. Особенно там где настраивается таймер.

2. Еще хорошо бы нарисовать модель в Протеусе и пройтись с отладчиком
IYra
Живу тут
 
Сообщения: 695
Зарегистрирован: 01 фев 2012 19:36
Откуда: Санкт-Петербург

Re: Динамическая индикация

Сообщение Denis_K » 06 окт 2018 15:03

IYra, здравствуйте. Я бы с радостью воспользовался отладчиком, но к сожалению еще не научился им пользоваться :) А модель нарисованная есть...
Вот прокомментировал код:
Код: Выделить всё

#define F_CPU 8000000L

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

unsigned int i;
unsigned int R1=0, R2=0, R3=0;  // переменные разрядов

void segchar (unsigned int seg) // формирование цифры
{
   switch(seg) // сегменты находятся на портС и портВ
   {
      case 1: PORTC = 0b11011111;      //1                                 
              PORTB = 0b11110111;
      break;
      case 2: PORTC = 0b11011101;      //2
              PORTB = 0b11011100;
      break;                                           
      case 3: PORTC = 0b11011101;      //3
              PORTB = 0b11010101;
      break;
      case 4: PORTC = 0b11011011;      //4
              PORTB = 0b11010111;
      break;                                                         
      case 5: PORTC = 0b11111001;      //5
              PORTB = 0b11010101;
      break;
      case 6: PORTC = 0b11111001;      //6
              PORTB = 0b11010100;
      break;                                       
      case 7: PORTC = 0b11011101;      //7
              PORTB = 0b11110111;
      break;
      case 8: PORTC = 0b11011001;      //8
              PORTB = 0b11010100;
      break;                                                     
      case 9: PORTC = 0b11011001;      //9
              PORTB = 0b11010101;
      break;
      case 0: PORTC = 0b11011001;      //0
              PORTB = 0b11110101;
      break;
   }
}

void timer_ini(void)
{   
   TCCR1B |= (1<<WGM12);   // устанавливаем режим СТС
   TIMSK1 |= (1<<OCIE1A);  // разрешаем прерывания Т1   
   OCR1AH = 0b00001111;    // число для сравнения
   OCR1AL = 0b01000010;
   TCCR1B |= (1<<CS12);    // устанавливаем делитель
}

unsigned int n_count=0;

ISR (TIMER1_COMPA_vect) // вход в прерывание Т1
{   
    if(n_count==0) {PORTC|=(1<<PORTC0);PORTC&=~(1 <<PORTC3);PORTC&=~(1<<PORTC4);segchar(R1);}    // включаем первый разряд
   if(n_count==1) {PORTC|=(1<<PORTC3);PORTC&=~(1<<PORTC4);PORTC&=~(1<<PORTC0);segchar(R2);}    // включаем второй разряд   
   if(n_count==2) {PORTC|=(1<<PORTC4);PORTC&=~(1<<PORTC0);PORTC&=~(1<<PORTC3);segchar(R3);} // включаем третий разряд
      
   n_count++;
   if (n_count>2) n_count=0; // переключаем разряды 0,1,2
}

void ledprint(unsigned int number)
{   
   R1=number/100;          // сотни
   R2=(number%100)/10;     // десятки
   R3=(number%100)%10;       // единицы
}

int main(void)
{
   timer_ini();         // инициализация таймера
   DDRD = 0b00010000;   // установка портов на выход
   DDRB = 0b11111111;
   DDRC = 0b11111111;
   PORTD = 0b00100000;
   PORTC = 0b11100110;
   PORTB = 0b11111111;
   i=0;
   sei();               // разрешение прерываний
   ledprint(123);       // вывод числа 123
   
   while(1)
    {   
      
       }
   }
Denis_K
Частенько бываю
 
Сообщения: 81
Зарегистрирован: 16 июн 2017 13:48
Откуда: Краснодарский край

Re: Динамическая индикация

Сообщение IYra » 06 окт 2018 15:06

Denis_K писал(а): А модель нарисованная есть...

Ну так выкладывай - посмотрим
IYra
Живу тут
 
Сообщения: 695
Зарегистрирован: 01 фев 2012 19:36
Откуда: Санкт-Петербург

Re: Динамическая индикация

Сообщение Denis_K » 06 окт 2018 15:13

Вот модель

Добавлено спустя 2 часа 14 минут 9 секунд:
Попробовал так:
Код: Выделить всё
ISR (TIMER1_COMPA_vect)
{   
   
   
    if(n_count==0) {PORTC|=(1<<PORTC0);PORTC&=~(1<<PORTC3);PORTC&=~(1<<PORTC4);segchar(ledprint(R1));}      
   if(n_count==1) {PORTC|=(1<<PORTC3);PORTC&=~(1<<PORTC4);PORTC&=~(1<<PORTC0);segchar(ledprint(R2));}      
   if(n_count==2) {PORTC|=(1<<PORTC4);PORTC&=~(1<<PORTC0);PORTC&=~(1<<PORTC3);segchar(ledprint(R3));}
      
   n_count++;
   if (n_count>2) n_count=0;
}

Теперь переключаются разряды, но как то раз через два... может тут лучше применить switch? я уже запутался...
Вложения
TOO_48.rar
(55.63 КБ) Скачиваний: 16
Denis_K
Частенько бываю
 
Сообщения: 81
Зарегистрирован: 16 июн 2017 13:48
Откуда: Краснодарский край

Re: Динамическая индикация

Сообщение IYra » 06 окт 2018 17:53

Denis_K писал(а):
Код: Выделить всё
ISR (TIMER1_COMPA_vect)
{   
    if(n_count==0) {PORTC|=(1<<PORTC0);PORTC&=~(1<<PORTC3);PORTC&=~(1<<PORTC4);segchar(ledprint(R1));}      
   if(n_count==1) {PORTC|=(1<<PORTC3);PORTC&=~(1<<PORTC4);PORTC&=~(1<<PORTC0);segchar(ledprint(R2));}      
   if(n_count==2) {PORTC|=(1<<PORTC4);PORTC&=~(1<<PORTC0);PORTC&=~(1<<PORTC3);segchar(ledprint(R3));}
      
   n_count++;
   if (n_count>2) n_count=0;
}


1. Что-то с таймером. Прерывание срабатывает каждые 130 мс. А должно максимум 10 мс. Надо уменьшать
2. Собери без оптимизации. В файле с расширением elf(отладочный) прочерки
IYra
Живу тут
 
Сообщения: 695
Зарегистрирован: 01 фев 2012 19:36
Откуда: Санкт-Петербург

Re: Динамическая индикация

Сообщение Denis_K » 06 окт 2018 19:56

1) Делитель в настройке таймера я умышленно увеличил, что бы визуально наблюдать смену разрядов, т.к. таймер уже полностью собранный :) .
При уменьшении времени все три цифры сливаются в "8".
2)Собрал без оптимизации, все тоже самое, только размер вырос с 2кб до 4кб...

Добавлено спустя 28 минут 16 секунд:
Почему-то вот здесь if(n_count==0) {PORTC|=(1<<PORTC0);PORTC&=~(1<<PORTC3);PORTC&=~(1<<PORTC4);segchar(ledprint(R1));} не тухнут РС3 и РС4... все три разряда постоянно включены.

Добавлено спустя 14 часов 22 минуты 17 секунд:
Выяснилось, что при использовании одного портВ для вывода цифр - все работает, только комбинирую с портС, то разряды не переключаются...
Применил маску для портС:
Код: Выделить всё
switch(seg)
   {
      case 1: PORTC ^= 0b00100000;                                       
                 PORTB = 0b11110111;
      break;
      case 2: PORTC ^= 0b00100010;
                 PORTB = 0b11011100;
      break;                                                                   
      case 3: PORTC ^= 0b00100010;
                 PORTB = 0b11010101;
      break;
      case 4: PORTC ^= 0b00100100;
                 PORTB = 0b11010111;
      break;                                                       
      case 5: PORTC ^= 0b00000110;
                 PORTB = 0b11010101;
      break;
      case 6: PORTC ^= 0b00000110;
                 PORTB = 0b11010100;
      break;                                                                   
      case 7: PORTC ^= 0b00100010;
                 PORTB = 0b11110111;
      break;
      case 8: PORTC ^= 0b00100110;
                 PORTB = 0b11010100;
      break;                                                     
      case 9: PORTC ^= 0b00100110;
                 PORTB = 0b11010101;
      break;
      case 0: PORTC ^= 0b00100110;
                 PORTB = 0b11110101;
      break;
   }

но теперь не правильно загораются сегменты... :(
Denis_K
Частенько бываю
 
Сообщения: 81
Зарегистрирован: 16 июн 2017 13:48
Откуда: Краснодарский край

Re: Динамическая индикация

Сообщение IYra » 07 окт 2018 12:48

Denis_K писал(а):Почему-то вот здесь if(n_count==0) {PORTC|=(1<<PORTC0);PORTC&=~(1<<PORTC3);PORTC&=~(1<<PORTC4);segchar(ledprint(R1));} не тухнут РС3 и РС4... все три разряда постоянно включены.


Функция segchar() устанавливает все в 1
case 1: PORTC = 0b11011111; //1
PORTB = 0b11110111;
поэтому 0 нужно устанавливать побитово
PORTC&=~(1<<PORTC5);
IYra
Живу тут
 
Сообщения: 695
Зарегистрирован: 01 фев 2012 19:36
Откуда: Санкт-Петербург

Re: Динамическая индикация

Сообщение Denis_K » 07 окт 2018 14:29

Спасибо, IYra. Я поздно до этого дошел :) ...
Сделал так:
Код: Выделить всё
switch(seg)
   {
      case 1: PORTC&=~(1<<PORTC5);                                       
              PORTB&=~(1<<PORTB3);
      break;
      case 2: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC5);
            PORTB&=~(1<<PORTB0);
            PORTB&=~(1<<PORTB1);
              PORTB&=~(1<<PORTB5);
      break;                                                                   
      case 3: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC5);
            PORTB&=~(1<<PORTB1);
            PORTB&=~(1<<PORTB3);
            PORTB&=~(1<<PORTB5);
      break;
      case 4: PORTC&=~(1<<PORTC2);
              PORTC&=~(1<<PORTC5);
              PORTB&=~(1<<PORTB3);
              PORTB&=~(1<<PORTB5);
      break;                                                       
      case 5: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC2);
              PORTB&=~(1<<PORTB1);
              PORTB&=~(1<<PORTB3);
              PORTB&=~(1<<PORTB5);
      break;
      case 6: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC2);
              PORTB&=~(1<<PORTB0);
              PORTB&=~(1<<PORTB1);
              PORTB&=~(1<<PORTB3);
            PORTB&=~(1<<PORTB5);
      break;                                                           
      case 7: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC5);
              PORTB&=~(1<<PORTB3);
      break;
      case 8: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC2);
              PORTC&=~(1<<PORTC5);
              PORTB&=~(1<<PORTB0);
              PORTB&=~(1<<PORTB1);
              PORTB&=~(1<<PORTB3);
              PORTB&=~(1<<PORTB5);
      break;                                                   
      case 9: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC2);
              PORTC&=~(1<<PORTC5);
              PORTB&=~(1<<PORTB1);
              PORTB&=~(1<<PORTB3);
              PORTB&=~(1<<PORTB5);
      break;
      case 0: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC2);
              PORTC&=~(1<<PORTC5);
              PORTB&=~(1<<PORTB0);
              PORTB&=~(1<<PORTB1);
              PORTB&=~(1<<PORTB3);
      break;
   }

Но теперь если в ledprint(111) или ledprint(555) и т.д., то индикация работает нормально, а если ledprint(123), то первую цифру выводит, а последующие - каша из сегментов...

Добавлено спустя 46 минут 32 секунды:
Файл .elf
Вложения
TOOmega48_2.rar
(3.93 КБ) Скачиваний: 15
Denis_K
Частенько бываю
 
Сообщения: 81
Зарегистрирован: 16 июн 2017 13:48
Откуда: Краснодарский край

Re: Динамическая индикация

Сообщение IYra » 07 окт 2018 16:12

Denis_K писал(а):Но теперь если в ledprint(111) или ledprint(555) и т.д., то индикация работает нормально, а если ledprint(123), то первую цифру выводит, а последующие - каша из сегментов...

Перед тем как устанавливать сегменты их нужно все очистить(то есть установить еденичку)
PORTC|=(1<<PORTC1);
PORTB|=(1<<PORTB3); и т.д.

И для отладки нужен main.c и .elf
IYra
Живу тут
 
Сообщения: 695
Зарегистрирован: 01 фев 2012 19:36
Откуда: Санкт-Петербург

Re: Динамическая индикация

Сообщение Denis_K » 07 окт 2018 16:38

Добавлено спустя 5 минут 3 секунды:
Вот настройки портов:
Код: Выделить всё
DDRD = 0b00010000;
   DDRB = 0b111111;
   DDRC = 0b1111111;
   PORTD = 0b00100000;
   PORTC = 0b1111111;
   PORTB = 0b111111;

Вроде бы все соответствует... на разрядах не стал выставлять "0" из- за обратного напряжения на сегментах...
Вложения
TOO.rar
(4.75 КБ) Скачиваний: 14
Denis_K
Частенько бываю
 
Сообщения: 81
Зарегистрирован: 16 июн 2017 13:48
Откуда: Краснодарский край

Re: Динамическая индикация

Сообщение IYra » 07 окт 2018 17:28

IYra писал(а):
Denis_K писал(а):Но теперь если в ledprint(111) или ledprint(555) и т.д., то индикация работает нормально, а если ledprint(123), то первую цифру выводит, а последующие - каша из сегментов...

Перед тем как устанавливать сегменты их нужно все очистить(то есть установить еденичку)
PORTC|=(1<<PORTC1);
PORTB|=(1<<PORTB3); и т.д.

Не точно выразился. Каждый раз !!!
То есть в начале функции segchar() надо чистить все сегменты
PORTC|=(1<<PORTC1);
PORTB|=(1<<PORTB3); и т.д.
а уж потом рисовать новое.
Или для каждой цифры чистить только свое (так будет быстрее выполняться)
IYra
Живу тут
 
Сообщения: 695
Зарегистрирован: 01 фев 2012 19:36
Откуда: Санкт-Петербург

Re: Динамическая индикация

Сообщение Denis_K » 07 окт 2018 18:22

IYra, спасибо! Получилось!
Написал так:
Код: Выделить всё
switch(seg)
   {
      case 1: PORTC&=~(1<<PORTC5);                                       
              PORTB&=~(1<<PORTB3);
         
            PORTC|=(1<<PORTC1);
            PORTC|=(1<<PORTC2);
            PORTB|=(1<<PORTB5);
            PORTB|=(1<<PORTB0);
            PORTB|=(1<<PORTB1);
            PORTB|=(1<<PORTB2);
            
            
      break;
      case 2: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC5);
            PORTB&=~(1<<PORTB0);
            PORTB&=~(1<<PORTB1);
              PORTB&=~(1<<PORTB5);
            
            PORTC|=(1<<PORTC2);
            PORTB|=(1<<PORTB3);
            
      break;                                                                   
      case 3: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC5);
            PORTB&=~(1<<PORTB1);
            PORTB&=~(1<<PORTB3);
            PORTB&=~(1<<PORTB5);
            
            PORTC|=(1<<PORTC2);
            PORTB|=(1<<PORTB0);
            
      break;
      case 4: PORTC&=~(1<<PORTC2);
              PORTC&=~(1<<PORTC5);
              PORTB&=~(1<<PORTB3);
              PORTB&=~(1<<PORTB5);
            
            PORTC|=(1<<PORTC1);
            PORTB|=(1<<PORTB0);
            PORTB|=(1<<PORTB1);
            
      break;                                                       
      case 5: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC2);
              PORTB&=~(1<<PORTB1);
              PORTB&=~(1<<PORTB3);
              PORTB&=~(1<<PORTB5);
            
            PORTC|=(1<<PORTC5);
            PORTB|=(1<<PORTB0);
            
      break;
      case 6: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC2);
              PORTB&=~(1<<PORTB0);
              PORTB&=~(1<<PORTB1);
              PORTB&=~(1<<PORTB3);
            PORTB&=~(1<<PORTB5);
            
            PORTC|=(1<<PORTC5);
            
      break;                                                           
      case 7: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC5);
              PORTB&=~(1<<PORTB3);
            
            PORTC|=(1<<PORTC2);
            PORTB|=(1<<PORTB5);
            PORTB|=(1<<PORTB2);
            PORTB|=(1<<PORTB0);
            PORTB|=(1<<PORTB1);
            
      break;
      case 8: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC2);
              PORTC&=~(1<<PORTC5);
              PORTB&=~(1<<PORTB0);
              PORTB&=~(1<<PORTB1);
              PORTB&=~(1<<PORTB3);
              PORTB&=~(1<<PORTB5);
            
      break;                                                   
      case 9: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC2);
              PORTC&=~(1<<PORTC5);
              PORTB&=~(1<<PORTB1);
              PORTB&=~(1<<PORTB3);
              PORTB&=~(1<<PORTB5);

            PORTB|=(1<<PORTB0);
            
      break;
      case 0: PORTC&=~(1<<PORTC1);
              PORTC&=~(1<<PORTC2);
              PORTC&=~(1<<PORTC5);
              PORTB&=~(1<<PORTB0);
              PORTB&=~(1<<PORTB1);
              PORTB&=~(1<<PORTB3);
            
            PORTB|=(1<<PORTB5);

      break;
   }
Denis_K
Частенько бываю
 
Сообщения: 81
Зарегистрирован: 16 июн 2017 13:48
Откуда: Краснодарский край

Re: Динамическая индикация

Сообщение Denis_K » 29 окт 2018 01:31

Дошел до такого кода
Код: Выделить всё
#define F_CPU 8000000L

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

unsigned char R1=0, R2=0, R3=0;
unsigned int number = 0;
char dr = 0;
volatile unsigned char napravlenie;
char dubllpush = 0;
unsigned int min = 0;
unsigned char sec = 0;
unsigned char n_count=0;

void segchar (unsigned int seg)    //цифры для индикации
{
   switch(seg)
   {
      case 0:
      PORTC&=~(1<<PORTC1);
      PORTC&=~(1<<PORTC2);
      PORTC&=~(1<<PORTC5);
      PORTB&=~(1<<PORTB0);
      PORTB&=~(1<<PORTB1);
      PORTB&=~(1<<PORTB3);
      
      PORTB|=(1<<PORTB5);
      break;
      
      case 1:
      PORTC&=~(1<<PORTC5);
      PORTB&=~(1<<PORTB3);
      
      PORTC|=(1<<PORTC1);
      PORTC|=(1<<PORTC2);
      PORTB|=(1<<PORTB5);
      PORTB|=(1<<PORTB0);
      PORTB|=(1<<PORTB1);
      PORTB|=(1<<PORTB2);
      break;
      
      case 2:
      PORTC&=~(1<<PORTC1);
      PORTC&=~(1<<PORTC5);
      PORTB&=~(1<<PORTB0);
      PORTB&=~(1<<PORTB1);
      PORTB&=~(1<<PORTB5);
      
      PORTC|=(1<<PORTC2);
      PORTB|=(1<<PORTB3);
      break;
      
      case 3:
      PORTC&=~(1<<PORTC1);
      PORTC&=~(1<<PORTC5);
      PORTB&=~(1<<PORTB1);
      PORTB&=~(1<<PORTB3);
      PORTB&=~(1<<PORTB5);
      
      PORTC|=(1<<PORTC2);
      PORTB|=(1<<PORTB0);
      break;
      
      case 4:
      PORTC&=~(1<<PORTC2);
      PORTC&=~(1<<PORTC5);
      PORTB&=~(1<<PORTB3);
      PORTB&=~(1<<PORTB5);
      
      PORTC|=(1<<PORTC1);
      PORTB|=(1<<PORTB0);
      PORTB|=(1<<PORTB1);
      break;
      
      case 5:
      PORTC&=~(1<<PORTC1);
      PORTC&=~(1<<PORTC2);
      PORTB&=~(1<<PORTB1);
      PORTB&=~(1<<PORTB3);
      PORTB&=~(1<<PORTB5);
      
      PORTC|=(1<<PORTC5);
      PORTB|=(1<<PORTB0);
      break;
      
      case 6:
      PORTC&=~(1<<PORTC1);
      PORTC&=~(1<<PORTC2);
      PORTB&=~(1<<PORTB0);
      PORTB&=~(1<<PORTB1);
      PORTB&=~(1<<PORTB3);
      PORTB&=~(1<<PORTB5);
      
      PORTC|=(1<<PORTC5);
      break;
      
      case 7:
      PORTC&=~(1<<PORTC1);
      PORTC&=~(1<<PORTC5);
      PORTB&=~(1<<PORTB3);
      
      PORTC|=(1<<PORTC2);
      PORTB|=(1<<PORTB5);
      PORTB|=(1<<PORTB2);
      PORTB|=(1<<PORTB0);
      PORTB|=(1<<PORTB1);
      break;
      
      case 8:
      PORTC&=~(1<<PORTC1);
      PORTC&=~(1<<PORTC2);
      PORTC&=~(1<<PORTC5);
      PORTB&=~(1<<PORTB0);
      PORTB&=~(1<<PORTB1);
      PORTB&=~(1<<PORTB3);
      PORTB&=~(1<<PORTB5);
      break;
      
      case 9:
      PORTC&=~(1<<PORTC1);
      PORTC&=~(1<<PORTC2);
      PORTC&=~(1<<PORTC5);
      PORTB&=~(1<<PORTB1);
      PORTB&=~(1<<PORTB3);
      PORTB&=~(1<<PORTB5);

      PORTB|=(1<<PORTB0);
      break;
      
      case 10:
      PORTC&=~(1<<PORTC5);
      PORTB|=(1<<PORTB3);
      PORTC|=(1<<PORTC1);
      PORTC|=(1<<PORTC2);
      PORTB|=(1<<PORTB5);
      PORTB|=(1<<PORTB0);
      PORTB|=(1<<PORTB1);
      PORTB|=(1<<PORTB2);

      break;
      case 11:
      PORTC|=(1<<PORTC5);
      PORTB|=(1<<PORTB3);
      PORTC|=(1<<PORTC1);
      PORTC|=(1<<PORTC2);
      PORTB|=(1<<PORTB5);
      PORTB|=(1<<PORTB0);
      PORTB|=(1<<PORTB1);
      PORTB|=(1<<PORTB2);
   }
}

void off()                         //выключение сегментов
{
   PORTB|=(1<<PORTB5);  //off
   PORTC|=(1<<PORTC5);
   PORTC|=(1<<PORTC1);
   PORTC|=(1<<PORTC2);
   PORTB|=(1<<PORTB3);
   PORTB|=(1<<PORTB0);
   PORTB|=(1<<PORTB1);
   PORTB|=(1<<PORTB2);
}

void TTT()                         //функция для установки прочерков
{
   PORTB&=~(1<<PORTB5);  //-
   PORTC|=(1<<PORTC5);
   PORTC|=(1<<PORTC1);
   PORTC|=(1<<PORTC2);
   PORTB|=(1<<PORTB3);
   PORTB|=(1<<PORTB0);
   PORTB|=(1<<PORTB1);
   PORTB|=(1<<PORTB2);
}

void init_timer_led(void)          //настройка таймера для динамической индикации
{
   TCCR1B |= (1<<WGM12);
   TIMSK1 |= (1<<OCIE1A);
   OCR1AH = 0b00001101;
   OCR1AL = 0b01001100;
   TCCR1B |= (1<<CS11);
}

void init_timer_encoder(void)      //настройка таймера для обработки задержки энкодера
{
   TCCR0B |= (1<<WGM02);
   TIMSK0 |= (1<<OCIE0A);
   OCR0A = 4;
   TCCR0B |= (1<<CS01)|(1<<CS00);
}

void init_timer_OO(void)           //настройка таймера для обратного отсчета и включение асинхронного режима
{
   ASSR |= (1 << AS2);
   TCNT2 = 0;
   TCCR2B |= (1 << CS22)|(1 << CS20);
   OCR2A = 255;
   TIMSK2 |=(1 << OCIE2A);
   TIFR2 = 0;
}

void init_ADC()                    //настройка АЦП для контроля напряжения на АКБ
{
   ADCSRA |= (1<<ADEN)|(1<<ADATE)|(1<<ADIF)|(1<<ADPS1)|(1<<ADPS2);
   ADMUX  |= /*(1<<REFS1)|*/(1<<REFS0)|(0<<ADLAR)|(1<<MUX1)|(1<<MUX2);
   ADCSRA |= (1<<ADSC);
}

void init_port()                   //настройка портов ввода-вывода
{
   DDRD = 0b00010111;
   DDRB = 0b111111;
   DDRC = 0b1111111;
   PORTD = 0b11100000;
   PORTC = 0b1111111;
   PORTB = 0b111111;
}

void enkoder()                     //обработка вращения энкодера
{
   if ( napravlenie & (1<<0)) //определяем было или нет зафексировано направление
   {
      if (PIND & (1<<6)){}
      else
      {
         if (PIND & (1<<7)){}
         else
         napravlenie = 0;
      }
   }
   else
   {
      
      //проверка на правое вращение
      
      if (PIND & (1<<6)) {}        //проверка порта на 0
      else
      {
         if (PIND & (1<<7))      //проверка порта на 1
         {
            napravlenie |=(1<<0);
            if (min < 999)     //проверка на больше
            {
               min++;
               return;
            }
         }
      }
      
      //проверка на левое вращение
      
      if (PIND & (1<<7)) {}         //проверка порта на 0
      else
      {
         if (PIND & (1<<6))       //проверка порта на 1
         {
            napravlenie |=(1<<0);
            if (min > 0)          //проверка на менше 1
            min--;
         }
      }
   }
}

void ledprint(number)              //вывод значения на индикатор
{
   asm("cli");
   R1=number/100;                 //разбивка по разрядам
   R2=(number%100)/10;
   R3=(number%100)%10;
   
   PORTD&=~(1<<PORTD4);           //выключение зумера
   
   if(number<100) {R1=11;}        //гашение первых разрядов при 0
   if(number<10) {R2=11;}
   if(number==0) {PORTD|=(1<<PORTD4);} //включение зумера при 0 минут
   asm("sei");
}

ISR(TIMER2_COMPA_vect)                          //прерывание по ASSR (здесь отсчет минут и "пип" зумера раз в секунду)
{
   if(dr > 2)
   {
      if(min>0)
      {
         sec++;
         PORTD|=(1<<PORTD4);
      }
      if(sec>59) sec=0, min--;
   }
}

ISR (TIMER1_COMPA_vect)                         //динамическая индикация (меняем разряд с нужной цифрой)
{
   if(n_count==0) {
      PORTC|=(1<<PORTC0);
      PORTC&=~(1<<PORTC3);
      PORTC&=~(1<<PORTC4);
   segchar(R1);}
   if(n_count==1) {
      PORTC|=(1<<PORTC3);
      PORTC&=~(1<<PORTC4);
      PORTC&=~(1<<PORTC0);
   segchar(R2);}
   if(n_count==2) {
      PORTC|=(1<<PORTC4);
      PORTC&=~(1<<PORTC0);
      PORTC&=~(1<<PORTC3);
   segchar(R3);}
   
   n_count ++;
   if (n_count>2) n_count=0;
}

ISR (TIMER0_COMPA_vect)                         //обработка энкодера без PD5 (PD5 - центральная кнопка энкодера)
{
   enkoder();
}

int main(void)
{
   /* инициализация всего :) */
   init_port();
   asm("cli");
   init_ADC();
   init_timer_OO();
   init_timer_led();
   init_timer_encoder();
   
   /* мигаем черточками )) */
   off();
   _delay_ms(500);
   TTT();
   _delay_ms(500);
   off();
   _delay_ms(500);
   TTT();
   _delay_ms(500);
   off();
   _delay_ms(500);
   
   sei();
   
   while(1)
   {
      for(char n = 0; n < 5; n++)        //обработка кнопки PD5
      {
         if((PIND&(1 << PD5)) == 0)
         dr++;
      }
      
      ledprint(min);                     //выводим минуты для отсчета
      
      if (ADC>670)                       //показатель заряда АКБ
      {
         PORTD|=(1<<PORTD1); //зеленый
         //PORTD&=~(1<<PORTD0);
         PORTD&=~(1<<PORTD2);
      }
      else
      {
         PORTD|=(1<<PORTD2); //красный
         PORTD&=~(1<<PORTD1);
         //PORTD&=~(1<<PORTD0);
      }
   }
}

и опять я в ступоре :-) ...
Во-первых первый разряд еле заметно подсвечивается цифрой третьего разряда - не знаю как такое возможно...
Во-вторых когда if (min < 999) или if (min > 0) - нет возможности при min-- уходить от нуля к 999, 998 и т.д. пишу так - if (min <= 999) или if (min >= 0), но теперь от нуля значения уходят в никуда, т.е. индикации тупо нет... как тогда нужно зациклить установку минут не только от 0 к 999 в плюс(0,1,2,3 и т.д.), но и от 0 к 999 в минус(0,999,998,997 и т.д.)?

Добавлено спустя 2 минуты 28 секунд:
Вот архив со всей требухой...
Вложения
TOO.rar
(58.17 КБ) Скачиваний: 10
Denis_K
Частенько бываю
 
Сообщения: 81
Зарегистрирован: 16 июн 2017 13:48
Откуда: Краснодарский край

Re: Динамическая индикация

Сообщение IYra » 29 окт 2018 20:12

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

Важен порядок.
1. Гасим все разряды
2. Рисуем цифру
3. Зажигаем нужный разряд
Код: Выделить всё
ISR (TIMER1_COMPA_vect)                         //динамическая индикация (меняем разряд с нужной цифрой)
{
   PORTC&=~(1<<PORTC0);PORTC&=~(1<<PORTC3);PORTC&=~(1<<PORTC4);     // Гасим
   if(n_count==0) {
      segchar(R1);  // Рисуем
      PORTC|=(1<<PORTC0);  // Зажигаем
      
   }
   if(n_count==1) {
      segchar(R2);
      PORTC|=(1<<PORTC3);
      }
   if(n_count==2) {
      segchar(R3);
      PORTC|=(1<<PORTC4);
      }
   
   n_count ++;
   if (n_count>2) n_count=0;
}


И еще в Протеусе в свойствах МК надо установить CLKDIV8 -> (1) Unprogrammed
чтобы не было деления частоты на 8
IYra
Живу тут
 
Сообщения: 695
Зарегистрирован: 01 фев 2012 19:36
Откуда: Санкт-Петербург

Re: Динамическая индикация

Сообщение Denis_K » 29 окт 2018 21:51

IYra, как всегда спасибо за наставление!
С индикацией теперь понятно... а вот как сделать при вращении энкодера min-- от 0 к 999?
В протеусе так делал для какой-то цели - уже не помню... старею :-) , но моделирую постоянно прошиваясь на реальной плате.
Denis_K
Частенько бываю
 
Сообщения: 81
Зарегистрирован: 16 июн 2017 13:48
Откуда: Краснодарский край

Re: Динамическая индикация

Сообщение IYra » 30 окт 2018 09:47

Denis_K писал(а):а вот как сделать при вращении энкодера min-- от 0 к 999?

Надо наверно так
Код: Выделить всё
  if (min < 999)     //проверка на больше
  {
               min++;
               return;
    }
   else min = 0 ;


так как min это unsigned int min = 0;
и меньше нуля быть не может и если от 0 отнять 1 сразу перескакивает на 64т чего то там
IYra
Живу тут
 
Сообщения: 695
Зарегистрирован: 01 фев 2012 19:36
Откуда: Санкт-Петербург

Re: Динамическая индикация

Сообщение Denis_K » 30 окт 2018 22:37

IYra, спасибо. Понял, исправил, все работает...
Denis_K
Частенько бываю
 
Сообщения: 81
Зарегистрирован: 16 июн 2017 13:48
Откуда: Краснодарский край


Вернуться в Разное



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

cron