I have an electronic card that contains the AVR atmega64A connect with DS3231 but when I try to read the time and date and assign them to the 7 SEGMENTS nothing is displayed (i think no communication between the components).
here you are my code :
I2c.H
#ifndef I2C_H_
#define I2C_H_
#include <avr/io.h>
#include <util/twi.h>
#define F_SCL 400000UL
#define TWBRX0 (((F_CPU/F_SCL)-16)/2)
#define TWBRX1 TWBRX0/4
#define TWBRX2 TWBRX0/16
#define TWBRX3 TWBRX0/64
#define NACK 0
#define ACK 1
#if (TWBRX0<=0xFF)
#define TWBRX TWBRX0
#define TWPSX 0
#elif (TWBRX1<=0xFF)
#define TWBRX TWBRX1
#define TWPSX 1
#elif (TWBRX2<=0xFF)
#define TWBRX TWBRX2
#define TWPSX 2
#elif (TWBRX3<=0xFF)
#define TWBRX TWBRX3
#define TWPSX 3
#else
#define TWBRX 0
#define TWPSX 0
#endif
void I2C_Init(void);
uint8_t I2C_Start(void);
uint8_t I2C_ReStart(void);
void I2C_Stop(void);
uint8_t I2C_Write(uint8_t );
uint8_t I2C_Read(uint8_t );
#endif /* I2C_H_ */
I2c.c
#include "i2c.h"
void I2C_Init(void)
{
TWBR = TWBRX;
TWSR = TWPSX;
}
uint8_t I2C_Start( void )
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_START)
return 0;
return 1;
}
uint8_t I2C_ReStart( void )
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_REP_START)
return 0;
return 1;
}
void I2C_Stop( void )
{
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
while(TWCR & (1<<TWSTO));
}
uint8_t I2C_Write( uint8_t data)
{
TWDR = data;
TWCR = (1<<TWINT)|(1<<TWEN) ;
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_MT_SLA_ACK)
return 0;
return 1;
}
uint8_t I2C_Read( uint8_t ACK_NACK)
{
while (!(TWCR & (1<<TWINT)));
TWCR = (ACK_NACK)?((1<<TWINT)|(1<<TWEN)|(1<<TWEA)):((1<<TWINT)|(1<<TWEN));
while (!(TWCR & (1<<TWINT)));
return TWDR;
}
Rtc.h
#ifndef RTC_H_
#define RTC_H_
#include "i2c.h"
typedef struct
{
uint8_t Second; /* 0..59 */
uint8_t Minute; /* 0..59 */
uint8_t Hour; /* 1..7 */
}Hora_t;
typedef struct
{
uint8_t Day; /* 1.. 31 */
uint8_t Month; /* 1..12 */
uint8_t Year; /* 00..99 */
}Fecha_t;
typedef struct
{
Hora_t hora;
Fecha_t fecha;
}RTC_t;
#define DS3231_SECONDS 0x00
#define DS3231_MINUTES 0x01
#define DS3231_HOURS 0x02
#define DS3231_WEEKDAY 0x03
#define DS3231_DAYS 0x04
#define DS3231_MONTHS 0x05
#define DS3231_YEARS 0x06
#define MASK_SEC 0b01111111
#define MASK_MIN 0b01111111
#define MASK_HORA 0b00111111
#define MASK_DIA 0b00111111
#define MASK_MES 0b00011111
#define MASK_ANIO 0b11111111
#define DS3231_READ 0b11010001
#define DS3231_WRITE 0b11010000
void RTC_Init();
uint8_t DS3231_GetReg(uint8_t );
void DS3231_SetReg(uint8_t , uint8_t );
void RTC_SetHora (Hora_t* );
void RTC_SetFecha(Fecha_t* );
void RTC_GetHora (Hora_t* );
void RTC_GetFecha(Fecha_t* );
void RTC_GetTime(RTC_t *);
void RTC_SetTime(RTC_t * );
#endif /* RTC_H_ */
Rtc.c
#include "rtc.h"
void RTC_Init()
{
I2C_Init();
}
uint8_t DS3231_GetReg( uint8_t address)
{
uint8_t ret;
I2C_Start();
I2C_Write(DS3231_WRITE);
I2C_Write(address);
I2C_ReStart();
I2C_Write(DS3231_READ);
ret = I2C_Read(NACK);
I2C_Stop();
return ret;
}
void DS3231_SetReg( uint8_t address, uint8_t val)
{
I2C_Start();
I2C_Write(DS3231_WRITE);
I2C_Write(address);
I2C_Write(val);
I2C_Stop();
}
void RTC_SetHora( Hora_t * hora)
{
I2C_Start();
I2C_Write(DS3231_WRITE);
I2C_Write(DS3231_SECONDS);
I2C_Write(hora->Second);
I2C_Write(hora->Minute);
I2C_Write(hora->Hour);
I2C_Stop();
}
void RTC_SetFecha( Fecha_t * fecha)
{
I2C_Start();
I2C_Write(DS3231_WRITE);
I2C_Write(DS3231_DAYS);
I2C_Write(fecha->Day);
I2C_Write(fecha->Month);
I2C_Write(fecha->Year);
I2C_Stop();
}
void RTC_GetHora( Hora_t* hora)
{
I2C_Start();
I2C_Write(DS3231_WRITE);
I2C_Write(DS3231_SECONDS);
I2C_ReStart();
I2C_Write(DS3231_READ);
hora->Second = (I2C_Read(ACK))& MASK_SEC;
hora->Minute = (I2C_Read(ACK))& MASK_MIN;
hora->Hour = (I2C_Read(NACK))& MASK_HORA;
I2C_Stop();
}
void RTC_GetFecha( Fecha_t* fecha )
{
I2C_Start();
I2C_Write(DS3231_WRITE);
I2C_Write(DS3231_DAYS);
I2C_ReStart();
I2C_Write(DS3231_READ);
fecha->Day = (I2C_Read(ACK)) & MASK_DIA;
fecha->Month = (I2C_Read(ACK)) & MASK_MES;
fecha->Year = (I2C_Read(NACK)) & MASK_ANIO;
I2C_Stop();
}
void RTC_GetTime( RTC_t * rtc)
{
RTC_GetHora(&rtc->hora);
RTC_GetFecha(&rtc->fecha);
}
void RTC_SetTime( RTC_t * rtc)
{
RTC_SetHora(&rtc->hora);
RTC_SetFecha(&rtc->fecha);
}
And my main program :
Main.c
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "rtc.h"
static const uint8_t Pattern[] = {
0b00010100, // 0
0b00111111, // 1
0b10011000, // 2 0b00100010
0b00011010, // 3
0b00110011, // 4
0b01010010, // 5
0b01010000, // 6 0b00000100
0b00011111, // 7
0b00010000, // 8
0b00010010, // 9
0b11111111}; // BLANK
#define LED PG3 // pin 18
#define output_low(port,pin) port &= ~(1<<pin)
#define output_high(port,pin) port |= (1<<pin)
#define set_input(portdir,pin) portdir &= ~(1<<pin)
#define set_output(portdir,pin) portdir |= (1<<pin)
#define HC595_DS_POS PC4 //Data pin (DS) pin location
#define HC595_SH_CP_POS PC5 //Shift Clock (SH_CP) pin location
#define HC595_ST_CP_POS PC6 //Store Clock (ST_CP) pin location
#define HC595_PORT PORTC
#define HC595_DDR DDRC
void IE74595_Out(uint8_t *p, unsigned char n)
{
unsigned char i, j;
uint8_t b;
output_low(HC595_PORT,HC595_ST_CP_POS);
output_low(HC595_PORT,HC595_SH_CP_POS);
for(j=0;j<n;j++)
{
b = Pattern[*(p+n-j-1)]; // Lay byte cao nhat truoc
// b = Pattern[*(p+j)]; // Lay byte cao nhat truoc
for(i=0;i<8;i++)
{
output_low(HC595_PORT,HC595_SH_CP_POS);
if(b & 0b00000001)
{
//MSB is 1 so output high
output_high(HC595_PORT,HC595_DS_POS);
}
else
{
//MSB is 0 so output low
output_low(HC595_PORT,HC595_DS_POS);
}
_delay_us(100);
output_high(HC595_PORT,HC595_SH_CP_POS);
b=b>>1; //Now bring next bit at MSB position
}
}
//_delay_us(5);
output_high(HC595_PORT,HC595_ST_CP_POS);
}
int main(void)
{
set_output(DDRC,HC595_DS_POS);
set_output(DDRC,HC595_SH_CP_POS);
set_output(DDRC,HC595_ST_CP_POS);
set_output(DDRG, LED);
//uint8_t Tempurature_C[2];
uint8_t Date_Clock[40]={5,9,1,6,1,1,0,9,1,7,1,5,4,2,6,2,8,7,0,7,1,2,3,5,1,5,4,2,1,7,5,9,1,9,4,8,1,5,2,3};
RTC_t t ;
RTC_Init();
uint8_t Annee;
uint8_t Mois;
uint8_t Jour;
uint8_t Heure;
uint8_t Munites;
uint8_t Secondes;
while (1)
{
RTC_GetTime(&t);
Annee = t.fecha.Year;
Mois = t.fecha.Month;
Jour = t.fecha.Day;
Heure = t.hora.Hour;
Munites = t.hora.Minute;
Secondes = t.hora.Second;
Date_Clock[40] = 2;
Date_Clock[39] = 0;
Date_Clock[38] = Annee/10;
Date_Clock[37] = Annee%10;
Date_Clock[36] = Mois/10;
Date_Clock[35] = Mois%10;
Date_Clock[34] = Jour/10;
Date_Clock[33] = Jour%10;
Date_Clock[32] = Heure/10;
Date_Clock[31] = Heure%10;
Date_Clock[30] = Munites/10;
Date_Clock[29] = Munites%10;
Date_Clock[28] = Secondes/10;
Date_Clock[27] = Secondes%10;
IE74595_Out(Date_Clock,40);
}
return 1;
}
I put this instruction: output_high(PORTG, LED); to see where the program hangs.
Because I do not have a JTAG that allows me to debug the program at the time of its execution I found that the program hangs when reading data. In this instruction : RTC_GetTime(&t);
Why ?
Thank's
Disable "ATmega103 Compatibility" Fuse bit. ATmega64A is by default shipped in ATmega103 compatibility mode and I2C (TWI) is not supported in this mode.