Встраиваемые системы. Проектирование приложений на микроконтроллерах семейства 68HC12/HCS12 с применением языка С - Стивен Барретт
Шрифт:
Интервал:
Закладка:
Рис. 4.91. Формат регистра данных порта PORTAD
Регистры результата ADR0H…ADR7HПосле завершения каждого преобразования в составе измерительной последовательности результат преобразования помещается в один из восьми регистров результата ADR0H…ADR7H. Номер регистра определяется режимом работы модуля ATD и разрядами CD…CA регистра управления ATDCTL5 (рис. 4.89). Регистры результата ADR0H…ADR7H восьмиразрядные, в памяти располагаются по адресам $0070…$007E. Формат регистров ADR0H…ADR7H приведен на рис. 4.92.
Рис. 4.92. Формат регистров результата модуля ATD
В регистрах ADR0H…ADR7H результат аналого-цифрового преобразования представляется в прямом коде без знака. Диапазон возможных значений кодов — 0…255. Для представления результата в абсолютных единицах необходимо код результата разделить на число единиц полной шкалы, а затем умножить на напряжение полной шкалы:
UIZM = KIZM/256×UREF
Вопросы для самопроверки1. Код измеренного напряжения на выходе 8-разрядного АЦП равен 10001010b. Потенциалы на входах опорных напряжений АЦП составляют URH=5,0 В и URL=0 В. Каково значение измеренного напряжения в Вольтах?
Ответ: Десятичный эквивалент двоичного кода 10001010b равен 138. Поэтому измеренное напряжение равно:
UIZM = KIZM/256×UREF = (138/256) (5,0 – 0) = 2,69 В
Тестовый регистр ATDTESTДвухбайтовый регистр ATDTEST располагается в памяти по адресам $0068 и $0069. Доступ к этому регистру возможен только в специальном режиме работы МК. В обычном пользовательском режиме работы этот регистр для чтения и для записи недоступен.
4.22.3. Пример программирования модуля ATD
Для того чтобы воспользоваться модулем аналого-цифрового преобразования ATD для измерения уровня напряжения на нескольких аналоговых входах МК, необходимо выполнить следующие действия:
• Подключить источники стабилизированного напряжения ко входам опорного напряжения VRF и VRL. Необходимо помнить, что напряжение на входе высокого уровня опорного напряжения VRF не должно превышать 5,0 В, а на входе низкого уровня VRL напряжение должно быть не менее 0 В. Кроме того, разность напряжений на входах VRF и VRL, равная напряжению полной шкалы АЦП UREF = URH–URL, не должна быть менее 2,5 В;
• Подключить источники измеряемых аналоговых сигналов ко входам AN0…AN7. Напряжение измеряемых сигналов должно находиться в диапазоне 0 В = USS≤UIZM≤UDD=5,0 В;
• Осуществить внутреннюю коммутацию напряжения питания к модулю ATD. Для этого записать 1 в бит ADPU регистра управления ATDCTL2. Адрес регистра — $0062;
• Выдержать паузу в 100 мкс для завершения переходных процессов в модуле ATD. В рассматриваемом ниже программном фрагменте мы покажем, как организовать такую задержку;
• Назначить режим работы модуля ATD посредством записи необходимых слов инициализации в управляющие регистры модуля;
• Запустить измерительную последовательность посредством записи в регистр управления ATDCTL5;
• Контролировать ход преобразования, используя флаги регистра состояния модуля ATDSTAT;
• Когда измерительная последовательность будет завершена, считать данные из регистров результата ADR0H…ADR7H в память МК;
• Если экономия энергии важна для Вашего применения, следует выключить модуль ATD, установив бит ADPU регистра ATDCTL2 в 0.
Мы рассмотрим программную реализацию действий по управлению модулем аналого-цифрового преобразования на примере простейшего цифрового вольтметра.
Цифровой вольтметрПрограммный фрагмент voltmeter.c производит измерение аналогового сигнала на входе AN6. Измерительная последовательность состоит из четырех преобразований. Режим измерения однократный. Результаты четырех последовательных преобразований одного и того же сигнала располагаются в четырех регистрах результата ADR0H…ADR3H. Эти измерения усредняются, что позволяет снизить влияние шумов. Полученный 8-разрядный двоичный код преобразуется к истинному значению измеряемого напряжения, умноженному на 100 d. Умножение на нормирующий коэффициент (100 в десятичной системе счисления) необходимо, чтобы использовать в программе целочисленные форматы представления данных. Полученный результат содержит одну десятичную цифру целой части измеренного напряжения, это единицы Вольт. А также две цифры десятичной дробной части. Это десятые и сотые доли Вольт в представлении результата. Промежуточные результаты исполнения программы, а также измеренное напряжение выводятся на экран персонального компьютера.
/*------------------------------------------------------------------------*/
/* filename: voltmeter.c */
/* В этом примере реализован простейший цифровой вольтметр. */
/* Программа выполняет одно измерение и выводит данные на экран */
/* персонального компьютера. Для того, чтобы выполнить следующее измерение*/
/* следует перезапустить программу */
/*------------------------------------------------------------------------*/
/*подключаемые файлы*/
#include <912b32.h>
#include <stdio.h>
#define DECIMAL 0х2Е /*определить код точки на экране*/
#define V 0х56 /*определить код символа "V" для экрана*/
/*используемые функции*/
void delay_100us(void);
void ADC_convert(void);
void delay_5ms (void);
void main(void) {
printf("HELLOn"); /*вывести приветствие на экран*/
ATDCTL2 = 0х80; /*включить питание модуля, запретить */
/*прерывания от модуля*/
printf("ADCn");
delay_100us(); /*задержка 100мкс*/
printf("warmed upn");
ATDCTL3 = 0х00; /*обеспечить доступ к модулю в отладочном режиме*/
ATDCTL4 = 0х01; /*установить 2 такта для времени выборки*/
/*и коэффициент деления, равный 4*/
printf("readyn");
ADC_convert(); /*реализовать цифровой вольтметр*/
}
/*---------------------------------------------------------------------*/
/* Функция ADC_convert 4 измерения, усредняет их, вычисляет абсолютное */
/* значение напряжения, а затем преобразует результат в коды ASCII для */
/* вывода на экран */
/*---------------------------------------------------------------------*/
void ADC_convert(void) {
unsigned int sumadr;
unsigned int avg_bin_voltage;
unsigned int int_voltage;
unsigned int ones_int;
unsigned int tenths_int;
unsigned int hundreths_int;
char ones;
char tenths;
char hundreths;
ATDCTL5 = 0х06; /*4 преобразования в последовательности, канал 6*/
/* Ожидать завершения измерительной последовательности*/
while((ATDSTAT & 0х8000) != 0х8000) {
;
}
/* Вывести коды преобразования на экран для контроля */
printf("%x %x %х %хn" , ADR0H, ADR1H, ADR2H, АDR3Н);
/* Взять среднее от 4 измерений для устранения шума*/
sumadr = ADR0H + ADR1H + ADR2H + ADR3H;
avg_bin_voltage = sumadr/4;
/*Преобразовать результат из двоичного кода к абсолютному значению,*/
/* умноженному на 100 D, получится число в диапазоне от 0 до 500 D*/
int_voltage = (100*avg_bin_voltage/255) * 5;
/*Выделить старший разряд результата и преобразовать в код ASCII */
/* Правило преобразования: десятичная цифра +48*/
ones_int = int_voltage/100;
ones = (char) (ones_int + 48);
/*Выделить второй разряд результата (десятые доли) и преобразовать в
код*/
/* ASCII */
tenths_int = (int_voltage ones_int*100)/10;
tenths = (char) (tenths_int + 48);
/*Выделить третий разряд результата (сотые доли) и преобразовать в
код*/
/* ASCII */
hundreths_int = (int_voltage ones_int*100 tenths_int*10) / 1;
hundreths = (char) (hundreths_int + 48);
/*Вывести значение измеренного напряжения на экран */
printf("%c.%c%cVn", ones, tenths, hundreths);
}
/*-----------------------------------------------------------------------*/
/* Функция delay_100us формирует задержку в 100 мкс, частота тактирования*/
/* межмодульных магистралей МК составляет 8 МГц */
/*-----------------------------------------------------------------------*/
void delay_100us(void) {
int i;
for (i=0; i<50; i++) {