в архиве имеются проект с исходниками и файл протеуса почему то не работает переписал с CV на WIN AWR ну и мк сменил с тини 2313 на мегу8
Код: Выделить всё
/******************************************************
Простой Кодовый замок на ATmega8
В устройстве примененён LCD дисплей 16x2
для пользовательского интерфейса.
Код написан и скомпилирован в avr-gcc + Studio AVR.
******************************************************/
//ATmega8
#define F_CPU 1600000UL
#include <avr/io.h> // Библиотека ввода/вывода
#include <util/delay.h> // Библиотека для работы с задержками
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include "lcd.h"
//*****************************************************************************
unsigned char temp; // Вспомогательный регистр
//*****************************************************************************
//Константы
#define LOAD_DDR DDRB
#define LOAD_PORT PORTB // Порт для управления соленойдом замка PORTB.3
#define LOAD_POS PB3 // Порт для управления соленойдом замка PORTB.3
// инициализация энергонезависимой памяти для хранения кода и установка его "1111"
EEMEM unsigned char eeprom_kod[4]={'1','1','1','1'};
// массив символов, соответствующих кнопкам на клавиатуре
const unsigned char buttons[3][4] PROGMEM = {{'1','4','7','*'},{'2','5','8','0'},{'3','6','9','#'}};
// переменные для хранения промежуточных данных
unsigned char kod[4], nkod[4], nkod2[4];
unsigned char i,j,k,n,state;
//*****************************************************************************
//;***********************Модуль инициализации*********************************
void setup(void);
//***********************Инициализация портов В/В******************************
void setup(void){
DDRD= 0b00000001; // Настраиваем порт D на вывод (передача на радиомодуль) D1 на ввод
PORTD=0b11111100; // по умолчанию в ноль. Все остальные порты на ввод без резисторов.
DDRB= 0b11111111; // Настраиваем порты на вывод.
PORTB=0b00000000; //
DDRC=0b00000111; // PC3-PC6 ввод на матрицу клавиатуры строки
// PC0-PC2 ввод с матрицы клавиатуры столбцы
PORTC=0b01111000; // Включаем подтягивающие резисторы на PB3-PB6
//*****************************************************************************
InitLCD(0); // Инициализируем LCD
// считываем текущий код из энергонезависимой памяти
kod[0]=eeprom_kod[0];
kod[1]=eeprom_kod[1];
kod[2]=eeprom_kod[2];
kod[3]=eeprom_kod[3];
LCDClear(); // Очищаем дисплей.
LCDWriteString(" Kodoviy zamok "); // Приветсвие при включении устройства.
LCDWriteStringXY(0,1," v0.1 "); // Наименование устройства.
_delay_ms(8000); // пауза, чтобы можно было
_delay_ms(8000); // прочитать приветствие
LCDClear(); // Очищаем дисплей.
state=0; // устанавливаем состояние 0 (ввод кода)
} // Конец модуля инициализации
//*******************************************************************************
void Wait(uint8_t n){
uint8_t i,temp;
temp=n*28;
for(i=0;i<temp;i++)
_delay_loop_2(0);
}
//*******************************************************************************
void LoadOn(){ // Подпрограмма включения нагрузки.
LOAD_PORT|=(1<<LOAD_POS);
}
//*******************************************************************************
void LoadOff(){ // Подпрограмма выключения нагрузки.
LOAD_PORT&=(~(1<<LOAD_POS));
}
//*******************************************************************************
// Опрос клавиатуры для замка
//*******************************************************************************
char key_press(){ // функция опроса клавиатуры
while(1){ //
while((~PINC & 0b01111000)!=0); // ничего не делать, пока не отпустят кнопку
for(i=0;i<3;i++){ // цикл перебора столбцов
PORTC=0xff & ~(0x01 << i);
for(j=3;j<7;j++){ // цикл перебора строк
if((PINC & (0x01 << j))==0){ // проверка нажатия на кнопу
_delay_ms(100); // пауза для исключения дребезга контактов
if(buttons[i][j-3]=='*'){ // дополнительная проверка для кнопки смены пароля
for(k=0;((PINC & (0x01 << j))==0 && k<100);k++){
_delay_ms(50); // пауза
}
if((PINC & (0x01 << j))==0){ // если удерживаем кнопку смены пароля больше 5 сек
state=1; // то устанавливаем состояние 1 (смена пароля)
return 0; // и выходим из функции, возвращая вместо символа ноль
}
else return buttons[i][j-3]; // если меньше 5 сек, то возвращаем символ
}
if((PINC & (0x01 << j))==0) return buttons[i][j-3]; // возвращаем символ
} // конец проверки нажатия на кнопу
} // конец цикла перебора строк
} // конец цикла перебора столбцов
} // конец while(1)
} // конец char key_press()
//*******************************************************************************
char key_obrabotka(){
while(1){
switch (state){
case 0: // режим "0" - ввод кода
LCDClear(); // Очищаем дисплей.
LCDWriteStringXY(0,0,"Vvedite kod:"); // просим ввести код
LCDWriteStringXY(0,1," "); // переводим курсор на начало второй строки
for(n=0;n<4;n++){ // опрашиваем клавиатуру и записывам символы в массив nkode[]
k=key_press(); // Вызываю функцию опроса клавиатуры
if(k==0)break; // если ф-я опроса клавиатуры вернула "0", то прекращаем ввод кода
nkod[n]=k; // иначе, сохраняем полученый символ в nkode[]
LCDWriteStringXY(0,1,"*"); // выводим на дисплей "*"
}
if(k==0)break; // если ф-я опроса вернула "0", то прервыаем выполнение оператора switch
// в результате он будет выполнен сначала и мы перейдем к смене кода
while(key_press()!='#'); // дожидаемся нажатия "#" в подтверждение ввода кода
// проверяем, совпадает ли ввеленный код с сохраненным в памяти
// если да - открываем замок, а если нет, то ничего не делаем
// потом, в любом случае, переходим к вводу пароля
if(nkod[0]==kod[0] && nkod[1]==kod[1] && nkod[2]==kod[2] && nkod[3]==kod[3]){
LCDClear(); // Очищаем дисплей
LCDWriteStringXY(0,0,"Kod verniy"); // Выводим текст
LoadOn(); // Подпрограмма включения нагрузки.
_delay_ms(2500); // Время удержания электромагнита замка
LoadOff(); // Подпрограмма выключения нагрузки.
_delay_ms(2500); // пауза для прочтения текста
}else{
LCDClear(); // Очищаем дисплей
LCDWriteStringXY(0,0,"Kod ne verniy!"); // Выводим текст
_delay_ms(5000); // пауза для прочтения текста
}
break; // выходим из оператора switch
case 1: // режим "1" - изменение пароля
LCDClear(); // Очищаем дисплей
LCDWriteStringXY(0,0,"Izmenenie koda"); // Выводим текст
_delay_ms(5000); // пауза для прочтения текста
LCDClear(); // Очищаем дисплей
LCDWriteStringXY(0,0,"Stariy kod:"); // Выводим текст
_delay_ms(5000); // пауза для прочтения текста
for(n=0;n<4;n++){
k=key_press();
if(k==0)break;
nkod[n]=k;
LCDWriteStringXY(0,1,"*"); // выводим на дисплей "*"
}
if(k==0)break;
while(key_press()!='#');
if(nkod[0]!=kod[0] || nkod[1]!=kod[1] || nkod[2]!=kod[2] || nkod[3]!=kod[3]){
LCDClear(); // Очищаем дисплей
LCDWriteStringXY(0,0,"Kod ne verniy!"); // Выводим текст
_delay_ms(5000); // пауза для прочтения текста
state=0;
break;
}
LCDClear(); // Очищаем дисплей
LCDWriteStringXY(0,0,"Noviy kod:"); // Выводим текст
_delay_ms(5000); // пауза для прочтения текста
for(n=0;n<4;n++){
k=key_press();
if(k==0)break;
nkod[n]=k;
LCDWriteStringXY(0,1,"*"); // выводим на дисплей "*"
}
if(k==0)break;
while(key_press()!='#');
LCDClear(); // Очищаем дисплей
LCDWriteStringXY(0,0,"Povtorite kod:"); // Выводим текст
_delay_ms(5000); // пауза для прочтения текста
for(n=0;n<4;n++){
k=key_press();
if(k==0)break;
nkod2[n]=k;
LCDWriteStringXY(0,1,"*"); // выводим на дисплей "*"
}
if(k==0)break;
while(key_press()!='#');
if(nkod[0]!=nkod2[0] || nkod[1]!=nkod2[1] || nkod[2]!=nkod2[2] || nkod[3]!=nkod2[3]){
LCDClear(); // Очищаем дисплей
LCDWriteStringXY(0,0,"Ne sovpadayut!"); // Выводим текст
_delay_ms(5000); // пауза для прочтения текста
state=0;
break; // выходим из оператора switch
}else{
// сохраняем новый код в энергонезависимую память
eeprom_kod[0]=nkod2[0];
eeprom_kod[1]=nkod2[1];
eeprom_kod[2]=nkod2[2];
eeprom_kod[3]=nkod2[3];
// обновляем текущий код в оперативной памяти
kod[0]=nkod2[0];
kod[1]=nkod2[1];
kod[2]=nkod2[2];
kod[3]=nkod2[3];
LCDClear(); // Очищаем дисплей
LCDWriteStringXY(0,0,"Kod izmenen!"); // Выводим текст
_delay_ms(5000); // пауза для прочтения текста
state=0;
}
break; // выходим из оператора switch
}
};
}// конец char key_obrabotka()
//*******************************************************************************
// Основной програмный цикл.
//*******************************************************************************
int main(void){
setup(); // Вызываю функцию инициализации МК
while(1){
key_obrabotka();
} // конец while(1)
return 1;
}
