logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[atmega8][Bascom] problem z odczytem czasu z PCF8583

Regan_3000 15 Lut 2010 18:09 2635 4
REKLAMA
  • #1 7698704
    Regan_3000
    Poziom 15  
    Witam.
    Co jest zle w tym kodzie?
    Na wyświetlaczu za miast czasu wyświetla mi się wartość 165:165:165

    Kod:
    $crystal = 16000000
    $regfile = "m8def.dat"                                      'deklaracja zmiennej określającej godziny
    
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5
    
    Config Sda = Portd.7
    Config Scl = Portd.6
    I2cinit
    
    
    Dim M As Byte
    Dim S As Byte
    Dim H As Byte
    Dim Dzien As Byte
    Cursor Off
    Cls
    S = Makebcd(44)
    M = Makebcd(40)
    H = Makebcd(17)
    Dzien = Makebcd(1)
    I2cstart
    I2cwbyte 160
    I2cwbyte 0
    I2cwbyte 8
    I2cstop
    I2cstart
    I2cwbyte 160
    I2cwbyte 2
    I2cwbyte S
    I2cwbyte M
    I2cwbyte H
    I2cwbyte Dzien
    I2cstop
    
    Do
    
    I2cstart
    I2cwbyte 160
    I2cwbyte 2
    I2cstart
    I2cwbyte 161
    I2crbyte S , Ack
    I2crbyte M , Ack
    I2crbyte H , Ack
    I2crbyte Dzien , Nack
    I2cstop
    
    S = Makedec(s)
    M = Makedec(m)
    H = Makedec(h)
    
    Locate 1 , 1
    Lcd H ; ":" ; M ; ":" ; S
    Locate 2 , 1
    Lcd Dzien
    Loop
  • REKLAMA
  • #2 7709244
    tadzik85
    Poziom 38  
    sprawdź działanie funkcji BCD();
  • REKLAMA
  • #3 7760831
    vetron
    Poziom 12  
    Witam. Właśnie stawiam swoje pierwsze kroki z pcfem i analizowałem Twój kod. Wydaje mi się że na nóżkę A0 masz podaną 1 logiczną, w związku z czym adres do zapisu jest 162 a do odczytu 163. W swoim kodzie zmień 160 na 162 dla zapisu i 161 na 163 dla odczytu. Po tych modyfikacjach program chodzi poprawnie z wyjątkiem wyświetlania danych na wyświetlaczu.
  • REKLAMA
  • #4 8001514
    dawidc
    Poziom 11  
    @Regan_3000
    Czy któraś z sugestii powyżej rozwiązała Twój problem?

    Mam identyczny problem. (Jestem na Atmedze16/8MHz)
    Pisze w C, zegar działa poprawnie gdyż obsersuję na oscyloskopie transmisję danych (zauważam zmianę dziesiątek sekund/sekund/minut w bcd na linii SDA), zapewne coś siedzi w kodzie.
    (PCF8583 podpięcie: SCL,SDA -> przez rezystory podciągające 5,6k do Atmegi16 /wykorzystuję twi Atmegi/, A0->masa, /INT -> N/C, OSCI i OSCO do kwarcu 32kHz, dodatkowo OSCI przez 33pF do Vcc /5V/ )

    plik "i2c.h":
    
    
    #include <avr/io.h> 
    
    #define SCL PC0 
    #define SDA PC1 
    
    #define uDLY 5 
    
    #define SDA_0 PORTC&=~_BV(SDA) 
    #define SDA_1 PORTC|=_BV(SDA) 
    #define SCL_0 PORTC&=~_BV(SCL) 
    #define SCL_1 PORTC|=_BV(SCL) 
    #define R_SDA bit_is_set(PINC,7) 
    
    //unsigned char i2cflag;                                  
    
                                          
    void i2c_delay(unsigned int p);                          
    void i2c_writebyte(unsigned char byte);                  
    unsigned char i2c_readbyte(void);                        
    void i2c_write(unsigned char deviceaddr, unsigned char address, unsigned char data);    
    unsigned char i2c_read(unsigned char deviceaddr, unsigned char address); 
    


    plik "i2c.c":
    
    
    #include "i2c.h" 
    
    void i2c_delay(unsigned int p) 
    { 
      unsigned int i; 
      unsigned char j; 
      for(i=0;i<p;i++) 
        for (j=0;j<10;j++); 
    } 
    
    
    void i2c_writebyte(unsigned char byte) 
    { 
        unsigned char i; 
    
        for (i=0;i<8;i++) { 
            if (byte>127) SDA_1; else SDA_0; 
            i2c_delay(uDLY); 
            SCL_1; i2c_delay(uDLY); 
            SCL_0; i2c_delay(uDLY); 
            byte<<=1; 
        } 
        SDA_1; i2c_delay(uDLY); 
        SCL_1; i2c_delay(uDLY); 
        DDRC&=~_BV(DDC4); 
        //if (R_SDA) i2cflag=0; else i2cflag=1; 
        SCL_0; i2c_delay(uDLY); 
        DDRC|=_BV(DDC4); 
    } 
    
    
    unsigned char i2c_readbyte(void) 
    { 
        unsigned char i,byte=0; 
    
        DDRC&=~_BV(DDC4);                      
        for (i=0;i<8;i++) { 
            byte<<=1; 
            if (R_SDA) byte|=1; 
            i2c_delay(uDLY); 
            SCL_1; i2c_delay(uDLY); 
            SCL_0; i2c_delay(uDLY); 
        } 
        DDRC|=_BV(DDC4);                      
        SDA_1; i2c_delay(uDLY); 
        SCL_1; i2c_delay(uDLY); 
        SCL_0; i2c_delay(uDLY); 
        return(byte); 
    } 
    
    
    void i2c_write(unsigned char deviceaddr, unsigned char address, unsigned char data) 
    { 
        unsigned char byte; 
        SDA_1; SCL_1; i2c_delay(uDLY); 
        SDA_0; i2c_delay(uDLY); 
        SCL_0; i2c_delay(uDLY); 
        byte=deviceaddr;                    
        i2c_writebyte(byte); 
        byte=address;                        
        i2c_writebyte(byte); 
        byte=data;                          
        i2c_writebyte(byte); 
        SDA_0; i2c_delay(uDLY); 
        SCL_1; i2c_delay(uDLY); 
        SDA_1; i2c_delay(uDLY); 
        for (byte=0;byte<255;byte++) {      
            SCL_0; i2c_delay(uDLY); 
            SCL_1; i2c_delay(uDLY); 
        } 
    } 
    
    
    unsigned char i2c_read(unsigned char deviceaddr, unsigned char address) 
    { 
        unsigned char byte; 
        SDA_1; SCL_1; i2c_delay(uDLY);      
        SDA_0; i2c_delay(uDLY);             // 
        SCL_0; i2c_delay(uDLY);             // 
        byte=deviceaddr;                    
        i2c_writebyte(byte); 
        byte=address;                        
        i2c_writebyte(byte); 
        SCL_1; i2c_delay(uDLY); 
        SDA_0; i2c_delay(uDLY); 
        SCL_0; i2c_delay(uDLY); 
        byte=deviceaddr+1;                  
        i2c_writebyte(byte); 
        byte=i2c_readbyte();                
        SDA_0; i2c_delay(uDLY);              
        SCL_1; i2c_delay(uDLY);             // 
        SDA_1; i2c_delay(uDLY);             // 
        return(byte); 
    } 
    
    



    przykładowy main.c:
    
    
    #include <avr/io.h> 
    #include <avr/delay.h> 
    #include <stdlib.h> 
    #include "i2c.h" 
    #include "lcd.h" 
    
    char bufor[10],bufor2[10]; 
    
    #define RTCAddress 0xa0
    #define ControlReg 0 
    
    void SetRTC (unsigned char *p) 
    {   unsigned char i; 
    
        for (i=1;i<=6;i++) 
        i2c_write(RTCAddress, i, *p++); 
        i2c_write(RTCAddress, ControlReg, 0x00); 
    } 
    
    void GetRTC (unsigned char *p) 
    {   unsigned char i; 
    
        for (i=1;i<=6;i++) 
        *p++=(i2c_read(RTCAddress, i)); 
        i2c_write(RTCAddress, ControlReg, 0x00); 
    } 
    
    void i2c_init() 
    { 
        DDRC|=_BV(SDA); 
        DDRC|=_BV(SCL); 
    } 
    
    
    
    int main(void) 
    { 
    
        unsigned char RtcBuffer[6]; 
        unsigned char hours, minutes, seconds, hundredths; 
        unsigned char year, month, day; 
    
    i2c_init(); 
    
      /* sample how to set clock (see PDF for registers) 
        RtcBuffer[0] = 0x78; 
        RtcBuffer[1] = 0x56; 
        RtcBuffer[2] = 0x34; 
        RtcBuffer[3] = 0x12; 
        RtcBuffer[4] = 0x30; 
        RtcBuffer[5] = 0x12; 
        SetRTC (&RtcBuffer); 
       */ 
    
    lcdinit();   
    lcdcls();
    
    while (1) 
    { 	
    
        		GetRTC(RtcBuffer);
    						
    		hours=10*(RtcBuffer[3] >> 4 & 0x3) + (RtcBuffer[3] & 0xf); 
                    minutes=10*(RtcBuffer[2] >> 4) + (RtcBuffer[2] & 0xf); 
                    seconds=10*(RtcBuffer[1] >> 4) + (RtcBuffer[1] & 0xf); 
                    hundredths=10*(RtcBuffer[0] >> 4) + (RtcBuffer[0] & 0xf); 
                    year=99; 
                    month=10*(RtcBuffer[5] >> 4 & 0x1) + (RtcBuffer[5] & 0xf); 
                    day=10*(RtcBuffer[4] >> 4 & 0x3) + (RtcBuffer[4] & 0xf); 
    				 
    	itoa(seconds,bufor,10);
    	lcdxy(0,0);
    	lcdwrite(bufor);
    
    	itoa(hundredths,bufor,10);
    	lcdxy(0,0);
    	lcdwrite(bufor);
    
    	itoa(month,bufor,10);
    	lcdxy(0,0);
    	lcdwrite(bufor);
    
    	itoa(day,bufor,10);
    	lcdxy(0,0);
    	lcdwrite(bufor);
    
    	itoa(year,bufor,10);
    	lcdxy(0,0);
    	lcdwrite(bufor);   
    	
    
    } 
    return 0; 
    } 
    



    Czytam o tym i2c już trochę, na forum są podobne tematy ale nikt nie pisze jak to rozwiązać, i w czym siedzi problem. Nie mogę wymyślić co jest nie tak, a czas nagli. Gdyby ktoś miał chwilkę czasu aby sprawdzić, lub chociaż naprowadzić mnie na właściwy trop byłbym niezmiernie wdzięczny :)


    //biblioteki ściągnąłem chyba z forum... ale szukałem tego tematu i nie potrafię na niego trafić ponownie
REKLAMA