МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ «ЛЬВІВСЬКА ПОЛІТЕХНІКА»
ЗВІТ
про виконання лабораторної роботи №5
з курсу “Мікропроцесорні пристрої”
на тему:
“Побудова модуля управління системи контролю доступу
на AVR-мікроконтролерах.
Робота з інтерфейсами 1-Wire, I2C, SPI”
Львів 2009
Мета роботи – ознайомитись з принципами побудови модулів управління систем контролю доступу. Вивчити правила обміну інформацією через інтерфейси 1-Wire, I2C, SPI та ознайомитися з їх програмною реалізацією для AVR-мікроконтролерів на мові С в середовищі CodeVisionAVR.
Варіант №3
Текст програми
// ???? ?????????? ??????? ???????? ??????? ?? ?? ??90S2313 ? iButton DS1990, I2C-RTC DS1307 ?? SPI-EEPROM 25LC256 (32Kx8)
// 09.02.2009 ?.
// ??????? ??????? ?? 7.3728 ???
////////////////////////////////////////////////////////////////////////////////////
// ???? ??? ??????????? iButton DS1990
#asm
.equ __w1_port = 0x18
.equ __w1_bit = 5
#endasm
////////////////////////////////////////////////////////////////////////////////////
// ???? ??? ??????????? I2C-RTC DS1307
#asm
.equ __i2c_port = 0x18
.equ __scl_bit = 2
.equ __sda_bit = 1
#endasm
////////////////////////////////////////////////////////////////////////////////////
#include <90S2313.h>
#include <1wire.h>
#include <i2c.h>
#include <delay.h>
////////////////////////////////////////////////////////////////////////////////////
// ?????????? ???? ????? - ????
typedef unsigned char byte;
////////////////////////////////////////////////////////////////////////////////////
// ????????? ???? ? ????
typedef struct
{
byte Second;
byte Minute;
byte Hour;
byte Day;
byte Date;
byte Month;
byte Year;
} DS1307_Data;
////////////////////////////////////////////////////////////////////////////////////
// ????????? ??????
// ?????????? ??????? ??? ?????????? ????????? ???? ? ????
DS1307_Data DS1307_1;
// ?????????? ??????? ??? ?????????? ????????????????? ?????? iButton DS1990A
byte ROM_Code[9];
////////////////////////////////////////////////////////////////////////////////////
//******************************************************************//
// ?????? SPI-EEPROM 25LC256
#define PORT_EEPROM PORTD
#define DDR_EEPROM DDRD
#define PIN_EEPROM PIND
#define CS 3
#define SCK 4
#define SI 5
#define SO 6
//******************************************************************//
// ?????? I2C-RTC DS1307
#define PORT_RTC PORTB
#define DDR_RTC DDRB
#define PIN_RTC PINB
#define SDA 1
#define SCL 2
//******************************************************************//
// ?????? iButton DS1990A
#define PORT_iButton PORTB
#define DDR_iButton DDRB
#define PIN_iButton PINB
#define Data_iButton 5
//******************************************************************//
// ?????? ???????????? ?????
#define PORT_Switch PORTB
#define DDR_Switch DDRB
#define PIN_Switch PINB
#define Switch 7
//******************************************************************//
// ?????? ???????????
#define PORT_Led PORTB
#define DDR_Led DDRB
#define PIN_Led PINB
#define Led 6
//******************************************************************//
// ?????? ?????? ??????
#define PORT_Out_Key PORTD
#define DDR_Out_Key DDRD
#define PIN_Out_Key PIND
#define Out_Key 2
//******************************************************************//
// ???? ?????? EEPROM 25LC256
#define EEPROM_READ 0x03
#define EEPROM_WRITE 0x02
#define EEPROM_WRDI 0x04
#define EEPROM_WREN 0x06
#define EEPROM_RDSR 0x05
#define EEPROM_WRSR 0x01
//******************************************************************//
// ???? ?????? iButton DS1990
#define SEARCH_ROM 0xF0
//******************************************************************//
// ?????? ????????? iButton
#define DS1990_FAMILY_CODE 0x01
//******************************************************************//
// ????????? ????? ? ???????
#define N_Record 50
//******************************************************************//
// ?????? ?????? ?????? ? ??????
#define Record_Size 16
//******************************************************************//
// ?????? ??????? ??????? ? EEPROM 25LC256
#define Record_Addr 0x40
//******************************************************************//
// ?????? ?????????? ??????? ? EEPROM
#define Record_Count_Addr 0x30
//******************************************************************//
// ??? ??????????? ?????? ? ????????????
#define T_msec 7000
//******************************************************************//
// ????????? ?????????????? ??????
#define N_Key 5
//******************************************************************//
// ??? ??????
#define Input_Record 0
#define Output_Record 1
//******************************************************************//
// E8C52A
// 3D2C90
/*----------------------------------------------------------------*/
// ??????????? ?????????????? ??????????? ??????????? ?? ?????? INT0
interrupt [2] void ext_interrupt0(void);
/*----------------------------------------------------------------*/
void Pin_Init(void);
// ??????? ???????? ????? ?????? ? ???
void DS1307_Init(void);
void DS1307_Read(DS1307_Data* arg1);
void DS1307_Write(DS1307_Data* arg1);
byte SPI_Send_Byte(byte data);
void SPI_Send_CMD1(byte cmd);
byte SPI_Read_SR(void);
byte SPI_Read_Data(int address, byte* buffer, byte n);
byte SPI_Write_Data(int address, byte* buffer, byte n);
void Save_Record(DS1307_Data* arg1, byte* code, byte type);
////////////////////////////////////////////////////////////////////////////////////////////
void main(void)
{
byte temp, ii, jj, temp1;
byte iButton_Arrary[N_Key][8];
Pin_Init();
DS1307_1.Second = 0x21; //03-03-09 19:32:21
DS1307_1.Minute = 0x32;
DS1307_1.Hour = 0x19;
DS1307_1.Day = 0x02;
DS1307_1.Date = 0x03;
DS1307_1.Month = 0x03;
DS1307_1.Year = 0x09;
DS1307_Init();
DS1307_Write(&DS1307_1);
// ????????? ????????????? ????? ? EEPROM-???'??
for(ii = 0; ii < N_Key; ii++)
temp = SPI_Read_Data(0x0000 + ii * 8, &iButton_Arrary[ii][0], 8);
// ??????????? ???????? ??????????? INT0 ??? ?????? ??????
GIMSK = GIMSK | 0x40;
MCUCR = MCUCR | 0x02;
while(1)
{
#asm("cli")
temp = w1_search(SEARCH_ROM, &ROM_Code[0]);
if (temp == 0)
{
#asm("sei")
}
else
{
// ?????
for(ii = 0; ii < N_Key; ++ii)
{
temp1 = 0;
for(jj = 0; jj < 8; ++jj)
{
if(ROM_Code[jj] != iButton_Arrary[ii][jj])
{
temp1 = 1;
break;
}
}
if(temp1 == 0)
break;
}
if(temp1 == 0)
{
DS1307_Read(&DS1307_1);
Save_Record(&DS1307_1, &ROM_Code[0], Input_Record);
PORT_Led.Led = 0;
PORT_Switch.Switch = 1;
delay_ms(T_msec);
PORT_Led.Led = 1;
PORT_Switch.Switch = 0;
}
else
#asm("sei");
}
delay_ms(1);
};
};
////////////////////////////////////////////////////////////////////////////////////////////////////////
void DS1307_Init(void)
{
// ????????????? ?2? ???? ?? ?????? ?????? ????????? ????????? ???? (RTC)
byte temp;
temp = i2c_start();
temp = i2c_write(0xd0);
temp = i2c_write(0x07);
temp = i2c_write(0b00000000);
i2c_stop();
};
////////////////////////////////////////////////////////////////////////////////////////////////////////
void DS1307_Read(DS1307_Data* arg1)
{
// ?????????? ???? ?? ???? ? RTC
byte temp2;
temp2 = i2c_start();
temp2 = i2c_write(0xd0);
temp2 = i2c_write(0x00);
i2c_stop();
temp2 = i2c_start();
temp2 = i2c_write(0xd1);
arg1->Second = i2c_read(1) & 0x7F;
arg1->Minute = i2c_read(1) & 0x7F;
arg1->Hour = i2c_read(1) & 0x3F;
arg1->Day = i2c_read(1) & 0x07;
arg1->Date = i2c_read(1) & 0x3F;
arg1->Month = i2c_read(1) & 0x1F;
arg1->Year = i2c_read(0);
i2c_stop();
};
////////////////////////////////////////////////////////////////////////////////////////////////////////
void DS1307_Write(DS1307_Data* arg1)
{
// ????? ???? ?? ???? ? RTC
byte temp2;
temp2 = i2c_start();
temp2 = i2c_write(0xd0);
temp2 = i2c_write(0x00);
temp2 = i2c_write(arg1->Second);
temp2 = i2c_write(arg1->Minute);
temp2 = i2c_write(arg1->Hour | 0b00000000);
temp2 = i2c_write(arg1->Day);
temp2 = i2c_write(arg1->Date);
temp2 = i2c_write(arg1->Month);
temp2 = i2c_write(arg1->Year);
i2c_stop();
};
////////////////////////////////////////////////////////////////////////////////////////////////////////
byte SPI_Send_Byte(byte data)
{
byte ii, temp, result = 0, temp1 = 0x80;
for(ii = 0; ii < 8; ++ii)
{
temp = PIN_EEPROM;
temp = temp & (1<<SO);
if(temp != 0)
result = result | temp1;
PORT_EEPROM.SI = (data & temp1) && 1;
#asm("nop");
PORT_EEPROM.SCK = 1;
temp1 = temp1 >> 1;
PORT_EEPROM.SCK = 0;
}
return result;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////
void Pin_Init(void)
{
PORT_EEPROM.CS = 1;
PORT_EEPROM.SCK = 0;
PORT_EEPROM.SI = 0;
PORT_EEPROM.SO = 0;
DDR_EEPROM.CS = 1;
DDR_EEPROM.SCK = 1;
DDR_EEPROM.SI = 1;
DDR_EEPROM.SO = 0;
PORT_Switch.Switch = 0;
DDR_Switch.Switch = 1;
PORT_Led.Led = 1;
DDR_Led.Led = 1;
PORT_Out_Key.Out_Key = 0;
DDR_Out_Key.Out_Key = 0;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////
byte SPI_Write_Data(int address, byte* buffer, byte n)
{
byte ii, result;
PORT_EEPROM.CS = 0;
SPI_Send_Byte(EEPROM_WRITE);
SPI_Send_Byte(address>>8);
SPI_Send_Byte(address);
for(ii = 0; ii < n; ++ii)
{
SPI_Send_Byte(buffer[ii]);
}
PORT_EEPROM.SI = 0;
PORT_EEPROM.CS = 1;
return result;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////
byte SPI_Read_Data(int address, byte* buffer, byte n)
{
byte ii, result;
PORT_EEPROM.CS = 0;
SPI_Send_Byte(EEPROM_READ);
SPI_Send_Byte(address>>8);
SPI_Send_Byte(address);
for(ii = 0; ii < n; ii++)
{
buffer[ii] = SPI_Send_Byte(0);
}
PORT_EEPROM.SI = 0;
PORT_EEPROM.CS = 1;
return result;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////
void SPI_Send_CMD1(byte cmd)
{
PORT_EEPROM.CS = 0;
SPI_Send_Byte(cmd);
PORT_EEPROM.SI = 0;
PORT_EEPROM.CS = 1;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////
byte SPI_Read_SR(void)
{
byte temp;
PORT_EEPROM.CS = 0;
temp = SPI_Send_Byte(EEPROM_RDSR);
temp = SPI_Send_Byte(0);
PORT_EEPROM.SI = 0;
PORT_EEPROM.CS = 1;
return temp;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////
interrupt [2] void ext_interrupt0(void)
{
byte ii;
delay_ms(10);
if(PIN_Out_Key.Out_Key == 0)
{
DS1307_Read(&DS1307_1);
for(ii = 0; ii < 8; ++ii)
ROM_Code[ii] = 0;
Save_Record(&DS1307_1, &ROM_Code[0], Output_Record);
PORT_Led.Led = 0;
PORT_Switch.Switch = 1;
delay_ms(T_msec);
PORT_Led.Led = 1;
PORT_Switch.Switch = 0;
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////////
void Save_Record(DS1307_Data* arg1, byte* code, byte type)
{
byte temp, temp1, temp2[3];
int start;
while((temp = SPI_Read_SR()) & 0x01) // ????????? ?????????? EEPROM
;
// ????????? ???????? ?????????? ????? ? ?????? temp1
temp = SPI_Read_Data(Record_Count_Addr, &temp1, 1);
if(temp1 == N_Record) // ???? ????????? ????????????? ????????
{
temp1 = 1; // ?????? ??????
start = Record_Addr;
}
else // ?????? ????????? ?????? ?????????? ??????
{
start = Record_Addr + Record_Size * (int)temp1;
temp1++; // ????????? ????????? ??????? ?? 1
}
SPI_Send_CMD1(EEPROM_WREN); // ????????? ????? ? EEPROM
while((temp = SPI_Read_SR()) & 0x01) // ????????? ?????????? EEPROM
;
// ???????? 8 ???? ????????????????? ?????? DS1990A
temp = SPI_Write_Data(start, code, 8);
while((temp = SPI_Read_SR()) & 0x01) // ????????? ?????????? EEPROM
;
SPI_Send_CMD1(EEPROM_WREN); // ????????? ????? ? EEPROM
while((temp = SPI_Read_SR()) & 0x01) // ????????? ?????????? EEPROM
;
temp2[0] = arg1->Date;
temp2[1] = arg1->Month;
temp2[2] = arg1->Year;
temp = SPI_Write_Data(start + 8, temp2, 3);
while((temp = SPI_Read_SR()) & 0x01)
;
SPI_Send_CMD1(EEPROM_WREN);
while((temp = SPI_Read_SR()) & 0x01)
;
temp = SPI_Write_Data(start + 15, &type, 1);
while((temp = SPI_Read_SR()) & 0x01)
;
SPI_Send_CMD1(EEPROM_WREN);
while((temp = SPI_Read_SR()) & 0x01)
;
temp = SPI_Write_Data(Record_Count_Addr, &temp1, 1);
};
Схема симуляції в Proteus
Висновок: на даній лабораторній роботі я ознайомився з принципами побудови модулів управління систем контролю доступу. Також я вивчив правила обміну інформацією через інтерфейси 1-Wire, I2C, SPI та ознайомився з їх програмною реалізацією для AVR-мікроконтролерів на мові С в середовищі CodeVisionAVR.