Bit-banging AVR: делаем сканер TWI шины

разделы: I2C, дата: 26 сентября 2015г.


bit-banging - это тоже, что
дерганье за ниточки

Используя познания из предыдущего поста: "Введение в Bit-banging: "режимы работы GPIO микроконтроллеров AVR, организация последовательной шины" можно сделать что нибудь полезное. "Софтовая" реализация I2C шины будет не зависеть от модели микроконтроллера, будет работать на тех пинах которые вы зададите, и на мой взгляд, что самое важное, может служить примером протокола для взаимодействия между несколькими различными микроконтроллерами.

Иллюстрация I2C протокола, взятая из AppNoteAVR315: Using the TWI module as I2C master представлена ниже:

Читать дальше

UART+AVR: функция форматного вывода printf()

разделы: AVR, UART, дата: 23 сентября 2015г.

Функция форматного вывода 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. Получилась такая штука:

Читать дальше

Введение в Bit-banging: "режимы работы GPIO микроконтроллеров AVR, организация последовательной шины

разделы: I2C, дата: 20 сентября 2015г.


pull-up c английского
переводится как подтягивание

Когда речь шла об управлении дисплеем HD44780, то там все было относительно ясно. Напрямую соединялось два устройства, одно работало только на прием, другое только на передачу. Поэтому достаточно было выставить нужный логический уровень на выводах GPIO микроконтроллера, чтобы все работало.

Несколько сложнее обстоят дела, когда нужно организовать обмен данными между несколькими устройствами. Выводы устройств имеют два состояния: логичская единица т.е. +5 или +3 Вольта и логический ноль, когда контакт соединен с "землей". Если начать соединять их напрямую, то произойдет короткое замыкание. Bit-banging это та тема, где нужно четко представлять, что происходит.

    Рассмотрим режимы работы GPIO в AVR микроконтроллерах:
  1. Push-pull режим. Режим на передачу, когда вывод GPIO подключен либо к Vcc либо GND. Задается записью единицы в соответствующий бит DDR(data direction register) регистра. Состояние GPIO меняется записью в соответствующий бит регистра PORT нуля или единицы. Должно быть понятно, что прямые соединения типа: {(GPIO=1) <==> GND} или {(GPIO=0) <==> Vcc} приведут к короткому замыканию!
  2. Высокоимпедансное состояние. Это когда GPIO не подключен ни к Vcc ни к GND. Это состояние по умолчанию для всех GPIO микроконтроллера. Задается записью нулей в соответствующие биты регистров DDR и PORT. В этом состоянии доступен только на чтение регистр PIN, который выдаст единицу если на GPIO подать высокий потенциал и ноль, если потонциал будет ниже трех вольт. В случае, если вывод GPIO никуда не подключен, т.е. "болтается в воздухе". т.е. состояние соответствующего бита регистра PIN считается неопределенным, т.е. лишино всякого смысла.
  3. Pull-up состояние, когда, GPIO подключен через подтягивающий резистор(pull-up) к Vcc. Задается записью в соответствующие биты: ноль в DDR, единица в PORT. В этом состоянии, на GPIO будет высокий потенциал, но прямое соединение GPIO с землей не приведет к короткому замыканию. В этом состоянии, при замыкании GPIO на землю, с регистра PIN будет считываться ноль, в остальное время будет считываться единица.

На основе этих трех состояний можно постоить последовательную шину вида:

Читать дальше

HD44780 + ATmega8: таймер с крупными цифрами

разделы: AVR, HD44780, дата: 15 сентября 2015г.


макет цифр

Небольшая демо-программа, таймер для ATmega8 с дисплеем HD44780. В качестве отправной точки использовал исходник из предыдущего поста. Идея была почерпнута здесь: LCD "Bigfont" Numbers over 2 or 4 lines".

Исходник:

Читать дальше

ATmega8: простая программа управления ЖК-дисплеем HD44780

разделы: AVR, HD44780, дата: 9 сентября 2015г.


Управление ЖК-дисплеем HD44780 довольно простое. Он имеет параллельную шину на 8 пин и три управляющих линии.

  1. Контакты D0-D7 это 8-битная шина. Может работать как в 8-битном режиме, так и в 4-битном. В последнем случае задействуются "старшие" пины D4-D7.
  2. RS выбор регистра. В контроллере дисплея имеется два регистра: регистр команд IR и регистр данных DR. В зависимости от того, что мы пишем в контроллер данные или подаем команды, с помощью RS линии мы выбираем "адресата". При RS равном нулю посылаются команды, при RS равном единице пишутся данные.
  3. E выполняет роль клавиши "Enter". Можно в каком угодно порядке и последовательности менять значения пинов контроллера дисплея, но когда управляющий пин E устанавливается в единицу, то всё, данные уходят в контроллер дисплея. Чтобы записать очередные данные следует E вновь сбросить в ноль.
  4. RW не используемый в данном случае пин, который переключает режимы дисплея с чтения на запись и обратно. В данном примере RW запитан на массу(землю), т.е. установлен в ноль, что означает работу дисплея только на прием, на получение и отображение данных и команд. При RW равном единице дисплей переводится в режим передачи, и тогда возможно прочитать BF(busy flag) - флаг занятости. Дело в том, что дисплей довольно медлительное устройство, и при записи в него команд или данных он становится на некоторое время недоступен. Чтобы понять, когда в него снова можно писать следует ждать когда сбросится BF. В данном примере вместо опроса BF используются задержки с гарантированным временем готовности дисплея. С опросом BF флага, программа работала бы конечно быстрее, но это, как говорится, палка о двух концах. Усложнение ради упрощения.

Читать дальше

ATmega8: работа на Си с USART/UART через прерывание

разделы: AVR, UART, дата: 16 августа 2015г.


UART для передачи использует два
провода, один на прием, другой
на передачу. Поэтому протокол
является полнодуплексным. Однако,
регистр данных UDR один.

Работа с UART через прерывания мне показалась более эффективной нежели через циклы ожидания. Потому что, программа кроме того что принимает или передает что-либо через UART, она, как правило, занята еще какими-то задачами, будь то опрос датчиков или вывод информации на дисплей. И в таком случае возникает совсем не простая проблема эффективного переключения между задачами. И если, например, ожидание приема корректных данных затянется то микроконтроллер по сути подвиснет. Делать прерывание ожидания по таймауту, это лишний код которого можно избежать, если реализовать рабту с UART через прерывания. Ниже приведен исходник эхо-программы которая читает строку через UART и посылает ее обратно. Строка должна оканчиваться символом двоеточия. В программе используется USART_RXC вектор, который срабатывает когда на порт что-то поступило. Обработчик прерывания это "что-то" переносит в рабочий буфер. Если принятый байт является символом двоеточия, то устанавливается флаг done, по которому главная программа понимает что были приняты какие-то данные. Конечно, следовало бы принятую строку заносить в сетк, но в данном случае решил исходник не усложнять.


Читать дальше

ATmega8: работа на Си с USART/UART

разделы: AVR, UART, дата: 2 августа 2015г.

Работа с UART на ATmega несколько проще чем с таймерами, но на мой взгляд, в целом эта тема более мутная, хотя и более интересная. Зависит от того, с какой стороны посмотреть.

Так же как и с таймерами, для работы c USART имеется набор прерываний:

и регистров:

Читать дальше

ATmega8: Blink без delay на Си

разделы: AVR, дата: 30 июля 2015г.

Нулевой таймер на ATmega8 не имеет апаратного ШИМ'а, поэтому ему трудно придумать применение кроме как простого счетчика. На 16MГц кварце и делителем на 64, прерывание по переполнению счетчика будет вызаваться с частотой 1КГц, т.е. каждый вызов будет равняться одной миллисекунде. Разрядности unsigned long для счетчика должно хватить на 49 дней. В целом, такой счетчик мало годится для построения часов, но в качестве таймера для расчета разных задержек подойдет вполне.

/* timer.c LED Blink whitout delay via 8-bit Timer0 for AVR ATmega8 */
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

volatile unsigned long millis;

ISR(TIMER0_OVF_vect)
{
	millis++;
}

int main(void)
{
        DDRB |= (1<<PB5); //  pinMode(13,OUTPUT); в Wiring

        TIMSK =(1<<TOIE0);  // timer0 enable
        TCCR0 = (1<<CS01) | (1<<CS00); // prescaler 1/64

	volatile unsigned  long curTime, lastTime, period;

	millis=0;
	lastTime=0;
	period=1000; // 1 sec

        sei();

        for (;;)
	{
		curTime=millis;
		if ((curTime -lastTime)> period)
		{
			PORTB ^= (1<<PB5);
			lastTime=curTime;
		}
	}

        return 0;
}

Читать дальше

ATmega8: таймер на компараторе, CTC режим

разделы: AVR, дата: 30 июля 2015г.

Второй 8-битный таймер ATmega8 - TIMER2. Кроме перывания по переполнению счетчика, расмотренное в предыдущем посте, TIMER2 имеет второе прерывание по значению компаратора. Т.е. не надо будет ждать переполнения счетчика, прерывание сработает когда счетчик достигнет определенного значения. Это позволяет более точно устанавливать частоту срабатывания и по сути является производным генератором частоты. Штука архиполезная, позволяет выставлять значения портов по какой либо-функции или наоборот снимать показания с портов с некой периодичностью. Используется для PWM, но PWM оставим на потом, сейчас будет полезно разобраться с CTC режимом работы компаратора, когда его можно использовать как счетчик.

CTC режим (Clear Timer on Compare Match Mode), это режим при котором зачение таймера сбрасывается при достижении занчения определенного в регистре OCR2. Для TIMER2 данный режим устанавливается в TCCR2 регистре флагом WGM21:

Читать дальше

ATmega8: счетчик на прерывании Timer/Counter overflow

разделы: AVR, дата: 28 июля 2015г.

Если посмотреть таблицу прерываний для ATmega8 из предыдущего поста, то видно, что почти половина из них, это прерывания для работы с таймерами/cчетчиками. Также для их конфигурации отведена значительная часть регистров:

Также для их конфигурации отведена значительная часть регистров:

Читать дальше