|
Управление светофорами на перекрестке
Программные примеры для микроконтроллеров PIC - MPLab IDE
(Управление светофорами на перекрестке)
Рассмотрим пример использования микроконтроллера PIC16F877 для управления
светофорами на перекрестке. Схема подключения светодиодов и кнопок запроса
на проход со стороны пешеходов, а также полного останова движения на
перекрестке представлены в табл. ниже (светодиоды и кнопки соединены с микроконтроллером
через резисторы 1 кОм).
В данном контексте '"направление" означает
направление движения по одной из пересекающихся
дорог, а "запрос пешехода" —
нажатие кнопки на пешеходном переходе в направлении,
пересекающем текущее. Кнопка "Останов
движения" может использоваться дорожными
службами.
Примечание: при компиляции проекта требуется добавить в проект следующие библиотеки: "16F877.h", "stdio.h".
#use delay(clock=10000000)
#fuses HS, WDT
#byte PORTD = 8 //Определяем порты D и B
#byte PINB = 6
//Определяем выводы для подключения светодиодов
#bit dir1_red = PORTD.4
#bit dir1_yellow = PORTD.5
#bit dir1_green = PORTD.6
#bit dir2_red = PORTD.1
#bit dir2_yellow = PORTD.2
#bit dir2_green = PORTD.3
//Определяем выводы для подключения кнопок
#bit dir1_button = PINB.0
#bit dir2_button = PINB.1
#bit stop_button = PINB.2
char time_left; //Счетчик времени для текущего состояния
int current_state; /* Флаг текущего состояния светофоров.
Его значение соответствует объявленному
ниже перечислимому типу */
char toggle_flag; /* Флаг, определяющий мигание красного сигнала
светофора в состоянии "stop" (то есть,
при запрете движения через перекресток) */
/* Перечислимый тип, определяющий числовые значения для
идентификаторов состояния перекрестка.
dir1_moving – в направлении 1 движение разрешено (зеленый свет),
в направлении 2 - запрещено (красный свет);
dir1_warning – направление 1 сейчас будет перекрыто, на обоих
светофорах горит желтый свет;
dir2_moving – в направлении 2 движение разрешено (зеленый свет),
в направлении 1 - запрещено (красный свет);
dir2_warning – направление 2 сейчас будет перекрыто, на обоих
светофорах горит желтый свет;
stop – в обоих направлениях движение запрещено, мигает
красный свет */
enum {dir1_moving, dir1_warning, dir2_moving, dir2_warning, stop};
void main()
{
port_b_pullups(TRUE); //Активизируем внутренние подтягивающие
//резисторы для порта В
set_tris_b(0xFF); //Все выводы порта В - входы
set_tris_d(0x00); //Все выводы порта D - выходы
current_state = dir2_warning; //Стартовое состояние – желтый
//свет в обоих направлениях при разрешенном втором
while(1) //Бесконечный цикл, в котором состояние опрашивается
{ //через каждую секунду
delay_ms(1000); //Задержка на 1 с
switch(current_state) //Опрос текущего состояния
{
//Если разрешено движение в направлении 1
case dir1_moving: dir1_red = 1;
dir1_yellow = 1;
dir1_green = 0; //Зеленый свет для 1
dir2_red = 0; //Красный свет для 2
dir2_yellow = 1;
dir2_green = 1;
//Если нажата кнопка пешеходом или "стоп"
if (dir1_button || stop_button)
{
//сокращает остаток времени до 10 с
if (time_left > 10) time_left = 10;
}
if (time_left != 0) //Если время еще не
{ //истекло, уменьшаем
--time_left; //счетчик на 1 с
continue; //Переходим в начало цикла
}
time_left = 5; //Если время истекло, даем
// еще 5 с для желтого света
//Включаем желтый предупреждающий сигнал
current_state = dir1_warning;
break;
//Если разрешено движение в направлении 1, но уже включен
//желтый предупреждающий сигнал
case dir1_warning: dir1_red = 1;
dir1_yellow = 0; //Желтый свет для 1
dir1_green = 1;
dir2_red = 0; //Для 2 – красный +
dir2_yellow = 0; //желтый свет
dir2_green = 1;
if (time_left != 0) //Если время еще не
{ //истекло, уменьшаем
--time_left; //счетчик на 1 с
continue; //Переходим в начало цикла
}
//Если время желтого света истекло,...
if (stop_button) //Если нажато "стоп",
//переходим в режим закрытия перекрестка
current_state = blink;
else
{ //Иначе, разрешаем на 30 с движение в
//направлении 2
time_left = 30;
current_state = dir2_moving;
}
break;
//Если разрешено движение в направлении 2
case dir2_moving: dir1_red = 0;
dir1_yellow = 1;
dir1_green = 1;
dir2_red = 1;
dir2_yellow = 1;
dir2_green = 0;
if (dir2_button || stop_button)
{
if (time_left > 10) time_left = 10;
}
if (time_left != 0)
{
--time_left;
continue;
}
time_left = 5;
current_state = dir2_warning;
break;
//Если разрешено движение в направлении 2, но уже включен
//желтый предупреждающий сигнал
case dir2_warning: dir1_red = 0;
dir1_yellow = 0;
dir1_green = 1;
dir2_red = 1;
dir2_yellow = 0;
dir2_green = 1;
if (time_left != 0)
{
--time_left;
continue;
}
if (stop_button)
current_state = blink;
else
{
time_left = 30;
current_state = dir1_moving;
}
break;
//Если активен запрет на движение через перекресток
case blink: dir1_yellow = 1; //На обоих светофорах
dir1_green = 1; //отключены зеленый и желтый
dir2_yellow = 1; //сигналы
dir2_green = 1;
toggle_flag ^= 1; //Переключаем состояние
//красного сигнала на противоположное
if (toggle_flag & 1) //Если флаг = 1,...
{
dir1_red = 1; //красный сигнал горит
dir2_red = 0;
}
else
{
dir1_red = 0; //иначе, красный сигнал гаснет
dir2_red = 1;
}
//Если кнопка "стоп" отпущена, переходим в
//рабочий режим
if (!stop_button) current_state = dir1_warning;
break;
//Состояние по умолчанию – dir2_warning
default: current_state = dir2_warning;
break;
}
}
}
|
Файлы проекта можно скачать здесь:
|
|
|