Ура, всё заработало - часы исправно идут. Не хватало лишь вот такой строчки в функции вывода чисел на лампы "DDRD=(1<<DS)|(1<<SH_CP)|(1<<ST_CP);" :D
Вот весь код:
Код
#include <avr/io.h>
#include <util/twi.h>
#define DS 0
#define SH_CP 1
#define ST_CP 2
#define adr_ds1307 0b11010000 //адресс на запись в ds1307
#define TWI_START 0
#define TWI_RESTART 1
#define TWI_STOP 2
#define TWI_TRANSMIT 3
#define TWI_RECEIVE_ACK 4
#define TWI_RECEIVE_NACK 5
unsigned char bin_digits[10]=
{
0b0000, //0
0b1000, //1
0b0100, //2
0b1100, //3
0b0010, //4
0b1010, //5
0b0110, //6
0b1110, //7
0b0001, //8
0b1001, //9
};
unsigned char twi(unsigned char action)
{
switch(action)
{
case TWI_START:
case TWI_RESTART:
TWCR = (1<<TWSTA) | (1<<TWEN) | (1<<TWINT) | (1<<TWIE);
break;
case TWI_STOP:
TWCR = (1<<TWSTO) | (1<<TWEN) | (1<<TWINT) | (1<<TWIE);
break;
case TWI_TRANSMIT:
TWCR = (1<<TWEN) | (1<<TWINT) | (1<<TWIE);
break;
case TWI_RECEIVE_ACK:
TWCR = (1<<TWEN) | (1<<TWINT) | (1<<TWEA)| (1<<TWIE);
break;
case TWI_RECEIVE_NACK:
TWCR = (1<<TWEN) | (1<<TWINT) | (1<<TWIE);
break;
}
if(action != TWI_STOP) while (!(TWCR & (1<<TWINT)));
return (TWSR & 0b11111000);
}
unsigned char i2c_read(unsigned char adr_slave, unsigned char adr_byte)
{
unsigned char readed_byte;
twi(TWI_START); //формируем сигнал START
TWDR=adr_slave; //загружаем адрес slave на запись
twi(TWI_TRANSMIT); //передаем адрес
TWDR=adr_byte; //загружаем адрес байта
twi(TWI_TRANSMIT); //передаем
twi(TWI_RESTART); //формируем рестарт (RESTART)
TWDR=adr_slave|1; //загружаем адрес DS1307 на чтение
twi(TWI_TRANSMIT); //передаем
twi(TWI_RECEIVE_ACK); //получаем подтверждение от slave
readed_byte=TWDR; //в "readed_byte" записываем принятый байт
twi(TWI_RECEIVE_NACK); //после чтения байта формируем NACK - больше данные не нужны
twi(TWI_STOP); //формируем сигнал STOP
return readed_byte;
}
void i2c_send(unsigned char adr_slave, unsigned char adr_byte, unsigned char data_byte)
{
twi(TWI_START); //формируем сигнал START
TWDR=adr_slave; //загружаем адрес slave на запись
twi(TWI_TRANSMIT); //передаем адрес
TWDR=adr_byte; //загружаем адрес байта
twi(TWI_TRANSMIT); //передаем
twi(TWI_RECEIVE_ACK); //получаем подтверждение от slave
TWDR=data_byte; //загружаем байт данных
twi(TWI_TRANSMIT); //передаем
twi(TWI_RECEIVE_ACK); //
twi(TWI_STOP); //формируем сигнал STOP
}
void OutBitFromByte(unsigned char out_bit_num, unsigned char input_bit_num, unsigned char input_byte)
{
unsigned char port=PORTD;
port&=~(1<<out_bit_num);
if (input_byte&(1<<input_bit_num))
port|=(1<<out_bit_num);
PORTD=port;
}
//===========================================функция записи данных в регистр 74HC595===========================================
void HC595_write(unsigned char d0, unsigned char d1, unsigned char d2, unsigned char d3, unsigned char d4, unsigned char d5)
{
DDRD=(1<<DS)|(1<<SH_CP)|(1<<ST_CP);
unsigned char i,j;
unsigned char dig[6];
dig[0]=d0;
dig[1]=d1;
dig[2]=d2;
dig[3]=d3;
dig[4]=d4;
dig[5]=d5;
for(j=0;j<=5;j++)
{
for(i=0; i<4; i++) //цикл для последовательного вывода 4 бит данных из массива
{
OutBitFromByte(DS,i,bin_digits[dig[j]]);
PORTD&=~(1<<SH_CP); //выводим "0" в линию SH_CP
PORTD|=(1<<SH_CP); //выводим "1" в линию SH_CP - считываем бит на входе регистра
}
}
PORTD|=(1<<ST_CP); //выводим "1" в линию ST_CP - "защелкиваем данные"
PORTD&=~(1<<ST_CP); //выводим "0" в линию ST_CP
}
int main(void)
{
TWSR &= ~(1<<TWPS0)|(1<<TWPS1); //биты предделителя
TWBR=114; //Настраиваем частоту шины
//(при 8MHz F_CPU получаем 8000000/(2*(16+114)) = 32kHz)
unsigned char h10, h1, m10, m1, s10, s1; //объявляем переменной для хранения значений часов, минут, секунд
unsigned char temp_byte;
temp_byte=i2c_read(adr_ds1307, 0x00);
if(temp_byte & 0b10000000) //проверяем 8-ой бит (если он "CH" = 1 - значит часы не запущены)
{
i2c_send(adr_ds1307,0x00,0b00000000); //запускаем часы DS1307
}
i2c_send(adr_ds1307,0x07,0b0010000); //задаём частоту генерации на SQW = 1 Hz
while(1)
{
//============секунды==================
temp_byte=i2c_read(adr_ds1307, 0x00); //считываем байт значений секунд
s1= (temp_byte & 0b00001111); //выделяем значение единиц секунд
s10=(temp_byte & 0b11110000)>>4; //выделяем значение десятков секунд
//============минуты===================
temp_byte=i2c_read(adr_ds1307, 0x01); //считываем байт значений минут
m1= (temp_byte & 0b00001111);
m10=(temp_byte & 0b11110000)>>4;
//============часы=====================
temp_byte=i2c_read(adr_ds1307, 0x02); //считываем байт значений часов
h1= (temp_byte & 0b00001111);
h10=(temp_byte & 0b11110000)>>4;
HC595_write(h10,h1,m10,m1,s10,s1); //записываем данные в регистры 74HC595
}
}