Урок по mikropascal для AVR. I2C
I2C - послідовна шина даних для зв'язку інтегральних схем. I2C використовує 2 двонаправлені лінії зв'язку SDA і SCL, підтягнуті до напруги живлення.
Приклад роботи I2C інтерфейсу.
Інтерфейс I2C використовується у багатьох пристроях, вони мають низьку вартість і простоту розробки пристроїв на них, ми розглянемо 2 з них: 24AA02 (2к-EEPROM з I2C інтерфейсом) і DS1307 ( годинник/календар реального часу також підключається по I2C.
Отже, перейдемо до справи. Для роботи з I2C в mikropascal є вбудована бібліотека, правда називається вона TWI library. Бібліотека має 8 команд:
- TWI_Init(clock : dword); - ініціалізація I2C. Параметр clock це частота роботи I2C в герцах, зазвичай використовується частота в 100 КГц або 100000 Гц.
- TWI_Busy() : byte; - повертає стан зайнятості шини I2C. 1 - якщо зайнята, 0 - якщо не зайнята.
- TWI_Start() : char; - якщо шина не зайнята, дає стартовий сигнал. Повертає 1 - якщо послідовність не завершена і 0 - якщо завершена.
- TWI_Read(ack : byte) : byte; - зчитує 1 байт.
- TWI_Write(data_ : byte); - відправляє 1 байт по шині I2C. Параметр data_ це байт який ми відправляємо на пристрій.
- TWI_Stop(); - відправляє завершальний сигнал. Нічого не повертає.
- TWI_Status() : byte; - повертає статус шини I2C.
- TWI_Close(); - закриває з'єднання I2C. Нічого не повертає.
Думаю, з цим усе зрозуміло, тому переходимо до коду. Спершу приєднаємо до 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. У 24AA02 2кб енергонезалежна пам'ять розбита на 8 секторів по 256 ячеек, запис однієї ячейки займає 10мс.
Тепер ідемо в Proteus. Робимо таку схему:
Запускаємо симуляцію і бачимо таку картину:
Значення PORTB перейшло в 0xAA, як і повинно було бути. З пам'яттю розібралися, тепер робимо нещо складніше.
DS1307 годинник/календар реального часу підключається по I2C інтерфейсу, відлічує секунди, хвилини, години, дні, число, місяць і рік. Ми будемо зчитувати секунди, хвилини і години та виводити їх на семисегментний індикатор.
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 Гц.
Ну от, урок підійшов до кінця. Тепер ви вмієте працювати з I2C в mikropascal for AVR. Всі необхідні відомості по підключенню пристрою та адресах даних можна знайти в документації до потрібного вам пристрою.
Прикріплені файли:
- Урок по I2C.zip (170 Кб)