logo
HCS12 с применением языка С - royallib

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;

}

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

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