0

我有一张包含 AVR atmega64A 与 DS3231 连接的电子卡,但是当我尝试读取时间和日期并将它们分配给 7 SEGMENTS 时,什么都没有显示(我认为组件之间没有通信)。

这是我的代码:

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_ */

I2cc

#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;
}

实时时钟

#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

#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);  
}

我的主程序:

主程序

#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;
}

我放了这条指令: output_high(PORTG, LED); 查看程序挂起的位置。

因为我没有允许我在程序执行时调试程序的 JTAG,所以我发现程序在读取数据时挂起。在此指令中: RTC_GetTime(&t);

为什么 ?

谢谢

4

1 回答 1

1

禁用“ATmega103 兼容性”保险丝位。ATmega64A 默认以 ATmega103 兼容模式发货,此模式不支持 I2C (TWI)。

于 2017-02-20T07:24:14.113 回答