Читайте также: |
|
Листинг 4.1.1 Код прошивки на Си.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <math.h>
#define SDA PD1
#define SCL PD0
#define READ_PCF 0xa1 //Адрес для чтения
#define WRITE_PCF 0xa0 //Адрес для записи
void init (void)
{
DDRB=0xFF;
DDRC0=1;
DDRC1=1;
DDRC2=1;
DDRC3=1;
DDRC4=1;
PORTC0=1;
PORTC1=1;
PORTC2=1;
PORTC3=1;
PORTC4=1;
DDRD=0b00000011;
PORTD=0b00000000;
TCCR2=0b00000100;
TIMSK=0b00000100;
EIMSK=0b11000000;
TCCR1A=0x00;
TCCR1B=0x09;
ISC00=0;
ISC01=0;
ISC10=0;
ISC11=0;
}
// регистр состояния по умолчанию выставлен в режиме часов со счетом времени изменять его не надо
unsigned char ack=0;
unsigned char data[3]={0,0,0};
unsigned char call[2]={0,12};
unsigned char ind=0;
unsigned char foc=0;
unsigned char pc=0;
unsigned char pt=0;
unsigned int tabkd=3992;
void start_cond (void) //Генерация условия старта
{
PORTD=_BV(SDA)|_BV(SCL);
asm("nop");
PORTD&=~_BV(SDA);
asm("nop");
PORTD&=~_BV(SCL);
}
void send_byte (unsigned char adr) //Отправка байта по I2С
{
unsigned char i;
for (i=0;i<8;i++)
{
if ((adr&0x80)==0x00) PORTD&=~_BV(SDA); //Выставить бит на SDA
else PORTD|=_BV(SDA);
asm("nop");
PORTD|=_BV(SCL); //Записать его импульсом на SCL
asm("nop");
PORTD&=~_BV(SCL);
time=time<<1;
}
DDRD&=~_BV(SDA);
PORTD|=_BV(SDA);
asm("nop");
PORTD|=_BV(SCL);
asm("nop");
if ((PIND&_BV(SDA))==_BV(SDA)) ack=1; //Считать ACK
PORTD&=~_BV(SCL);
PORTD&=~_BV(SDA);
DDRD|=_BV(SDA);
}
unsigned char get_byte (void) //Считывание байта по I2C
{
unsigned char i, res=0;
DDRD&=~_BV(SDA);
PORTD|=_BV(SDA);
for (i=0;i<8;i++)
{
res=res<<1;
PORTD|=_BV(SCL); //Импульс на SCL
asm("nop");
if ((PIND&_BV(SDA))==_BV(SDA)) res=res|0x01;//Чтение SDA
PORTB&=~_BV(SCL);
asm("nop");
}
PORTD&=~_BV(SDA); //Подтверждение ACK
DDRD|=_BV(SDA);
asm("nop");
PORTD|=_BV(SCL);
asm("nop");
PORTD&=~_BV(SCL);
return res;
}
void stop_cond (void) //Генерация условия стоп
{
PORTD=_BV(SCL);
asm("nop");
PORTD&=~_BV(SDA);
asm("nop");
PORTD|=_BV(SDA);
}
void read_time (void) //Считать данные в массив data
{
unsigned char i;
start_cond();
send_byte (WRITE_PCF);
send_byte (0x02);
start_cond();
send_byte(READ_PCF);
for (i=0;i<3;i++)
data[i]=get_byte();
stop_cond();
}
void write_time (void) //Записать данные из массива data
{
unsigned char i;
start_cond();
send_byte (WRITE_PCF);
send_byte (0x02);
for (i=0;i<3;i++)
send_byte (data[i]);
stop_cond();
}
void seven_segment (unsigned char z) // Код 7-сегментного индикатора
{
if (z==0) PORTB=0b00111111; else
if (z==1) PORTB=0b00000110; else
if (z==2) PORTB=0b01011011; else
if (z==3) PORTB=0b01001111; else
if (z==4) PORTB=0b01100110; else
if (z==5) PORTB=0b01101101; else
if (z==6) PORTB=0b01111101; else
if (z==7) PORTB=0b00000111; else
if (z==8) PORTB=0b01111111; else
if (z==9) PORTB=0b01101111;
}
void vivod_time (unsigned char j) // Отображение времени
{
if (j==4)
{
if (data[0]%2==0) PORTD7=1; else PORTD7=0;
}
if (j==3)
{
seven_segment(data[2]\10);
PORTC0=0;
PORTC1=1;
PORTC2=1;
PORTC3=1;
}
if (j==2)
{
seven_segment(data[2]%10);
PORTC0=1;
PORTC1=0;
PORTC2=1;
PORTC3=1;
}
if (j==1)
{
seven_segment(data[1]\10);
PORTC0=1;
PORTC1=1;
PORTC2=0;
PORTC3=1;
}
if (j==0)
{
seven_segment(data[1]%10);
PORTC0=1;
PORTC1=1;
PORTC2=1;
PORTC3=0;
}
}
void vivod_call (unsigned char j) // ОТображение будильника
{
if (j==3)
{
seven_segment(call[2]\10);
PORTC0=0;
PORTC1=1;
PORTC2=1;
PORTC3=1;
}
if (j==2)
{
seven_segment(call[2]%10);
PORTC0=1;
PORTC1=0;
PORTC2=1;
PORTC3=1;
}
if (j==1)
{
seven_segment(call[1]\10);
PORTC0=1;
PORTC1=1;
PORTC2=0;
PORTC3=1;
}
if (j==0)
{
seven_segment(call[1]%10);
PORTC0=1;
PORTC1=1;
PORTC2=1;
PORTC3=0;
}
}
void kor_time (void) // Коррекция времени
{
if (PIND4==0)
{
if (foc==1)
{
if (data[2]<23) data[2]++; else data[2]=0;
data[0]=0;
write_time();
}; else
if (foc==2)
{
if (data[1]<59) data[1]++; else data[1]=0;
data[0]=0;
write_time();
}
}
}
void kor_call (void) // Коррекция будильника
{
if (PIND4==0)
{
if (foc==1)
{
if (call[2]<23) call[2]++; else call[2]=0;
}; else
if (foc==2)
{
if (call[1]<59) call[1]++; else call[1]=0;
}
}
}
void call_signal(void) // Сигнал будильника
{
if (data[0]%2==0)
{
DDRC4=1;
OCR1A=tabkd;
TCCR1A=0x40;
};
else
{
TCCR1A=0x00;
DDRC4=0;
}
}
INTERUPT(TIM2_OVF) // Прерывания по переполнению от таймера счетчика
{
if (foc==0)
{
read_time();
if (ind==0)
{
vivod_time(pt);
if (pt==4) pt=0; else pt++;
}
else
{
vivod_call(pc);
if (pc==3) pc=0; else pc++;
}
if ((data[1]==call[0]) && (data[2]==call[1])) call_signal(); else PORTC4=0;
}; else
{
if (ind==0)
{
kor_time();
vivod_time(pt);
if (pt==4) pt=0; else pt++;
}
else
{
kor_call();
vivod_call(pc);
if (pc==3) pc=0; else pc++;
}
}
}
INTERUPT (EXT_INT0) // Внешнее прерывание от кнопки "Индикация"
{
if (ind==0) ind=1; else ind=0;
}
INTERUPT (EXT_INT1) // Внешнее прерывание от кнопки "Фокус"
{
if (foc<2) foc++; else foc=0;
}
int main(void)
{
init();
sei();
while(1);
return 0;
}
Заключение
В ходе проведенной работы была разработана принципиальная схема и прошивка микроконтроллера для часов с будильником. Исходя из рассмотренных вариантов был выбран наиболее оптимальный для решения поставленной задачи. Осуществлен подбор элементов для схемы и описан принцип работы в виде блок схемы алгоритма программы.
Список литературы
1. cxem.net [Электронный ресурс] // cxem.net – Режим доступа:
http://cxem.net/house/1-199.php
2. radiokot.ru [Электронный ресурс] // Радио кот– Режим доступа:
http://radiokot.ru/circuit/digital/home/11/
3. avr.ru [Электронный ресурс] // www.avr.ru – Режим доступа:
http://avr.ru/ready/measure/time/rtc
4. Datasheet т на микроконтроллер ATmega8
5. Datasheet на микроконтроллер PIC16F628A
6. Datasheet на микросхему-хронометр PCF8583
7. Datasheet на микросхему-хронометр DS1302
8. Белов А.В. Создаем устройства на микроконтроллерах.
Санкт-Петербург. 2007. – 295 с.
9. Хартов В.Я. Микроконтроллеры AVR. Москва. 2007. – 239 с.
Дата добавления: 2015-08-02; просмотров: 90 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Принципиальная электрическая схема | | | Tu che m'hai Preso il Cuor |