В одном из предыдущих постов, я рассказывал про подключение термопары к Arduino. Теперь настало время рассмореть подключение к AVR микроконтроллерам на чистом Си, благо, как выяснилось, это совсем не сложно.
Напомню, что термопара подключается через адаптер MAX6675, который в свою очередь подключается к микроконтроллеру через SPI интерфейс.
После I2C, SPI интерфейс скорее всего покажется очень простым. Если расмотреть аппаратную реализацию SPI, то там есть регистр данных SPDR, записью или чтением с которого и осуществляется вся работа c SPI.
Программная реализация, как выяснилось, не намного сложнее, но сначала о том, что такое SPI. Фирменный аппнот к SPI можо найти на сайте Atmel: AVR151: Setup And Use of The SPI
рассмотрим схему подключения взятую оттуда:
Вот именно такой упрощеный режим используется в MAX6675. Документация:MAX6676 datasheet
Предлагаю еще раз взглянуть на формат передачи:
Данные передаются пакетами по два байта. Под температуру отводится 12 бит. 15-й бит, бит знака. LSB - младший значащий бит, MSB - старший значащий бит. Оффициальная легенда:
Значение температуры передается в градусах Цельсия, в диапазоне от 0 до 1024. 1024 - это десять бит, в то время как данные передаются 12-битным форматом. Значит, чтобы получить значение в градусах, нужно будет полученое число разделить на 4. Меня немного смутил второй бит, device ID. В смысле я не очень понимаю как может один бит служить идентификатором. Его скорее можно назвать битом корректности.
Если припомнить, то в случае с Arduino я использовал библиотеку: MAX6675-library
На проверку, там оказался довольно простой код:
Я решил не изобретать велосипед, и переписать код на чистом Си. В качестве шаблона использовал проект из предыдущего поста. Я отбросил файлы относящиеся к TWI, после чего осталось переписать main.c в соответсвии со своими целями:
#include <avr/io.h> #include <util/delay.h> #include <uart.h> #define pSCLK PD6 #define pCS PD5 #define pMISO PD4 #define ddrPORT DDRD #define csPORT PORTD #define sclkPORT PORTD #define misoPIN PIND static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); uint8_t spi_read(void); int main(void) { //---- init init_uart(); DDRB |= (1<<PB5); // led indicator // CS:chip select ddrPORT |= (1<<pCS); csPORT |= (1<<pCS); // set VCC // clock line ddrPORT |= (1<<pSCLK); // set GND // data line ddrPORT &= ~(1<<pMISO); // high impedance state uint16_t data=0; //---- ready indication blink13(3); //ready indication stdout = &mystdout; printf("Ok, I'm ready!\n"); //---- main body for (;;) { csPORT &=~(1<<pCS); //digitalWrite(cs, LOW); _delay_ms(1); data=(uint16_t)spi_read(); data <<= 8; data |= (uint16_t)spi_read(); if (data & 0x4) { printf("Thermocouple don't attached!\n"); } else { data >>= 3; data /= 4; printf("temp: %d\n", data); } csPORT |=(1<<pCS); //digitalWrite(cs, HIGH); _delay_ms(1000); }; return 0; } uint8_t spi_read(void) { uint8_t i,ret ,value; ret=0; i=8; do { i--; sclkPORT &=~(1<<pSCLK);// digitalWrite(sclk, LOW); _delay_ms(1); value=misoPIN &(1<<pMISO); if (value) { //set the bit to 0 no matter what ret |= (1 << i); } sclkPORT |=(1<<pSCLK); // digitalWrite(sclk, HIGH); _delay_ms(1); } while (i > 0); return ret; }
Результат работы программы:
В данном случае виден результат воздействия горелки на термопару.
Скачать проект вместе со сборочными файлами и прошивкой для ATmega8 можно здесь.
Структура проекта:
├── examples │ └── MAX6675 │ ├── CMakeLists.txt │ ├── Makefile │ └── main.c ├── hex │ ├── READ.ME │ ├── max6675.elf │ └── max6675.hex └── libs ├── uart.c └── uart.h