МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ «ЛЬВІВСЬКА ПОЛІТЕХНІКА»
ЗВІТ
про виконання лабораторної роботи №4
з курсу “Мікропроцесорні пристрої”
на тему:
“Побудова охоронних систем з GSM-сигналізацією на AVR-мікроконтролерах.
Знайомство з середовищем CodeVisionAVR”
Львів 2009
Мета роботи – ознайомитись з принципами побудови охоронних систем з GSM-сигналізацією і їх програмно-апаратною реалізацією на AVR-мікроконтролерах. Отримати навики написання програм для AVR-мікроконтролерів на мові С в середовищі CodeVisionAVR.
Варіант №3
Розрахунки
STATUS:
1-1
2-2
3-0
4-2
N1=5*106/(256*1,5)=13020
N2=5*106/(256*14)=1395
Текст програми
gsm.h:
#include <90S2313.h>
#include <delay.h>
#include <stdio.h>
#include <sleep.h>
//////////////////////////////////////////////////////////////////
#define CR 0x0D
#define LF 0x0A
#define Ctrl_Z 0x1A
// Тактова частота
#define xtal 5000000L
// Період мигання світлодіоду з частотою 1.5 Гц (1 с) DIV = 256
#define Timer1_1 13020
// Період мигання світлодіоду з частотою 14 Гц (0.1 с) DIV = 256
#define Timer1_2 1395
#define Timer0_1 39
////////////////////////////////////////////////////////////////////////
// Швидкість обміну між МК та GSM-модемом
#define Baud_Rate 9600
// Регістр USR
#define RXC 7
#define TXC 6
#define UDRE 5
#define FE 4
#define OR 3
// Регістр UСR
#define RXCIE 7
#define TXCIE 6
#define UDRIE 5
#define RXEN 4
#define TXEN 3
#define CHR9 2
#define RXB8 1
#define TXB8 0
////////////////////////////////////////////////////////////////////////
#define S1_PORT PORTD
#define S2_PORT PORTB
#define S1_DDR DDRD
#define S2_DDR DDRB
#define S1_PIN PIND
#define S2_PIN PINB
#define SCH_1 2
#define SCH_2 2
////////////////////////////////////////////////////////////////////////
#define LED_PORT PORTB
#define LED_DDR DDRB
#define LED_PIN PINB
#define LED 3
////////////////////////////////////////////////////////////////////////
#define SW_PORT PORTB
#define SW_DDR DDRB
#define SW_PIN PINB
#define SW 5
/////////////////////////////////////////////////////////////////////////
// TCCR0
#define CS02 2
#define CS01 1
#define CS00 0
// TCCR1A
#define COM1A1 7
#define COM1A0 6
#define PWM11 1
#define PWM10 0
// TCCR1B
#define ICNC1 7
#define ICES1 6
#define CTC1 3
#define CS12 2
#define CS11 1
#define CS10 0
// TIMSK
#define TOIE1 7
#define OCIE1A 6
#define TICIE 3
#define TOIE0 1
/////////////////////////////////////////////////////////////////////////////////////
// Глобальні змінні
// Стан сигналізації: 0 (State_Off) - виключена, 1 (State_On) - включена
unsigned char State = 0;
#define State_Off 0
#define State_On 1
// Стан шлейфу 1: 0 (No_Alarm)- немає спрацювання, 1 (Alarm) - є спрацювання, 2 (No_Control) - шлейф не контролюється
unsigned char S1_Status;
#define No_Alarm 0
#define Alarm 1
#define No_Control 2
// Стан шлейфу 2: 0 - немає спрацювання, 1 - є спрацювання, 2 - шлейф не контролюється
unsigned char S2_Status;
// Номер адміністратора у форматі +380хх1234567
unsigned char Number[13] = {0};
gsm.c:
#include <GSM.h>
interrupt [7] void Timer0_Ovf(void)
{
unsigned char temp;
// Прочитати стан секретної кнопки
temp = SW_PIN;
temp = temp & (1<<SW);
if (State == State_Off) // Якщо охорона виключена
{
if (temp == 0)
State = State_On; // Якщо кнопка натиснута - включити охорону
}
else if(State == State_On) // Якщо охорона включена
{
if (temp != 0)
State = State_Off; // Якщо кнопка ненатиснута - виключити охорону
}
};
//////////////////////////////////////////////////////////////////
interrupt [5] void Timer1_COMP(void)
{
unsigned char temp;
temp = PORTB ^ 0b00001000;
PORTB = temp;
};
void Pin_Init(void);
void SMS_Send(char* cmd, unsigned char type);
void Schleif_Test(unsigned char s1, unsigned char * status, unsigned char number);
enum SMS_Type{Security_On, Security_Off, Alarm_Schleif_1, Alarm_Schleif_2};
//////////////////////////////////////////////////////////////////
void main(void)
{
unsigned char k, m, temp;
// Номер індексу першої комірки телефонної книги SIM-карти
unsigned char s1, s2, s3;
// Масив для відправки АТ-команд
unsigned char CMD[25] = {0};
// Масив для прийому відповідей від GSM-модему
unsigned char My[30] = {0};
// Час постановки на охорону
unsigned char T_1;
// Час зняття з охорони
unsigned char T_2;
// Конфігурація шлейфу 1: 0 - викл., 1 - нормально розімкнений, 2 - нормально замкнутий
unsigned char S_1;
// Конфігурація шлейфу 2: 0 - викл., 1 - нормально розімкнений, 2 - нормально замкнутий
unsigned char S_2;
// Налаштування виводів МК
Pin_Init();
// Налаштування швидкості передачі 9600 Бод
UBRR = xtal/16/Baud_Rate-1;
// Дозволити прийом і передачу даних: 8 біт, 1 стоповий, 1 стартовий.
UCR = (1<<RXEN) + (1<<TXEN);
// Затримка 4 секунди для переходу модему в робочий режим
delay_ms(4000);
// Послати команду АТЕ0 - відключення еха
CMD[0] = 'A';
CMD[1] = 'T';
CMD[2] = 'E',
CMD[3] = '0';
CMD[4] = CR;
// Відіслати команду
puts(CMD);
// Прийом відповіді
k = 0;
while(1)
{
m = getchar(); // Отримати символ
if(m == LF) // Це символ нового рядку?
k++;
if(k == 2) // Якщо отримано два LF - прийом відповіді завершено
break;
};
// Послати команду АТ+CPBS="SM" - вибір телефонної книги
CMD[0] = 'A';
CMD[1] = 'T';
CMD[2] = '+';
CMD[3] = 'C';
CMD[4] = 'P';
CMD[5] = 'B';
CMD[6] = 'S';
CMD[7] = '=';
CMD[8] = '"';
CMD[9] = 'S';
CMD[10] = 'M';
CMD[11] = '"';
CMD[12] = CR;
// Відіслати команду
puts(CMD);
// Прийом відповіді
k = 0;
while(1)
{
m = getchar(); // Отримати символ
if(m == LF) // Це символ нового рядку?
k++;
if(k == 2) // Якщо отримано два LF - прийом відповіді завершено
break;
};
//////////////////////////////////////////////////////////////////////////////////
// Послати команду АТ+CPBR=? - вивести параметри активної телефонної книги
CMD[0] = 'A';
CMD[1] = 'T';
CMD[2] = '+';
CMD[3] = 'C';
CMD[4] = 'P';
CMD[5] = 'B';
CMD[6] = 'R';
CMD[7] = '=';
CMD[8] = '?';
CMD[9] = CR;
CMD[10] = 0;
k = 0;
m = 0;
// Відіслати команду
puts(CMD);
while(1)
{
My[m] = getchar(); // Зберегти прийнятий символ в масиві My[]
temp = My[m];
m++; // Збільшити лічильник прийнятих символів на 1
if(temp == LF) // Це символ нового рядку?
k++;
if(m == 29) // Якщо досягнуто кінець масиву My[] – почати запис спочатку
m = 0;
if(k == 4) // Якщо отримано 4 символи LF - прийом відповіді завершено
break;
};
s1 = My[10]; // Прочитати номер першої комірки телефонної книги з прийнятої відповіді
s2 = My[11];
s3 = My[12];
///////////////////////////////////////////////////////////////////////////////////
// Команда АТ+CPBR=s1s2s3 – зчитати вміст першої комірки телеф. книги (комірка STATUS)
CMD[0] = 'A';
CMD[1] = 'T';
CMD[2] = '+';
CMD[3] = 'C';
CMD[4] = 'P';
CMD[5] = 'B';
CMD[6] = 'R';
CMD[7] = '=';
CMD[8] = s1;
CMD[9] = s2;
CMD[10] = s3;
CMD[11] = CR;
CMD[12] = 0;
k = 0;
m = 0;
temp = 0;
// Відіслати команду
puts(CMD);
while(1)
{
temp = getchar(); // Прийняти символ
if(temp == '"') // Якщо прийнято символ “ прочитати наступні 4 символи
{
m++;
}
else if(m > 0 & m < 5)
{
My[m-1] = temp; // Прочитати 4 цифри, які задають налаштування системи
m++;
}
if(temp == LF) // Якщо отримано 4 символи LF - прийом відповіді завершено
k++;
if(k == 4)
break;
};
// Сформувати з прийнятих символів значення часових затримок та типи шлейфів
S_1 = My[0] - 0x30; S_2 = My[1] - 0x30; T_1 = (My[2] - 0x30 + 1)*10; T_2 = (My[3] - 0x30 +
1)*10;
/////////////////////////////////////////////////////////////////////////
// // Сформувати номер наступної комірки телефонної книжки
s3 = s3 + 1;
if(s3 == 0x40)
{
s3 = 0x30;
s2 = s2 + 1;
if(s2 == 0x40)
{
s2 = 0x30;
s1 = s1 + 1;
}
}
//s1++;
// Команда АТ+CPBR=s1s2s3+1 – зчитати вміст другої комірки телеф. книги –
// номер телефону адміністратора
CMD[0] = 'A';
CMD[1] = 'T';
CMD[2] = '+';
CMD[3] = 'C';
CMD[4] = 'P';
CMD[5] = 'B';
CMD[6] = 'R';
CMD[7] = '=';
CMD[8] = s1;
// CMD[9] = CR;
// CMD[10] = 0;
CMD[9] = s2;
CMD[10] = s3;
CMD[11] = CR;
CMD[12] = 0;
k = 0;
m = 0;
temp = 0;
// Відіслати команду
puts(CMD);
while(1)
{
temp = getchar(); // Прийняти символ
if(temp == '"') // Якщо прийнято символ “ прочитати наступні 13 символів
{
m++;
}
else if(m > 0 & m < 14)
{
Number[m-1] = temp; ; // Зберегти номер адміністратора в масиві Number
m++;
}
if(temp == LF) // Якщо отримано 4 символи LF - прийом відповіді завершено
k++;
if(k == 4)
break;
};
////////////////////////////////////////////////////////////////////////////
// Команда АТ+CMGF= 1 – задати текстовий режим відправки повідомлень
CMD[0] = 'A';
CMD[1] = 'T';
CMD[2] = '+';
CMD[3] = 'C';
CMD[4] = 'M';
CMD[5] = 'G';
CMD[6] = 'F';
CMD[7] = '=';
CMD[8] = '1';
CMD[9] = CR;
CMD[10] = 0;
// Відіслати команду
puts(CMD);
k = 0;
m = 0;
while(1)
{
My[m] = getchar();
m++;
if(My[m-1] == LF) // Якщо отримано 2 символи LF - прийом відповіді завершено
k++;
if(k == 2)
break;
};
///////////////////////////////////////////////////////////////////////////////
// Дозволити перехід в режим пониженого енергоспоживання
sleep_enable();
Lab1:
// Стан - охорона виключена
State = 0;
// Стан шлейфів - не було спрацювань
S1_Status = 0;
S2_Status = 0;
// Опитування секретної кнопки з періодом 0.1 с.
// Дозволити переривання від таймера Т0 по переповненню
TIMSK = (1<<TOIE0);
// Коефіцієнт ділення - 1024. Період опитування = 1024*256/4000000 = 0.06 с.
TCCR0 = (1<<CS02) + (1<<CS00);
// Дозволити переривання
#asm("sei");
///////////////////////////////////////////////////////////////////////////////
while(1)
{
idle(); // Перейти в режим пониженого енергоспоживання
if(State == 1) // Якщо включено охорону – вийти з циклу
break;
};
///////////////////////////////////////////////////////////////////////////////
// Зупинити таймер Т0
TCCR0 = 0;
// Затримка Т1 для виходу з об'єкту
for(temp = 0; temp < T_1; temp++)
delay_ms(1000);
// Відіслати SMS-повідомлення
SMS_Send(CMD, Security_On);
// Мигати світлодіодом з частотою F1
OCR1 = Timer1_1;
//TCCR1A = (1<<COM1A0);
TCCR1B = (1<<CS12) + (1<<CTC1);
TIMSK = TIMSK + (1<<6);
// Опитувати кнопку з частотою 0.06 с
TCCR0 = (1<<CS02) + (1<<CS00);
///////////////////////////////////////////////////////////////////////////////
while(1)
{
idle();
if(State == 0) // Якщо охорону виключили
{
TCCR0 = 0; // Зупинити таймер Т0
SMS_Send(CMD, Security_Off); // Відіслати SMS повідомлення Security_Off
TCCR1B = 0; // Зупинити таймер Т1
TCCR1A = 0;
LED_PORT.LED = 0; // Включити світлодіод на 3 сек
delay_ms(3000);
LED_PORT.LED = 1;
break;
}
else // Якщо охорона включена
{
Schleif_Test(S_1, &S1_Status, 1); // Опитати шлейф 1
Schleif_Test(S_2, &S2_Status, 2); // Опитати шлейф 2
if(S1_Status == 1 || S2_Status == 1) // Якщо є спрацювання шлейфу
{
OCR1 = Timer1_2; // Мигати світлодіодом
TCNT1 = 0;
TCCR0 = 0; // Зупинити таймер Т0
//------------------------------------------------------------------------------------
for(temp = 0; temp < T_2; temp++)
delay_ms(1000); // Затримка для виключення охорони
temp = SW_PIN; // Опитати кнопку
temp = temp & (1<<SW);
if(temp == 0) // Якщо охорону не відключено
{
if(S1_Status == 1) // Якщо спрацював шлейф 1
{
SMS_Send(CMD, Alarm_Schleif_1); // Відіслати SMS повідомлення Alarm_Schleif_1
S1_Status = 2; // Не реагувати на шлейф 1 поки він не вернеться
// в неактивний стан
}
if(S2_Status == 1) // Якщо спрацював шлейф 1
{
SMS_Send(CMD, Alarm_Schleif_2); // Відіслати SMS повідомлення Alarm_Schleif_2
S2_Status = 2; // Не реагувати на шлейф 2 поки він не вернеться
// в неактивний стан
}
delay_ms(4000);
TCCR0 = (1<<CS02) + (1<<CS00); // Продовжити опитувати кнопку з частотою 0.06 с
}
else // Якщо охорону встигли відключити
{
State = 0;
TCCR0 = 0; // Зупинити таймер Т0
SMS_Send(CMD, Security_Off); // Відіслати SMS повідомлення Security_Off
TCCR1B = 0; // Зупинити таймер Т1
TCCR1A = 0;
LED_PORT.LED = 0; // Включити світлодіод на 3 сек
delay_ms(3000);
LED_PORT.LED = 1;
break;
}
}
}
};
goto Lab1; // Перейти на мітку Lab1
/////////////////////////////////////////////////////////////////
};
//////////////////////////////////////////////////////////////////
void Pin_Init(void)
{
S1_PORT.SCH_1 = 0;
S1_DDR.SCH_1 = 0;
S2_PORT.SCH_2 = 0;
S2_DDR.SCH_2 = 0;
LED_PORT.LED = 1;
LED_DDR.LED = 1;
SW_PORT.SW = 1;
SW_DDR.SW = 0;
};
//////////////////////////////////////////////////////////////////
// Функція відправки SMS-повідомлення
// Вхідні параметри: cmd - текстовий рядок для запису команди, type - тип повідомлення
void SMS_Send(char* cmd, unsigned char type)
{
unsigned char m;
cmd[0] = 'A';
cmd[1] = 'T';
cmd[2] = '+';
cmd[3] = 'C';
cmd[4] = 'M';
cmd[5] = 'G';
cmd[6] = 'S';
cmd[7] = '=';
cmd[8] = '"';
cmd[9] = Number[0];
cmd[10] = Number[1];
cmd[11] = Number[2];
cmd[12] = Number[3];
cmd[13] = Number[4];
cmd[14] = Number[5];
cmd[15] = Number[6];
cmd[16] = Number[7];
cmd[17] = Number[8];
cmd[18] = Number[9];
cmd[19] = Number[10];
cmd[20] = Number[11];
cmd[21] = Number[12];
cmd[22] = '"';
cmd[23] = CR;
cmd[24] = 0;
puts(cmd);
while(1)
{
m = getchar();
if(m == '>')
break;
};
m = getchar();
if(type == Alarm_Schleif_1 || type == Alarm_Schleif_2)
{
cmd[0] = 'S';
cmd[1] = 'l';
cmd[2] = 'e',
cmd[3] = 'i';
cmd[4] = 'f';
cmd[5] = ' ';
cmd[7] = Ctrl_Z;
cmd[8] = CR;
cmd[9] = 0;
if(type == Alarm_Schleif_1)
cmd[6] = '1';
else
cmd[6] = '2';
}
else if(type == Security_On || type == Security_Off)
{
cmd[0] = 'S';
cmd[1] = 'e';
cmd[2] = 'c',
cmd[3] = 'u';
cmd[4] = 'r';
cmd[5] = 'i';
cmd[6] = 't';
cmd[7] = 'y';
cmd[8] = ' ';
cmd[9] = 'O';
if(type == Security_On)
{
cmd[10] = 'n';
cmd[11] = Ctrl_Z;
cmd[12] = CR;
cmd[13] = 0;
}
else
{
cmd[10] = 'f';
cmd[11] = 'f';
cmd[12] = Ctrl_Z;
cmd[13] = CR;
cmd[14] = 0;
}
}
puts(cmd);
};
//////////////////////////////////////////////////////////////////////////////////////
// Функція перевірки стану шлейфу.
// Вхідні параметри: s1 - конфігурація шлейфу, number - номер шлейфу
// Вихідні параметри: записує у змінну status стан шлейфу
void Schleif_Test(unsigned char s1, unsigned char* status, unsigned char number)
{
unsigned char temp;
if (s1 != 0)
{
if(number == 1)
{
temp = S1_PIN;
temp = temp & (1<<SCH_1);
}
else
{
temp = S2_PIN;
temp = temp & (1<<SCH_2);
}
if ((s1 == 1) & (temp == 0) & (*status != No_Control)) // Якщо НРК і є спрацювання
*status = Alarm;
else if ((s1 == 1) & (temp != 0) & (*status == No_Control)) // Якщо НРК і немає спрацювання
*status = No_Alarm;
if ((s1 == 2) & (temp != 0) & (*status != No_Control)) // Якщо НЗК і є спрацювання
*status = Alarm;
else if ((s1 == 2) & (temp == 0) & (*status == No_Control)) // Якщо НЗК і немає спрацювання
*status = No_Alarm;
}
};
Схема симуляції в Proteus
Висновок: на даній лабораторній роботі я ознайомився з принципами побудови охоронних систем з GSM-сигналізацією і їх програмно-апаратною реалізацією на AVR-мікроконтролерах. Також я отримав навики написання програм для AVR-мікроконтролерів на мові С в середовищі CodeVisionAVR.