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



 

Урок 16

Часть 5

 

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

 

В предыдущей части занятия уже начали работать с кодом всерьёз и передали адрес устройства и адрес первой ячейки памяти в шины TWI.

Ну, давайте продолжим начатое дело.

Дальше мы работаем в соответствии с той диаграммой из даташита микросхемы, которую мы посмотрели в предыдущей части урока.

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

Передать мы попробуем сразу 32 байта. А чтобы не было слишком много кода, мы создадим массив в файле DS1307Eeprom.c

 

#include «main.h»

unsigned char bt[32];

 

Затем запишем в каждую ячейку массива число в функции main() после передачи адреса ячейки памяти, ну можно, конечно и раньше, но мы проинициализируем массив тут

 

I2C_SendByte(0);//передаем младшую часть адреса ячейки памяти

USART_Transmit(TWSR);//читаем статусный регистр

bt[0]=0x30; bt[1]=0x31; bt[2]=0x32; bt[3]=0x33; bt[4]=0x34; bt[5]=0x35; bt[6]=0x36; bt[7]=0x37;

bt[8]=0x38; bt[9]=0x39; bt[10]=0x3A; bt[11]=0x3B; bt[12]=0x3C; bt[14]=0x3D; bt[14]=0x3E; bt[15]=0x3F;

bt[16]=0x40; bt[17]=0x41; bt[18]=0x42; bt[19]=0x43; bt[20]=0x44; bt[21]=0x45; bt[22]=0x46; bt[23]=0x47;

bt[24]=0x48; bt[25]=0x49; bt[26]=0x4A; bt[27]=0x4B; bt[28]=0x4C; bt[29]=0x4D; bt[30]=0x4E; bt[31]=0x4F;

 

Теперь непосредственно начнём передачу в шину, а, следовательно, и в ячейки памяти микросхемы.

Так как алгоритм передачи байта одинаков, то мы вполне можем использовать цикл for. Создадим локальную переменную в main()

 

int main(void)

{

  int i=0;

 

А теперь, прежде чем написать цикл, мы напишем особую функцию для передачи. Там уже будет отслеживаться статус операции (не всё же нам время в терминал смотреть), в результате которого мы будем. если что-то не так, генерировать ошибку.

 

 

А так как мы будем проверять разные статусы, то давайте в файл eepromext.h напишем некоторые макросы для вариантов статусов

 

#include «main.h»

#define TW_MT_DATA_ASK 0x28 // Ведущий передал данные и ведомый подтвердил прием

#define TW_MR_DATA_ASK 0x50 // Ведущий принял данные и передал подтверждение

#define TW_MR_DATA_NASK 0x58 // Ведущий передал данные и ведомый подтвердил прием

 

Функцию напишем в файле eepromext.c

 

#include «eepromext.h»

int EE_WriteByte(unsigned char c)

{

  TWDR=c;//запишем байт в регистр данных

  TWCR = (1<<TWINT)|(1<<TWEN);//включим передачу данных

  while(!(TWCR&(1<<TWINT)));//подождем пока установится TWIN

  if ((TWSR & 0xF8) != TW_MT_DATA_ASK)

  {

    return 1;

  }

  return 0;

}

 

 

В принципе мы здесь делаем то же самое, что и в функции I2C_SendByte, только мы проверяем статус. Если будет статус не тот, то функция вернёт 1, а если всё нормально — то 0.

Также мы видим здесь то, что здесь применен сброс в ноль младших трех битов. Хотя в данной ситуации это не имеет смысла, так как они и так в нуле, мы не используем биты деления, но для универсальности пусть будет маскирование, так как мало ли, когда-то придется использовать делитель.

Теперь давайте данную функцию и будем использовать в цикле for в main(), только проверять результат мы не будем. Если что-то пойдёт не так, то тогда и проверим. Пока будем читать статусный регистр обычным способом — через USART

 

bt[24]=0x48; bt[25]=0x49; bt[26]=0x4A; bt[27]=0x4B; bt[28]=0x4C; bt[29]=0x4D; bt[30]=0x4E; bt[31]=0x4F;

for(i=0;i<=31;i++)

{

  EE_WriteByte(bt[i]);

  USART_Transmit(TWSR);//читаем статусный регистр

}

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

USART_Transmit(TWSR);//читаем статусный регистр

 

Теперь давайте скомпилируем проект, прошьём контроллер открыв терминальную прогармму и запустив в ней соединение.

Мы должны увидиеть вот такой результат

 

image21

 

То есть ведущий у нас принял все байты, включая и свой адрес устройства.

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

Этим делом мы уже займёмся с помощью специальной функции чтения на следующем занятии. А в чтении есть свои подводные камни.

 

 

Предыдущая часть Программирование МК AVR Следующая часть

 

Техническая документация на микросхему AT24C32

 

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

Программатор USBASP USBISP с адаптером USBASP USBISP 3.3 с адаптером

Модуль RTC DS1307 с микросхемой памяти

 

 

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

 

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

3 комментария на “AVR Урок 16. Интерфейс TWI (I2C). Часть 5
  1. Alexander:

    можно было инициализировать массив таким способом:
    bt[32] = {0};
    uin8_t i;
    for(i=0; i<32; i++)
    {
    bt[i] = 0x30+i;
    }

  2. Arct:

    [#define TW_MR_DATA_NASK 0x58 // Ведущий передал данные и ведомый подтвердил прием]
    Может всёж таки НЕ подтвердил приём? На что намекает «_NASK»…
    Кст, эти дефайны уже определены в «util\twi.h» (AVR GCC toolchain).

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*