Спойлер
Код: Выделить всё
#define F_CPU 9600000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define QDEL _delay_loop_2(3)
#define HDEL _delay_loop_2(5)
#define I2C_PORT PORTB
#define I2C_PIN PINB
#define I2C_DDR DDRB
#define SDA PB3
#define SCL PB4
#define SCL_LOW I2C_DDR|=((1<<SCL))
#define SCL_HIGH I2C_DDR&=(~(1<<SCL))
#define SDA_LOW I2C_DDR|=((1<<SDA))
#define SDA_HIGH I2C_DDR&=(~(1<<SDA))
#define RTC_ADR 0x68
#define SEC_ADR 0x00
#define MIN_ADR 0x01
#define HOUR_ADR 0x02
#define DAY_ADR 0x04
#define MONTH_ADR 0x05
#define YEAR_ADR 0x06
#define LED PB0
#define PIN_INT0 PB1
#define RELAY PB2
#define RELAY_ON PORTB|=((1<<RELAY))
#define RELAY_OFF PORTB&=(~(1<<RELAY))
#define LED_ON PORTB|=((1<<LED))
#define LED_OFF PORTB&=(~(1<<LED))
volatile uint8_t button_flag;
void I2C_Init(void);
void I2C_Start(void);
void I2C_Stop(void);
uint8_t I2C_WriteByte(uint8_t data);
uint8_t I2C_ReadByte(uint8_t ack);
uint8_t RTC_Read(uint8_t adr);
void RTC_Write(uint8_t adr, uint8_t data);
void RTC_SetValue(uint8_t val, uint8_t adr);
static uint8_t RTC_ReadValue(uint8_t adr);
ISR(INT0_vect)
{
button_flag = 1;
_delay_ms(500);
}
int main(void)
{
uint8_t hour = 0;
button_flag = 0;
DDRB = 0xff;
I2C_Init();
DDRB &= ~(1<<PIN_INT0);
PORTB |= (1<<PIN_INT0); // Включаем подтягивающий резистор
GIMSK |= (1<<INT0); // Разрешаем внешнее прерывание на int0
MCUCR &= ~(1<<ISC01)|(1<<ISC00); // Настраиваем условие прерывания
LED_ON;
RELAY_OFF;
sei();
while((hour > 0x10 && hour < 0x22) || button_flag == 1)
{
hour = RTC_Read(HOUR_ADR);
_delay_ms(300);
}
button_flag = 0;
cli();
while(1)
{
LED_OFF;
RELAY_ON;
}
}
void I2C_Init(void)
{
uint8_t i;
I2C_PORT&=(1<<SDA);
I2C_PORT&=(1<<SCL);
for(i=0;i<10;i++)
{
SCL_HIGH;
HDEL;
SCL_LOW;
HDEL;
}
SDA_HIGH;
SCL_HIGH;
}
void I2C_Start(void)
{
SCL_HIGH;
HDEL;
SDA_LOW;
HDEL;
}
void I2C_Stop(void)
{
SDA_LOW;
HDEL;
SCL_HIGH;
QDEL;
SDA_HIGH;
HDEL;
}
uint8_t I2C_WriteByte(uint8_t data)
{
uint8_t i;
for(i=0;i<8;i++)
{
SCL_LOW;
QDEL;
if(data & 0x80)
SDA_HIGH;
else
SDA_LOW;
HDEL;
SCL_HIGH;
HDEL;
while((I2C_PIN & (1<<SCL))==0);
data=data<<1;
}
SCL_LOW;
QDEL;
SDA_HIGH;
HDEL;
SCL_HIGH;
HDEL;
uint8_t ack=!(I2C_PIN & (1<<SDA));
SCL_LOW;
HDEL;
return ack;
}
uint8_t I2C_ReadByte(uint8_t ack)
{
uint8_t data=0x00;
uint8_t i;
for(i=0;i<8;i++)
{
SCL_LOW;
HDEL;
SCL_HIGH;
HDEL;
while((I2C_PIN & (1<<SCL))==0);
if(I2C_PIN &(1<<SDA))
data|=(0x80>>i);
}
SCL_LOW;
QDEL;
if(ack)
{
SDA_LOW;
}
else
{
SDA_HIGH;
}
HDEL;
SCL_HIGH;
HDEL;
SCL_LOW;
HDEL;
return data;
}
uint8_t RTC_Read(uint8_t adr)
{
uint8_t ack, data;
I2C_Start();
ack = I2C_WriteByte((RTC_ADR<<1)|0);
if(!ack) return 0;
ack = I2C_WriteByte(adr);
if(!ack) return 0;
I2C_Start();
ack = I2C_WriteByte((RTC_ADR<<1)|1);
data = I2C_ReadByte(0);
I2C_Stop();
return data;
}
void RTC_Write(uint8_t adr, uint8_t data)
{
uint8_t ack;
I2C_Start();
ack = I2C_WriteByte((RTC_ADR<<1)|0);
if(!ack) return;
ack = I2C_WriteByte(adr);
if(!ack) return;
ack = I2C_WriteByte(data);
if(!ack) return;
I2C_Stop();
}
void RTC_SetValue(uint8_t val, uint8_t adr)
{
val = ((val/10) << 4)|(val%10);
RTC_Write(adr, val);
}
uint8_t RTC_ReadValue(uint8_t adr)
{
uint8_t value;
value = RTC_Read(adr);
value = (((value&0xF0)>>4)*10)+(value&0x0F);
return value;
}


