Урок по mikropascal for AVR.I2C

IC — последовательная шина данных для связи интегральных схем. I2C использует 2 двунаправленные линии связи SDA и SCL, подтянутые к напряжению питания.

Пример работы IC интерфейса.

Интерфейс IC используется во многих устройствах, они имеют низкую стоимость и простоту разработки устройств на них, мы рассмотрим 2 из них: 24AA02 (2к-EEPROM с I2C интерфейсом) и DS1307 ( часы/календарь реального времени также подключаемый по I2C.

Итак, перейдём к делу. Для работы с I2C в mikropascal есть встроенная библиотека, правда называется она TWI library. Библиотека имеет 8 команд:

  • TWI_Init(clock : dword); — инициализация IC. Параметр clock это частота работы IC в герцах, обычно используется частота в 100 КГц или 100000 Гц.
  • TWI_Busy() : byte; — возвращает состояние занятости шины IC. 1 — если занята, 0 — если не занята.
  • TWI_Start() : char; — если шина не занята даёт стартовый сигнал. Возвращает 1 — если последовательность не завершена и 0 — если завершена.
  • TWI_Read(ack : byte) : byte; — считывает 1 байт.
  • TWI_Write(data_ : byte); — отправляет 1 байт по шине IC. Параметр data_ это байт который мы отправляем на устройство.
  • TWI_Stop(); — отправляет завершающий сигнал. Ничего не возвращает.
  • TWI_Status() : byte; — возвращает статус шины IC.
  • TWI_Close(); — закрывает соединение IC. Ничего не возвращает.

Думаю с этим всё понятно, поэтому переходим к коду. Сперва присоединим к ATmega8 энергонезависимую память 24AA02. Напишем программу которая будем сначала записывать в байт в память, потом считывать его и отправлять на PORTB. Вот так выглядит наш код:

 program _24aa02;  begin      DDRB:=0xff;        /Порт Б на вывод      twi_Init(100000);  /Инициализируем I2C с частотой 100 КГц      twi_Start();       /Старт I2C      twi_write(0xa4);   /Отправляем ячейку      twi_write(1);      /Отправляем сектор EEPROM      twi_write(0xaa);   /Записываем байт      twi_stop();        /Стоп I2C
      delay_ms(50);            twi_start();      twi_write(0xa4);      twi_write(1);      twi_start();      twi_write(0xa5);   /Отправляем ячейку на один больше того в который записали      PORTB:=twi_read(0);/Считываем в Порт Б значение байта      twi_stop();       end.

Думаю тут всё должно быть понятно, укажу только некоторые характеристики 24AA02. У 24АА02 2кб энергонезависимая память разбитая на 8 секторов по 256 ячеек, запись одной ячейки занимает 10мс.

Теперь идём в Proteus. Делаем такую схему:

Запускаем симуляцию и видим такую картину:

Значение PORTB перешло в 0xAA как и должно было быть. С памятью разобрались теперь делаем нечто посложнее.

DS1307 часы/календарь реального времени подключаемые по IC интерфейсу, отсчитывают  секунды, минуты, часы, дни, число, месяц и год. Мы будем считывать секунды, минуты и часы и выводить их на семисегментный индикатор.

Получился вот такой код:

 program ds1307; var    sec,mint,hour:byte;    i,temp:integer;    secs,mins,hours:array[3] of char; const      d0:byte=192;      d1:byte=249;      d2:byte=164;      d3:byte=176;      d4:byte=153;      d5:byte=146;      d6:byte=130;      d7:byte=248;      d8:byte=128;      d9:byte=144;      dp:byte=127; begin      twi_init(100000);      mint:=0;      hour:=0;      sec:=1;      DDRB:=0xff;      DDRD:=0x0f;       twi_start();      twi_write(0xd0);      twi_write(0);      twi_stop();       twi_start();      twi_write(0xd0);      twi_write(1);      twi_stop();       twi_start();      twi_write(0xd0);      twi_write(2);      twi_stop();       while true do      begin          if PIND.6=0 then begin              mint:=dec2bcd(mint);              inc(mint);              if mint>89 then mint:=0;              twi_start();              twi_write(0xd0);              twi_write(1);              twi_write(mint);              twi_stop();          end;          if PIND.7=0 then begin             hour:=dec2bcd(hour);             inc(hour);             if hour>35 then hour:=0;             twi_start();             twi_write(0xd0);             twi_write(2);             twi_write(hour);             twi_stop();          end;          twi_start();          twi_write(0xd0);          twi_write(0);          twi_start();          twi_write(0xd1);          sec:=twi_read(1);          mint:=twi_read(1);          hour:=twi_read(0);          twi_stop();           sec:=bcd2dec(sec);          mint:=bcd2dec(mint);          hour:=bcd2dec(hour);           bytetostr(mint,mins);          bytetostr(hour,hours);           for temp:=1 to 25 do begin          for i:=0 to 3 do begin              if i>=2 then begin              if i=2 then portd:=4;              if i=3 then portd:=8;              case mins[i-1] of                   '1':portb:=d1;                   '2':portb:=d2;                   '3':portb:=d3;                   '4':portb:=d4;                   '5':portb:=d5;                   '6':portb:=d6;                   '7':portb:=d7;                   '8':portb:=d8;                   '9':portb:=d9;                   '0':portb:=d0;                   ' ':portb:=d0;              end;              end              else begin                   portd:=i+1;                   case hours[i+1] of                        '1':portb:=d1;                        '2':portb:=d2;                        '3':portb:=d3;                        '4':portb:=d4;                        '5':portb:=d5;                        '6':portb:=d6;                        '7':portb:=d7;                        '8':portb:=d8;                        '9':portb:=d9;                        '0':portb:=d0;                        ' ':portb:=d0;                   end;              end;              delay_ms(10);          end;          end;      end;  end.

Теперь Протеус:

Теперь, под торжественную музыку, запускаем нашу схему и надеемся что она работает.

И, о чудо, она работает! Как вы уже догадались 2 кнопки внизу предназначены для регулировки времени, кварц частотой 32768 Гц.

Ну вот, урок подошёл к концу. Теперь вы умеете работать с IC в mikropaskal for AVR. Всю необходимую информацию по подключению устройства и адресах данных можно найти в документации к нужному вам устройству.