Jak na hodiny s PCF8583P v CodeVisionAVR

mám s tim trochu problem sekundy to zobrazuje se záseky tři sekundy probjehnou richle a čtvrtá se spoždením víslední čas je v pořádku
jak to napsat abi to zobracovalo čas normálně
používám nato ATmega168 ale chtel bich to dostat do ATtiny2313 jen to musim umenčít abi se to tam vešlo

tady je program

//8,000000 MHz
#include <mega168.h>
#include <delay.h>
// I2C Bus functions
#asm
.equ __i2c_port=0x05 ;PORTB
.equ __sda_bit=1
.equ __scl_bit=2
#endasm
#include <i2c.h>
#include <pcf8583.h> // PCF8583 Real Time Clock functions
#include <alcd.h> // Alphanumeric LCD Module functions

//nastavení DS18S20
#define WIRE_DDR_OUT DDRD.4=1; //out
#define WIRE_DDR_IN DDRD.4=0; //in
#define WIRE_PORT_1 PORTD.4=1; //‘Px0=1’
#define WIRE_PORT_0 PORTD.4=0; //‘Px0=0’
#define WIRE_PIN PIND.4 //PIN0

unsigned int teplota;
unsigned char i,V,ctenitlacitek;
unsigned char h,m,s,hs; //zde je čas hodini,minuti,sekundi,milisekundi

//statickí promění pro komunikaci s DS18S20
flash unsigned char SKIP_ROM=0xCC;
flash unsigned char READ_SCRATCHPAD=0xBE;
flash unsigned char CONVERT_T=0x44;

//převod čísel z binárního na desítkoví pošle ho na lcd
void VIPIS (unsigned char promnena,unsigned char X,unsigned char Y)
{
unsigned char C=promnena/10;
lcd_gotoxy(X,Y);
lcd_putchar(C+0x30);

       lcd_gotoxy(X+1,Y);
       lcd_putchar((promnena-(C*10))+0x30);
      }; 

//funkce pro DS18S20
void ZAPIS (unsigned char data)
{
//‘ZAPIS’ je vždi dvakrát po ‘RESET’ proto neni v ‘ZAPIS’ nastaven ‘out’ ani vístup (‘PB4=1’) je to v ‘RESET’ jen jednou
for(i=0;i<8;i++)
{
if((data&(1<<i)) > 0)
{
WIRE_PORT_0; //‘PB4=0’
delay_us(5);

           WIRE_PORT_1;      //'PB4=1'              
           delay_us(65);
          }
         else
          {
           WIRE_PORT_0;      //'PB4=0'                  
           delay_us(60);

           WIRE_PORT_1;      //'PB4=1'              
           delay_us(10);
           }         
         };
          
       };

void RESET ()
{
chibaA:
WIRE_DDR_OUT; //out DDRB.4=1;
WIRE_PORT_0; //‘PB4=0’
delay_us(500); //reset (min 480us)

   WIRE_DDR_IN      //in
   WIRE_PORT_1;     //('PB4=1') zapne pull-up 
   delay_us(65);    //čeká než se nabije čídlo (nabijí se min 15us max 60us)
   
   if(WIRE_PIN==1)    //jeli 'PB4=1' chiba opakuje reset 
   {
    delay_us(480);     //po 480us čidlo ukončí komunikaci a je na 'PB4=1' 
    goto chibaA;      //jestli nepřišel present puls tak se vrátí k resetu
   };
   delay_us(480);     //po 480us čidlo ukončí komunikaci a je na 'PB4=1'
   WIRE_DDR_OUT;      //out
   
};      

void CTENI ()
{
teplota=0x0000;

    for(i=0;i<16;i++)                                    
     {                                                  
      WIRE_PORT_0;              //'PB4=0'
      WIRE_DDR_OUT;             //out
      delay_us(5);              //pulz po zkončení čidlo posílá data (min 1us)
        
      WIRE_DDR_IN               //in
      WIRE_PORT_1;              //'PB4=1'
      delay_us(10);            
           
      if((WIRE_PIN)>0)            //jeli 'PB4=1' zapíše do teploti '1' na pozici 'i' -->tedi 0 až 15
       {                        //jeli 'PB4=0' nezapíše nic na pozici zustane puvodní hodnota tedi '0'
        teplota|=(1<<i);                     
       };
      delay_us(55);            //než čidlo dokončí odesílání jednoho bitu
     };             

};

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
#asm(“cli”) //deaktivuje přerušení
TCNT0=0x00; //nasipe do čítače 0x00 čítač počítá odtut!!!

       if(ctenitlacitek>=7)
       {
       if((PINC.5==0)&&(ctenitlacitek>=7))       
        {
         switch(V) 
         { 
          case 1: 
                h++; 
                if(h>=24) 
                {
                 h=0; 
                };
          break;      
          case 2:   
                m++; 
                if(m>=60) 
                {
                 m=0; 
                };
          break;      
          case 3:              
                s++; 
                if(s>=60) 
                {
                 s=0; 
                };
          break;
         };
         ctenitlacitek=0;
        };                                                   //rtc_get_time(0,&h,&m,&s,&hs);
       if((PINC.4==0)&&(ctenitlacitek>=7))       
        {     
         switch(V) 
         { 
          case 1:
                h--; 
                if(h<=0) 
                {
                 h=23; 
                };
                
          break;      
          case 2:             
                m--; 
                if(m<=0) 
                {
                 m=59; 
                };             
          break;      
          case 3:             
                s--; 
                if(s<=0) 
                {
                 s=59; 
                };
          break;
         };                        
         ctenitlacitek=0;
        };          
       if((PINC.3==0)&&(ctenitlacitek>=7))
        {
         V++;
        
         if(V==4)
         {
          rtc_set_time(0,h,m,s,hs);
         }
         if(V>=4)
         {
          V=0; 
         };
         ctenitlacitek=0;
        };                  
       }  
       else
       {
       ctenitlacitek++;     
       };

#asm(“sei”) //aktivuje přerušení
}

void main(void)
{
PORTC=0x38;
DDRC=0x00;

TCCR0B=0x05;
TIMSK0=0x01;

/*
// I2C Bus initialization /
i2c_init();
/

// PCF8583 Real Time Clock initialization /
rtc_init(0,0);
/

// Alphanumeric LCD initialization
// Connections specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTD Bit 5
// RD - PORTD Bit 6
// EN - PORTD Bit 7
// D4 - PORTD Bit 0
// D5 - PORTD Bit 1
// D6 - PORTD Bit 2
// D7 - PORTD Bit 3
// Characters/line: 16 */
lcd_init(16);

//kontrola počáteční hodnoti
RESET();
ZAPIS(SKIP_ROM); //jen kdiž je na dráte 1 čidlo
ZAPIS(READ_SCRATCHPAD); //prikaz pro vipsani teploti (musi nasledovat ‘CTENI ();’)
CTENI (); //čte teplotu

if(teplota==0x00AA) //jeli ‘teplota’ = +85°C vše OK jinak se zavře do smičky
{
;
}
else
{
;
}

lcd_gotoxy(9,0);
lcd_putsf(“: :”);

#asm(“sei”) //aktivuje přerušení
while (1)
{
//příkazi pro meření teploti
RESET();
ZAPIS(SKIP_ROM); //jen kdiž je na dráte 1 čidlo
ZAPIS(CONVERT_T); //prikaz pro meření teploti

  delay_ms(760);             //doba meření pro 9bit=94ms 12bit=750ms  (je to divní mín jak 600ms a procesor načte hodnotu z minulího meření)
       
  //příkazi pro načtení teploti
  RESET();                                 
  ZAPIS(SKIP_ROM);           //jen kdiž je na dráte 1 čidlo
  ZAPIS(READ_SCRATCHPAD);    //prikaz pro vipsani teploti (musi nasledovat 'CTENI ();')
  CTENI ();
   
   if(1==(teplota&(0x01)))   //ovjeří zda teplota končí 0,5 nebo 0 kuli celočíselnímu delení 
   {       
    lcd_gotoxy(3,0);
    lcd_putsf(",5");
   }  
   else 
   {       
    lcd_gotoxy(3,0);
    lcd_putsf(",0");
   }; 
          
  teplota=teplota/2;
  VIPIS(teplota,1,0);    //teplotu
   
  if(V==0)
   { 
    rtc_get_time(0,&h,&m,&s,&hs);         //ctení času
   };
   VIPIS(h,7,0);         //vipiše hodini
    VIPIS(m,10,0);     //minuti
    VIPIS(s,13,0);      //sekundy
  }

}

tady je zevrudní schema

:arrow_right: administrator: přejmenováno z “jak na hodini s PCF8583P v CodeVisionAVR”

Neche sa mi to studovat ale jednu pripomienku mam, zbytocne deley 750ms, a procak sa flaka, bud pouzi casovac alebo odpocitaj cykly v hlavnej slucke medzitym nech procesor nieco robi kontroluje tlacida pise na displej a podobne…

sori že píšu až teť
chápu že se ti to nechce studovat :slight_smile:
tlačitka čtu v přerušení a asi je dam nák na int
skusil sem tam dát místo toho zpoždení tohle :

  for(i=0;i<80;i++)
  {       
  if(V==0)
   { 
    rtc_get_time(0,&h,&m,&s,&hs);         //ctení času
   }; 
    VIPIS(h,7,0);                     //vipíše hodini na 7a8 pozici na LCD 
    VIPIS(m,10,0); 
    VIPIS(s,13,0);      
  };

ale rozumní to moc neni

Tvůj problém je v tom čekání 750ms, čtení RTC taky něco zabere a zápis do LCD taky není z nejrychlejších - a RTC nepočká, takže je jasné, že to všechno do 1 sekundy nestihneš.

Nejjednodušší v tvém případě bude asi do přerušení od čítače přidat nastavení příznaku pro spuštění konverze třeba spust_konverzi

[code]void main(void)
{
PORTC=0x38;
DDRC=0x00;

TCCR0B=0x05;
TIMSK0=0x01;

/*
// I2C Bus initialization /
i2c_init();
/

// PCF8583 Real Time Clock initialization /
rtc_init(0,0);
/

// Alphanumeric LCD initialization
// Connections specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTD Bit 5
// RD - PORTD Bit 6
// EN - PORTD Bit 7
// D4 - PORTD Bit 0
// D5 - PORTD Bit 1
// D6 - PORTD Bit 2
// D7 - PORTD Bit 3
// Characters/line: 16 */
lcd_init(16);

//kontrola počáteční hodnoti
RESET();
ZAPIS(SKIP_ROM); //jen kdiž je na dráte 1 čidlo
ZAPIS(READ_SCRATCHPAD); //prikaz pro vipsani teploti (musi nasledovat ‘CTENI ();’)
CTENI (); //čte teplotu

if(teplota==0x00AA) //jeli ‘teplota’ = +85°C vše OK jinak se zavře do smičky
{
;
}
else
{
;
}

lcd_gotoxy(9,0);
lcd_putsf(": :");

#asm(“sei”) //aktivuje přerušení
while (1)
{
//**odsud změna
if(spust_konverzi)
{
//příkazi pro meření teploti
RESET();
ZAPIS(SKIP_ROM); //jen kdiž je na dráte 1 čidlo
ZAPIS(CONVERT_T); //prikaz pro meření teploti

//příkazi pro načtení teploti
RESET();
ZAPIS(SKIP_ROM); //jen kdiž je na dráte 1 čidlo
ZAPIS(READ_SCRATCHPAD); //prikaz pro vipsani teploti (musi nasledovat ‘CTENI ();’)
CTENI ();

spust_konverzi=0; //vynulování příznaku
}

///*** konec změny
if(1==(teplota&(0x01))) //ovjeří zda teplota končí 0,5 nebo 0 kuli celočíselnímu delení
{
lcd_gotoxy(3,0);
lcd_putsf(",5");
}
else
{
lcd_gotoxy(3,0);
lcd_putsf(",0");
};

teplota=teplota/2;
VIPIS(teplota,1,0); //teplotu

if(V==0)
{
rtc_get_time(0,&h,&m,&s,&hs); //ctení času
};
VIPIS(h,7,0); //vipiše hodini
VIPIS(m,10,0); //minuti
VIPIS(s,13,0); //sekundy
}
}

[/code]

‘‘lou’‘dík ale moc sem to nepochopil do ‘‘spust_konverzi’’ bych musel negde neco zapsat abych mohl ovjeřit podmínku (’‘if(spust_konverzi)’’)

//**odsud změna
if(spust_konverzi)
{
//příkazi pro meření teploti
RESET();
ZAPIS(SKIP_ROM); //jen kdiž je na dráte 1 čidlo
ZAPIS(CONVERT_T); //prikaz pro meření teploti

//příkazi pro načtení teploti
RESET();
ZAPIS(SKIP_ROM); //jen kdiž je na dráte 1 čidlo
ZAPIS(READ_SCRATCHPAD); //prikaz pro vipsani teploti (musi nasledovat ‘CTENI ();’)
CTENI ();

spust_konverzi=0; //vynulování příznaku
}

///*** konec změny

vimislel sem neco takovího

// Timer1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)//16bitoví časocač
{
#asm(“cli”) //deaktivuje přerušení

//’‘do while’'čte čas tak dlouho dokud nedojde ke změňe času
do
{
if(V==0) //čte čas jen kdiž se čas neupravuje
{
rtc_get_time(0,&h,&m,&s,&hs); //ctení času
};
LCD++;***************************************
}while(S==s);
S=s;

//zde plnim čítač vigeneroval to ‘‘CodeVisionAVR’’
// Reinitialize Timer1 value Znovu inicializovat hodnotu časovače
TCNT1H=0xE17A >> 8;
TCNT1L=0xE17A & 0xff;
// Place your code here Umístěte kód zde

VIPIS(LCD,5,1);//*************************************
LCD=0;// '‘LCD’'je tu jen prozatim hlídá kolikrát načte čas za sekundu

if(l==0) //příkazi pro meření teploti
{
l++;
//příkazi pro meření teploti
RESET();
ZAPIS(SKIP_ROM); //jen kdiž je na dráte 1 čidlo
ZAPIS(CONVERT_T); //prikaz pro meření teploti
}
else //vipis teploti
{
l=0;
//příkazi pro načtení teploti
RESET();
ZAPIS(SKIP_ROM); //jen kdiž je na dráte 1 čidlo
ZAPIS(READ_SCRATCHPAD); //prikaz pro vipsani teploti (musi nasledovat ‘CTENI ();’)
CTENI();

if(teplota>=0xFF92) //ovjeří zda teplota je kladná nebo záporná
{
lcd_gotoxy(0,0);
lcd_putsf("-");
teplota=~teplota;
teplota++;
}
else
{
lcd_gotoxy(0,0);
lcd_putsf(" ");
};

if(1==(teplota&(0x01))) //ovjeří zda teplota končí 0,5 nebo 0 kuli celočíselnímu delení
{
lcd_gotoxy(3,0);
lcd_putsf(",5");
}
else
{
lcd_gotoxy(3,0);
lcd_putsf(",0");
};
VIPIS(teplota/2,1,0); //vipíše teplotu
};

//vždi odvážně vipisuje čas
VIPIS(h,7,0);
VIPIS(m,10,0);
VIPIS(s,13,0);

#asm(“sei”) //aktivuje přerušení
}

jednou za sekundu dojde k přerušení
následne čte čas tak dlouho dokud nedojde ke změňe
(pozor ‘‘do while’’ probíhá tak dlouho dokuť je podmínka splnená)
pak naplním čítač plním ho tadi kuli hornímu ‘‘do while’’
v ‘‘LCD’’ je uloženo kolikrát sem načet teplotu v danej sekunďe (3 až 4)
měřim a čtu teplotu poprví měřim další sekundu čtu a vipíšu teplotu jednou za 2s
vipíšu čas
v hlavní smičce nemam nic dřív sem tam měl měření teploti ale dělalo to chyby psalo to znaky i na jiní sloupečky a seklo se to taky parkrát
teť se to neseká ale nefungujou mi tlačítka dam je nák na přerušení jen nevim jak je zapojit

‘‘lou’’ možná by to šlo jednou za sekundu čidlo (DS18S20) by melo tu teplotu změřit za 93.75 ms vrací totiž jen 9-bit hodnotu tich 750 ms by odpovídalo 12-bit aje kdiž počkam mín než 600 ms tak načtu ješte starou teplotu