Главная Новости

Урок 24.1 Знакомство с I2C

Опубликовано: 05.09.2018

Статья про I2С должна была появиться уже давно. Не смотря на кажущуюся простоту работы интерфейса, охватить все оказалось довольно непросто, поэтому подходящей фазы луны так и не было чтобы собрать все в кучу Ситуацию решил исправить iEugene0x7CA и внести свет науки в массы, я лишь поправил стиль изложения.

Вначале нужно познакомить читателя  с тем, о чем дальше пойдет речь. Для обмена данными с периферией существуют различные интерфейсы, например мы уже ранее рассматривали SPI. Его недостаток — для обмена данными используются четыре ножки, если задействовано несколько устройств, то ножку CS — chip select нужно тянуть для каждого устройства отдельную. Таким образом, если используются три внешних устройства, то у микроконтроллера будет задействовано шесть ножек.

Ножки это важный ресурс и высокая скорость, которой обладает SPI не всегда нужна, поэтому альтернативой является интерфейс I2C, который работает со скоростью до 400кГц и обладает 7 битным адресным пространством и теоретически позволяет подключать до 128 ведомых устройств. Ну и самое главное, для передачи данных используется всего две ножки микроконтроллера и не важно сколько у вас сидит устройств на шине данных 1, 2 или 128.

Сами ножки называются SCL и SDA, по первой подаются тактовые импульсы, по второй передаются данные. Особенностью является то, что обе линии должны быть подтянуты к плюсу питания через резисторы, абсолютно всегда, иначе ничего работать не будет.

Теперь о самом главном, как микроконтроллер узнает с каким устройством он общается? Для этого у каждого устройства есть свой адрес. Адрес можно узнать в даташите на устройство. Кроме того, обычно несколько бит адреса микросхемы позволено выставлять пользователю, дабы тот мог повесить несколько микросхем одного типа на одну I2C шину, например если одной внешней 64 кБ EEPROM не хватило и разработчик решил повесить 8 таких. После отсылки адреса чипа на шину, если микросхема с таковым там была и все подключено верно — именно она будет воспринимать следующие байты, остальные информацию на шине проигнорируют.

В atmega8 есть два варианта передачи данных по протоколу I2c — использование аппаратного модуля TWI(two wire interface) или программного ногодрыга. Программная реализация достаточно проста в использовании, однако имеет недостаток — после отсылки данных микроконтроллером, нужно тупить и ждать пока внешнее устройство ответит, в случае с использования аппаратной шины прием можно организовать в прерывании. Однако, для микроконтроллеров не имеющих на своем борту аппаратного модуля это единственное решение. Кроме того, шину можно повесить на любой порт, что может быть удобно при разводке плат.

Для начального ознакомления мы будем использовать программную библиотеку, в Codevision вкладка визарда называется I2C, а библиотека i2c.h. Функций в библиотеке присутствует не так много: i2c_init() — необходима для инициализации; i2c_start() — инициализирует начало передачи данных, также возвращает 1, если шина свободна и 0, если шина занята; i2c_stop() — окончание передачи; i2c_read() — принять данные; i2c_write() — передать данные.

В функциях приема и передачи есть маленькая хитрость, называется ack — работает очень просто: после завершения приема/передачи 8-ми бит, следующий такт периферия сама подтягивает линию данных к земле, контроллер при этом только «слушает» линию, и если там действительно 0 (т.е. периферия удачно приняла/отдала байт и сигнализирует об этом мастеру), то процесс продолжается. Если нет, то случился какой-то сбой. Чтобы при чтении получать подтверждение приема, отправляем i2c_read(1), если не хотим i2c_read(0).

Одной теорией сыт не будешь, хорошо бы еще научиться конкретно опрашивать периферию! Какой она бывает? Компасы-магнитометры, гироскопы-акселерометры, термометры, датчики влажности, освещенности, атмосферного давления, внешние АЦП, внешнюю EEPROM, аудиопроцессоры, эквалайзеры, экранчики, ИК-дальномеры, и еще много всякого вкусного. В общем понятно думаю, что не умея работать с I2C — вы многое теряете.

Наконец обещанный экшн, протоколы связи из даташита на 24LC512.

Подробно рассмотрим 2 основных фичи, к остальному при желании функции написать будет не проблема. Основные в данном случае- это запись произвольного байта и чтение, тоже произвольного(byte write и random read). Адресация в 24LC512 не страничная, а побайтовая, работать с такой системой очень удобно. Проще всего записывать данные, смотрим сейчас одним глазом на диаграмму из даташита и пытаемся разобраться, что же там происходит:

1. Посылаем на шину команду «старт». На практике это просто подтягивание шины на 1 такт, после этого все подключенные к ней устройства начинают «слушать» следующий байт, указывающий адрес микросхемы, с которой мы хотим работать. Старт- отдельная функция их i2c.h либы;

2. Посылаем байт с адресом.

Как видим, первый бит адресного байта(читается справа-налево) указывает, будем мы работать с 24LC512 в режиме чтения или записи. Запись — это 0. Далее идут 3 адресных бита, которые может выставить пользователь, подтянув ножки 1, 2, и 3 нашей 24LC512 к земле или питанию. Для простоты подтягиваем все к земле. Нужно это, дабы можно было подключить на I2C шину не одну EEPROM этого типа. Следующие 4 бита- это уже заводской адерс конкретно этой микросхемы. Выходит, для обращения к микрухе в режиме записи нужно кинуть на шину число «0b10100000″.

3. и 4. Теперь бросаем 2 байта с адерсом того байта, который мы хотим записать. 24LC512 имеет 64 кБ памяти и для адресации каждого из них нам нужно в аккурат 16-битное число(2^16=65536, что с поправкой на тот факт, что килобайт- это 1024 байта дает нам в аккурат 64 кБ).

5. Бросаем собственно то, что хотели записать.

6. Ну, и команда «стоп»!

Все, мы записали один байт в энергонезависимую память! Если посмотрите на функцию записи из исходника тестовой прошивки — вы найдете там эти 6 простых шагов, взятых из даташитной картинки. Аналогично диаграмме из даташита действуем и для чтения данных. По сути все так же, строго идем по даташиту, используя стандартные функции i2c.h. Единственный момент, могущий показаться не очень понятным- это строка «i2c_write(Ext_EEPROM_Adr | 1)», представляющая собой банально добавление к первому биту адреса единички, т.е. обращение к 24LC512 в режиме чтения.

#include <mega8.h> #include <delay.h> // I2C Bus functions #asm . equ __i2c_port = 0x15 //Адрес порта C . equ __sda_bit = 4 . equ __scl_bit = 5 #endasm #include <i2c.h> #include <stdio.h> #define Ext_EEPROM_Adr 0b10100000 // Адрес 24LC512 на I2C шине unsigned char high_byte , low_byte , message [ 23 ] = { 'H' , 'E' , 'L' , 'L' , 'O' , ',' , ' ' , 'e' , 'x' , 't' , 'e' , 'r' , 'n' , 'a' , 'l' , ' ' , 'E' , 'E' , 'P' , 'R' , 'O' , 'M' , '!' } ; unsigned char eeprom_read ( unsigned char address2 , unsigned char address1 ) //Функция чтения из внешней EEPROM { unsigned char data ; i2c_start ( ) ; //Кидаем команду "Cтарт" на шину I2C i2c_write (Ext_EEPROM_Adr ) ; //Кидаем на шину адрес 24LC512 i2c_write (address2 ) ; //Старший байт адресного пространства 24LC512 i2c_write (address1 ) ; //Младший байт i2c_start ( ) ; //Снова посылаем "старт" в шину i2c_write (Ext_EEPROM_Adr | 1 ) ; //Обращаемся к 24LC512 в режиме чтения, т.е. по адресу 101000001 data =i2c_read ( 0 ) ; //Принимаем данные с шины и сохраняем в переменную i2c_stop ( ) ; //Посылаем команду "Cтоп" return data ; //Возвращаем значение прочитанного } void eeprom_write ( unsigned char address2 , unsigned char address1 , unsigned char data ) //Функция записи во внешнюю EEPROM { i2c_start ( ) ; //Кидаем команду "Cтарт" на шину I2C i2c_write (Ext_EEPROM_Adr ) ; //Кидаем на шину адрес 24LC512 i2c_write (address2 ) ; //Старший байт адресного пространства 24LC512 i2c_write (address1 ) ; //Младший байт i2c_write (data ) ; //Посылаем байт для записи i2c_stop ( ) ; //Посылаем команду "Стоп" delay_ms ( 5 ) ; //Даем микросхеме время записать данные, EEPROM довольно медлительна } void main ( void ) { DDRD = 0xFF ; // I2C Bus initialization i2c_init ( ) ; // USART initialization // Communication Parameters: 8 Data, 1 Stop, No Parity // USART Receiver: Off // USART Transmitter: On // USART Mode: Asynchronous // USART Baud Rate: 9600 UCSRA = 0x00 ; UCSRB = 0x08 ; UCSRC = 0x86 ; UBRRH = 0x00 ; UBRRL = 0x33 ; //Записываем для теста короткую строку "HELLO, external EEPROM!" в первые 23 байта внешней EEPROM for ( low_byte = 0 ; low_byte < 23 ; low_byte ++ ) { eeprom_write (high_byte , low_byte , message [low_byte ] ) ; } //Кидаем в UART содержимое первых 23-х байтов адресного пространства 24LC512 for ( low_byte = 0 ; low_byte < 23 ; low_byte ++ ) { putchar ( eeprom_read ( 0x00 , low_byte ) ) ; delay_ms ( 100 ) ; } while ( 1 ) ; }

Поздравляшки! Вы только что прошли краткий курс работы с периферией на I2C шине, теперь можете покупать любую цацку с I2C интерфейсом и строить свои функции для игры с таковой!

Разделы

» Ваз

» Двигатель

» Не заводится

» Неисправности

» Обзор

» Новости


Календарь

«    Август 2017    »
ПнВтСрЧтПтСбВс
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 

Архив

О сайте

Затраты на выполнение норм токсичности автомобилей в США на период до 1974 г.-1975 г произошли существенные изменения. Прежде всего следует отметить изменение характера большинства работ по электромобилям: работы в подавляющем большинстве стали носить чисто утилитарный характер. Большинство созданных в начале 70х годов электромобилей поступили в опытную эксплуатацию. Выпуск электромобилей в размере нескольких десятков штук стал обычным не только для Англии, но и для США, ФРГ, Франции.

ПОПУЛЯРНОЕ

РЕКЛАМА

www.school4mama.ru © 2016. Запчасти для автомобилей Шкода

rss