Page 1 of 1
Динамическая индикация
Posted: 05 Oct 2018 16:30
by Denis_K
Пытаюсь написать код для таймера под свои нужды, но никак не выходит с индикацией... Разряды не перебираются по одному, а меняются сразу три цифры...
Например: пишу на вывод число 123, а выводится сначала 1, затем 2 и потом 3 на трех разрядах(111 >> 222 >> 333), все это зациклено. Хотя по задумке
должно быть 1 в первом разряде, 2 во втором и 3 в третьем с числом на выходе 123. Что я делаю не так?
Добавлено спустя 3 часа 16 минут 17 секунд:
Вот код без скачивания...
Code: Select all
#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)
{
}
}
Re: Динамическая индикация
Posted: 06 Oct 2018 13:23
by IYra
Denis_K wrote:
Вот код без скачивания...
1. В коде желательно больше комментариев. Особенно там где настраивается таймер.
2. Еще хорошо бы нарисовать модель в Протеусе и пройтись с отладчиком
Re: Динамическая индикация
Posted: 06 Oct 2018 15:03
by Denis_K
IYra, здравствуйте. Я бы с радостью воспользовался отладчиком, но к сожалению еще не научился им пользоваться
А модель нарисованная есть...
Вот прокомментировал код:
Code: Select all
#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)
{
}
}
Re: Динамическая индикация
Posted: 06 Oct 2018 15:06
by IYra
Denis_K wrote: А модель нарисованная есть...
Ну так выкладывай - посмотрим
Re: Динамическая индикация
Posted: 06 Oct 2018 17:27
by Denis_K
Вот модель
Добавлено спустя 2 часа 14 минут 9 секунд:
Попробовал так:
Code: Select all
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? я уже запутался...
Re: Динамическая индикация
Posted: 06 Oct 2018 17:53
by IYra
Denis_K wrote:
Code: Select all
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(отладочный) прочерки
Re: Динамическая индикация
Posted: 07 Oct 2018 10:46
by Denis_K
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 секунд:
Выяснилось, что при использовании одного портВ для вывода цифр - все работает, только комбинирую с портС, то разряды не переключаются...
Применил маску для портС:
Code: Select all
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;
}
но теперь не правильно загораются сегменты...
Re: Динамическая индикация
Posted: 07 Oct 2018 12:48
by IYra
Denis_K wrote:
Почему-то вот здесь 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);
Re: Динамическая индикация
Posted: 07 Oct 2018 15:15
by Denis_K
Спасибо,
IYra. Я поздно до этого дошел
...
Сделал так:
Code: Select all
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
Re: Динамическая индикация
Posted: 07 Oct 2018 16:12
by IYra
Denis_K wrote:
Но теперь если в ledprint(111) или ledprint(555) и т.д., то индикация работает нормально, а если ledprint(123), то первую цифру выводит, а последующие - каша из сегментов...
Перед тем как устанавливать сегменты их нужно все очистить(то есть установить еденичку)
PORTC|=(1<<PORTC1);
PORTB|=(1<<PORTB3); и т.д.
И для отладки нужен main.c и .elf
Re: Динамическая индикация
Posted: 07 Oct 2018 16:43
by Denis_K
Добавлено спустя 5 минут 3 секунды:
Вот настройки портов:
Code: Select all
DDRD = 0b00010000;
DDRB = 0b111111;
DDRC = 0b1111111;
PORTD = 0b00100000;
PORTC = 0b1111111;
PORTB = 0b111111;
Вроде бы все соответствует... на разрядах не стал выставлять "0" из- за обратного напряжения на сегментах...
Re: Динамическая индикация
Posted: 07 Oct 2018 17:28
by IYra
IYra wrote:Denis_K wrote:
Но теперь если в ledprint(111) или ledprint(555) и т.д., то индикация работает нормально, а если ledprint(123), то первую цифру выводит, а последующие - каша из сегментов...
Перед тем как устанавливать сегменты их нужно все очистить(то есть установить еденичку)
PORTC|=(1<<PORTC1);
PORTB|=(1<<PORTB3); и т.д.
Не точно выразился.
Каждый раз !!!
То есть в начале функции
segchar() надо чистить все сегменты
PORTC|=(1<<PORTC1);
PORTB|=(1<<PORTB3); и т.д.
а уж потом рисовать новое.
Или для каждой цифры чистить только свое (так будет быстрее выполняться)
Re: Динамическая индикация
Posted: 07 Oct 2018 18:22
by Denis_K
IYra, спасибо! Получилось!
Написал так:
Code: Select all
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;
}
Re: Динамическая индикация
Posted: 29 Oct 2018 00:34
by Denis_K
Дошел до такого кода
Code: Select all
#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 секунд:
Вот архив со всей требухой...
Re: Динамическая индикация
Posted: 29 Oct 2018 19:12
by IYra
Denis_K wrote:Дошел до такого кода и опять я в ступоре
...
Во-первых первый разряд еле заметно подсвечивается цифрой третьего разряда - не знаю как такое возможно...
Важен порядок.
1. Гасим все разряды
2. Рисуем цифру
3. Зажигаем нужный разряд
Code: Select all
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
Re: Динамическая индикация
Posted: 29 Oct 2018 20:51
by Denis_K
IYra, как всегда спасибо за наставление!
С индикацией теперь понятно... а вот как сделать при вращении энкодера min-- от 0 к 999?
В протеусе так делал для какой-то цели - уже не помню... старею
, но моделирую постоянно прошиваясь на реальной плате.
Re: Динамическая индикация
Posted: 30 Oct 2018 08:47
by IYra
Denis_K wrote:а вот как сделать при вращении энкодера min-- от 0 к 999?
Надо наверно так
Code: Select all
if (min < 999) //проверка на больше
{
min++;
return;
}
else min = 0 ;
так как min это unsigned int min = 0;
и меньше нуля быть не может и если от 0 отнять 1 сразу перескакивает на 64т чего то там
Re: Динамическая индикация
Posted: 30 Oct 2018 21:37
by Denis_K
IYra, спасибо. Понял, исправил, все работает...