Avrstudio 4. библиотека для avr. модуль для i2c или twi

AvrStudio 4. Библиотека для AVR. Модуль для I2C или TWI

Введение

Для Arduino написано много библиотек бери да пользуйся, не исключение и шина I 2 C. А если посмотреть в сторону тех кто пишет на AvrStudio, то будет голое поле. Библиотеку писал на основе открытой библиотеки которую я скачал с сайта http://www.procyonengineering.com.

Информации про интерфейс в интернете много, а библиотек для работы с ним нет. Только GitHub в помощь.

Несколько слов про интерфейс. Интерфейс, по-философии, чем-то похож на интерфейс 1-wire. Только для 1-wire синхронизация идет по времени и сигналам, а тут только по отдельной линии. Привожу таблицу сравнения

I2C 1-Wire
сброс линии нет есть
стартовый бит есть есть
адрес устройства есть есть
Сигнал присутствия есть есть
стоповый бит есть нет

Лично для меня реализация интерфейса показалась достаточно сложной, объемной. Плюс данного интерфейса высокая скорость и возможность коммуникации между многими устройствами, что является не маловажным. Своего рода TCP/IP для мира микроконтроллеров. Можете посмотреть ради интереса фолианты по TCP/IP.

Подключение библиотеки

Перейдем к цели, а именно рассказать про использование библиотеки. Библиотека состоит из 2 файлов: i2c.h и i2c.c.

1. В начале необходимо скинуть эти 2 файла в папку с проектом.

2. Подключить в главном си-файле заголовочный файл: #include

3. Затем необходимо открыть опции конфигурирования проекта: Project—>Configuration Option

3.1. В вкладке General необходимо в строке Frequency указать частоту тактирования контроллера . ВНИМАНИЕ: если это не сделать проект будет выдавать ошибку.

3.2. Затем необходимо Включить корневую папку проекта в поиск Стандартных библиотек. Для этого во вкладке Include Directories нажимают кнопку New(Insert) и выбирают папку проекта.

3.3. Последний этап это включение файла i2c.c в проект. Для этого в дереве проекта на папке Source File кликают 2 раза ПКМ и выбирают пункт Add Existing File(s) и добавляют файл i2c.c. После этого проект должен собраться.

Библиотека может работать в режиме Мастер или Slave. В библиотеке можно подключить/отключить любой режим.

По-умолчанию библиотека собирается в режиме Master.

Описание концепции работы библиотеки

Иногда скачаешь библиотеку, и думаешь как ей пользоваться? А потом решаешь свою написать. Поэтому опишу почему пришел к такой структуре библиотеки. Библиотеку начал писать для работы с LCD2004 по I 2 C. Разных чипов работающих по I 2 C навалом, но все они работают по принципу EEPROM памяти. В начале Мастер посылает пакет в котором записывает в один или два байта адрес ячейки с которой хочет начать чтение данных в памяти, а затем Начинает их читать. Интерфейс я бы сказал ОЧЕНЬ ВЕЖЛИВЫЙ, это тебе не UART. Хочу передаю, хочу не передаю и ответственности за приемник никакой. Тут же Мастер интересуется кому посылает, готов сам откликнуться на чужую нужду и бросить свое дело. Ведомый же всегда скажет если дома, если есть место честно об этом скажет, а если не может больше принять данных, то тоже сообщит.

Рассмотрим запись и чтение данных из EEPROM памяти at24c512. Схема подключения представлена на рисунке.

В данном случае at24c512 имеет адрес устройства 0b1010000. Дебаггер для I2C присоединил для удобства. В таблице привожу общение контроллера с памятью. Само общение можно посмотреть с помощью Дебаггера. Каждая строка в таблице коммуникации это попадание в прерывание для Master.

Вот так выглядит таблица ячеек памяти для at24c512 после записи.

AVR Урок 16. Интерфейс TWI (I2C). Часть 7

Урок 16

Интерфейс TWI (I2C)

В предыдущей части занятия уже продолжили свою работу с отправкой значений в память микросхемы EEPROM по интерфейсу TWI. Только проверить мы смогли это, исключительно веря статусам.

А в данной части урока мы закрепим полученные знания и подключим по шине I2C переходник для модуля символьного дисплея, тем самым также получим возможность подключать дисплей по двум проводам.

Модуль дисплея мы будем подключать с дисплеем символным высотой в 4 строки и шириной в 20 символов, или как попросту говорят 20×4.

Мы в уроке 12 уже разбиравли с вами подобный дисплей, только он был размерностью 16×2 и подключали мы его по 4-битному интерфейсу.

Теперь у нас дисплей 20×4. Его модуль также собран с применением контроллера дисплея HD44780. Возможны тамже варианты применения аналогов, но программирование их вообще не отличается ни чем.

По 4-битному способу программирования модуль дисплея LCD2004 мало чем отличается от LCD1602, в основном, можно сказать только адресацией знакомест. В конце урока мы просто подправим функцию позиционирования.

Основная задача занятия – научить данный модуль общаться с МК AVR посредством шины I2C (TWI) с помощью соответствующего переходника.

Поэтому давайте немного познакомимся с данным переходником.

Выглядит он следующим образом

У него черыре ножки для соединения с МК – это питание, общий провод и две ножки I2C.

Также мы видим, что к нему подпаяна гребёнка из 16 контактов для соединения с соответствующими контакта модуля дисплея. Так как контакты на переходнике типа «ПАПА», то на модуль дисплея я, соответственно, подпаял гребёнку с контактами типа «МАМА» ну и посредством этих двух контактных площадок я его с модулем и соединил.

Купить данный дисплей можно много где. В описании видеоверсии под роликом находится ссылка, где его приобретал я. Только там где я приобретал, один было купить невозможно, минимум три, но цена была такова, что я с удовольствием их купил. Сейчас, по-моему, продавец уже предлагает минимальную партию из 5 штук, но цену вроде ещё убавил. Поэтому есть смысл. Я не думаю, что у кого-то, кто постоянно занимается с контроллерами. в наличии есть только один такой дисплей.

Ну что ж, теперь рассмотрим, из чего состоит собственно данный переходник. Там, соответственно, есть регулятор контрастности, поэтому теперь нам не нужно будет заботиться о его отдельном подключении. А сердцем данного переходника служит микросхема PCF8574, преобразующая последовательный код I2C в 8-битные логические состояния на выходе.

Вот, собственно, схема данного переходника (нажмите на картинку для увеличения изображения)

Здесь прекрасно видно подключение микросхемы. У нее существуют три адресных контакта, которые способны изменить адрес устройства для I2C также, как это было в случае микросхемы EEPROM, рассмотренной в предыдущих частях нашего занятия. Соответственно, существуют контакты питания VCC и GND, а также контакты шины I2C – SDA и SCL, ну и, конечно же, восемь контактов логических состояний, управляемых данной микросхемой. Только подключен будет модуль дисплея. как мы видим посредством 4-битного подключения. Это сделано потому, что контактов на шине микросхемы всего 8, а нам нужно ещё оперировать с помощью них управляющими ножками модуля дисплея (RS, RW и E, который здесь назван CS), а также включением подсветки (контакт P3). Подсветка, соответственно, в целях защиты от больших токов контакта параллельного порта микросхемы управляется с помощью ключевого транзистора 8050. Также установлен светодиод через токоограничивающий резистор, сигнализирующий нам о подаче питания на преобразователь, ну и. как уже было выше сказано, регулятор контрастности. Ещё существуют два подтягивающих резистора по 4,7 килоом, подключенные к ножкам шины I2C, назначение которых мы прекрасно знаем.

Ну вот, собственно, и всё насчёт схематического решения переходника.

Теперь немного по техническим характеристикам самой микросхемы PCF8574.

Питание микросхемы осуществляется постоянным напряжением в диапазоне от 2,5 до 7 вольт, так что бояться нам нечего.

Токи по портам входным – максимально 20 милиампер, по выходным – 25.

Также ещё немаловажным для нас является параметр максимальной скорости по I2C – он не должен превышать 100 кГц.

Нам, конечно, спешить некуда, дисплей всё-таки символьный, но если мы захотим на шину I2C повесить ещё что-то и захотим от этого чего-то большего быстродействия, то мы обязаны об этом помнить.

Также посмотрим адрес, по которому мы будем, собственно, с ней общаться по I2C. В даташите их два в зависимости от типа микросхемы. Нам нужен вот этот

Так как мы в данный переходник данные будем только отправлять, то давайте посмотрим диаграмму протокола общения с ним по шине I2C для записи байтов (нажмите на картинку для увеличения изображения)

Запись здесь идёт стандартно. Просто у нас не память EEPROM и никаких ячеек адресных у нас в микросхеме нет. передаём мы сразу данные. Данные можно передавать как по несколько байт. так и по одному. Как только мы передадим условие СТОП, на этом и заканчивается передача. И передавать мы будем только по одному байту, так как со скоростью 100 кГц контроллер дисплея вряд ли сможет работать, да это и не нужно.

Читайте также  Что такое ток?

Ну вот мы немного и разобрались с переходником.

Теперь, конечно проект.

Проект был создан с именем I2CLCD80.

Стандартно создан и подключен файл main.h.

Также подключены файлы lcd.h и lcd.c из проекта урока 12 по подключению подобного дисплея по 4-битной шине Test09. Затем данные файлы были переименованы соотвественно для избежания путаницы в lcdtwi.c и lcdtwi.h, а также в связи с этим хедер-файл немного претерпел изменения и внутри в директивах.

Код в главный файл I2CLCD80.c был полностью скопирован из того же проекта Test09 из файла Test09.c.

Ещё, конечно же были подключены файлы twi.h и twi.c из проекта прошлых частей данного занятия DS1307Eeprom.

Ну и. соответственно, все данные файлы были также подключены в файле main.h. Вот его полный исходный код

#define F_CPU 8000000UL

#include «twi.h»

#include «lcdtwi.h»

В файле lcdtwi.c подключили также файл lcdtwi.h

#include «lcdtwi.h»

Начнём теперь адаптировать понемногу код к переходнику.

Напишем ещё одну функцию в файл twi.c для передачи байта по адресу, чтобы упростить вызов. Напишем её после функции передачи байта в шину, так как мы ею будем пользоваться

void I2C_SendByteByADDR ( unsigned char c , unsigned char addr )

I2C_StartCondition (); // Отправим условие START

I2C_SendByte ( addr ); // Отправим в шину адрес устройства + бит чтения-записи

I2C_SendByte ( c ); // Отправим байт данных

I2C_StopCondition (); // Отправим условие STOP

Также не забываем о прототипе в хедере.

Теперь в файле реализации функций дисплея lcdtwi.c мы создадим глобальную переменную, которая будет в себе хранить значение состояния контактов на параллельной шине микросхемы, чтобы нам его не читать из шины I2C, а просто помнить его именно в переменной

unsigned char portlcd = 0; //ячейка для хранения данных порта микросхемы расширения

Теперь исправим макроподстановки в файле lcdtwi.h и добавим ещё некоторые в соответствии со схемой на переходник

void sendcharlcd ( unsigned char c );

#define e1 I2C_SendByteByADDR ( portlcd |=0x04,0b01001110) // установка линии E в 1

#define e0 I2C_SendByteByADDR ( portlcd &=

0x04,0b01001110) // установка линии E в 0

#define rs1 I2C_SendByteByADDR ( portlcd |=0x01,0b01001110) // установка линии RS в 1

#define rs0 I2C_SendByteByADDR ( portlcd &=

0x01,0b01001110) // установка линии RS в 0

#define setled () I2C_SendByteByADDR ( portlcd |=0x08,0b01001110) // включение подсветки

#define setwrite () I2C_SendByteByADDR ( portlcd &=

0x02,0b01001110) // установка записи в память дисплея

Здесь, в принципе всё понятно. Мы отправляем определённые значения в шину I2C, для того чтобы менять состояение ножек параллельной шины на микросхеме, причем не изменив при этом состояние остальных ножек, для чего и идёт постоянное логическое сложение с состоянием данной параллельной шины. Все битовые операции нам давно знакомы и говорить подробно о них мы не будем.

Вернёмся теперь в файл lcdtwi.c и подправим там тоже некоторые вещи.

Первым делом, коненчно же у нас несколько изменится функция отправки половины байта в контроллер дисплея. Там мы изменим только одну строку и уберём установку значения порта D, так как мы его не используем теперь и он у нас свободен

void sendhalfbyte ( unsigned char c )

e1 ; //включаем линию Е

I2C_SendByteByADDR ( portlcd | c ,0b01001110);

e0 ; //выключаем линию Е

Теперь функция setpos. В неё также нужно будет внести определённые изменения. так как у нас изменилось разрешение дисплея. У него увеличилось количество строк и колонок.

Для этого заглянем в техническую документацию на дисплей и посмотрим адресацию в нём памяти DDRAM

Здесь всё ясно, нам нужны только адреса первого символа в каждой строке, на них мы и будем смещаться по строкам

void setpos ( unsigned char x , unsigned y )

switch ( y )

case 0:

sendbyte ( x |0x80,0);

break ;

case 1:

sendbyte ((0x40+ x )|0x80,0);

break ;

case 2:

sendbyte ((0x14+ x )|0x80,0);

break ;

case 3:

sendbyte ((0x54+ x )|0x80,0);

break ;

Смысл байта 0x80 я думаю все знают. Здесь мы устанавливаем седьмой бит, чтобы контроллер дисплея распознал команду записи в DDRAM в соответствии с таблицей инструкций.

Также нужно в функции инициализации дисплея включить подстветку и запись

setled (); //подсветка

setwrite (); //запись

Здесь, в принципе, всё.

Перейдём в главный файл I2CLCD80.c и удалим там функцию инициализации порта port_ini.

Также удалим и в функции main() вызов инициализации порта, а вместо него включим инициализацию шины TWI

I2C_Init (); //инициализируем TWI

LCD_ini (); //инициализируем дисплей

Также давайте после инициализации дисплея вызовем на всякий случай его очистку, а то частенько мусор остаётся после персборки и перезагрузки

LCD_ini (); //инициализируем дисплей

clearlcd (); //очистим дисплей

Соберём код и прошьём контроллер.

После этого на дисплее мы должны увитель вот такую знакомую картину

Ну, и теперь, я думаю, логично будет проверить работоспособность двух нижних строк дисплея. Добавим код в main()

str_lcd ( «String 2» );

setpos (4,2);

str_lcd ( «String 3» );

setpos (6,3);

str_lcd ( «String 4» );

Соберём код, прошьём контроллер и проверим это

Ну вот теперь всё!

В данной части занятия мы усовершенствовали свои знания в области программирования шины I2C в контроллерах AVR, тем самым также мы неплохо разгрузили значительное количество ножек контроллера.

Программатор и модуль RTC DS1307 с микросхемой памяти можно приобрести здесь:

Смотреть ВИДЕОУРОК (нажмите на картинку)

Nagits’s Blog

programming, fizfak science, etc…

AVR: Передача данных по шине I²C (I2C, IIC, TWI)

Налаживаем обмен данными между двумя контроллерами по шине I²C

  • SCL — линия последовательной передачи синхроимпульсов («при передаче посылок по шине I2C каждый ведущий генерирует свой синхросигнал на линии SCL» — http://ru.wikipedia.org/wiki/I%C2%B2C)
  • SDA — линия последовательной передачи данных

  • один предлагают специалисты компании Atmel в апноутах (AVR315 Использование модуля TWI в качестве ведущего интерфейса I2C и AVR311 Использование модуля TWI в качестве подчиненного интерфейса I2C)
  • другой принадлежит мистеру Pascal Stang, автору известного набора джентльмена Procyon AVRlib.
  • i2c.c и i2c.h — главное, что нам надо, однако в этих файлах есть ссылки на другие заголовочные файлы из библиотеки:
  • i2cconf.h — так-то в нем ваще ничо нет :), кроме двух define-ов
  • global.h — в нем определены F_CPU и CYCLES_PER_US + еще 2 заголовочных файла:
  • avrlibdefs.h — часто всеми используемые упрощения clearbit, setbit и тому подобное
  • avrlibtypes.h — здесь переопределены типы, например «typedef unsigned char u08;» и т.д.

UPD1: Если хотите подробно разобраться с I2C и TWI и написать свою библиотеку для этого интерфейса, читайте статью https://nagits.wordpress.com/2010/12/18/avr_i2c_eeprom/.

Ваша оценка:

Share this:

  • Twitter
  • Facebook

Понравилось это:

Похожее

Written by nagits

9 октября, 2010 в 20:21

комментариев 20

Subscribe to comments with RSS.

спасибо за либу все ок, проблема в массиве [ОСНОВНОМ] там собака порылась, удачи

проблема в том, что в TWDR Slave данные не хотят залазить, а в остальном …… всё хорошо всё хорошо!

Доброго здоровья после праздников!
поясните пожалуйста , если возможно, передачу данных слевом мастеру при запросе мастером SLA+R в Вашем примере. Идея состоит в том, что бы мастер опрашивал N подчинённых выбирая по усмотрению прог-мы данные, обрабатывал их и при получении аварийного отправлял на все подчинённые свои рекомендации. Если имеется готовый проект приблизительно в эту тему буду очень благодарен. Спасибо за Ваше участие.

Взаимно)
Честно говоря, не совсем понимаю, что надо пояснить). Вашу идею понял, но о5-таки не понимаю в чем проблема. Если вопрос еще актуален, будьте добры, поконкретнее..

спасибо, я новенький в этом деле, но оч как нужно….Если не сложно выложете пожалуйста кусочек кода что б я мог понять что он както работает и отзывается(совсем остальным думаю уже как то разберусь).Да я поставил резисторный делитель, поидеи все должно быть Ок.(использую мегу 128 повесил контакты на scl- 0 и sda- 1, пишу на AVRcodevision)заранее спасибо

да у меня возникли проблемы с программной частью….схему подключил как по даташиту(хотя основная проблема в том что у меня контроллер то 5в а там 3в в акселерометре((( не спалю?) а в программной части не пойму что нужно ему отправить что б он активировался и начал слать данные.

Читайте также  Управление биполярным шаговым двигателем без использования драйвера

1) разумеется, нужно понизить напряжение, хотя бы делитель поставьте..
2) готовые решения по программной части вы вряд ли найдете. И вряд ли кто-то вам сделает (такие вещи уже обычно за бесплатно не делаются). Самое верное решение — а) разобраться в работе I2C и TWI, а затем б) сделать все самому ручками по даташиту (разделы SINGLE BYTE READ, SINGLE BYTE WRITE)

спасибо, я новенький в этом деле, но оч как нужно….Если не сложно выложете пожалуйста кусочек кода что б я мог понять что он както работает и отзывается(совсем остальным думаю уже как то разберусь).Да я поставил резисторный делитель, поидеи все должно быть Ок.(использую мегу 128 повесил контакты на scl- 0 и sda- 1, пишу на AVRcodevision)заранее спасибо

доброго времени суток,уже месяц пытаюсь зделать нечто)))и все без резульатно(((
вобщем у меня есть мега128 и mma7455 (аксилирометр),необходимо подключить его по i2c (их не один должен быть)но как это зделать? пишу на с codevisionVR…. помогите разобратся, заранее спасибо!

А в чем конкретно то проблема? Я скачал даташит, там есть схема подключения акселерометра по I2C. Для этого интерфейса на mma задействованы ножки 13 и 14. Подключить таких штук к микроконтроллеру с одним I2C интерфейсом вы сможете только 2 штуки, наскока я понял, если постоянная часть адреса mma7455 на заводе зашивается одна и та же. Для изменения переменной части адреса задействована ножка 4 (почему только одна ? :-(, при том что есть еще на корпусе аж целых 3 na), вот отсюда и ограничение в 2 девайса.

А как вешать на шину I2C несколько ведомых, наверное вам известно — https://nagits.files.wordpress.com/2010/12/121810_1006_avr2.gif?w=614 (из статьи AVR: РАБОТАЕМ С ВНЕШНЕЙ ПАМЯТЬЮ I2C EEPROM типа 24CXX).

8 и 9 ножки отведены для каких-то прерываний, если их будете подключать, то их понадобится 4 штуки для двух акселерометров

Ну а с программной частью если проблемы, то читайте даташит и какую-нибудь статью, например эту AVR: РАБОТАЕМ С ВНЕШНЕЙ ПАМЯТЬЮ I2C EEPROM типа 24CXX https://nagits.wordpress.com/2010/12/18/avr_i2c_eeprom/ (здесь подробно рассказываю о модуле TWI в AVR для работы с шиной I2C)

Доброго здоровья!
Спасибо за статью актуальна.
Интересует возможность подключения к примеру десяти подчиненных мег

Взаимно)
Если я правильно понял вопрос, то да, вы можете подключить и 100 подчиненных мег — делается по схеме http://t1.gstatic.com/images?q=tbn:ANd9GcQZ2MCZ2gstwUzEB6VcHh-nQeRAZJw-4WkmdCczWBcr8VJqq7vu.

Я так прикинул, в принципе все ограничивается 255-тью контроллерами — из-за допустимого диапазона адресов 0x00 — 0xFF, но мне кажется это программное ограничение не составит особого труда преодолеть, если вдруг найдется хардкор-мен))

Введение

В составе некоторых микроконтроллеров AVR есть модуль двухпроводного последовательного интерфейса (Two -wire Serial Interface или TWI). Модуль предназначен для организации обмена данными между микросхемами, подключенными к двухпроводной шине. Основное преимущество этого интерфейса перед SPI и UART`ом — это возможность организации сети из нескольких устройств.

Двухпроводный интерфейс является аналогом I2C интерфейса фирмы Philips, только в случае AVR, не поддерживает высокие скорости передачи данных (свыше 400 kbit/s). Соображения, по которым Atmel использует другое названия, видимо связано с нежеланием платить Philips за лицензию.

В этом материале мы разберемся с основами двухпроводного последовательного интерфейса, а в следующих перейдем к работе с TWI модулем AVR.

Далее я буду опираться на даташит atmega16 и спецификацию I2C.

Подключение устройств к I2C шине

I2C шина представляет собой две двунаправленные линии связи — SDA (Serial Data Line) и SCL (Serial Clock Line). По SDA передаются данные, по SCL тактовый сигнал. Обе линии подтянуты через резисторы к плюсу питания.

Устройства на шине подразделяются на ведущих (master) и ведомых (slave). Ведущие запускают и завершают передачу данных, ведомые — отвечают на запросы. Одни — начальники, другие — подчиненные. Микроконтроллеры могут совмещать в себе обе эти функции.

Выходные каскады устройств, поддерживающих I2C, выполнены как структуры с открытым коллектором/стоком. При подключении к шине, они образуют схему монтажного «И». Это значит, что любое устройство, установившее низкий логический уровень на линии шины, «проваливает» высокий уровень остальных устройств.

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

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

Передача данных по I2C

Данные передаются поразрядно (спасибо кэп!), старшим разрядом вперед. Каждый разряд сопровождается тактовым сигналом.

Начало и окончание передачи данных сопровождается специальными состояниями шины — СТАРТ и СТОП. Эти состояния формирует ведущее устройство. Также ведущий может сформировать состояние повторного старта до формирования состояния СТОП.

Данные передаются по I2C шине со служебной информацией. Все вместе это называется пакетом. Существуют адресные пакеты и пакеты данных. Адресные пакеты состоят из 7-и разрядного адреса, управляющего бита R/W и бита квитирования (весь пакет — 9 бит). Адресный пакет нужен, чтобы обратиться к конкретному устройству.

R/W — определяет последующее направление передачи данных. Бит квитирования — это ответ ведомого устройства на принятый адрес. Если адрес распознан, ведомый выдает на линию SDA низкий уровень. В противном случае на линии удерживается высокий уровень.

Под адрес отведено 7 разрядов, что как бы намекает на возможность адресации 128 устройств, но это не совсем так. Во-первых существует ряд служебных адресов, например, 0000000 — это адрес общего вызова (обращение ко всем ведомым устройствам). Во-вторых есть режим 10-и разрядной адресации, когда адрес передается двумя пакетами. Не буду углубляться в эту тему, только скажу, что адреса из диапазона 1111000. 1111111 не рекомендуется использовать в TWI модуле AVR (курим даташит).

Пакеты данных состоят из байта данных и бита квитирования, то есть тоже имеют длину 9 бит. После приема каждого байта данных, принимающее устройство (приемник) отвечает передающему устройству (передатчику), устанавливая на линии SDА низкий уровень (это и есть бит квитирования). Если принимающее устройство получило последний байт или больше не может продолжать прием данных, оно должно «оставить» на линии SDA высокий уровень.

В общем случае, полный цикл обмена по I2C состоит из следующих шагов:

— формирование состояния СТАРТ,
— передача адресного пакета,
— передача пакетов данных,
— прием пакетов данных,
— формирование состояния СТОП.

Начало работы с AVR Studio 4 (урок 1)

Для работы с AVR Studio 4 необходимо само собой её установить. Если она уже установлена, то можете пропустить этот шаг.

Установка:
создаешь каталог c:/avr/ – тут будут лежать рабочие программы.
создаешь каталог например c:/works/ – тут будут лежать твои работы.
надо что бы были короткие пути, что бы не было проблем с ними.

Дальше, качаешь и устанавливаешь в каталог c:/avr/
WinVR
AVRStudio4_SP3

Есть вообще AVRStudio5 но и AVRStudio4 пока вполне хватает.

Вся работа будет проходить в AVRStudio4, WinAVR нужна только из-за библиотеки AVR-GCC (Для того, что бы можно было писать на Си)
НО! первым надо установить именно WinAVR , иначе библиотека AVR-GCC не подцепится.

Дальше запускаешь AVRStudio4 и создаешь проект.

Тут думаю разберешься.
AVR-GCC для того, что бы писать на Си
Atmel Avr Assembler соответственно для ассемблера.

Начинать разбираться с МК лучше с нуля. А это значит с Ассемблера, значит создаешь тот, который Atmel AVR Assembler.

Потом выбирай микроконтроллер Atmega8.

дальше нужно выбрать симулятор. выбирай: AVR Simulator -> Amega8

ну теперь нажимай финишь.

когда создастся проект, будет большой, белый, чистый лист. тут будет код.

немного про содержимое этого листа

“комментарии” – это текст, пропускаемый компилятором, при компиляции.
перед началом комментария должен стоять спец символ, пользуюсь символом ; “точка с запятой”, есть еще “дабл сшеш” (//),
вот примеры комментариев

команды записываются в каждой строчке. т.е. одна команда – одна строчка.
допустим есть команды с двумя “параметрами”, с одним, или без ничего

С этим все ясно. дальше сложнее. Каждая команда, имеет размер 1, 2 или 3 байта.

Видите связь размера команды с параметрами?

Читайте также  Технология поддержания температуры теплоносителя

У каждого микроконтроллера свой ассемблер, хотя мнимоника у них похожа, т.е. команда MOV у мк одной серии будет выглядеть в машинном коде допустим 0x12 а у другого 0x55.
что бы при компиляции, скомпилировалось в нужном нам коде мы должны сказать компилятору, для какого мк у нас пишется программа.
это вообще выбирается при создании проекта.
По этому мы выбрали микроконтроллер Atmega8.

Но и тут не все. для облегчения нашей жизни, в AVRStudio4 есть набор констант, которые именуются вроде как “Макроассемблер”.

Для тог, что бы их подгрузить нужно в начале кода вставить строчку

в самом начале кода, ставится таблица прерываний. Что это такое и как это работает, объясню в другой заметке. Но а пока, будем писать её так:

После этого идет уже сам код

Но тут есть одна (точнее не одна, а много) особенностей.

Для удобства написания кода, для его понятности и для облегчения относительных переходов, нам подарили маркеры, как они выглядят? “RESET:” и “MAIN:” это маркеры, в их именах могут содержаться почти любые символы латинского алфавита и цифры. Маркеры не могут иметь имена функций и команд, допустим “NOP”.
Как к ним переходит? Допустим командой RJMP.

Так же, из Маркеров, можно сделать подпрограмму(процедуру), по завершению которой, мы вернемся туда, от куда её вызывали. Для вызова её, используем команду “RCALL (подпрограмма)”, а что бы вернуться из Подпрограммы(процедуры), нужно закончить её командой “RET”. У нас должен получиться такой код:

Как работает команда “RCALL”, при её вызове, адрес из какого места её вызвали, помещается в СТЕК, а по вызове команды “RET”, извлекается из регистра “стек”. СТЕК нужно инициализировать.

Что бы нам работать с нашим мк, нужно его инициализировать. т.к. мк, это устройство универсальное, в нем есть много портов ввода/вывода, и периферийных устройств. таких как УСАПП, ШИМ, ЦАП, АЦП и т.д. Первым делом в инициализации мк нужно указать начало “стека”. Инициализацию мы проводим после маркера “RESET:”.

Если бы мы не вводили команду .include “m8def.inc” в начале кода, то нам пришлось бы писать так:

Разница существенная, на мой взгляд.

СТЕК, это память магазинного типа: (последний вошедший, выходит первым).
Магазинного типа – это не супермаркет, а рожок от автомата. надеюсь все представили как в него заряжаются патроны и как они потом от туда извлекаются.
Нужно уделять очень большое внимание памяти СТЕК, т.к. любая незначительная ошибка в работе с ним, может привести к срыву стека. Это на столько важная тема, что я решил посветить ей целую тему и напишу её в отдельной заметке.

Таким образом у нас получился такой код:

На данном этапе, можно скомпилировать проект и запустить его для отладки, но по скольку код у нас ничего не делает, можно будет выявить только синтаксические ошибки в коде.

Для правильного процесса отладки, необходимо задать эмулятору частоту, с которой будет работать МК, это делается только после компиляции и запуска отладки,
значит находим в панели меню “Build”, раскрываем её и видим “Build and Run”, после чего, мы увидим желтую стрелочку на против первой команды в нашем листинге кода. Теперь мы ищем в панели меню “Debug” и нажимаем “AVR Simulator Options”, открывается такое окно:

В котором мы можем поменять МК и его частоту, так же, на панели с права, мы видим некоторую информацию о нашем МК: его максимальную частоту, объемы памяти(EEPROM, RAM, FLASH). Теперь открываем даташит на Atmega8, на странице 203 (общий список регистров) и 205 (общий список команд) и приступай к написанию своей программы.
И запомни, не бойся экспериментировать с симулятором, он от этого не сломается!

Программная реализация протокола I2C на AVR в CodeVisionAVR

Пару лет назад, изучая Atmega8, я захотел программно реализовать работу с устройствами на шине i2c, но как-то не задалось. С аппаратным i2c, напротив, не было никаких проблем и затея как-то забылась.

Но недавно я прочитал статью на Датагоре «Несколько функций для програмной реализации протокола I2C на AVR», в которой автор выложил свой пример программной реализации протокола под IAR. Я в тот же миг переписал всё в CodeVision, но, к сожалению, у меня опять не заработало как надо.
Решил набраться терпения и разобраться сам.

Содержание / Contents

  • 1 Разбираемся с протоколом i2c
  • 2 Проверим код с помощью записи/считывания AT24C08
  • 3 Тестируем протокол в железе
  • 4 Итого

↑ Разбираемся с протоколом i2c

На этом рисунке я изобразил поведение линии SCL при передаче одного бита и длиной в один такт, а также пояснил некоторые понятия. С SCL вроде бы всё ясно, надо разобраться с SDA.
Так вот, при записи бита, надо на линии SDA выставлять значение, в соответствии с содержанием этого бита. Причём делать это лучше всего в середине паузы. Сразу появился вот такой код:

Далее рассмотрим чтение бита из шины. Нужно точно также протактировать линию SCL и прочитать значение линии SDA сразу после фронта импульса SCL. Вот код:

Теперь пора рассмотреть все дефайны, которых, как известно, мало не бывает:

Далее нужно научиться передавать байт. Тут ничего сложного:

Хотелось бы пояснить, что шина i2c устроена так, что при передаче байта мы должны отправить восемь бит данных и потом прочитать бит — так называемый «акнолидж» (ack). Это такой бит подтверждения, посылаемый устройством на шине, который сигнализирует нам, что устройство благополучно «проглотило» наш байт.
При работе с устройствами этот бит, как правило, говорит устройству о конце/продолжении передачи при чтении нескольких байт из него. Так же иногда этот «акнолидж» надо иногда передавать устройству, особенно при чтении данных с него.

С записью байта понятно, разберемся с чтением. Тут ситуация в точности наоборот — мы сначала читаем восемь бит байта, а потом выдаем этот «акнолидж».
Реализация приема байта:

Теперь пропишем пресловутые функции старт/стоп, как требует протокол:

↑ Проверим код с помощью записи/считывания AT24C08

Для проверки я решил использовать Ардуино Nano и микросхему памяти AT24C08 . Обратите внимание, аналоги, например чип ST24C08, имеют немного другую распиновку, сверяйтесь с даташитами.
Для контроля работы сначала хотел использовать последовательный порт, но потом решил, что это лишнее и решил обойтись обычным светодиодом, ведь он уже распаян на Ардуинке. Работу с микросхемой AT24C08 расписывать не буду, всё есть в документации к ней.

Написанный код я сначала тестирую в Протеусе (ISIS 7 Proteus). Привожу осциллограмму работы:

На осциллограмме видно, что синхросигнал линии SCL получен ровный, данные на линии SDA выставляются верно. Но есть и минус: всплески сигнала на линии SDA. Я долго выяснял, откуда они взялись. Оказалось, что этот всплеск возникает сразу после передачи/приёма бита «акнолидж» (ACK). Устранить этот недостаток мне так и не удалось, оставил, как есть. На работу данный всплеск не должен влиять.
Может на досуге ещё подумаю над этим или кто-нибудь из опытных читателей подскажет в комментариях.

↑ Тестируем протокол в железе

Переходим к тесту в железе. Воткнул в беспаечную макетную плату (breadboard) платку ARDUINO NANO , микросхему AT24C08 и соединил всё проводками. Я для прошивки Ардуинки использую стандартный Ардуиновский бутлоадер (загрузчик) и программу XLoader, а вы можете использовать привычный вам способ.

При первом запуске у меня пошел дым. Что-то не так! Оказалось, что я перепутал распиновку микросхемы памяти AT24C08 . Обидно. В Ардуино у меня сгорел диод по питанию и микросхема памяти вышла из строя. Я заменил и то и другое.

Прошил, включаю: светодиод «молчит». Потыкал тестером и понял, что совершенно забыл про подтягивающие резисторы. Воткнул их. Молчок. Немного подумав и покурив даташит на AT24C08, подал на вывод памяти WP (Write Protect — защита записи, pin 7) не ноль, а единицу.

↑ Итого

На фото видно, что тестовый светодиод горит. Это означает, что всё сработало! Наш код можно сохранить и поместить в папку с примерами.

Всем удачи, а меня с почином. Это первая моя статья.
В скором времени планирую написать статью о протоколе SPI.

Камрад, рассмотри датагорские рекомендации

🌼 Полезные и проверенные железяки, можно брать

Куплено и опробовано читателями или в лаборатории редакции.