Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
HCS12 с применением языка С - royallib.ru.doc
Скачиваний:
118
Добавлен:
11.03.2016
Размер:
2.28 Mб
Скачать

8.8.1. Краткий обзор проекта

Мы исследуем здесь базовую систему циклического опроса, используемую для управления стереоусилителем. Мы рассматривали уже такой усилитель в главе 2, когда обсуждали проектирование систем и затем в данной главе в качестве примера системы циклического опроса. На рис. 8.18 представлен общий вид системы усилителя. Шесть переключателей на передней панели блока или на пульте дистанционного управления используются, чтобы выбрать один из шести источников звукового сигнала. На усилитель в любой момент времени подается сигнал только с одного источника.

Рис. 8.18. Краткий обзор усилителя

8.8.2. Пример кода

Приведенный код, который используется, чтобы управлять усилителем, состоит из кода инициализации и цикла опроса. Цикл опроса непрерывно проверяет изменение в состоянии переключателей на лицевой панели блока (PORTB) или дистанционном управлении (PORTA). Алгоритм управления UML приведен на рис. 8.19.

Рис. 8.19. Алгоритм программы UML для усилителя

//file name: ampl2.с

//function: program provides control of amplifier

//target controller: Motorola 68HC912B32 evaluation board (EVB)

// - 32K Flash EEPROM available at $8000

// - Compiler options:

// - Program Memory: 0x8000

// - DataMemory: 0x0800

// - Stack Pointer: 0x09FF

//

// Эта программа обеспечивает управление звуковым усилителем.

// Усилитель может принимать звуковой сигнал от ряда

// источников. Пользователь может выбирать источник сигнала

// для усиления с помощью переключателей на лицевой панели

// (связанных с портом B), либо переключателей на пульте

// дистанционного управления (связанных с портом A). Процессор

// управляет светодиодами на передней панели(связанными с портом P)

// и показывающими активный источник сигнала и включает реле(связанные

// с портом T), подсоединяющие один из источников сигнала к усилителю

//

// Функции портов ввода

//

// Порт А, входной - вводит сигналы от пульта дистанционного управления,

// требует импульсов высокого логического уровня длительностью в 100 мс

// PA7 выкл. звука от пульта дист. управления высокий - импульс 100 мс

// PA6 Дополнительный канал (ДК) от пульта дист. управления высокий

// импульс 100 мс

// PA5 магнитофон # 2 от пульта дист. управления высокий - импульс 100 мс

// PA4 магнитофон # 1 от пульта дист. управления высокий - импульс 100 мс

// PA3 тюнер от пульта дист. управления высокий - импульс 100 мс

// PA2 CD от пульта дист. управления высокий - импульс 100 мс

// PA1 пианино от пульта дист. управления высокий - импульс 100 мс

// PA0 предусилитель от пульта дист. управления высокий - импульс 100 мс

// Порт В входной - от переключателей на лицевой панели блока

// PB0 предусилитель от переключателя на лицевой панели, вжатый перек-

// лючатель = вкл

// PB1 пианино от переключателя на лицевой панели, вжатый переключатель = вкл

// PB2 CD от переключателя на лицевой панели, вжатый переключатель = вкл

// PB3 тюнер от переключателя на лицевой панели, вжатый переключатель = вкл

// PB4 магнитофон # 1 от переключателя на лицевой панели, вжатый пе-

// реключатель = вкл

// PB5 магнитофон # 2 от переключателя на лицевой панели, вжатый пе-

// реключатель = вкл

// PB6 ДК от переключателя на лицевой панели, вжатый переключатель = вкл

// PB7 выкл. звука от переключателя на лицевой панели, вжатый перек-

// лючатель = вкл

//

//Порт P выходной - светодиоды на лицевой панели

//PP0 сигнал на силовое реле и на светодиоды и сигнал низкого уровня

//для //светодиодов в буфер

//PP1 светодиод пианино выходной низкопотенциальный сигнал - 10 мА

//PP2 светодиод CD выходной низкопотенциальный сигнал - 10 мА

//PP3 светодиод тюнер выходной низкопотенциальный сигнал - 10 мА

//PP4 светодиод магнитофон # 1 выходной низкопотенциальный сигнал - 10 мА

//PP5 светодиод магнитофон # 2 выходной низкопотенциальный сигнал - 10 мА

//PP6 светодиод ДК выходной низкопотенциальный сигнал - 10 мА

//PP7 светодиод выкл. звука, сигнал на силовое реле

//

//Порт T выходной - драйверы реле

//PT0 реле RESET выход на реле RESET высокий уровень - импульс 5 мс

//PT1 реле пианино выход на реле пианино высокий уровень - импульс 5 мс

//PT2 реле CD выход на реле CD высокий уровень - импульс 5 мс

//PT3 реле тюнера выход на реле тюнера высокий уровень - импульс 5 мс

//PT4 реле магнитофон # 1 выход на реле магнитофон # 1 высокий уро-

//вень - импульс 5 мс

//PT4 реле магнитофон # 2 выход на реле магнитофон # 2 высокий уро-

//вень - импульс 5 мс

//PT6 реле ДК выход на реле ДК высокий уровень //- импульс 5 мс

//PT7 высокий уровень - импульс 10 мс для подачи питания на оптроны

//светодиодов и усилитель

//Подача питания (от сети или от источника 5 В):

//Конфигурация портов:

//1. Порт A: конфигурирован как входной, отжатый переключатель - запрет

//2. Порт B: конфигурирован как входной, отжатый переключатель - разрешение

//3. Порт P: конфигурирован как выходной, все линии в 1

//4. Порт T: конфигурирован как выходной, все линии в 0

//5. Установка "RELAY-RESET" (PTO) импульсом высокого состояния 5 мс

//6. Установка "RELAY-CD" (PT2) импульсом высокого состояния 5 мс

//7. Установка "WHICH-INPUT" позиция сохранения = "CD"

//8. Цикл PP1-РР6 (устанавливаются в низкое состояние) светодиоды

// показывают , что контроллер работает

//9. Переход к последовательности "PREAMP ON"

//

//Логика работы :

//Последовательность "PREAMP ON"

//1. Ожидание установки "S-PREAMP-PWR" (PB0) или "R-PREAMP-PWR" (РАО)

//2. Установка "LED-MUTE-RELAY" (PP7)

//3. Установка "LED-PWR-RELAY" (PP0)

//4. Считывание позиции в "WHICH-INPUT"

//5. Установка "LED-xxxxx" = позиция "WHICH-INPUT"

//6. Установка PT7(1) импульсом 10 мс

//7. DE-Assert "LED-MUTE-RELAY" (PP7) через ~3 с.

//8. переход к режиму "SCAN"

//

//Последовательность "SCAN"

//1.Ожидание входного сигнала от (PB0-PB7) или от (PA0-PA7)

//2. IF = "x-PREAMP-PWR" - переход к последовательности "PREAMP OFF"

//3. IF = "x-MUTE" GOTO - переход к последовательности "MUTE"

//4. IF = любой входной сигнал от (PB1-PB6) или (PA1-PA6)- переход к

"CHANGE"

// последовательность "INPUT"

//

// последовательность "CHANGE INPUT":

//1. Включить "LED-MUTE-RELAY" (PP7)

//2. Включить "RELAY-RESET" (PT0) импульсом высокого уровня 5 мс

//3. Включить "RELAY-xxxxx" (PT1-PT6) (в соответствии с выбором

// "WHICH-INPUT" импульсом высокого уровня 5 мс)

//4. Включить "LED-xxxxx" (PP1-PP6) (в соответствии с выбором

// "WHICH-INPUT")

//5. Очистить Old/Input сохранить новое значение "WHICH-INPUT"

//6. DE-переключение "MUTE-RELAY" (PP7) примерно через 3 с.

//7. Перейти к последовательности "SCAN"

//

// последовательность "MUTE":

//1. Переключить "LED-MUTE-RELAY" (PP7)

//2. Перейти к последовательности "SCAN"

//

//Последовательность "PREAMP OFF":

//1. Включить "LED-MUTE-RELAY" (PP7)

//2. DE-переключение "LED-PWR-RELAY" (PP0)

//3. DE-переключение всех светодиодов (PP1-РР6)

//4. Включить PT7(1) импульсом 10 мс

//5. DE-переключение "LED-MUTE-RELAY" (PP7) примерно через 3 с.

//6. Перейти к последовательности "PREAMP ON"

//

//авторы: Steven Barrett и Daniel Pack

//Дата разработки: 19 июня 2004

//Последняя редакция: 20 июня 2004

//*******************************************************************

//*******************************************************************

//включенные файлы

#include <912b32.h> //B32 EVB header file

#include "func_def.h" //функции-прототипы, глобальные переменные

//main program*******************************************************

// глобальные переменные

int which_input; //вход усилителя

int keep_going; //ввод переменных

int mute; //флаг управления выключением звука

unsigned char old_PORTB = 0xff; //текущие значения PORTB

unsigned char old_PORTA = 0x00; //текущие значения PORTA

unsigned char new_PORTB, new_PORTA; //новые значения PORTA, PORTB

void main(void) {

 asm(" .area vectors(abs)\n"

  " .org 0xFFF8\n" //инициализация вектора сброса для 68HC12 B32

  " .word 0x8000, 0x8000, 0x8000, 0x8000\n"

  " .text");

 initialize_task();

 //главный цикл

 while(1) { //ожидается сигнал на включение питания

  if ((PORTB==0xFE)||(PORTA==0X01))

  //PORTB переключается в низкое, PORTA - в

  // высокое состояние

  { //вы забыли включить питание! Запрос на операцию включения

   keep_going = 1; //цикл считывания переменных

   PORTP=0x7E; //включение LED-MUTE-RELAY PP7(0)

               //LED-PWR-RELAY PP0(0) (0111_1110)

   which_input_task();

   activate_power_relay_task();

   delay_3s(); //задержка 3 с.

   PORTP = 0x80; // DE-переключение PD7(1) - включение звука

   while(keep_going) //прохождение меню - главный цикл опроса

   {

    process_PORTB_input_task();

    process_PORTA_input_task();

   }

  }//end if - ожидание включения питания - питание не подано!

 }//end while(1)

}//конец главного цикла

//*******************************************************************

// определение функций

//*******************************************************************

initialize_task: начальные установки усилителя

//*******************************************************************

void initialize_task(void) {

 mute = on; //turn mute on

 initialize_timer(); // инициализация таймера

 initialize_ports(); // инициализация портов

 initialize_pins(); // инициализация состояния отдельных выводов

 which_input = 2 ; //по умолчанию включается вход CD(2)

                   //включение светодиодов на лицевой панели

 PORTP = 0x81; //включение всех светодиодов PD1-PD6 низким активным

               // уровнем (1000_0001)

 delay_3s(); //задержка 3 с

 PORTP = 0xff; //выключение светодиодов

}

//*******************************************************************

//which_input_task: опрос входов, установка текущего состояния

//*******************************************************************

void which_input_task(void) {

 switch(which_input) { // подсвечивается светодиод для используемого

                       // входа (по умолчанию вход 2 - CD)

 case 1: //Пианино

  phono_task();

  break;

 case 2: //CD

  CD_task();

  break;

 case 3: //Тюнер

  tuner_task();

  break;

 case 4: //Магнитофон 1

  tape1_task();

  break;

 case 5: //Магнитофон 2

  tape2_task();

  break;

 case 6: //Дополнительный канал (ДК)

  aux_task();

  break;

 default:;

 }//конец switch

}

//*******************************************************************

//phono_task: конфигурируется вход от Радио

//*******************************************************************

void phono_task(void) {

 PORTT |= 0x02; //устанавливается PT1(1) (0000_0010)

 delay_5ms();

 PORTT &= ~0x02; // выключается PT1(0)

 PORTP = 0x7E; //гасятся все светодиоды

 PORTP &= ~0x02; //включается светодиод 1 (0)

}

//******************************************************************

//CD_task: конфигурируется вход от CD

//******************************************************************

void CD_task(void) {

 //CD

 PORTT |= 0x04; // устанавливается PT2(1) (0000_0100)

 delay_5ms();

 PORTT &= ~0x04; // выключается PT2(0)

 PORTP |= 0x7E; //гасятся все светодиоды

 PORTP &= ~0x04; // включается светодиод 2 (0)

}

//******************************************************************

//tuner_task: конфигурируется вход от тюнера

//******************************************************************

void tuner_task(void) {

 //TUNER PORTT |= 0x08; // устанавливается PT3(1) (0000_1000)

 delay_5ms();

 PORTT & = 0x08; // выключается PT3(0

 PORTP |= 0x7E; //гасятся все светодиоды

 PORTP &= ~0x08; // включается светодиод 3 (0)

}

//******************************************************************

//tape1_task: конфигурируется вход от магнитофона 1

//******************************************************************

void tape1_task(void) {

 //TAPE#1

 PORTT |= 0x10; //assert PT4(1) (0001_0000)

 delay_5ms();

 PORTT &= ~0x10; // выключается PT4(0)

 PORTP |= 0x7E; //гасятся все светодиоды

 PORTP &= ~0x10; // включается светодиод 4 (0)

}

//******************************************************************

//tape2_task: конфигурируется вход от магнитофона 2

//******************************************************************

void tape2_task(void) {

 //TAPE#2

 PORTT |= 0x20; // устанавливается PT5(1) (0010_0000)

 delay_5ms();

 PORTT &= ~0x20; // выключается PT5(0)

 PORTP |= 0x7E; //гасятся все светодиоды

 PORTP & = ~0x20; // включается светодиод 5 (0)

}

//******************************************************************

//aux_task: конфигурируется вход от дополнительного канала

//******************************************************************

void aux_task(void) {

 //ДК

 PORTT |= 0x40; // устанавливается PT6(1) (0100_0000)

 delay_5ms();

 PORTT &= ~0x40; // выключается PT6(0)

 PORTP |= 0x7E; //гасятся все светодиоды

 PORTP &= ~0x40; // включается светодиод 6(0)

}

//******************************************************************

//activate_power_relay_task(): включается реле силового питания

//******************************************************************

void activate_power_relay_task(void) {

 PORTT |= 0x80; // устанавливается PT7(1) импульсом 10 мс

 delay_5ms();

 delay_5ms();

 PORTT &= ~0x80; // выключается PT7

}

//******************************************************************

//process_PORTB_input_task(): определяется выбранный вход от PORTB

//******************************************************************

void process_PORTB_input_task(void) {

 new_PORTB = PORTB; //read PORTB

 if (new_PORTB != old_PORTB) { //считывание состояния порта PORTB

  switch(new_PORTB) { //PORTB устанавливается на низкий уровень

  case 0xFE: //PB0 "S-PREAMP-PWR" (1111_1110)

   if (process_valid_input_PORTB(new_PORTB)) {

    preamp_off();

    keep_going=0;

   }

   break;

  case 0xFD: //PB1 "S-PHONO" (1111_1101)

   if (which_input !=1) {

    if (process_valid_input_PORTB(new_PORTB) {

     which_input = 1;

     change_input();

    }

   }

   break;

  case 0xFB: //PB2 "S-CD" (1111_1011)

   if (which_input!=2) {

    if (process_valid_input_PORTB(new_PORTB)) {

     which_input = 2;

     change_input();

    }

   }

   break;

  case 0xF7: //PB3 "S-TUNER" (1111_0111)

   if (which_input != 3) {

    if (process_valid_input_PORTB(new_PORTB)) {

     which_input = 3;

     change_input();

    }

   }

   break;

  case 0xEF: //PB4 "S-TAPE#1" (1110_1111)

   if (which_input != 4) {

    if (process_valid_input_PORTB(new_PORTB)) {

     which_input = 4;

     change_input();

    }

   }

   break;

  case 0xDF: //PB5 "S-TAPE#2" (1101_1111)

   if (which_input != 5) {

    if (process_valid_input_PORTB(new_PORTB)) {

     which_input = 5;

     change_input();

    }

   }

   break;

  case 0xBF: //PB6 "S-AUX" (1011_1111)

   if (which_input != 6) {

    if (process_valid_input_PORTB(new_PORTB)) {

     which_input = 6;

     change_input();

    }

   }

   break;

  case 0x7F: //PB7 "S-MUTE" (0111_1111)

   if (process_valid_input_PORTB(new_PORTB)) {

    mute_toggle();

   }

   break;

  default:; //all other cases

  } //конец switch(new_PORTB)

 } //конец if new_PORTB

 old_PORTB=new_PORTB; //update PORTB

}

//******************************************************************

//process_PORTA_input_task():определяется выбранный вход от PORTA

//******************************************************************

void process_PORTA_input_task(void) {

 new_PORTA = PORTA; //Читать PORTA

 if (new_PORTA != old_PORTA) { //выбор входа по состоянию порта PORTA

  switch (new_PORTA) { //PORTA переводится в высокое состояние

  case 0x01: //РАО "R-PREAMP-PWR" (0000_0001)

   if (process_valid_input_PORTA(new_PORTA)) {

    preamp_off();

    keep_going=0;

   }

   break;

  case 0x02: //PA1 R-PHONO" (0000_0010)

   if (which_input != 1) {

    if (process_valid_input_PORTA(new_PORTA)) {

     which_input = 1;

     change_input();

    }

   }

   break;

  case 0x04: //PA2 "R-CD" (0000_0100)

   if (which_input != 2) {

    if (process_valid_input_PORTA(new_PORTA)) {

     which_input = 2;

     change_input();

    }

   }

   break;

  case 0x08: //РАЗ "R-TUNER" (0000_1000)

   if (which_input != 3) {

    if (process_valid_input_PORTA(new_PORTA)) {

     which_input = 3;

     change_input();

    }

   }

   break;

  case 0x10: //PA4 "R-TAPE#1" (0001_0000)

   if (which_input != 4) {

    if (process_valid_input_PORTA(new_PORTA)) {

     which_input = 4;

     change_input();

    }

   }

   break;

  case 0x20: //PA5 "R-TAPE#2M (0010_0000)

   if (which_input != 5) {

    if (process_valid_input_PORTA(new_PORTA)) {

     which_input = 5;

     change_input();

    }

   }

   break;

  case 0x40: //PA6 "R-ДОПОЛНИТЕЛЬНЫЙ КАНАЛ" (0100_0000)

   if (which_input != 6) {

    if (process_valid_input_PORTA(new_PORTA)) {

     which_input = 6;

     change_input();

    }

   }

   break;

  case 0x80: //PA7 "R-MUTE" (1000_0000)

   if (process_valid_input_PORTA(new_PORTA)) {

    mute_toggle();

   }

   break;

   default:; //all other cases

  } //конец switch(new_PORTA)

 }//конец if new_PORTA

 old_PORTA = new_PORTA; //изменяется состояние PORTA

}

//******************************************************************

//initialize_timer:установка частоты таймера обслуживающего счетчик

//******************************************************************

void initialize_timer(void) {

 TMSK2 = 0x05; //установка на 250 КГц

 TSCR = 0x80; //разрешение работы таймера

}

//******************************************************************

//initialize_ports: начальная конфигурация портов

//******************************************************************

void initialize_ports(void) {

 DDRA=0x00; //конфигурация PORTA в качестве входного

 PORTA=0x00; //запрет на подключение подтягивающих резисторов в PORTA

 DDRB=0x00; //конфигурация PORTB в качестве входного

 PORTB=0xff; //разрешение подключения подтягивающих резисторов в PORTB

 DDRT=0xff; // конфигурация PORTT в качестве выходного

 PORTT=0x00; // установка на низкий уровень

 DDRP=0xff; // конфигурация PORTD в качестве выходного

 PORTP=0xff // установка на высокий уровень

}

//******************************************************************

//******************************************************************

//initialize_pins: установка отдельных выводов

//******************************************************************

void initialize_pins(void) {

 PORTT=0x01; //сброс реле PT0(1) 5 мс импульс с

 // активным уровнем (0000_0001)

 //delay_5ms():

 PORTT=0x00;

}

//******************************************************************

//delay_5ms: Задержка на 5 мс сформированная из базе частоты таймера

//в 250 кГц

//******************************************************************

void delay_5ms(void) {

 int i;

 for(i=0; i<1250; i++)

  asm("nop"); //требуется только один импульс таймера

}

//******************************************************************

//delay_3s: Задержка на 3 с

//******************************************************************

void delay_3s(void) {

 int i;

 for(i=0;i<600;i++) delay_5ms();

}

//******************************************************************

//change_input: изменение активного входа

//******************************************************************

void change_input(void) {

 PORTP &= ~0x80; //установка LED-MUTE-RELAY PP7(0) 1000_0000

 PORTT |= 0x01; //установка сброса реле PT0(l) 5 мс

 delay_5ms();

 PORTT &= ~0x01; //turn off PT0

 switch(which_input) {

 case 1: //PHONO

  phono_task();

  break;

 case 2: //CD

  CD_task();

  break;

 case 3: //TUNER

  tuner_task();

  break;

 case 4: //TAPE#1

  tape1_task();

  break;

 case 5: //TAPE#2

  tape2_task();

  break;

 case 6: //AUX

  aux_task();

  break;

  default:;//все другие входы

 }//конец switch

 delay _3s();

 PORTP |= 0x80; //сброс LED-MUTE-RELAY PP7(1)

}

//******************************************************************

//mute_toggle: включение и выключение звука

//******************************************************************

void mute_toggle(void) {

 if (mute == off) {

  PORTP &= ~0x80; //установка LED-MUTE-RELAY PP7(0)

  mute = on;

 } else {

  PORTP |= 0x80; // сброс LED-MUTE-RELAY PP7(1)

  mute = off;

 }

}//end mute_toggle

//******************************************************************

//preamp_off: turn amplifier off

//******************************************************************

void preamp_off(void) {

 PORTP &= ~0x80; //установка LED-MUTE-RELAY PP7(0)

 PORTP |= 0x01; //сброс LED-PWR-RELAY PP0(1)

 PORTP |= 0x7e; //сброс светодиодов PP1-PP6(1)(0111_1110)

 //установка PT7 импульсом 10 мс

 PORTT |= 0x80; //установка PT7(1) импульсом 10 мс

 delay_5ms();

 delay_5ms();

 PORTT &= ~0x80; //сброс PT7

 delay_3s();

 PORTP = 0x80; //сброс PP7(1) LED-MUTE-RELAY

 keep_going=0;

}

//******************************************************************

//process_valid_input_PORTA: проверка состояния пульта дистанционного

//управления, длительностью не менее 50 мс

//******************************************************************

int process_valid_input_PORTA(unsigned char portx) {

 int valid_input; //установить флаг ошибочного входа

 unsigned int current_count;

 valid_input = TRUE;

 current_count = TCNT; // задать текущее состояние

 while (TCNT < (current_count+12500)) { //отследить активный вход за 50 мс

  if (portx==PORTA) valid_input = TRUE;

  else valid_input = FALSE;

  if (!valid_input) break; //цикл while

 }//end while

 return valid_input;

}

//******************************************************************

//process_valid_input_PORTB: проверка состояния переключателей на

//лицевой панели,длительностью не менее 50 мс

//******************************************************************

int process_valid_input_PORTB(unsigned char portx) {

 int valid_input; //установить флаг ошибочного входа

 unsigned int current_count;

 valid_input = TRUE;

 current_count = TCNT; // задать текущее состояние

 while (TCNT < (current_count+12500)){ //отследить активный вход за 50 мс

  if (portx==PORTB) valid_input = TRUE;

  else valid_input = FALSE;

  if (!valid_input) break; //цикл while

 }//конец while

 return valid_input;

}

//******************************************************************

//******************************************************************

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]