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

7.3.3. Расчет интерфейса модуля atd

В разделе 5.9 мы описали, как подключить аналоговое устройство ввода данных к МК 68HC12, использовав методику расчета интерфейса преобразователя. Мы можем применить этот материал для разработки устройства, изменяющего диапазон входного напряжения от исходного ±10 В до диапазона от 0 до 5 В, совместимого с подсистемой аналого-цифрового преобразования для 68HC12.

Структурная схема согласующего устройства приводится на рис. 7.13. Это устройство должно сформировать напряжение 5 В на входе АЦП микроконтроллера, когда на вход вольтметра подается 10 В, и 0 В на входе АЦП при напряжении в –10 В на входе вольтметра. Чтобы выполнить такое преобразование, входной сигнал должен быть умножен на масштабирующий коэффициент, и, кроме того, должно быть создано напряжение смещения. В нашей схеме операцию масштабирования выполняет блок K, и его выходной сигнал суммируется с сигналом смещения B.

Рис. 7.13. К расчету согласующего устройства

По рассмотренной ранее методике составим два уравнения с двумя неизвестными, чтобы описать работу интерфейса преобразователя нашего проекта:

V2max = V2min * K + B

V1max = V1min * K + B

Нетрудно установить, что V1min = –10 В, а V2min = + 10 В, в то время как V1max = 0 В, и V2max = 5 В. Подставим эти значения в нашу систему уравнений:

5 = 10 * K + В

0 = (–10) * K + В

В результате решения системы получим масштабный множитель K = 0.25, и напряжение смещения B = 2.5 В. Cоздадим схему на ОУ с коэффициентом передачи 0.25, и добавим напряжение смещения в 2.5 В.

При работе вольтметра после преобразования входного напряжения встроенным в МК АЦП, мы должны выполнить пересчет кода оцифровки, чтобы получить фактически измеренное входное напряжение для вывода его на дисплей. Эта операция выполняется с помощью программного обеспечения.

7.3.4. Структура программы и блок-схема алгоритма

Мы приводили структуру программы и блок-схему алгоритма для каждого из рассматриваемых проектов. Для этого проекта мы оставляем разработку структуры и блок схемы читателю в качестве домашней работы (задание 17).

7.3.5. Программа управления

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

/* Имя файла: voltmeter2.с                                          */

/* Это программа для реализации простого вольтметра на базе АЦП,    */

/* встроенного в МК HC12. Приведенный программный код выполняет     */

/*одно преобразование и затем программа может вручную               */

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

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

#include <912b32.h>

#include <stdio.h>

void delay_100us(void);

void ADC_convert(void);

void delay_5ms(void);

void main(void) {

 asm(" .area vectors (abs)\n" /*код инициализации вектора reset B32 */

  " .org 0xFFF8\n"

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

  " .text");

 initialize_LCD(); /*инициализация ЖК дисплея */

 ATDCTL2 = 0x80; /*подача питания на АЦП, разрешение прерываний */

 delay_5ms(); /*ожидание входа АЦП в рабочий режим */

 ATDCTL3 = 0x00;

 ATDCTL4 = 0x01; /*8-разрядный результат, время выборки 2 АЦП */

                 /*clk, коэффициент деления 4 */

 ADC_convert(); /*АЦП преобразование */

}

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

/* void ADC_convert(void): функция, осуществляющая одно преообразо- */

/* вание и сохраняющая доступ пользователя к нему. Затем функция    */

/* преобразует текущий результат в цифровое значение. Таким образом */

/* каждое отдельное число может быть выделено, преобразовано в ASCII*/

/* код и выведено на ЖКД                                            */

void ADC_convert() {

 unsigned int sumadr;

 unsigned int avg_bin_voltage;

 unsigned int int_voltage;

 unsigned int tens_int;

 unsigned int ones_int;

 unsigned int tenths_int;

 unsigned int hundredths_int;

 double voltage, abs_voltage;

 char tens;

 char ones;

 char tenths;

 char hundredths;

 ATDCTL5 = 0x06; /*проводится 4 преобразования, канал 6 */

 while((ATDSTAT & 0x8000)!= 0x8000) {

  /*Подождите окончания преобразования */

 }

 /*усреднение по четырем результатам */

 sumadr = ADR0H + ADR1H + ADR2H + ADR3H;

 avg_bin_voltage = sumadr/4;

 /* преобразование результата в напряжение, лежащее в диапазоне от */

 /* 0.00 до 5.00 В */

 voltage = (avg_bin_voltage/256)*5;

 /*приведение напряжения к диапазону от -10.00 до +10.00 В */

 /*обращение процесса, выполняемого аналоговым интерфейсом */

 abs_voltage = (fabs)((voltage - 2.5) * 4);

 /*преобразование результата в целое число в диапазоне от -1000 */

 /* до +1000 */

 int_voltage = (100*voltage);

 /*Выделение и преобразование наибольшей значащей цифры в */

 /* ASCII код десятичного значения, прибавление 48, */

 /* результат дает ASCII код */

 tens_int = int_voltage/1000;

 tens = (char)(tens_int + 48);

 /*Выделение и преобразование следующей наибольшей значащей цифры в */

 /* ASCII код десятичного значения, прибавление 48, */

 /* результат дает ASCII код*/

 ones_int = int_voltage/100;

 ones = (char)(ones_int + 48);

 /*Выделение и преобразование следующей наибольшей значащей цифры в */

 /* ASCII код десятичного значения, прибавление 48, */

 /* результат дает ASCII код */

 tenths_int = (int_voltage - ones_int*100)/10;

 tenths = (char)(tenths_int + 48);

 /*Выделение и преобразование следующей наибольшей значащей цифры в */

 /* ASCII код десятичного значения, прибавление 48, */

 /* результат дает ASCII код */

 hundredths_int = (int_voltage - ones_int*100 - tenths_int*10)/1;

 hundredths = (char)(hundredths_int + 48);

 /*Вывод результата на ЖКД */

 if (voltage < 0) putchars('-'); /*Вывести отрицательный знак*/

 else putchars('+'); /*Вывести положительный знак*/

 putchars(tens);

 putchars(ones);

 putchars('.');

 putchars(tenths);

 putchars(hundredths);

 putchars(' ');

 putchars('V');

}

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

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

/*задержка в 100 мкс, на базе таймера с частотой 8 МГц              */

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

void delay_100us(void) {

 int i;

 for (i=0; i<50; i++) {

  asm("nop");

 }

}

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

/*задержка в 5 мс, на базе таймера с частотой 8 МГц                 */

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

void delay_5ms(void) {

 int i;

 for (i=0; i<50; i++) {

  delay_100us();

 }

}

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

/*Функции инициализации посылают на ЖКД необходимую стартовую       */

/* последовательность. Формируется последовательность команд инициали-*/

/* зации соответствующих техническим данным производителя дисплея.  */

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

void initialize_lcd(void) {

 delay_5ms();

 delay_5ms();

 delay_5ms(); /*задержка на 15 мс перед включением ЖКД */

 putcommands(0x38); /*установочный интерфейс */

 delay_5ms();

 putcommands(0x38);

 delay_100us();

 putcommands(0x38);

 putcommands(0x38);

 putcommands(0x0C);

 putcommands(0x01); /*Очистить дисплей */

 putcommands(0x06); /*Установить режим увеличения адреса на единицу*/

 putcommands(0x0E); /*Включить дисплей,вывести мигающий курсор */

 putcommands(0x02); /*Возврат */

}

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

/* Функция вывода инициализирует порт данных, создает сигналы RS и  */

/* разрешения и посылает их на соответствующий порт                 */

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

void putchars(unsigned char c) {

 DDRP = 0xFF; /*установить Port P как выходной */

 DDRDLC = DDRDLC | 0x0C; * установить PORTDLC[3:2] как выходной */

 PORTP = c; /* присвоить знак С порту данных */

 PORTDLC= PORTDLC|0x08 /* установить RS в 1 для данных */

 PORTDLC= PORTDLC|0x04 /* установить E в 1 ( PORTDLC[5] = 1) */

 PORTDLC = 0; /* установить E и RS в 0 */

 delay_5ms(); /* подождать 5мс */

}

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

/*Функция putcommand пересылает данные в контроллер на ЖК дисплея   */

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

void putcommands(unsigned char d) {

 DDRP = 0xFF; /*установить порт PORTP в качестве выходного */

 DDRDLC = DDRDLC|0x0C; /*установить выводы PORTDLC[3:2] */

                       /* в качестве выходных */

 PORTDLC = PORTDLC & 0xF7; /* команда RS = 0 */

 PORTP = d; /*передача команды на на ЖКД */

 PORTDLC = PORTDLC|0x04; /*E = 1 */

 PORTDLC =0; /*E = 0 */

 delay_5ms(); /*пауза 5 мс */

}

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

/*Функция lcd_print посылает строку на ЖК дисплей                   */

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

void lcd_print(char *string) {

 putcommands(0x02); /*установка курсора на первую строку */

                    /*putcommand для выделения строки */

 while(*(string) != '\0') {

  putchars(*string);

  string++;

 }

}

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

/*задержка в 5 мс, на базе таймера с частотой 8 МГц                 */

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

void delay_5ms(void) {

 int i;

 for (i=0; i<50; i++) {

  delay_100us();

 }

}

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

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

/*задержка в 100 мкс, на базе таймера с частотой 8 МГц              */

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

void delay_100us(void) {

 int i;

 for(i=0; i<50; i++) {

  asm("nop");

 }

}

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

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