Код: Выделить всё
/*
* Clock.cpp
*
* Created: 12.12.2012 14:45:41
* Author: Триод
*/
#ifndef F_CPU
# define F_CPU 16000000 /* 16 MHz */
#endif
#include <avr/io.h>
#include <avr/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
//массив во флэш-памяти для русских символов
const char Decode2Rus[255-192+1] PROGMEM = {
0x41,0xA0,0x42,0xA1,0xE0,0x45,0xA3,0xA4,
0xA5,0xA6,0x4B,0xA7,0x4D,0x48,0x4F,0xA8,
0x50,0x43,0x54,0xA9,0xAA,0x58,0xE1,0xAB,
0xAC,0xE2,0xAD,0xAE,0xAD,0xAF,0xB0,0xB1,
0x61,0xB2,0xB3,0xB4,0xE3,0x65,0xB6,0xB7,
0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0x6F,0xBE,
0x70,0x63,0xBF,0x79,0xE4,0x78,0xE5,0xC0,
0xC1,0xE6,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7 };
volatile unsigned char hours=0, minutes=0, seconds=00, flag=1;
volatile unsigned char count=0, btn2=0, btn3=0, btn4=0;
volatile unsigned char btn2l=0, btn3l=0, btn4l=0;
//Комманды управления дисплеем
#define LCD_CLEAR 0x01
#define LCD_HOME 0x02
#define LCD_ON 0x0C
#define LCD_OFF 0x08
#define LCDPORT PORTD
#define LCDDDR DDRD
#define LCD_PIN_RS PORTD2
#define LCD_PIN_E PORTD3
#define LCD_PIN_D4 PORTD4
#define LCD_PIN_D5 PORTD5
#define LCD_PIN_D6 PORTD6
#define LCD_PIN_D7 PORTD7
#define LCD_STRING_ADR(adr) (0x80|adr) //Позиция вывода символа
#define COMMAND 0
#define DATA 1
#define sbi(reg, bit) (reg|=(1<<bit))
#define cbi(reg, bit) (reg&=~(1<<bit))
#define ckbi(reg, bit) reg & (1<<bit)
#define LED_PORT PORTC
#define BTN_PORT PINC
#define LED_GREEN PORTC0
#define LED_RED PORTC1
#define BUTTON2 PINC2
#define BUTTON3 PINC3
#define BUTTON4 PINC4
#define short_press 3 //Короткое нажатие
#define long_press 10 //Длинное нажатие
//#define _delay_ms //
//#define _delay_us //
//Тактирование LCD
void lcd_clk()
{
sbi(LCDPORT,LCD_PIN_E);
_delay_ms(1);
cbi(LCDPORT,LCD_PIN_E);
_delay_ms(1);
}
//отправка байта в LCD
void lcd_send(unsigned char type, unsigned char c)
{
if (type==COMMAND)
{cbi(LCDPORT,LCD_PIN_RS);}//RS=0 - комманда
else
{sbi(LCDPORT,LCD_PIN_RS);}
//Передача старшего полубайта
if (bit_is_set(c,7))
{ sbi(LCDPORT,LCD_PIN_D7);}
else
{cbi(LCDPORT,LCD_PIN_D7);}
if (bit_is_set(c,6))
{ sbi(LCDPORT,LCD_PIN_D6);}
else
{cbi(LCDPORT,LCD_PIN_D6);}
if (bit_is_set(c,5))
{ sbi(LCDPORT,LCD_PIN_D5);}
else
{cbi(LCDPORT,LCD_PIN_D5);}
if (bit_is_set(c,4))
{ sbi(LCDPORT,LCD_PIN_D4);}
else
{cbi(LCDPORT,LCD_PIN_D4);}
lcd_clk();
//Передача младшего полубайта
if (bit_is_set(c,3))
{ sbi(LCDPORT,LCD_PIN_D7);}
else
{cbi(LCDPORT,LCD_PIN_D7);}
if (bit_is_set(c,2))
{ sbi(LCDPORT,LCD_PIN_D6);}
else
{cbi(LCDPORT,LCD_PIN_D6);}
if (bit_is_set(c,1))
{ sbi(LCDPORT,LCD_PIN_D5);}
else
{cbi(LCDPORT,LCD_PIN_D5);}
if (bit_is_set(c,0))
{ sbi(LCDPORT,LCD_PIN_D4);}
else
{cbi(LCDPORT,LCD_PIN_D4);}
lcd_clk();
}
void lcd_write(char*t) //Отображение строки символов
{
unsigned char i;
for (i=0;i<255;i++)
{
if (t[i]==0)
{
return;
}
else
{
if (t[i]>=192)
{
lcd_send(DATA, pgm_read_byte(&(Decode2Rus[t[i]-192])));
}
else
{
lcd_send(DATA, t[i]);
}
}
}
}
void lcd_init() //Инициализация LCD
{
LCDPORT=0x00;
LCDDDR=0xff;
_delay_ms(50);
//Конфигурирование 4-хбитного режима
sbi(LCDPORT,LCD_PIN_D5);
sbi(LCDPORT,LCD_PIN_D4);
lcd_clk();
_delay_us(50);
lcd_clk();
_delay_us(50);
lcd_clk();
_delay_us(50);
cbi(LCDPORT,LCD_PIN_D4);
lcd_clk();
_delay_ms(3);
lcd_send(COMMAND, 0x28);
lcd_send(COMMAND, LCD_OFF);
lcd_send(COMMAND, LCD_CLEAR);
lcd_send(COMMAND, LCD_ON);
}
void inttolcd(unsigned int posi, long value)
{
char buff[16];
itoa(value,buff,10);
lcd_send(COMMAND,LCD_STRING_ADR(posi));
lcd_write(buff);
}
void puttolcd(unsigned int posi, int value)
{
lcd_send(COMMAND,LCD_STRING_ADR(posi));
lcd_send(DATA, value);
}
void char_to_lcd(unsigned int posi, char* str)
{
lcd_send(COMMAND, LCD_STRING_ADR(posi));
lcd_write(str);
}
void clearlcd()
{
lcd_send(COMMAND,LCD_CLEAR);
}
void InitTIMER1 (void)
{
//With 16 MHz clock and 65536 times counting T/C1 overflow interrupt
// will occur every:
// 1<<CS12 1048.576 mS (Fclk/256)
//TCCR1B = (1<<CS12);
sbi(TCCR1B, CS12);
//коррекция счетчика, чтобы время было ровно 1 секунда
TCNT1 = 3035;
/* Enable timer 1 overflow interrupt. */
//TIMSK = (1<<TOIE1);
sbi(TIMSK,TOIE1);
}
void InitTIMER0()
{ sbi(TCCR0, CS02);
sbi(TCCR0, CS00);
sbi(TIMSK,TOIE0);
//(Fclk/1024)
}
void check_btn2 ()
{
if (~ckbi(BTN_PORT, BUTTON2)) //Если кнопка нажата, инкреминируем флаг btnX,
{ //но держим его в границах от 0 до long_press
if (btn2==long_press)
{
btn2=long_press;
btn2l=1;
}
else
{
btn2++;
}
}
else
{
if (btn2==0)
{
btn2=0;
}
else
{
btn2=0;
btn2l=0;
}
};
};
void check_btn3 ()
{
if (~ckbi(BTN_PORT, BUTTON3)) //Если кнопка нажата, инкреминируем флаг btnX,
{ //но держим его в границах от 0 до long_press
if (btn3==long_press)
{
btn3=long_press;
btn3l=1;
}
else
{
btn3++;
}
}
else
{
if (btn3==0)
{
btn3=0;
}
else
{
btn3=0;
btn3l=0;
}
};
};
void check_btn4 ()
{
if (~ckbi(BTN_PORT, BUTTON4)) //Если кнопка нажата, инкреминируем флаг btnX,
{ //но держим его в границах от 0 до long_press
if (btn4==long_press)
{
btn4=long_press;
btn4l=1;
}
else
{
btn4++;
}
}
else
{
if (btn4==0)
{
btn4=0;
}
else
{
btn4=0;
btn4l=0;
}
};
};
ISR (TIMER0_OVF_vect)
{//Опрашиваем кнопки по таймеру. Если нажата-инкреминируемсчётчик, если отпущена - сбрасываем.
//Как только счётчик дойдёт до какого-то значения, обрабатываем нажатие
//Ждём три "оборота"таймера
if (count++>1)
{
count=0;
check_btn2();
check_btn3();
check_btn4();
}
}
ISR (TIMER1_OVF_vect)
{ //Счётчик времени
TCNT1 =3035;
if (seconds++==59)
{
seconds=0;
if (minutes++==59)
{
minutes=0;
if (hours++==23)
{
hours=0;
}
}
}
flag=1;
}
void Led_Btn_Init()
{
//Настраиваем вход (кнопки)
cbi(DDRC,DDRC2);
cbi(DDRC, DDRC3);
cbi(DDRC, DDRC4);
//Подтяжка
sbi(PORTC,PORTC2);
sbi(PORTC,PORTC3);
sbi(PORTC,PORTC4);
//Настраиваем выходы (светодиоды)
sbi(DDRC, DDRC0);
sbi(LED_PORT, LED_GREEN);
sbi(DDRC, DDRC1);
sbi(LED_PORT,LED_RED);
}
void display_time()
{ //Формируем строку вида HH:MM:SS и выводим её на экран
char hr[2], mn[2], sc[2], tm[9];
if (hours<10)
{
itoa(hours,hr,10);
hr[1]=hr[0];
hr[0]='0';
}
else
{
itoa(hours,hr,10);
};
tm[0]=hr[0];
tm[1]=hr[1];
if (minutes<10)
{
itoa(minutes,mn,10);
mn[1]=mn[0];
mn[0]='0';
}
else
{
itoa(minutes,mn,10);
};
tm[3]=mn[0];
tm[4]=mn[1];
if (seconds<10)
{
itoa(seconds,sc,10);
sc[1]=sc[0];
sc[0]='0';
}
else
{
itoa(seconds,sc,10);
};
tm[6]=sc[0];
tm[7]=sc[1];
tm[2]=':';
tm[5]=':';
tm[8]=0;
cli();
char_to_lcd(0x40, tm);
sei();
}
void inc_minute()
{
if (minutes++==59)
{
minutes=0;
if (hours++==23)
{
hours=0;
}
}
display_time();
}
void inc_hour()
{
if (hours++==23)
{
hours=0;
}
display_time();
}
int main(void)
{
Led_Btn_Init();
InitTIMER1();
InitTIMER0();
lcd_init();
lcd_write("Местное время");
sei();
while(1)
{
//----Установка минут кнопкой
if ((btn3>=short_press)&&(btn3l==0)) //Короткое нажатие
{
cbi(LED_PORT, LED_GREEN);
inc_minute();
_delay_ms(50);
}
else
{
sbi(LED_PORT,LED_GREEN);
};
if (btn3l) //Длинное нажатие
{
cbi(LED_PORT, LED_RED);
inc_minute();
_delay_ms(50);
}
else
{
sbi(LED_PORT,LED_RED);
};
//---------------
//-------Установка часов кнопкой
if ((btn2>=short_press)&&(btn2l==0)) //Короткое нажатие
{
inc_hour();
_delay_ms(50);
};
if (btn2l) //Длинное нажатие
{
inc_hour();
_delay_ms(50);
};
//---------------------
//Сброс секунд кнопкой
if ((btn4>=short_press)&&(btn4l==0)) //Короткое нажатие
{
seconds=0;
display_time();
TCNT1 = 3035;//Перезапускаем таймер
};
if (btn4l) //Длинное нажатие
{
seconds=0;
display_time();
TCNT1 = 3035;//Перезапускаем таймер
};
//---------------------
while(flag==1)
{
display_time();
flag=0;
};
};
}