28.03.2024, Четверг, 23:09
01.10.2013 в 01:47
Секундомер на ATMega8A
Итак, таймер доработан на предмет возможности остановки отсчёта времени с просмотром результата - количества набежавших секунд (и их десятых долей).
В схеме пришлось освободить пин PD2 под прерывание INT0, сегмент С переброшен на PD7, а сегмент DP (десятичная точка) выкинут на PB1.
Соответственно лёгкая правка кода в этой части в комментариях не нуждается (тем более, что структуру цифр в виде массивов-слов одного порта удалось сохранить, а вот на битву с адекватной работой схемы в Протеусе ушло немало времени.
Проблема решена после прочтения вот этого текста:

необходимо  получить  гашение  на  короткий период  индикатора  при  смене  разрядов,  а  произойти  оно  может  при  подаче  уровней  логических нулей  на  сегменты  индикатора,  т.е.  во  все  разряды  порта  PortB,  к  которым  они  подключены. 
Сделать это можно двумя командами: 

Код
movlw b'00000000' ; записать все нули в регистр аккумулятор 
movwf   PortB      ; записать содержимое аккумулятора в  PortB

 
Адаптируя к имеющимся условия, получаем, что  PORTD надо выставлять в единицу (отключая тем самым все сегменты индикатора) перед каждым включением каждого разряда, как-то так:
           PORTD=0xff;   
           PORTD=digit[n];   
           PORTC=razryad[0]; 
           delay_ms(5);
           PORTD=0xff; 
           PORTD=digit[i];   
           PORTC=razryad[1]; 
           delay_ms(5);
          ...
Ну и весьма немало времени убито на "остановку времени",  сорри за каламбур.
Но ведь, начав криэйтить, и подойдя столь близко к ожидаемому результату, 

нельзя 

Алсо, схема:


Полный листинг программы в CodeVisionAVR:

#include <io.h> 
#include <delay.h> 

   int i,j,k,n;    // дякую тобі, Боже, що С - не C#
 static flash unsigned char digit[] =   
 { 
   (0b01000100), //0 
   (0b01111101), //1 
   (0b10100100), //2  // сегмент С теперь на месте DP, а DP - на PORTB.1
   (0b00110100), //3 
   (0b00011101), //4 
   (0b00010110), //5 
   (0b00000110), //6 
   (0b01111100), //7 
   (0b00000100), //8 
   (0b00010100) //9   
 }; 
     
 static flash unsigned char razryad[] =   
 { 
   (1), //0 
   (2), //1 
   (4), //2 
   (8), //3 
 };      
     
void lampON()
{
PORTB.0=1;
DDRB.0=1;
}

void lampOff()
{
PORTB.0=0;
DDRB.0=1;
while (1) 
   { 
       PORTD=0xff;   
       PORTD=digit[n];   
       PORTC=razryad[0]; 
       delay_ms(5);
       PORTD=0xff; 
       PORTD=digit[i];   
       PORTC=razryad[1]; 
       delay_ms(5);   
       PORTD=0xff;   
       PORTB.1=0; // точка    
       PORTC=razryad[2];   
       delay_ms(2);  
       PORTB.1=1; // выкл. точку
       PORTD=digit[k]; 
       PORTC=razryad[2];    // включать после каждого обновления сегмента надо!   
       delay_ms(3);
       PORTD=0xff;   
       PORTD=digit[j/5]; // десятые доли   
       PORTC=razryad[3];   
       delay_ms(5);
   }  
}
          
interrupt [EXT_INT0] void ext_int0_isr(void)
{
if (PINB.0==0) lampON();
 else lampOff();
}    

 void main(void) 
 { 
  // DDRD.2=0; // теперь D2 - не сегмент, а вход для прерывания
  // PORTD.2=1;   
   SREG|= (1<<7); //разрешаем общие прерывания
   GICR|=(1<<6);   //разрешаем прерывание по INT0    
   MCUCR|=(1<<1); //прерывание по ниспадающему фронту сигнала на INT0    
   DDRB=0x7; 
   PORTB=0b00000010;  
   PORTD=0x00;   
   DDRD=0b11111111; 
   PORTC=0xF;   
   DDRC=0xF;//0b11111111; 
     
 while (1) 
  {   
   for(n=0;n<10;n++) 
   {   
    for(i=0;i<10;i++) 
    { 
       for(k=0;k<10;k++) 
       { 
           for(j=0;j<50;j++) 
           { 
           PORTD=0xff;   
           PORTD=digit[n];   
           PORTC=razryad[0]; 
           delay_ms(5);
           PORTD=0xff; 
           PORTD=digit[i];   
           PORTC=razryad[1]; 
           delay_ms(5);   
           PORTD=0xff;   
           PORTB.1=0; // точка    
           PORTC=razryad[2];   
           delay_ms(2);  
           PORTB.1=1; // выкл. точку
           PORTD=digit[k]; 
           PORTC=razryad[2];  
           delay_ms(3);
           PORTD=0xff;   
           PORTD=digit[j/5]; // десятые доли   
           PORTC=razryad[3];   
           delay_ms(5);   
           }   
       } 
    } 
   } 
 } 
 }


Видео-свидетельство успеха прилагается 
(дизайн прототипа платы, конечно, не для слабонервных:), но как для программиста - сойдёт)



В Протеусе тоже все добре:


Казалось бы, что тут ещё добавишь... но совершенству нет предела:), дребезг кнопки ресета, например, устранить можно (а то и вовсе оставить одну кнопку - ресет по второму нажатию после остановки), обратный отсчёт времени реализовать, так что to be continue...

Количество просмотров: 3974. Комментариев: 2
1 Admin   (13.10.2013 13:13) [Материал]
Доработано, результат описан здесь: http://herozero.do.am/news....0-13-16
dth="100%" cellspacing="0" cellpadding="0" class="commTable">
Имя *:
Email:
Подписка:1
Код *: