Помогите с асинхронным таймером на AtMega8a

Обсуждаем контроллеры компании Atmel.
Ответить
Встал на лапы
Аватара пользователя
Сообщения: 91
Зарегистрирован: Сб фев 17, 2018 00:08:56

Сообщение Jack-Sidr »

Вот весь код:
Спойлер

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

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

unsigned char bin[64] = {

0b00000000,
0b00100000,
0b00010000,
0b00110000,
0b00001000,
0b00101000,
0b00011000,
0b00111000,
0b00000100,
0b00100100,
0b00010100,
0b00110100,
0b00001100,
0b00101100,
0b00011100,
0b00111100,
0b00000010,
0b00100010,
0b00010010,
0b00110010,
0b00001010,
0b00101010,
0b00011010,
0b00111010,
0b00000110,
0b00100110,
0b00010110,
0b00110110,
0b00001110,
0b00101110,
0b00011110,
0b00111110,
0b00000001,
0b00100001,
0b00010001,
0b00110001,
0b00001001,
0b00101001,
0b00011001,
0b00111001,
0b00000101,
0b00100101,
0b00010101,
0b00110101,
0b00001101,
0b00101101,
0b00011101,
0b00111101,
0b00000011,
0b00100011,
0b00010011,
0b00110011,
0b00001011,
0b00101011,
0b00011011,
0b00111011,
0b00000111,
0b00100111,
0b00010111,
0b00110111,
0b00001111,
0b00101111,
0b00011111,
0b00111111,
};




//переменные
unsigned char hour, min, sec;

ISR(TIMER2_COMP_vect){
sec++;
if (sec > 59) { min ++; sec = 0;};
if (min > 59) { hour ++; min = 0;};
if (hour > 23) {hour = 0;};
}



void ShowTime(char h, char m, char s){
PORTB = bin[h];
PORTD |= (1 <<PD5);
_delay_ms(1);
PORTD &= ~(1 <<PD5);
PORTB = bin[m];
PORTD |= (1 <<PD6);
_delay_ms(1);
PORTD &= ~(1 <<PD6);
PORTB = bin[s];
PORTD |= (1 <<PD7);
_delay_ms(1);
PORTD &= ~(1 <<PD7);
}


int main(void) {
//SetUp
DDRB = 0b11111111;
DDRD = 0b11100000;
DDRC|= (0 << PC2)|(0<<PC3);
PORTC |= (1 << PC2)|(1<<PC3);

 asm ("cli");
ASSR |= (1 << AS2);
  while (ASSR != (0b00001000))
 {
 asm ("nop");
 }
TCCR2 |= (1<<CS20) | (1<<CS22) | (1<<WGM21);
OCR2 = 255; 
TIMSK |= (1<<OCIE2); 
TIFR = 0;
 asm ("sei");  

while(1){


if((PINC & (1<<PC2)) == 0){
_delay_ms(50);
while((PINC & (1<<PC2)) == 0){}
min++;
if (min > 59) min = 0;
}

if((PINC & (1<<PC3)) == 0){
_delay_ms(50);
while((PINC & (1<<PC3)) == 0){}
hour++;
if (hour > 23) hour = 0;
}

ShowTime(hour, min, sec);
}
return 0;
}
Я уменьшил убегание (проблема была в минутах, последняя минута сбрасывалась в 0 за одно прерывания)
было так:

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

ISR(TIMER2_COMP_vect){
if (sec++ >= 59) { min ++; sec = 0;};
if (min >= 59) { hour ++; min = 0;};
if (hour >= 23) {hour = 0;};
}
Теперь они спешат на 20 секунд в час, все еще много, но лучше чем на 1,5 минуты.
При этом запускал параллельно с секундомером на ноутбуке, и заметно что одна секунда на часах отображается немного быстрее чем нужно.
Реклама
Вымогатель припоя
Сообщения: 593
Зарегистрирован: Ср янв 06, 2010 10:01:46

Сообщение metan »

Я думаю, нужно переделать на прерывание по переполнению, и всё наладится
У меня в CodeVision вот так

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

TIMSK &=~(1<<OCIE2 | 1<< TOIE2);	// Запрещаем прерывания таймера 2
ASSR  = 1<<AS2;				// Включаем асинхронный режим
TCNT2 = 0;
TCCR2 = 5<<CS20; 			// Предделитель на 128 на 32768 даст 256 тиков в секунду
					// Что даст 1 прерывание по переполнению в секунду.

while(ASSR & (1<<TCN2UB | 1<<OCR2UB | TCR2UB));

TIFR  |= 1<<OCF2 | 1<< TOV2;		// Сбрасываем флаги прерываний, на всякий случай.


// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK |= 1<< TOIE2 | 1<<TOIE0;	


////////////////////////

interrupt [TIM2_OVF] void timer2_ovf_isr(void) {
  seconds++; normalize();  
}
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 91
Зарегистрирован: Сб фев 17, 2018 00:08:56

Сообщение Jack-Sidr »

Я изначально и пытался делать по переполнению (посмотри самый первый код в шапке)

Добавлено after 8 minutes 18 seconds:
Еще вопрос, в прерывания по переполнение, в какой тик происходит прерывание? В 256 или 257?
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Jack-Sidr писал(а):в какой тик происходит прерывание? В 256 или 257?
при переходе из 255 в 0
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Встал на лапы
Аватара пользователя
Сообщения: 91
Зарегистрирован: Сб фев 17, 2018 00:08:56

Сообщение Jack-Sidr »

Тогда какая разница в прерывания по совпадению с 255 и прерыванию по переполнению?
Реклама
Вымогатель припоя
Сообщения: 593
Зарегистрирован: Ср янв 06, 2010 10:01:46

Сообщение metan »

Jack-Sidr писал(а):какая разница в прерывания?
1
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 91
Зарегистрирован: Сб фев 17, 2018 00:08:56

Сообщение Jack-Sidr »

На тик дольше или меньше?
Вымогатель припоя
Сообщения: 593
Зарегистрирован: Ср янв 06, 2010 10:01:46

Сообщение metan »

меньше
Встал на лапы
Аватара пользователя
Сообщения: 91
Зарегистрирован: Сб фев 17, 2018 00:08:56

Сообщение Jack-Sidr »

Если на тик менше, значит прерывания будут срабатывать чаще, значит часы будут идти быстрее, а они у меня и так спешат.
Чем тогда поможет прерывание переполнениям?
Встал на лапы
Аватара пользователя
Сообщения: 99
Зарегистрирован: Сб янв 12, 2013 22:43:10
Откуда: Москва

Сообщение -Valerius- »

Спойлер

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

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

unsigned char bin[64] = {

0b00000000,
0b00100000,
0b00010000,
0b00110000,
0b00001000,
0b00101000,
0b00011000,
0b00111000,
0b00000100,
0b00100100,
0b00010100,
0b00110100,
0b00001100,
0b00101100,
0b00011100,
0b00111100,
0b00000010,
0b00100010,
0b00010010,
0b00110010,
0b00001010,
0b00101010,
0b00011010,
0b00111010,
0b00000110,
0b00100110,
0b00010110,
0b00110110,
0b00001110,
0b00101110,
0b00011110,
0b00111110,
0b00000001,
0b00100001,
0b00010001,
0b00110001,
0b00001001,
0b00101001,
0b00011001,
0b00111001,
0b00000101,
0b00100101,
0b00010101,
0b00110101,
0b00001101,
0b00101101,
0b00011101,
0b00111101,
0b00000011,
0b00100011,
0b00010011,
0b00110011,
0b00001011,
0b00101011,
0b00011011,
0b00111011,
0b00000111,
0b00100111,
0b00010111,
0b00110111,
0b00001111,
0b00101111,
0b00011111,
0b00111111,
};




//переменные
unsigned char hour, min, sec;

ISR(TIMER2_COMP_vect)
{
    sec++;
    if (sec == 60)
      {
          sec = 0;
          min ++; 
      };

    if (min == 60)
      { 
          min = 0;
          hour ++; 
      };
    if (hour > 23)
      {
         hour = 0;
      };
}

void ShowTime(char h, char m, char s){   // Не очень понятно как работает эта функция. Можно подробней её описать?
PORTB = bin[h];
PORTD |= (1 <<PD5);
_delay_ms(1);
PORTD &= ~(1 <<PD5);
PORTB = bin[m];
PORTD |= (1 <<PD6);
_delay_ms(1);
PORTD &= ~(1 <<PD6);
PORTB = bin[s];
PORTD |= (1 <<PD7);
_delay_ms(1);
PORTD &= ~(1 <<PD7);
}


int main(void) {
//SetUp
DDRB = 0b11111111;
DDRD = 0b11100000;
DDRC|= (0 << PC2)|(0<<PC3);
PORTC |= (1 << PC2)|(1<<PC3);

 asm ("cli");

                                                           //  
ASSR |= (1 << AS2);                   // Разрешаем тактирование  таймера Т2 от кварца 32768 (асинхронный режим)
  while (ASSR != (0b00001000))    // Ожидаем разрешения записи  
 {
     asm ("nop");
 }
TCCR2 |= (1<<CS21) | (1<<CS22) | (1<<WGM21);    //  Тактирование: 32768 делим на предделитель (256) = 128. Сброс по совпадению.
OCR2 = 127;                                                            //  В регистр сравнения заносим 127! При совпадении, таймер перейдёт в вектор 
                                                                               //  прерывания на следующем такте, итого = 128.  
TIMSK |= (1<<OCIE2);                                             //  Разрешаем прерывание по совпадению T2
TIFR = 0;                                                                 //  Сброс флагов.

 asm ("sei");  

while(1){


if((PINC & (1<<PC2)) == 0){                                    //  Кнопки
_delay_ms(50);
while((PINC & (1<<PC2)) == 0){}
min++;
if (min > 59) min = 0;
}

if((PINC & (1<<PC3)) == 0){                                   //  Кнопки
_delay_ms(50);
while((PINC & (1<<PC3)) == 0){}
hour++;
if (hour > 23) hour = 0;
}

ShowTime(hour, min, sec);
}
return 0;
}
Код немного причесал, но есть ещё вопросы- в частности: весь проект выложить можно?- и интересует выставление фьюзов контролёра.
Вымогатель припоя
Сообщения: 593
Зарегистрирован: Ср янв 06, 2010 10:01:46

Сообщение metan »

Может, я и не логичен, конечно. Но я ответил на вопрос
Jack-Sidr писал(а):какая разница в прерывания по совпадению с 255 и прерыванию по переполнению?
Разумеется имея в виду первую часть фразы "по совпадению с 255"
Дальше думайте сами. Тем более что я вам дал 100% рабочий код.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

-Valerius- писал(а):Код немного причесал, но есть ещё вопросы
вот-вот, вопросы есть. например, вот это вот что такое и зачем?
-Valerius- писал(а):unsigned char bin[64] = {
0b00000000,
0b00100000,
0b00010000,
0b00110000,
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 91
Зарегистрирован: Сб фев 17, 2018 00:08:56

Сообщение Jack-Sidr »

1.Фьюзы я не менял, только внутрение конденсаторы отключил.
2. Пробовал я по совпадению с 127, но так как часы спешили, решил попробовать с 128, ведь это по идее должно замедлить ход.
3.

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

void ShowTime(char h, char m, char s){   // функция динамической индикации
PORTB = bin[h]; //выводы PB0-5 подключены к светодиодами, выставляем часы двоичным кодом. 
PORTD |= (1 <<PD5);  //открываем n-p-n транзистор столбика с часами
_delay_ms(1); //без задержки транзистор не успевает полностью закрыться, и светятся все столбики
PORTD &= ~(1 <<PD5); //закрываем транзистор часов
PORTB = bin[m];  // выставляем минуты
PORTD |= (1 <<PD6); // открываем транзистор минут
_delay_ms(1);
PORTD &= ~(1 <<PD6); // закрываем
PORTB = bin[s]; //секунды
PORTD |= (1 <<PD7);
_delay_ms(1);
PORTD &= ~(1 <<PD7);
}
4. Почему именно предделитель на 256 и сравнение с 127, а не предделитель на 128 и сравнение с 255, разве во втором случае не точнее будет?
Последний раз редактировалось Jack-Sidr Вт фев 20, 2018 08:01:50, всего редактировалось 1 раз.
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

В идеальных условиях, если по совпадению

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

OCR2=0x7E; 1 секунда

OCR2=0x80; 1,0078 секунды

OCR2=0x7E; 0,99219 секунды
В последних двух видим что за 3600 секунд +-28секунд набегает.

Я делал так (кварц китайский, по всей видимости не на 32768)
Спойлер

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

// Timer/Counter 2 initialization
// Clock source: Crystal on TOSC1 pin
// Clock value: PCK2/128
// Mode: Normal top=0xFF
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=(0<<EXCLK) | (1<<AS2);
TCCR2A=(0<<COM2A1) | (0<<COM2A0) | (0<<COM2B1) | (0<<COM2B0) | (0<<WGM21) | (0<<WGM20);
TCCR2B=(0<<WGM22) | (1<<CS22) | (0<<CS21) | (1<<CS20);
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;


interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
// Place your code here
TCNT2 = 128; 
   if(++t_milli ==2)
   {t_milli=0;
   if (++t_second==60)
   {
      t_second=0;
      if (++t_minute==60)
      {
       TCNT2--; // здесь вношу корректировку
       t_minute=0;
       if (++t_hour==24)
       {
        t_hour=0;
       }
      }
   } 
   }
}
В результате за 72 часа убежали на 0,5-1 секунды.
Встал на лапы
Аватара пользователя
Сообщения: 91
Зарегистрирован: Сб фев 17, 2018 00:08:56

Сообщение Jack-Sidr »

Похоже на правду, и убегает примерно на столько, прийду домой попробую потом отпишусь.

Добавлено after 4 hours 35 minutes 33 seconds:
[uquote="ARV",url="/forum/viewtopic.php?p=3312601#p3312601"]
-Valerius- писал(а):Код немного причесал, но есть ещё вопросы
вот-вот, вопросы есть. например, вот это вот что такое и зачем?
-Valerius- писал(а):unsigned char bin[64] = {
0b00000000,
0b00100000,
0b00010000,
0b00110000,
[/uquote]

Часы выводят время двоичным кодом, а поскольку у меня не получилось развести выводы в правильном порядке, это по сути костыль, а вообще посмотрев в шапку, можно найти фото часов, и понять это)
Встал на лапы
Аватара пользователя
Сообщения: 91
Зарегистрирован: Сб фев 17, 2018 00:08:56

Сообщение Jack-Sidr »

[uquote="-Valerius-",url="/forum/viewtopic.php?p=3312505#p3312505"]Код немного причесал, но есть ещё вопросы- в частности: весь проект выложить можно?- и интересует выставление фьюзов контролёра.[/uquote]

Не знаю как, но ваше "причесевание" помогло, оставлял на ночь, и за 8,5 часов набежало лишних 30 секунд, что, безусловно шаг вперед.
Модератор
Аватара пользователя
Сообщения: 19055
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

лишних 30 секунд за 8,5 часов - это примерно 0,1%. но для часов это плохо...
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Мой уютный бложик... заходите!
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 91
Зарегистрирован: Сб фев 17, 2018 00:08:56

Сообщение Jack-Sidr »

Именно, они отображают время не на индикаторах, а на светодиодных столбиках двоичным кодом, поэтому и нужны числа от 0 до 59 в двоичном коде. (Пожалуйста, посмотри в шапку, там есть фото собранных часов, и они никак не похожи на обычные часы)
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Jack-Sidr писал(а):поэтому и нужны числа от 0 до 59 в двоичном коде
а 64 варианта зачем? :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Ответить

Вернуться в «AVR»