СОДЕРЖАНИЕ
1. Задание на разрабатываемое устройство
1.1 Требования к охранным, пожарным шлейфам
1.3 Требования к конфигурированию и настройке устройства
2. Электронные компоненты печатной платы
.1 Технические характеристики и параметры основных компонентов печатной платы
.2 Применяемые схемотехнические решения
3. Программное обеспечение микроконтроллера
.2 Задачи операционной системы реального времени
3.3 Взаимодействие задач и прерываний
.4 Функции обработчиков прерываний
.6 Передача параметров настройки по USB
4. Программное обеспечение Windows Form C#
.1 Определение общей структуры приложения
4.2 Создание библиотеки из ссылочных типов содержащие поля данных
Счет выполняем в программе прерывания:
EXTI15_10_IRQHandler (void) // вызов при нажатии любой кнопки
{
// определяем текущее положение ключа мультиплексора_t Ukaz=DMA_GetCurrDataCounter (DMA2_Stream0);
// если прерывание на линии RF - это радиобрелок(EXTI_GetITStatus (EXTI_Line14)! = RESET)
{(Ukaz)0x10: // ключ мультиплексора в положении S1
// дополнительно считываем текущее состояние( (VhodRF [4] = (GPIOE->IDR & GPIO_Pin_14)? 1: 0))
// увеличиваем счет для кнопки обрабатываемый в задаче vObrabVhodov[4] ++;;
}
// очищаем флаг прерывания_ClearITPendingBit (EXTI_Line14);
// передаем управление следующему прерыванию_FROM_ISR (1);
}
Рассмотрим фрагменты кода реализации некоторых задач:
) Задача обработки уставок АЦП - vObrabUstADC. В программе конфигурирования сигнализации под Windows7 пользователь выбирает необходимый канал, для каждого канала существует возможность настройки четырех уставок АЦП и уставок времени АЦП. Уставки АЦП - это те значения выше или ниже которых (направление работы также выбирается пользователем) выполняется набор действий. Эти действия также настраиваются пользователем и могут выполнять отправку SMS сообщений, срабатывание определенного выхода сигнализации. Уставка времени АЦП нужна для защиты от наводок и бросков напряжений в канале. Пользователь может задать время в диапазоне значений 250-500 мсек.
В разделе 4.3 при описании функции обработчика прерывания по таймеру, определено время полного сканирования напряжения всех каналов 10 мсек, эта функция также отдает семафор-механизм ОСРВ позволяющий обеспечивать синхронизацию выполнения задачи с выполнением прерывания. Как только функция прерывания по окончанию замеров всех 16 каналов отдает семафор, задача захватывает его и происходит обработка значений. Если семафор не доступен, а планировщик запустил данную задачу она должна блокироваться на время не менее 10 мсек. Поскольку сравнение результатов замера каждой уставки АЦП выполняется каждые 10мсек, то выполнив сравнение 25 раз и если замеренное значение будет выше или ниже уставки все 25 раз (или 250 мсек) значит сигнализация сработала, необходимо выполнять дальнейшие действия. Таким образом выполняется защита от наводок оговоренном в техническом задании (см. Раздел 2.1). Основные переменные обрабатываемые в этой задачи являются:количество каналов сконфигурированных пользователем;[16] - массив с номерами используемых каналов;[16] [4] - многомерный массив хранит два значения 0 - уставка в данный момент активна, 1-уставка в данный момент не активна. Это дает возможность активировать брелоком необходимую уставку.ConvertedValue [ChanelADC [chet]] - массив содержит замеренные значения напряжения[16] [4] - массив хранит уставки АЦП введенные пользователем[16] [4] - массив содержит данные по уставкам, сколько раз замеренное значение достигало уставки.
vObrabUstADC (void *pvParameters)
{ …….(;;)
{
// проверяем доступность двоичного семафора - отдает функция прерывания(xSemaphoreTake (xSemPrerADC,10))
{
// сканируем по всем введенным пользователем каналам(i=0; i<lenkan; i++)
{
/*в зависимости от направления действия уставки и активности
канала в данный момент*/(ADCstr [chet] - >napravl [j] ==0 && UslAktiv [i] [j] ==0)
{ // выполняем необходимое сравнение(ADC3ConvertedValue [ChanelADC [chet]] < (ResMasADC [chet] [j] - 0xA))
++FlagMas [i] [j]; // ведем счет данным сравнениям
………….
}…………
}
// если счет достиг уставки по времени(FlagMas [i] [j] >=UslovDelFlag [chet] [j])
/*используя очередь передаем в задачу отправки номер канала и номер
уставки, длинна очереди - 16 равна длинне каналов */. nomkan=chet;. nomstrok=j;(xQueueSoob, (void*) &DataSoob,154);
// выводим задачу отправки из блокированного
состояния(OtpSoobSim); }}}
) Задача выполняющая отправку SMS сообщений - vOtpravSMS. Как только появляется условие для отправки сообщения, задача обработки уставок сохраняет в очереди структурную переменную которая хранит номер канали и номер уставки и выводит данную задачу из приостановленного состояния. Очередь - механизм ОСРВ позволяющий передавать информацию между задачами, так и между задачами и прерываниями.
vOtpravSMS (void *pvParameters)
{(;;)
{
{ // проверяем что очередь не пуста=xQueueReceive (xQueueSoob,&ReciveData,0);(xStatus==pdPASS)
{ // если существует условие отправки SMS(ADCstr [ReciveData. nomkan] - >vidOpovesh [ReciveData. nomstrok] == 0)
// если на один канал сконфигурировано несколько телефонов(t=0; (tel=ADCstr [ReciveData. nomkan] - >nomertel [t])! =0xFF; t++)
{ // то отправляем на все телефоны данного канала_CRITICAL ();_soob (tel,ReciveData. nomkan,ReciveData. nomstrok);_CRITICAL ();(4340); // задержка 4 сек для отправки SMS SIM900
}
// отправляем пока в очереди есть сообщения
}} while (uxQueueMessagesWaiting (xQueueSoob));
// после чего данная задача сама себя приостанавливает(NULL);
}
Особенности выполнения данной задачи наличие критической секции при вызове функции отправки сообщения. В этой функции выполняется кодирование сообщения и через определенные интервалы времени SIM900 передаются команды управления с сообщением. Одним из недостатков FreeRTOS является то что в критической секции нельзя вызвать функцию vTaskDelay () - блокировки задачи на определенное время, и передачи на это время, управления другим задачам. Данная особенность основана на том, что vTaskDelay () - работает от прерывания SysTick - т.е. при ее вызове разрешаются маскируемые прерывания и автоматически вызывается функция taskEXIT_CRITICAL () выхода из критической секции.
При передаче данных от ПО компьютера, оно открывает необходимый COM порт и передает все данные. Драйвер обеспечивающий связь COM порта с пакетами USB передаваемых контроллеру обеспечивает максимальный размер пакета данных 64 бита. Процесс получения данных выполняется через контрольную точку 0. В конце передачи пакета данных генерируется прерывание и вызывается функция обработки данных - VCP_DataRx (uint8_t* Buf, uint32_t Len) в файле usbd_cdc_vcp. c. Чтобы не превысить лимит в 64 байта и избежать потери данных передача данных выполняется по каналам настроенным в пользовательском приложении. Например вначале передаем данные по строкам вначале строка №1 затем строка №2 и. т.д.
Для строки №1 первое передаваемое сообщение будет N79529091812 - это номер телефона, вторым сообщением следует Hиванов Е.П. - это пользователь, С030001 - для этой строки используется четвертый канал который работает с телефонами под индексами 00 и 01 в массиве телефонов и. т.д. Все передаваемые сообщения обрабатываются по первому символу и записываются в соответствующую структуру данных.
Структура получаемых данных описана в файле StructUSB_tel. h:
struct
{_t Nom_Chan [MAXKANADC]; // номера используемых каналов_t kolvo; // общее количество телефонов_t Numb_tel [MAXKOLVOTEL] [12]; // здесь сохраняются телефоны
} Tel_Def;
#define TelefoneM ( (Tel_Def*) TEL_BASE)
#define TEL_BASE 0x080E0000
Где TEL_BASE - базовый адрес структурной переменной телефоны,
все данные сохраняем в последнем 11 секторе Flash памяти [5] Рис 4.6.1.
Рис 4.6.1 Карта Flash памяти микроконтроллера
Также определим массив структурных переменных содержащие настройки каналов:
struct
{_t kolispADC; // количество используемых уставок_t vidOpovesh [4]; // вид оповещения для каждой уставки_t SoobSMS [4] [60]; // сообщение для каждой уставки_t UrovADC [4] [2]; // уставка значений напряжений_t ZadADC [4] [2]; // задержка для каждой уставки_t napravl [4]; // направление действия
……….
} KanADC;
#define TEL_BASE 0x080E0000
#define ADCstr ( (KanADC *) ADC_struct) - данные по каналам записываются по адресу 0x080E021D.
Пример реализации функции записи данных во флэш память Рис 4.6.2:uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len)
{ ……uint8_t fi=0;(* Buf=='N') // встретили букву N это телефоны
{=fiS+1; // вспомогательная переменная хранит общее количество тел.++;_unlock (); // разблокируем flash память для записи(fi==0)_erase_page (0x58); // если это первый телефон очищаем память_write_start (); // начинаем запись телефонов(pi=0; pi<11; pi++)>Numb_tel [fi] [pi] =*Buf++;>Numb_tel [fi] [pi] =’\0’;_write_end (); // конец записи во flash_lock (); // блокируем запись++; // ведем счет текущим телефонам
…….
}
Рис 4.6.2 Запись конфигурационных данных во Flash память
Создадим приложение, для настройки GSM сигнализации, используя Windows Form C# Visual Studio 2010. Перед проектированием приложения определимся со структурой проекта - типы и количество окон (форм), какие поля будет содержать окна, какие данные в них будут вводиться их диапазоны.
Окна приложения. Структура проекта должна содержать одно главное окно с основными вкладками. Должна быть возможность добавления новых окон и ввод в них новых значений, с возможностью сохранения настроек главного окна. Определим пусть данное окно будет формата MDI - многооконный интерфейс Рис П1.1.
Определим основные вкладки главного окна: данные, входы, выходы. Вкладка данные должна содержать:
Номер телефона - сюда вносится номер куда будет оправляться сообщение или выполняться дозвон, максимальная длинна данных 11 символов, поле для ввода только числовых значений, при вводе букв отображается ошибка;
владелец - сюда вносится любая тестовая или цифровая информация для быстрого доступа, и пояснения чей номер. Размер поля 30 символов, возможность ввода как буквенной так и цифровой информации;
Сообщения - сюда вносим текст отправляемого сообщения. Поле длинной 60 символов, включает как текст так и числа (максимальный размер пакета данных передаваемого по USB 64байта см. п 4.6 Передача параметров настройки по USB);
Дочернее окно должно содержать строки для ввода четырех уставок, основные компоненты которые должны содержаться в строках Рис. П.1.2:
Checkbox - для активации определенной уставки;
Направление срабатывания - для задания режима контроля, выше чем введенное значение в поле уровень АЦП или ниже;
Уровень АЦП - содержит контролируемую уставку напряжения;
Выдержка - хранит время в диапазоне 250-500мсек, возможность редактирования с шагом 10;
Вид оповещения - окно будет иметь вид выпадающего списка в котором будут содержаться следующие значения - Ни звонка ни SMS, SMS, звонок, SMS и звонок. Если выбрано значение звонок то ввод информации в окно сообщения будет невозможным (заблокирован);
Активация АЦП - heckbox для работы с брелками и кнопками, когда при нажатии определенной кнопки активируется необходимая уставка. После выбора данного гаджета становятся активными окна с выпадающим списком для выбора входов - для активации и деактивации и временной выдержки в диапазоне от 1 до 60 сек;
Выходы - окно с выпадающим списком содержащим программные выходы с выход1 по выход10.
Вкладка входы и выходы главного окна содержит программные входы и выходы которые можно сконфигурировать на определенные аппаратные входы и выходы GSM сигнализации.
Окончательный вариант приложения изображен на Рис П.1.3,
П.1.4.
Для создания библиотеки при разработке проекта используя шаблон Class Library (библиотека классов), создадим сборку с расширением dll которая будет хранить данные в определенных нами полях формы.
Ustavki
{
…………
[Serializable]class Kanal: Ienumerable
{Stroka [] str = new Stroka [4];Kanal ()
{(int I = 0; I < 4; ++i)[i] = new Stroka ();
}Ienumerator GetEnumerator ()
{(int I = 0; I < 4; ++i)return str [i];
}
[Serializable]class GlavnOkno
{string [] nomer_tel=new string [30];string [] famil=new string [30];int [] nom_kanal=new int [30];bool [,] vhod_usl = new bool [10, 8];int [,] vhod_napr = new int [10, 8];bool [,] vihod = new bool [10, 8];bool [,] vihod_inv = new bool [10, 8];
}
}
Данная библиотека содержит основной тип канал Kanal реализующий интерфейс Ienumerable. При создании главного окна вызывается конструктор данного класса который создает четыре объекта-строки Stroka. Класс Stroka содержит все поля дочернего окна - уровни напряжения АЦП, выдержки времени, различные условия и свойства для доступа к полям. При создании объектов класса Stroka ее поля инициализируются начальными значениями которые выводятся в дочернем окне. Реализовав интерфейс Ienumerable методом GetEnumerator () для объектов типа канал мы получаем доступ к любой строке из 16 каналов используя индексатор. При создании главного окна мы создаем массив объектов Kanal, таким образом каждое вновь созданное окно содержит свои 16 каналов. Кроме того каждое главное окно содержит объект класса GlavnOkno - содержащее открытые поля для номеров телефона, входам, выходам и другим вспомогательным полям. Все типы помечены аттрибутом Serializable что дает возможность сохранять все поля в бинарном файле.
Основная сборка проекта содержит конструктор формы основного окна и в основной проект добавлена ссылка на файл dll описанный в 5.2 Данный конструктор запускается при создании главного окна. Также в ней содержутся функции по созданию и заполнению начальными значениями дочерних окон каналов, вспомогательные методы для работы с элементами управления checkbox, элементами datagridview textbox, combobox, button.