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. У 24АА02 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 в mikropaskal for AVR. Всю необходимую информацию по подключению устройства и адресах данных можно найти в документации к нужному вам устройству.
Прикрепленные файлы:
- Урок по I2C.zip (170 Кб)
Комментарии (0) | Я собрал (0) | Подписаться
Для добавления Вашей сборки необходима регистрация