Как мы уже знаем, цифро-аналоговые преобразователи (ЦАП, DAC) преобразуют дискретный (двоичный) код в аналоговый сигнал - как правило напряжение. Не менее востребованным в цифровой электронике является обратное преобразование - аналого-цифровой преобразователь (АЦП, англ. Analog-to-digital converter, ADC). Наиболее важными характеристиками АЦП являются разрядность/разрешение - минимальное изменение величины аналогового сигнала, которое может быть зафиксировано, а также частота дискретизации (Sampling rate) - частота выборки цифровых значений из аналогового сигнала.
Микроконтроллер PIC18F4620 имеет на борту один аппаратный АЦП разрядностью 10 бит 2^10=1024
с максимальной частотой дискретизации (если верить производителю) 100 тысяч выборок в секунду. Также в микроконтроллере предусмотрен мультиплексор, позволяющий в нужный момент времени программно переключать на вход АЦП 13 различных ног. В качестве опорного напряжения для АЦП может служить как источник питания Vdd/Vss (обычная практика), так и внешний источник на ногах 4 и 5 (AN2/AN3). Напряжение на входе АЦП не должно выходить за пределы опорного.
config.h | liquid-crystal.c | hex | picsim.js
Работа с символьным дисплеем описывалась в предыдущем материале. Тут мы реализовали функцию putch
, что позволяет работать с LCD через стандартную функцию С printf
. Поскольку в нашем случае длина выводимой на дисплей строки всегда постоянна, нет необходимости его очищать - достаточно просто переводить курсор домой перед каждым новым вызовом printf
.
/*
xc8 --chip=18f4620 main.c
*/
#define _XTAL_FREQ 5e4
#include <xc.h>
#include <stdio.h>
#include <stdint.h>
#include "config-4620.h"
#include "liquid-crystal.c"
// http://microchip.wikidot.com/faq:29
void putch(const uint8_t byte) {
lcd_dat(byte);
}
int main() {
uint32_t adc_samples_counter = 0;
// lcd
PORTD = TRISD = 0;
PORTE = 0;
TRISE = 1; // ADC input RE0
// ADC analog input RE0
ADCON0bits.CHS3 = ADCON0bits.CHS1 = 0;
ADCON0bits.CHS2 = ADCON0bits.CHS0 = 1;
ADCON0bits.ADON = 1;
lcd_init();
lcd_no_cursor();
lcd_no_blink();
while(1) {
ADCON0bits.GO = 1; // start ADC conversion
while (ADCON0bits.GO == 1); // wait untill conversion finish
lcd_home();
printf("%4d:0x%04x",
(((uint16_t)ADRESH)<<2)|(ADRESL>>6),
++adc_samples_counter);
}
return 0;
}
Как нетрудно догадаться по картинке у данной симуляции опорное напряжение 5 Вольт. С помощью битов CHS3-CHS0 выбирается с какого вывода микроконтроллера аналоговый сигнал поступает на вход АЦП - в данном случае это RE0. Бит ADON включает АЦП, для старта преобразования необходимо программно выставить флаг GO, по окончании преобразования этот флаг будет сброшен аппаратно (автоматически). Так как разрядность микроконтроллера 8 бит, что меньше разрядности АЦП, то результат преобразования размещается одновременно в двух регистрах - ADRESH и ADRESL. Выравнивание 10 битного числа в этих двух регистров задаётся битом ADFM, хотя надобность знать о его существовании возникает редко.
Далее матричная клавиатура.