Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
White Wolf
3 / 3 / 4
Регистрация: 08.04.2008
Сообщений: 85
Завершенные тесты: 1
1

Часы на atmega8

12.03.2017, 18:19. Просмотров 1171. Ответов 6
Метки нет (Все метки)

Добрый день.
Забуксовал с часами. Часы на 7 сегментных индикаторах. Не пойму как вывести Каждую цифру на свое место. Получается, что цифры бегут по разрядам, но не горят, как им положено. Делаю в ATMEL Studio 6.
Вот схема и код.
Часы на atmega8


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
 
volatile unsigned char second, minute, hour;
volatile unsigned char segcounter = 2;
 
void set_time(unsigned char hour, unsigned char minute)
{
    
    unsigned char numbers_7seg[] =
    {
        0xc0, //0
        0xf9, //1
        0xa4, //2
        0xb0, //3
        0x99, //4
        0x92, //5
        0x82, //6
        0xf8, //7
        0x80, //8
        0x90  //9
    };
    
    unsigned char hours_7seg_1 = hour / 10;
    unsigned char hours_7seg_2 = hour % 10;
    unsigned char minutes_7seg_3 = minute / 10;
    unsigned char minutes_7seg_4 = minute % 10;
 
    PORTC = (1 << segcounter); // Засвечиваем общий катод, подаем лог. 1    
    switch (segcounter)
    {
        case 2:
        PORTD = numbers_7seg[hours_7seg_1];
        break;
        case 3:
        PORTD = numbers_7seg[hours_7seg_2];
        break;
        case 4:
        PORTD = numbers_7seg[minutes_7seg_3];
        break;
        case 5:
        PORTD = numbers_7seg[minutes_7seg_4];
        break;
    }
    if(segcounter++ > 4) segcounter = 2;
}
 
ISR(TIMER2_OVF_vect) // Прерывание по переполнению Т2
{
    if(second++ >= 59)
    {
        second = 0;
        minute++;
    }
    if(minute > 59)
    {
        minute = 0;
        hour++;
    }
    if(hour > 23)
    hour = 0;
    
    set_time(hour, minute);    
}
 
int main(void)
{
    DDRB = 0x00;
    DDRC = 0x3c;
    DDRD = 0xff;
    PORTB |= (1 << PB6);
    PORTB |= (1 << PB7);
    PORTC |= 0x3c;
    
    TIMSK &= ~(1 << OCIE2)|(1 << TOIE2); // Запрещаем прерывания по T2
    ASSR |= (1 << AS2); // Включаем асинхронный режим T2
    TCNT2 = 0; // Сбрасываем регистр счета
    TCCR2 |= (1 << CS22)|(1 << CS20); // Предделитель на 128(32768/128 = 256 тиков/c)
    
    sei(); // Глобально разрешаем прерывания
    
    TIMSK |= (1 << TOIE2); // Разрешаем прерывание по переполнению Т2
    
    hour = 12;
    minute = 00;
    
    while(1)
    {
        unsigned char dr;
        
        if((PINC&(1 << PC0)) == 0 && PINC&(1 << PC1)) // Если кнопка Часы+ нажата
        {
            dr = 0;
            for(unsigned char i = 0; i < 10; i++) // Программный антидребезг контактов
            {
                _delay_ms(5);
                if((PINC&(1 << PC0)) == 0)
                dr++;
            }
            if(dr > 5)
            {
                if(hour++ >= 23) hour = 0;    // Увеличиваем часы
                //PORTD = dig_8;
            }
        }
        
        if((PINC&(1 << PC1)) == 0 && PINC&(1 << PC0)) // Если кнопка Минуты+ нажата
        {
            dr = 0;
            for(unsigned char i = 0; i < 10; i++) // Программный антидребезг контактов
            {
                _delay_ms(5);
                if((PINC&(1 << PC1)) == 0)
                dr++;
            }
            if (dr > 5)
            {
                if(minute++ >= 59) minute = 0; // Увеличиваем минуты
                //PORTD = dig_4;
            }
        }
    }
}
Как вообще вывести каждую цифру на свою позицию. Статей в интернете много, но я не пойму. Тупой наверное. ))
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.03.2017, 18:19
Ответы с готовыми решениями:

Разница между ATMEGA8-16AI и ATMEGA8-16AU
Кто подскажет, в чем разница между ATMEGA8-16AI и ATMEGA8-16AU. Смотрю в Платане цены между ними...

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

Даны целые числа m (часы) и n (минуты) .Определить наименьшее время (в минутах) когда совпадут минуты и часы
Даны целые числа m (часы) и n (минуты) .Определить наименьшее время (в минутах) до того момента ...

Даны целые числа m (часы) и n (минуты) .Определить наименьшее время (в минутах) когда совпадут минуты и часы
Даны целые числа m (часы) и n (минуты) .Определить наименьшее время (в минутах) до того момента ...

Преобразовать введенное значение в часы и минуты и выводит на экран в виде “часы: минуты”
Здравствуйте, помогите пожалуйста с написанием программы. Написать программу, которая запрашивает...

6
pyzhman
791 / 485 / 66
Регистрация: 15.05.2012
Сообщений: 2,749
12.03.2017, 20:18 2
Цитата Сообщение от White Wolf Посмотреть сообщение
Тупой наверное. ))
Не надо наговаривать на себя.
Цитата Сообщение от White Wolf Посмотреть сообщение
Как вообще вывести
Динамическая индикация.
1. Выводите нужную цифру в разряд единиц минут (крайний правый). Ждете не более 5 мсек.
2. Выводите нужную цифру в разряд десятков минут. Ждете не более 5 мсек.
3. Выводите нужную цифру в разряд единиц часов. Ждете не более 5 мсек.
4. Выводите нужную цифру в разряд десятков часов (крайний слева). Ждете не более 5 мсек.
5. Уходите на пункт 1.
0
ValeryS
Модератор
7447 / 5639 / 716
Регистрация: 14.02.2011
Сообщений: 19,210
Завершенные тесты: 1
12.03.2017, 21:11 3
pyzhman, так он так и делает
только не совсем правильно
для начала нужно погасить все разряды
C
1
PORTC = 0;
потом вывести на PORTD нужное значение и только потом
C
1
PORTC = (1 << segcounter);
иначе возможны "призраки", одна цифра будет видна в двух разрядах
Цитата Сообщение от White Wolf Посмотреть сообщение
C
1
if(segcounter++ > 4) segcounter = 2;
вот тут еще одна ошибка, значения 5 никогда не будет
следовательно ветка
Цитата Сообщение от White Wolf Посмотреть сообщение
C
1
2
case 5:
     PORTD = numbers_7seg[minutes_7seg_4];
не исполнится
я бы сделал так
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 PORTC = 0; //гасим все 
    switch (segcounter)
    {
        case 2:
        PORTD = numbers_7seg[hours_7seg_1];
        PORTC =1<<2;
       segcounter=3;
        break;
        case 3:
        PORTD = numbers_7seg[hours_7seg_2];
        PORTC =1<<3;
       segcounter=4;
        break;
        case 4:
        PORTD = numbers_7seg[minutes_7seg_3];
        PORTC =1<<4;
       segcounter=5;
        break;
        case 5:
        PORTD = numbers_7seg[minutes_7seg_4];
        PORTC =1<<5;
       segcounter=2;
        break;
    }
0
White Wolf
3 / 3 / 4
Регистрация: 08.04.2008
Сообщений: 85
Завершенные тесты: 1
12.03.2017, 21:52  [ТС] 4
ValeryS,получается, что на индикацию всех 4 цифр тратится 4 секунды? Ведь таймер срабатывает раз в секунду. А сразу нельзя все разряды отобразить? Цифры уже погаснут, пока следующая секунда начнется.

Добавлено через 22 минуты
Или я неправильно понимаю и таймер переполнится 256 раз за секунду? И прерывание сработает 256 за секунду?
0
ValeryS
Модератор
7447 / 5639 / 716
Регистрация: 14.02.2011
Сообщений: 19,210
Завершенные тесты: 1
12.03.2017, 22:30 5
Цитата Сообщение от White Wolf Посмотреть сообщение
Ведь таймер срабатывает раз в секунду.
не совсем так
есть 8 битные и 16битные таймеры
у обоих есть прерывание по переполнению,другие прерывания пока не рассматриваем
как они работают?
у каждого таймера ести специальный регистр у 8 битного он соответственно 8 бит и максимальное число которое может в нем находится это 255
у 16 битного в реистре может находитс максимум 65535
с каждым "тиком" значение регистра увеличивается и когда к 255(или 65535) прибавляется 1 то значение в регистре становится равным 0,регистр переполняется в этот момент и происходит прерывание
чтобы понятней было представь что у тебя есть один десятичный индикатор
вот так идет отсчет
0 1 2 3 4 5 6 7 8 9 0(переполнение) 1 2 3 4 5 6 7 8 9 0(переполнение)
сталось узнать что такое "тики"
Это частота процессора деленная на значения предделителя, у каждого таймера свой предделитель
например частота 1 МГц предделитель 1, тики будут приходить с периодичностью 1 мкСек
записав в регистр число 255 будешь иметь прерывания с периодом 1 мкСек, записав 0 период 256 мкСек
период рассчитывается 256-х(65536-х) где икс число записаное в регистр

исходя из этого, решение: использовать два таймера один для подсчета времени с периодом 1 Сек, второй для индикации с периодом например 10 мСек
Цитата Сообщение от White Wolf Посмотреть сообщение
А сразу нельзя все разряды отобразить?
к сожалению нельзя, при динамической индикации в каждый момент времени светится один разряд и только благодаря инерционности зрения, при определенной частоте кажется что они горят одновременно
0
pyzhman
791 / 485 / 66
Регистрация: 15.05.2012
Сообщений: 2,749
13.03.2017, 08:05 6
Цитата Сообщение от ValeryS Посмотреть сообщение
при определенной частоте
Частота должна быть не менее 50 Гц. При четырех разрядах каждый должен отображаться в течение не более 1/50/4= 5 мсек. Т.о. таймер должен срабатывать не реже чем каждые 5 мсек.
1
Voland_
1689 / 1034 / 97
Регистрация: 04.01.2010
Сообщений: 3,485
17.03.2017, 10:59 7
Цитата Сообщение от pyzhman Посмотреть сообщение
Частота должна быть не менее 50 Гц.
дополню. Вдобавок, эта частота должна быть относительно стабильной (то есть не стоит делать это итервативно, в главном потоке приложения), ибо в противном случае, символы либо могут иметь разную степень свечения, в итоге, либо "помаргивать" в процессе работы.
Переключение отображения символов должно выполняться в прерывании таймера (или какой-то стабильной по времени периферии), и желательно - с повышенным приоритетом, в нагруженной системе.
0
17.03.2017, 10:59
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.03.2017, 10:59

Из секунд - часы, минуты и секунды. Из минут - часы, минуты
private void button4_Click(object sender, EventArgs e) { if (textBox3.Text ==...

Программа, которая переводит часы и минуты в минуты или минуты – в часы и минуты
Составьте программу, которая в зависимости от входных данных переводит часы и минуты в...

ATMEGA8
Подскажите пожалуйста чем отличаються микроконтролер atmega8 от например етого ATmega8A-PU? И...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru