Вы вошли на сайт, как Гость
Регистрация

Управление светофорами на перекрестке

Программные примеры для микроконтроллеров 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;
    }
  }
}

Файлы проекта можно скачать здесь: