Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование встроенных приложений Keil uvision

.pdf
Скачиваний:
83
Добавлен:
06.01.2021
Размер:
4.29 Mб
Скачать

СПБГУАП группа 4736 / Индустрия 4.0

4.5. Основы работы с аналого-цифровым преобразователем

Цель работы – освоение принципов работы аналого-цифро- вого преобразователя (АЦП) в составе МК К1986ВЕ92QI на базе отладочной платы МилКиТЭС.

Задачи:

1)Создать новый проект в среде KEIL MDK-ARM;

2)Написать рабочий программный код с комментариями;

3)Проверить работоспособность программного кода;

4)Выполнить индивидуальные задания;

5)Написать отчёт о проделанной работе.

4.5.1. Введение

Микроконтроллер К1986ВЕ92QI имеет в своем составе два 12разрядных АЦП. С помощью АЦП можно оцифровать сигнал от 16 внешних аналоговых выводов порта D и от двух внутренних каналов, на которые выводятся датчик температуры и источник опорного напряжения.

Врамках работы будет рассмотрен пример чтения напряжения

срезистора подключенного к каналу 4 АЦП (PD4) в режиме потенциометра (рис. 41).

Рис. 41. Электрическая схема подключения резистора R46 к 4 каналу АЦП МК

99

СПБГУАП группа 4736 / Индустрия 4.0

4.5.2. Настройка АЦП

Для начала работы с модулем АЦП в составе МК К1986ВЕ92QI необходимо провести его инициализацию.

Последовательность работы с АЦП:

1)Включение тактирования модуля АЦП;

2)Инициализация АЦП;

3)Настройка порта ввода/ввода на вход в режим работы с АЦП;

4)Установка канала АЦП для измерений;

5)Подача команды начала преобразования;

6)Чтение результата преобразований.

Первым делом следует включить тактирование модуля АЦП в регистре MDR_RST_CLK->PER_CLOCK. После этого необходимо настроить конфигурацию АЦП с помощью регистра

MDR_ADC->ADC1_CFG (листинг 9)

/*------------------------------------------------------------*/ void MCU_ADC_init()

{

MDR_RST_CLK->PER_CLOCK |= (1 << 17); // вкл. тактирование АЦП

MDR_ADC->ADC1_CFG = (1 // вкл. АЦП

|(0 << 1)

// сброс бита «начала преобразования»

|(0 << 2)

// источник синхросигнала - CPU_CLK

|(1 << 3)

// автоматич. запуск после завершения преобразования

|(0 << 4)

// номер канала преобразования будет уст. позже

|(0 << 9)

// переключение каналов выкл

|(0 << 10)

// автоматический контроль уровней откл.

|(0 << 11)

// источник опорного напряжения – внутр.(AUсс=VDD =3.3В)

|(3 << 12)

// коэффициент деления частоты ADC_clk = HCLK/8 = 10 М

|(0 << 16)

// работа двух АЦП одновременно откл.

|(0 << 17)

// датчик температуры и опорного напряжения откл.

|(0 << 18)

// усилитель для датчика темп. и ист. опорного напр.откл

|(0 << 19)

// оцифровка датчика температуры откл.

|(0 << 20));

// оцифровка источника опорного напряжения на 1.23 В откл.

}

 

/*------------------------------------------------------------

*/

Листинг 9. Рабочий код инициализации АЦП МК

100

СПБГУАП группа 4736 / Индустрия 4.0

Также следует настроить PD4 в режим работы как аналоговый вход. Это следует делать с помощью битовых масок, чтобы не повредить настройки других выводов PORTD:

/*------------------------------------------------------------

*/

MDR_PORTD->OE

&=~ (1 << 4); // настройка PD4 на вход

MDR_PORTD->ANALOG &=~ (1 << 4); // перевод PD4 в аналоговый режим работы

/*------------------------------------------------------------

*/

После выполнения инициализации АЦП необходимо устано-

вить канал:

 

/*------------------------------------------------------------

*/

void MCU_ADC_set_ch(uint8_t channel)

 

{

 

// проверка номера канала и возврат в случае выхода из диапазона if (channel > 15) return;

MDR_ADC->ADC1_CFG |= channel << 4; // уст. канала АЦП

}

/*------------------------------------------------------------

*/

Для начала операции преобразования напряжения требуется подать команду начала преобразования. Для этого следует записать “1” в первый бит регистра MDR_ADC->ADC1_CFG:

/*

------------------------------------------------------------*/

void MCU_ADC_start_conv(void)

{

 

 

MDR_ADC->ADC1_CFG |= 1 << 1; // команда начала преобразования

}

 

/*

------------------------------------------------------------*/

На этом подготовительная часть работы закончена, можно переходить к чтению результатов преобразования.

101

СПБГУАП группа 4736 / Индустрия 4.0

4.5.3. Проведение измерений напряжения

После подготовки функций инициализации АЦП, портов ввода/вывода, установки канала и начала преобразований, АЦП готов к работе.

Время преобразования АЦП зависит от времени установки канала, заряда внутренней емкости и времени преобразования. Эти времена, в свою очередь, зависят от настройки тактирования модуля АЦП.

Спустя некоторое время после подачи команды начала преобразования результат преобразования помещается в регистр

MDR_ADC->ADC1_RESULT. Регистр MDR_ADC->ADC1_RE- SULT также содержит информацию о номере канала преобразования (рис. 42).

Рис. 42. Содержание регистра MDR_ADC->ADC1_RESULT

Рассмотрим функцию чтения результатов преобразования

АЦП:

/*------------------------------------------------------------

*/

uint32_t MCU_ADC_read(void)

{

 

uint32_t ADC_data = 0;

// локальная для хранения результата преобр.

MCU_ADC_start_conv();

// команда начала преобразования

//пустой цикл - ожидание окончания преобразования while(!(MDR_ADC->ADC1_STATUS) & (1<<2)) { }

ADC_data = MDR_ADC->ADC1_RESULT; // чтение результата преобразований

//очистка битов содержащих номер канала преобразования – обнуление

//старшего полубайта регистра

ADC_data

= ADC_data & 0x0FFF;

return ADC_data; // возврат результата преобразования

}

 

/*------------------------------------------------------------

*/

Проведем измерение напряжения с канала 4 АЦП и выведем результат в виде отсчетов на дисплей (листинг 10).

102

СПБГУАП группа 4736 / Индустрия 4.0

/*------------------------------------------------------------

 

*/

#include "MDR32Fx.h"

 

// подключение библиотеки МК

#define F_CPU 8000000

 

// указание тактовой частоты МК

#include "milkites_delay.h"

// подключение библиотеки задержек

#include "milkites_display.h" // подключение библиотеки дисплея

#define LCD_led_en

MDR_PORTE->RXTX |= (1<<2) // вкл. подсветки

#define LCD_led_dis

MDR_PORTE->RXTX &= ~(1<<2) // выкл. подсветки

/*========================== Функции АЦП ========================== */

void MCU_ADC_init(){

// инициализация

void MCU_ADC_set_ch(uint8_t channel){ // установка канала

void MCU_ADC_start_conv(void){

//

начало преобразования

uint32_t MCU_ADC_read(void){

//

чтение

/*================================================================= */ int main()

{

uint32_t ch_4_counts = 0; // переменная результ. преобразования АЦП

MDR_RST_CLK->PER_CLOCK = 0xffffffff; // вкл. тактирования периферии МК

MDR_PORTE->OE

= 0xff37; //

биты 7,6,3 PORTE - входы, др. - выходы

MDR_PORTE->FUNC

=

0x0000;

//

функция - порт, основная функция

MDR_PORTE->PWR

=

0xff37;

//

макс. быстрый фронт

MDR_PORTE->ANALOG = 0xffff; // режим работы порта - цифровой ввод/вывод

MDR_PORTD->OE

&=~ (1 << 4); // настройка PD4 на вход, канал 4 АЦП

MDR_PORTD->ANALOG &=~ (1 << 4); // перевод PD4 в аналоговый режим работы

delay_init();

 

// инициализация системы задержек

LCD_init();

 

// инициализация дисплея

LCD_clear();

 

// очистка дисплея

LCD_led_en;

 

// вкл. подсветки дисплея

MCU_ADC_init();

 

// инициализация АЦП МК

while (1)

 

 

 

{

 

 

 

MCU_ADC_set_ch(4);

 

// уст. канала АЦП

ch_4_counts = MCU_ADC_read();

// чтение 4 канала АЦП

LCD_set_cursor(0);

 

// установка курсора дисплея

LCD_print_text(" отсчеты АЦП = ");

// вывод текста

LCD_print_num(ch_4_counts);

 

// вывод результатов АЦП в

 

 

 

// отсчетах

LCD_print_text("

");

 

// очистка поля вывода

delay_ms(100);

 

 

 

} // while

 

 

 

} // main

 

 

 

/*------------------------------------------------------------

 

 

*/

Листинг 10. Тестовая программа модуля АЦП МК

103

СПБГУАП группа 4736 / Индустрия 4.0

После компиляции и загрузки тестовой программы, на экране платы МилКиТЭС должны появиться отсчеты АЦП, они будут меняться при повороте ручки потенциометра R39 (рис. 43).

Рис. 43. Результат работы тестовой программы

104

СПБГУАП группа 4736 / Индустрия 4.0

4.5.4. Контроль границ измерений АЦП

При построении устройств на основе АЦП часто возникает задача анализировать границы измерений. В составе модуля АЦП МК К1986ВЕ92QI имеется аппаратный блок контроля границ измерений. Контроль границ измерений на аппаратном уровне позволяет упростить задачу анализа измерений, появляется возможность оперативной реакции на события выхода измерений за допустимые границы.

При необходимости отслеживать нахождение оцифрованных значений в допустимых пределах можно задать нижнюю и верхнюю допустимые границы в регистрах ADC1_L_LEVEL и ADC1_H_LEVEL. При этом если установлен бит Cfg_REG_RNGC,

то в случае, если результат преобразования выходит за границы, выставляется флаг Flg_REG_AWOIFEN, а в регистре результата будет полученное значение [5].

Для использования блока контроля границ измерений, кроме основных настроек АЦП, также необходимо:

1)Установить бит Cfg_REG_ RNGC в “1” (бит 10 регистра

MDR_ADC->ADC1_CFG);

2)Разрешить генерировать прерывание по событию выставления флага выхода за границы Flg_REG_AWOIFEN;

3)Задать верхнюю и нижнюю границы оцифрованных значений в регистрах ADC1_X_LEVEL;

4)Написать функцию обработчика прерываний:

/*------------------------------------------------------------*/ void MCU_ADC_lvl_ctrl_init(uint16_t l_level, uint16_t h_level)

{

// обнуление старшего полубайта уровней, число не более 12 бит l_level = l_level & 0x0FFF;

h_level = h_level & 0x0FFF;

MDR_ADC->ADC1_CFG |= 1 << 10; // разрешение автоматич. контроля уровней // разрешение генерир. прерывание по событию выхода за допустимые границы

MDR_ADC->ADC1_STATUS=1 << 3;

 

MDR_ADC->ADC1_L_LEVEL = l_level;

// верхняя граница зоны допуска

MDR_ADC->ADC1_H_LEVEL = h_level;

// нижняя граница зоны допуска

}

 

/*------------------------------------------------------------

*/

105

СПБГУАП группа 4736 / Индустрия 4.0

Функция инициализации аппаратного блока контроля границ измерений написана. Создадим функцию обработчика прерывания, где будем устанавливать в “1” специальную переменную – флаг:

/*------------------------------------------------------------

*/

void ADC_IRQHandler(void)

 

{

 

adc_lvl_flag = 1; // уст. флага выхода измерений за допустимые границы

// разрешение генерир. прерывание по событию выхода за допустимые границы

MDR_ADC->ADC1_STATUS = 1 << 3;

 

}

 

/*------------------------------------------------------------

*/

Функция ADC_IRQHandler будет вызываться тогда, когда произойдет событие выхода результата преобразований АЦП за нижнюю или верхнюю допустимые границы.

Следует обратить внимание на имя функции void ADC_IRQHandler(void). Оно должно быть строго детерминировано для совпадения с адресом вектора прерывания.

Анализируя флаг adc_lvl_flag в основном цикле программы можно предусмотреть реакцию на это событие (листинг 11). Для примера будем включать светодиод PA0 (рис. 44).

Рис. 44. Результат реакции программы на выход результатов измерения за допустимые границы

106

СПБГУАП группа 4736 / Индустрия 4.0

/*------------------------------------------------------------

 

*/

#include "MDR32Fx.h"

 

// подключение библиотеки МК

#define F_CPU 8000000

 

// указание тактовой частоты МК

#include "milkites_delay.h"

// подключение библиотеки задержек

#include "milkites_display.h" // подключение библиотеки дисплея

#define LCD_led_en

MDR_PORTE->RXTX |= (1<<2) // вкл. подсветки

#define LCD_led_dis

MDR_PORTE->RXTX &= ~(1<<2) // выкл. подсветки

uint8_t adc_lvl_flag = 0; // флаг выхода измерений за допустимые границы

/*========================== Функции АЦП ========================== */

void MCU_ADC_init(){

// инициализация

void MCU_ADC_set_ch(uint8_t channel){ // установка канала

void MCU_ADC_start_conv(void){

//

начало преобразования

uint32_t MCU_ADC_read(void){

//

чтение

// инициализация блока контроля границ измерений

void MCU_ADC_lvl_ctrl_init(uint16_t l_level, uint16_t h_level){

void ADC_IRQHandler(void) // обработчик прерывания от АЦП

/*================================================================= */

int main()

{

uint32_t ch_4_counts = 0; // переменная результата преобр. АЦП

MDR_RST_CLK->PER_CLOCK = 0xffffffff; // вкл. тактирования всей периферии МК

MDR_PORTA->OE

= 0xffff;

// настройка PORTA на выход

MDR_PORTA->FUNC

= 0x0000;

// функция - порт, основная функция

MDR_PORTA->PWR

= 0xffff;

// максимально быстрый фронт

MDR_PORTA->ANALOG

= 0xffff;

// режим работы порта - цифровой ввод/вывод

MDR_PORTE->OE

= 0xff37;

// биты 7,6,3 PORTE - входы (кнопки), др. -

выходы

 

 

MDR_PORTE->FUNC

= 0x0000;

// функция - порт, основная функция

MDR_PORTE->PWR

= 0xff37;

// макс. быстрый фронт

MDR_PORTE->ANALOG

= 0xffff;

// режим работы порта - цифровой ввод/вывод

MDR_PORTD->OE

&=~ (1 << 4); // настройка PD4 на вход, канал 4 АЦП

MDR_PORTD->ANALOG

&=~ (1 << 4); // перевод PD4 в аналоговый режим работы

delay_init();

 

// инициализация системы задержек

LCD_init();

 

// инициализация дисплея

LCD_clear();

 

// очистка дисплея

LCD_led_en;

 

// вкл. подсветки дисплея

MCU_ADC_init();

 

// инициализация АЦП МК

NVIC_EnableIRQ(ADC_IRQn);

// разрешение прерывания от АЦП

//инициализация блока контроля границ измерений:

//нижняя граница – 500 отсчетов АЦП, верхняя - 3500

MCU_ADC_lvl_ctrl_init(500, 3500);

107

СПБГУАП группа 4736 / Индустрия 4.0

while (1)

 

 

{

 

 

MCU_ADC_set_ch(4);

 

// уст. канала АЦП

ch_4_counts = MCU_ADC_read();

// чтение 4 канала

LCD_set_cursor(0);

 

// установка курсора дисплея

LCD_print_text(" отсчеты АЦП = ");

// вывод текста

LCD_print_num(ch_4_counts);

// вывод отсчетов АЦП

LCD_print_text("

");

// очистка поля вывода

delay_ms(100);

 

 

// анализ флага выхода измерений за допустимые границы if(adc_lvl_flag == 1)

{ // измерения за пределами допустимых границ

MDR_PORTA->RXTX = 0x0001 //вкл. светодиод PA0

adc_lvl_flag = 0; //сброс флага выхода за допустимые границы

}

else // измерения в пределах границ

MDR_PORTA->RXTX=0x0000; //выкл. светодиод PA0

}// while

}// main

/*------------------------------------------------------------

*/

Листинг 11. Рабочий код программы анализа выхода результатов измерения за допустимые границы

108