// sketch_09_01_SPI_ADC
#include
const int chipSelectPin = 10;
void setup()
{
Serial.begin(9600);
SPI.begin();
pinMode(chipSelectPin, OUTPUT);
digitalWrite(chipSelectPin, HIGH);
}
void loop()
{
int reading = readADC(0);
Serial.println(reading);
delay(1000);
}
int readADC(byte channel)
{
unsigned int configWord = 0b11000 | channel;
byte configByteA = (configWord >> 1);
byte configByteB = ((configWord & 1) << 7);
digitalWrite(chipSelectPin, LOW);
SPI.transfer(configByteA);
byte readingH = SPI.transfer(configByteB);
byte readingL = SPI.transfer(0);
digitalWrite(chipSelectPin, HIGH);
// printByte(readingH);
// printByte(readingL);
int reading = ((readingH & 0b00011111) << 5)
+ ((readingL & 0b11111000) >> 3);
return reading;
}
void printByte(byte b)
{
for (int i = 7; i >= 0; i--)
{
Serial.print(bitRead(b, i));
}
Serial.print(" ");
}
Функция printByte использовалась на этапе разработки для вывода двоичных данных. Несмотря на то что Serial.print может выводить двоичные значения, она не добавляет ведущие нули, что немного усложняет интерпретацию данных. Функция printByte, напротив, всегда выводит все 8 бит.
Чтобы увидеть данные, поступающие от микросхемы MCP3008, уберите символы // перед двумя вызовами printByte, и данные появятся в окне монитора последовательного порта.
Наиболее интересный для нас код сосредоточен в функции readADC, которая принимает номер канала АЦП (от 0 до 7). Прежде всего нужно выполнить некоторые манипуляции с битами, чтобы создать конфигурационный байт, определяющий вид преобразования аналогового сигнала и номер канала.
Микросхема поддерживает два режима работы АЦП. В одном выполняется сравнение двух аналоговых каналов, а во втором, несимметричном режиме (который используется в этом примере), возвращается значение, прочитанное из указанного канала, как в случае с аналоговыми входами на плате Arduino. В документации к MCP3008 (http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf) указывается, что в настроечной команде должны быть установлены четыре бита: первый бит должен быть установлен в 1, чтобы включить несимметричный режим, следующие три бита определяют номер канала (от 0 до 7).
Микросхема MCP3008 не поддерживает режим побайтовой передачи, в котором действует библиотека SPI. Чтобы MCP3008 распознала эти четыре бита, их нужно разбить на два байта. Далее показано, как это делается:
unsigned int configWord = 0b11000 | channel;
byte configByteA = (configWord >> 1);
byte configByteB = ((configWord & 1) << 7);
Первый байт конфигурационного сообщения содержит две единицы, первая из которых может не понадобиться, а вторая — это бит режима (в данном случае несимметричного). Другие два бита в этом байте — старшие два бита номера канала. Оставшийся бит из этого номера передается во втором конфигурационном байте как самый старший бит.
Следующая строка устанавливает уровень LOW в линии выбора ведомого устройства, чтобы активировать его:
digitalWrite(chipSelectPin, LOW);
После этого отправляется первый конфигурационный байт:
SPI.transfer(configByteA);
byte readingH = SPI.transfer(configByteB);
byte readingL = SPI.transfer(0);
digitalWrite(chipSelectPin, HIGH);
Аналоговые данные не будут передаваться обратно, пока не будет отправлен второй байт. 10 битов данных из АЦП разбиты на два байта, поэтому, чтобы подтолкнуть отправку оставшихся данных, выполняется передача нулевого байта.
Затем в линии выбора ведомого устанавливается уровень HIGH как признак того, что передача завершена.
Полученное 10-битное значение пересчитывается, как показано в следующей строке:
int reading = ((readingH & 0b00011111) << 5)
+ ((readingL & 0b11111000) >> 3);