AVR. Учебный Курс. Использование AVR TWI для работы с шиной IIC (i2c)

Про шину IIC я писал уже неоднократно. Вначале было описание протокола, потом пример работы в лоб, а недавно камрад Ultrin выложил пример работы с i2c на базе блока USI. Да и в интернете полно статей по использованию этой шины в своих целях. Одно плохо — все они какие то однобокие. В подавляющем большинстве случаев используется конфигурация «Контроллер-Master & EEPROM-Slave». Да еще и на программном мастере. И ни разу я не встречал материала, чтобы кто то сделал Контроллер-Slave или описал многомастерную систему, когда несколько контроллеров сидят на шине и решают арбитражем конфликты передачи. Пустоту пора заполнять, решил я и завязал узелок на память… Да только веревочку пролюбил :)

Обещаного три года ждут, вот я таки пересилил лень, выкроил время и сообразил полноценную библиотеку для работы с аппаратным модулем TWI, встроенным во все контроллеры серии MegaAVR. Давно грозился.

Кошмар на крыльях ночи
Во-первых, я сразу же отказался от концепции тупого последовательного кода. Когда у нас есть некоторая функция SendByte(Address,Byte) которая шлет данные по шине, а потом возвращает 1 или 0 в зависимости от успешности или неуспешности операции. Метод прост, дубов, но медленный. Т.е. пока мы байт не пошлем мы не узнаем ушло ли оно, а значит будем вынуждены тупить и ждать. Да, шина i2c может быть очень быстрой. До 100кбит ЕМНИП, но даже это время, а я все же за высокоскоростное выполнение кода, без тормозных выдержек. Наш выбор — диспетчеризация и работа на прерываниях.

Суть в том, что мы подготавливаем данные которые нужно отослать. Дальше запускаем аппаратуру передачи и возвращаемся к своим делам. А зверский конечный автомат, что висит на прерывании TWI передатчика сам передает данные, отвлекая основную программу только тогда, когда нужен какой-либо экшн (например сунуть очередной байт в буфер передачи). Когда же все будет передано, то он генерит событие, которое оповещает головную программу, что мол задание выполнено.
Как? Ну это уже от конкретной реализации событий программы зависит. Может флажок выставить или байт состояния конечного автомата подправить, а может и задачу на конвейер диспетчера набросить или Event в почтовый ящик задачи скинуть. Если юзается RTOS.
(далее…)

Read More »

Использование интерфейса USI в режиме мастера TWI

Возникла необходимость использовать EEPROM совместно с контроллером ATTiny44. Соответственно выбор пал на AT24C64, работающую по интерфейсу I2C (TWI по атмеловской терминологии). Порыл в документации и в инете — с виду вроде все просто, но при реализации алгоритма несколько раз возникали вилы нигде толком не обозначенные, поэтому решил написать статейку.

Я не мега-гуру, поэтому если будут ошибки или недочеты — надеюсь спецы в комментах поправят. Код буду приводить на Си в простом быдло-кодерском исполнении, так как пока нет нужды заморачивать более сложные варианты. Теперь обо всем по порядку…

Примечание: для понимания материала статьи желательно представлять работу TWI интерфейса и микросхем serial eeprom. Прочитать об этом можно в статьях DI HALT’a про IIC интерфейс и, например, в статье про часы (где-то еще попадалась статья про работу конкретно с serial eeprom, но не нашел…)
(далее…)

Read More »

Пример виртуальной машины

Как то раз я описывал концепцию создания языка программирования для устройства. Который бы позволил запихать сложнейший алгоритм или последовательность действий в виде компактного скрипта.

Простой пример для чего это нужно — фрезерный станок с ЧПУ. И надо на нем выточить голову Сократа из цельного куска металла. Задача, на самом деле, не шибко сложная.

Но попробуйте написать прошивку, двигающую резцом, в виде классического конечного автомата — двигающую резцом в зависимости от условий или состояний. Да вы сдохнете раньше чем это сможете сделать.

Другое дело если разбить программу на элементарные операции, вроде «Резец вверх», «резец вниз», «шаг на n мм», а прошивке скормить последовательность этих микроопераций в виде байт-кода или текстового скрипта. Как все серьезно упрощается. Да и попутно можно нашинковать Платона с Гераклом, было бы желание, да образец для копирования.

Т.е. у нас появился свой язык устройства, полностью отвязанный от аппаратной реализации и оперирующий только органами устройства. И вот тут, главное, не впасть в высокоуровневую прелесть и не начать изобретать универсального интерпретируемого языка аля JAVA для микроконтроллеров. В условиях ограниченных ресурсов это полный бред.

Наоборот, этот язык нужно максимально упрощать за счет усложнения процедур машины, затачивая их строго под текущую задачу, а не делая нечто универсальное. Тогда можно выжать максимум из контроллера.

Ну, хватит воды, приведу пример того, что у меня получилось за вечерок курения в код. Код рабочий, но я там ничего не оптимизировал. Так, накидал чтоб работало, до ума доведете сами. Сделано все на базе ядра диспетчера. Я его уже описывал, поэтому работу его функций пояснять не буду
(далее…)

Read More »

Виртуальная машина и байт код

Часто требуется делать большие последовательности сложных операций — например полетное задание для робота. Да, можно запихать все это дело в основную программу, но вдруг что то пойдет не так как надо и алгоритм надо будет переделать — придется переделывать всю программу.

Тут на помощь придет виртуальная машина. Суть в чем — в памяти контроллера, в основную программу, занесены основные процедуры управления устройством. Если это робот, то это могут быть такие простые команды как «вперед», «назад», «повернуть» и так далее.

Дальше мы увязываем это все в таблицу переходов, где у каждой команды будет номер-смещение.

Потом нам нужен обработчик скриптов, который бы брал откуда нибудь, нашу последовательность действий — скрипт и преобразовывал это в вызовы реальных кусков кода -микрооперации.
Обработчик скриптов может быть той же самой задачей диспетчера, запущенной фоном. А откуда он будет брать данные неважно. Их вполне можно засасывать по usart или тащить из EEPROM памяти. А можно загнать на IIC память и получится сменный картридж :)
(далее…)

Read More »

AVR. Учебный Курс. Работа на прерываниях

Одним из серьезных достоинств контроллеров AVR является дикое количество прерываний. Фактически, каждое периферийное устройство имеет по вектору, а то и не по одному. Так что на прерываних можно замутить кучу параллельных процессов. Работа на прерываниях является одним из способов сделать псевдо многозадачную среду.

 
Идеально для передачи данных и обработки длительных процессов.

 
Для примера покажу буфферизированный вывод данных по USART на прерываниях.

 
В прошлых примерах был такой код:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Отправка строки
void SendStr(char *string)
{
while (*string!='\0')
	{
	SendByte(*string);
	string++;
	}
}
 
// Отправка одного символа
void SendByte(char byte)
{
while(!(UCSRA & (1< <UDRE)));
UDR=byte;
}

 
Данный метод, очевидно, совершенно неэффективен. Дело в том, что у нас тут есть тупейшее ожидание события — поднятие флага готовности USART. А это зависит, в первую очередь, от скорости передачи данных. Например, на скорости 600 бод передача каких то 600 знаков будет длиться 9 секунд, блокируя работу всей программы, что ни в какие ворота не лезет.

 
Как быть?
(далее…)

Read More »

Датчик Холла

Есть такой интересный эффект — если через квадратную проводящую пластину гнать постоянный ток, а саму пластину пронизать магнитным полем, чтобы линии индукции проходили через ее сечение, то летящие по пластине электроны отклоняются силой Лоуренса.

А раз так, то с одного края электронов будет больше чем с другой. Возникает разность потенциалов, то есть напряжение. И чем больше ток и сильней поле, тем большая разность будет. Это и есть эффект Холла.

Дальше дело за малым — берем источник стабильного тока, чем стабильней тем лучше, ведь от стабильности зависит точность показаний. Прогоняем постоянный ток по пластине, ловим да усиливаем разность потенциалов до осязаемых величин. В результате получаем отличную вещь — датчик магнитного поля, он же датчик Холла.
(далее…)

Read More »

Эндрю Таненбаум «Операционные системы. Разработка и реализация»

Автор:Эндрю Таненбаум
Название:Операционные системы. Разработка и реализация
Издательство:Питер
Описание: 
 Давненько я не выкладывал полезных книжек. Надо исправляться.
Итак, раз уж начал задвигать на тему программирования, то нельзя забыть такого автора как Эндрю Таненбаум.
Программисты про него и так знают — как никак это один из классических авторов, а его труды детально расписывают принципы построения операционных систем. Причем описывается это все буквально на пальцах, на упрощенных аналогиях. Впрочем, примеров на Си тоже хватает. Местами занудновато и многое к нашей области не применимо, но для общего развития совершенно не помешает. Книжка из серии обязательных к прочтению.

Read More »

Монтаж плат с SMD компонентами с помощью паяльной пасты и фена.

Когда в единственный нормальный магазин в городе, чуть ли не на заказ, привезли паяльную пасту, я был за ней первый в очереди :)
Давно уже хотел полностью перейти на SMD, как наиболее ленивую технологию — дырки сверлить лень и была паяльная станция LINKO 850, китайский клон незнаю чего (Ну, судя по стилю написания логотипа, косят они все под HAKKO =) Своего рода Adibas =) прим. DI HALT), пока использовавшаяся только для демонтажа. Мосфеты ей с материнок выковыривать — милое дело. Паста у меня была BAKU BK-30G (У меня такая же грязюка есть. Мерзкая вещь, но паять ей прикольно. прим. DI HALT) (далее…)

Read More »

AVR. Учебный курс. Конечный автомат

Каждый кто пытался разбираться с конечными автоматами наверняка натыкался на всякие замудреные графы, какие то графики. Многие посчитав это слишком сложным плюнули и забили. А Зря!

С простейшим конечным автоматом каждый из нас сталкивался с самого детства — это механическая авторучка. Объект с единственной функцией «Нажатие кнопки», но в зависимости от очередности результат разный. Стержень то прячется, то вылазит.

Так и в нашем случае — конечный автомат это функция которая запоминает свое состояние и при следующем вызове делает свое черное дело исходя из прошлого опыта. Простой пример — мигалка (псевдокод):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
; Глобальные переменные
u08 Blink_State;
 
void Blink(void)
{
if (Blink_State == 1)
	{
	Led_On();
	Blink_State = 0;
	Return;
	}
if (Blink_State == 0)
	{
	Led_Off();
	Blink_State = 1;
	Return;
	}
}

Вызывая эту функцию подряд мы заставим диодик менять свое состояние при каждом вызове.
(далее…)

Read More »

AVR. Учебный Курс. Архитектура Программ. Часть 4

Вытесняющий диспетчер
Давным-давно, когда я учился в школе, мне не давал покоя вопрос. Как работают параллельные операционки? Как тот же самый Windows умудряется переключать процессы, не терять регистры (да, я тогда уже начинал учить асму), как он определяет момент переключения, почему все это работает? Виртуальная память, проверка на ошибочный код — никто ничего этого не объяснял. Все твердили про какие-то там объекты, классы, и говорили очень виртуально. А мне мясо, мясо давай!

Но вот прошло время, и я начал писать программы под МК. Тут я получил полную свободу действий и абсолютную прозрачность кода. И почти сразу я стал писать свою операционку. Не для того, чтобы что-то запускать на ней, а лишь для того, чтобы по ходу понять и сообразить, как же все это устроено. И эта статья как раз о том, что я узнал.

Отмазки
Сея программа не более чем учебный пример. Т.к. не тестировалась в серьезных условиях. Не использовалась в каких либо проектах, а гонялась только на эмуляторе. Смысл ее не дать готовое решение, а показать принцип и механизм работы диспетчера операционной системы с принудительным переключением задач. Да и AVR это не та платформа на которой имеет смысл городить вытесняющие диспетчеры.

Немного теории
Думаю не секрет, что любая многозадачная операционка работает на прерываниях таймера. Даже на x86 архитектуре без него никуда.

При срабатывании прерывания процессор идет на обработчик, а там прописано примерно так:

  • 1) Сохранение регистров.
    • 1.1) Сохранение виртуальной памяти — в файл подкачки или еще куда-нибудь.
  • 2) Сохранение текущего адреса.
  • 3) Загрузка регистров след. процесса.
    • 3.1) Загрузка виртуальной памяти.
  • 4) Загрузка адреса возврата.
  • 5) Переход по этому адресу.

По сути — не так уж и много работы, если исключить пункты X.Y. Всего и делов — сохранить, загрузить и вернуться. Вот именно это я и реализовал — простейшее ядро операционки, БЕЗ проверок и т.д.
(далее…)

Read More »