Урок по mikropascal for 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. У 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. Всю необходимую информацию по подключению устройства и адресах данных можно найти в документации к нужному вам устройству. 

Прикрепленные файлы:

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

Ваш адрес email не будет опубликован.