После UART, реализация TWI модуля на AVR кажется довольно корявой и без понимания I2C протокола будет не просто его освоить. Однако, если разобраться с "софтовой" эмуляцией протокола, то работа с TWI модулем уже не составит труда.
Не последне место в этом списке должно быть у официального аппнота: AVR315: Using the TWI module as I2C master
Если открыть руководство для ATmega8, на странице 156 раздел "Two-Wire Serial Interface", то там даже будет примерный набросок программы для работы с TWI:
bit-banging - это тоже, что
дерганье за ниточки
Используя познания из предыдущего поста: "Введение в Bit-banging: "режимы работы GPIO микроконтроллеров AVR, организация последовательной шины" можно сделать что нибудь полезное. "Софтовая" реализация I2C шины будет не зависеть от модели микроконтроллера, будет работать на тех пинах которые вы зададите, и на мой взгляд, что самое важное, может служить примером протокола для взаимодействия между несколькими различными микроконтроллерами.
Иллюстрация I2C протокола, взятая из AppNoteAVR315: Using the TWI module as I2C master представлена ниже:
Функция форматного вывода printf довольно мощное средство языка Си. Приминительно к микроконтроллерам, возможно, сначала не совсем понятно, что там считать за стандарный поток вывода и как здесь может работать printf(). Библиотека avr-libc содержит файл stdio.h которая включает реализацию стандарных функций ввода-вввода.
<stdio.h>: Standard IO facilities
Я взял оттуда ХеллоВорлд:
#include <stdio.h> static int uart_putchar(char c, FILE *stream); static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); static int uart_putchar(char c, FILE *stream) { if (c == '\n') uart_putchar('\r', stream); loop_until_bit_is_set(UCSRA, UDRE); UDR = c; return 0; } int main(void) { init_uart(); stdout = &mystdout; printf("Hello, world!\n"); return 0; }
И модифицировал пример из поста ATmega8: работа на Си с USART/UART через прерывание заменив функцию writeSerial(char* str) на printf. Получилась такая штука:
pull-up c английского
переводится как подтягивание
Когда речь шла об управлении дисплеем HD44780, то там все было относительно ясно. Напрямую соединялось два устройства, одно работало только на прием, другое только на передачу. Поэтому достаточно было выставить нужный логический уровень на выводах GPIO микроконтроллера, чтобы все работало.
Несколько сложнее обстоят дела, когда нужно организовать обмен данными между несколькими устройствами. Выводы устройств имеют два состояния: логичская единица т.е. +5 или +3 Вольта и логический ноль, когда контакт соединен с "землей". Если начать соединять их напрямую, то произойдет короткое замыкание. Bit-banging это та тема, где нужно четко представлять, что происходит.
На основе этих трех состояний можно постоить последовательную шину вида:
Небольшая демо-программа, таймер для ATmega8 с дисплеем HD44780. В качестве отправной точки использовал исходник из предыдущего поста. Идея была почерпнута здесь: LCD "Bigfont" Numbers over 2 or 4 lines".
Исходник:
Управление ЖК-дисплеем HD44780 довольно простое. Он имеет параллельную шину на 8 пин и три управляющих линии.