Код: Выделить всё
/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
This program was produced by the
CodeWizardAVR V2.05.3 Standard
Automatic Program Generator
© Copyright 1998-2011 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project : GUARD
Version : 1.0
Date : 23.01.2013
Author : TOB
Comments: Кодовый замок c приводом от автомобильного замка.
Для смены кода, подать питание с нажатыми кнопками 1234, после сигнала ввести код.
Chip type : ATtiny2313A
AVR Core Clock frequency: 4,000000 MHz
Memory model : Tiny
External RAM size : 0
Data Stack size : 32
*////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <tiny2313A.h>
#include <delay.h>
#define DOOR_STATUS (1<<0) //флаг закрытой двери
#define ACTUATOR_STATUS (1<<1) //флаг закрытого замка
#define PGM_MODE (1<<2) //флаг режим программирования
#define OPEN_KEY (1<<3) //флаг кнопка "ОТКРЫТЬ" нажата
#define CODE_COMPARE (1<<4) //флаг правильный код
#define NEW_CODE (1<<5) //флаг введен новый код
#define NEW_PRES (1<<6) //флаг начало ввода нового кода
#define OPEN_PIN PINB.7 //кнопка "ОТКРЫТЬ" (0-нажата)
#define DOOR_PIN PIND.6 //датчик двери (0-закрыта)
#define KEY_PORT PINB //пины клавиатуры
#define REL_OPEN_PIN PORTD.0 //пин реле открытия замка
#define REL_CLOSE_PIN PORTD.1 //пин реле закрытия замка
#define BUSER_PIN PORTD.5 //пин пищалки
#define CLOSE 1 //для процедуры актюатора
#define OPEN 0 //для процедуры актюатора
#define ACTUATOR_DELAY 1000 //мс, длительность импульса привода
#define AVTO_CLOSE_DELAY 600 //10с, число тактов 0.0163с, задержка автоматического закрытия, если дверь не открыли
#define CLOSE_DELAY 300 //5с, число тактов 0.0163с, задержка перед закрытием (должно выполняться условие AVTO_CLOSE_DELAY>=CLOSE_DELAY)
#define KEY_DELAY 2 //32мс, число тактов 0.0163с, период сканирования кнопок
#define INPUT_DELAY 60 //2с, максимальная пауза при вводе кода, число сканирований клавиатуры
#define CODE_SIZE 4 //число символов кода
#define KEY_SIZE 6 //число сканируемых кнопок
flash char KEY_MASS[12]= //массив ASCII кодов кнопок
{
0x30, //0
0x31, //1
0x32, //2
0x33, //3
0x34, //4
0x35, //5
0x36, //6
0x37, //7
0x38, //8
0x39, //9
0x0F, //*
0x23 //#
};
flash char NOTE_MASS[45][2]= //массив нот
{
/*
500кГц Частота Нота
239 2093 C7
213 2349 D7
190 2637 E7
179 2794 F7
159 3136 G7
142 3520 A7
127 3951 H7
*/
159,700, //пи
142,100, //бриу бриу
159,50,
142,50,
159,100,
0,25,
179,50,
190,100,
213,25,
190,25,
179,300, //па па па паам
0,400,
179,300,
0,400,
179,300,
0,200,
255,1000,
213,100, //брынь
0,50,
190,100,
0,50,
179,100,
0,50,
159,100,
0,50,
142,50, //сирена
159,50,
179,50,
190,50,
213,50,
239,50,
213,50,
190,50,
179,50,
159,50,
142,50
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
eeprom unsigned char eep_code[CODE_SIZE];
unsigned char real_code[CODE_SIZE];
unsigned char input_code[CODE_SIZE];
unsigned char new_code[CODE_SIZE];
unsigned char status_flag_reg;
unsigned int tim1_ovf_count0, tim1_ovf_count1;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//прерывание по переполнению таймера 1, инкремент счетчиков
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
if (tim1_ovf_count0<2540) tim1_ovf_count0++; //частота сканирования
if (tim1_ovf_count1<2540) tim1_ovf_count1++; //задержка перед закрытием
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//процедура инициализации контроллера
void ini(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out
// State7=P State6=P State5=P State4=P State3=P State2=P State1=P State0=0
PORTB=0xFE;
DDRB=0x01;
// Port D initialization
// Func6=In Func5=Out Func4=In Func3=In Func2=In Func1=Out Func0=Out
// State6=P State5=0 State4=P State3=P State2=P State1=0 State0=0
PORTD=0x5C;
DDRD=0x23;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 500,000 kHz
// Mode: CTC top=OCR0A
// OC0A output: Disconnected
// OC0B output: Toggle on compare match
TCCR0A=0x12;
TCCR0B=0x00;
//TCCR0B=0x02;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 4000,000 kHz
// Mode: Normal top=0xFFFF
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x01;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x80;
// Global enable interrupts
#asm("sei")
}
//процедура управления приводом
void actuator(char action)
{
if (action) {REL_CLOSE_PIN=1; delay_ms(ACTUATOR_DELAY); REL_CLOSE_PIN=0; status_flag_reg|=ACTUATOR_STATUS;} //закрыть замок
else {REL_OPEN_PIN=1; delay_ms(ACTUATOR_DELAY); REL_OPEN_PIN=0; status_flag_reg&=~ACTUATOR_STATUS;} //открыть замок
}
//процедура генерации звуков
void saund(unsigned char first_note, unsigned char last_note)
{
static unsigned char i;
TCCR0B=0x02; //инициализация таймера 500кГц
for (i=first_note; i<last_note; i++) //цикл проигрывания диапазона нот из массива
{
OCR0A=NOTE_MASS[i][0]; //нота (чвстота) в регистр сравнения таймера в режиме СТС
delay_ms(NOTE_MASS[i][1]); //длительность ноты
};
TCCR0B=0x00; OCR0A=0x00; BUSER_PIN=0; //остановить таймер
}
//процедура сканирования датчиков
void sensor(void)
{
if (DOOR_PIN) status_flag_reg&=~DOOR_STATUS; else status_flag_reg|=DOOR_STATUS; //если дверь открыта, то сбросить флаг
if (OPEN_PIN) status_flag_reg&=~OPEN_KEY; else status_flag_reg|=OPEN_KEY; //если кнопка не нажата, то сбросить флаг
}
//процедура сканирования клавиатуры
void key(void)
{
static unsigned char i,j,k,l;
if (l<INPUT_DELAY) l++; //если счетчик определения максимальной паузы при вводе не переполнен, то инкремент
else
{
if (status_flag_reg&NEW_PRES) //если же пауза слишком большая - счетчик переполнен и кнопка была нажата, то
{
saund(10,17); //сигнал превышения паузы при вводе
for (j=0; j<CODE_SIZE; j++) input_code[j]=0; //очистить массив введенного кода
status_flag_reg&=~NEW_PRES; //сбросить флаг нажатия на кнопку
i=0;j=0;k=0; //сброс счетчиков
};
};
for (i=1; i<=KEY_SIZE; i++) //цикл сканирования клавиатуры
{
if ((~KEY_PORT)&(1<<i)) //если сканируемая кнопка нажата, то
{
l=0; //сбрасываем счетчик для определения паузы при вводе
status_flag_reg|=NEW_PRES; //установить флаг нажатия на кнопку
saund(0,1); //сигнал подтверждения нажатия
while((~KEY_PORT)&(1<<i)) {}; //ничего не делать пока кнопка нажата
delay_ms(200); //предотвращение дребезга
input_code[j]=KEY_MASS[i]; //введенный символ заносим в массив ввода
if ((j++)==(CODE_SIZE-1)) //если массив ввода заполнен, то
{
for (j=0; j<CODE_SIZE; j++) new_code[j]=input_code[j]; //введенный код сохранить как новый
status_flag_reg|=NEW_CODE; //установить флаг нового кода
for (j=0; j<CODE_SIZE; j++) if (input_code[j]==real_code[j]) k++; //цикл посимвольной проверки введенного кода
if (k==CODE_SIZE) //если совпали все символы, то
{
status_flag_reg|=CODE_COMPARE; //устанавливаем флаг
saund(17,25); //сигнал подтверждения кода
}
else if(!(status_flag_reg&PGM_MODE))saund(10,17); //иначе, если не режим программирования, то сигнал ошибки
for (j=0; j<CODE_SIZE; j++) input_code[j]=0; //очистить массив введенного кода
status_flag_reg&=~NEW_PRES; //сбросить флаг нажатия на кнопку
i=0;j=0;k=0; //сброс счетчиков
};
};
};
}
//программная процедура
void main(void)
{
static unsigned char i;
ini(); //инициализация контроллера
saund(0,1);
delay_ms(4000); //пауза 5с
if (DOOR_PIN) actuator(OPEN); else actuator(CLOSE); //если дверь открыта, то открыть замок, иначе закрыть замок
if (!(KEY_PORT&0b00011110)) //если при вкл. нажаты кнопки 1234, то начинаем цикл программирование
{
saund(25,35); saund(25,35); //сигнал подтверждения входа в режим программирования
while(!(KEY_PORT&0b00011110)) {}; //ничего не делать пока кнопки нажаты
delay_ms(200); //предотвращение дребезга
status_flag_reg|=PGM_MODE; //установить флаг режима программирования
while (status_flag_reg&PGM_MODE) //цикл выполняется пока есть флаг режима программирования
{
if (tim1_ovf_count0>KEY_DELAY) {tim1_ovf_count0=0; key();}; //периодически сканируется клавиатура
if (status_flag_reg&NEW_CODE) //если введен новый код, то
{
for (i=0; i<CODE_SIZE; i++) eep_code[i]=new_code[i]; //сохранить новый код в ЕЕПРОМ
status_flag_reg&=~NEW_CODE; //сбросить флаг нового кода
status_flag_reg&=~PGM_MODE; //сбросить флаг режима программирования
saund(17,25); //сигнал подтверждения обновления кода
};
};
};
for (i=0; i<CODE_SIZE; i++) real_code[i]=eep_code[i]; //читать код из ЕЕПРОМ
while (1) //цикл рабочего режима
{
if (tim1_ovf_count0>KEY_DELAY) {tim1_ovf_count0=0; sensor(); key();};
switch (status_flag_reg&0b00000011)
{
case 0b00000000: //замок открыт, дверь открыта
{
// saund(1,9); //сигнализация открытой двери
tim1_ovf_count1=AVTO_CLOSE_DELAY-CLOSE_DELAY; //начать отсчет перед закрытием замка
status_flag_reg&=~CODE_COMPARE;
break;
};
case 0b00000001: //замок открыт, дверь закрыта
{
saund(1,9); //сигнализация открытого замка
if (status_flag_reg&OPEN_KEY) tim1_ovf_count1=0; //предотвращает передергивание замка при нажатой кнопке "ОТКРЫТЬ"
if (tim1_ovf_count1>AVTO_CLOSE_DELAY) actuator(CLOSE); //автоматическое закрытие по истечению паузы, если дверь не была открыта
status_flag_reg&=~CODE_COMPARE;
break;
};
case 0b00000010: //замок закрыт, дверь открыта (ошибочная ситуация)
{
actuator(OPEN); //открыть замок
status_flag_reg&=~CODE_COMPARE;
break;
};
case 0b00000011: //замок закрыт, дверь закрыта
{
if ((status_flag_reg&CODE_COMPARE)|(status_flag_reg&OPEN_KEY)) //если флаг верного кода или кнопка "ОТКРЫТЬ" нажато, то
{
actuator(OPEN); //открыть замок
status_flag_reg&=~CODE_COMPARE; //сбросить флаг верного кода
};
tim1_ovf_count1=0; //сбрасывается счетчик для автоматического закрытия
break;
};
};
};
}