PICSim.js - аналого-цифровой преобразователь

Как мы уже знаем, цифро-аналоговые преобразователи (ЦАП, 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

screenshot

Работа с символьным дисплеем описывалась в предыдущем материале. Тут мы реализовали функцию 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, хотя надобность знать о его существовании возникает редко.

Далее матричная клавиатура.

links

social