AFON // радиотехник affonya@mail.ru
← Проекты на AVR

Проект 34. Внешняя EEPROM 24C02 по шине I²C

Аппаратный модуль TWI обменивается данными с микросхемой памяти по двум проводам. Проект разбирает старт, адресацию, повторный старт и стоп — весь протокол I²C.

Задача

Записать байт во внешнюю память и прочитать его обратно.

Микроконтроллер: ATmega8, кварц 4 МГц. Среда: Atmel Studio / avra (или avra / Atmel Studio). Как настроить среду и прошить контроллер — в статье программирование AVR.

Что понадобится

  • ATmega8
  • кварц 8 МГц + 2×22 пФ
  • микросхема 24C02
  • два резистора 4,7 кОм (подтяжки шины)
  • 8 светодиодов для индикации

Схема подключения

ВыводПодключение
PC4 / SDAлиния данных, подтяжка 4,7 кОм на +5 В
PC5 / SCLлиния тактирования, подтяжка 4,7 кОм
A0…A2 микросхемына GND — базовый адрес 0xA0
WPна GND, иначе запись заблокирована

Алгоритм

  1. Задать скорость шины через регистр TWBR.
  2. Сформировать условие START и передать адрес микросхемы с признаком записи.
  3. Отправить адрес ячейки и данные, завершить обмен условием STOP.
  4. Для чтения повторить старт с признаком чтения и принять байт без подтверждения.

Листинг на ассемблере

Код проверен ассемблером и собирается без ошибок. Скачать: a34.asm · a34.hex (готовая прошивка).

;=======================================================
; Проект 34. Внешняя EEPROM 24C02 по шине I2C (TWI)
; ATmega8, 8 МГц. SDA — PC4, SCL — PC5, подтяжки 4,7 кОм
; Записываем байт в ячейку 0x10 и читаем его обратно
;=======================================================
.include "m8def.inc"

.def tmp  = r16
.def data = r17

.equ EE_W = 0xA0                        ; адрес 24C02 для записи
.equ EE_R = 0xA1                        ; адрес для чтения

.cseg
.org 0x0000
        rjmp    RESET

RESET:
        ldi     tmp, low(RAMEND)
        out     SPL, tmp
        ldi     tmp, high(RAMEND)
        out     SPH, tmp

        ldi     tmp, 0xFF
        out     DDRB, tmp               ; индикация на светодиодах
        ldi     tmp, 32                 ; TWBR: ~100 кГц при 8 МГц
        out     TWBR, tmp

        ;--- запись значения 0x5A в ячейку 0x10 ---
        rcall   TwiStart
        ldi     data, EE_W
        rcall   TwiWrite
        ldi     data, 0x10              ; адрес ячейки
        rcall   TwiWrite
        ldi     data, 0x5A              ; данные
        rcall   TwiWrite
        rcall   TwiStop
        rcall   Delay10ms               ; пауза на цикл записи EEPROM

        ;--- чтение той же ячейки ---
        rcall   TwiStart
        ldi     data, EE_W
        rcall   TwiWrite
        ldi     data, 0x10
        rcall   TwiWrite
        rcall   TwiStart                ; повторный старт
        ldi     data, EE_R
        rcall   TwiWrite
        rcall   TwiReadNack
        rcall   TwiStop
        out     PORTB, data             ; показываем прочитанное

MAIN:
        rjmp    MAIN

TwiStart:
        ldi     tmp, (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
        out     TWCR, tmp
TS_W:
        in      tmp, TWCR
        sbrs    tmp, TWINT              ; ждём завершения операции
        rjmp    TS_W
        ret

TwiWrite:
        out     TWDR, data
        ldi     tmp, (1<<TWINT)|(1<<TWEN)
        out     TWCR, tmp
TW_W:
        in      tmp, TWCR
        sbrs    tmp, TWINT
        rjmp    TW_W
        ret

TwiReadNack:
        ldi     tmp, (1<<TWINT)|(1<<TWEN)       ; без ACK — последний байт
        out     TWCR, tmp
TR_W:
        in      tmp, TWCR
        sbrs    tmp, TWINT
        rjmp    TR_W
        in      data, TWDR
        ret

TwiStop:
        ldi     tmp, (1<<TWINT)|(1<<TWSTO)|(1<<TWEN)
        out     TWCR, tmp
        ret

Delay10ms:
        ldi     r18, 130
E1:      ldi     r19, 255
E2:      dec     r19
        brne    E2
        dec     r18
        brne    E1
        ret

Пояснения

  • Каждая операция TWI завершается установкой флага TWINT — ждать его обязательно, иначе следующая команда собьёт обмен.
  • Повторный старт нужен, чтобы сменить направление обмена, не отпуская шину: иначе другой ведущий успел бы вклиниться.
  • После записи микросхеме нужно несколько миллисекунд на внутренний цикл — обращение раньше времени вернёт ошибку.

Что дальше

Разобравшись с этим проектом, переходите к следующему в разделе проекты на PIC. Справочник по архитектуре и периферии контроллеров — на странице микроконтроллеры AVR.