Существует интересный макрос, который используется для определения количества элементов в объявленном массиве. Его обычное определение выглядит так:

#define N_ELEMENTS(X) (sizeof(X)/sizeof(*(X)))

   Данный макрос удобно применять для перебора всех элементов массива в циклах.

void foo(void)
{
   uint8_t bar[] = {0, 1, 2, 3, 4};
   uint8_t i;

   /* передать каждый элемент массива bar[] */
   for (i = 0; i < N_ELEMENTS(bar); ++i){
      txc(bar[i]);
   }
}

   Выводы микроконтроллеров AVR сгруппированы в порты. Как правило порты состоят из восьми выводов, но также они могут быть и урезанными, как, например, у некоторых микроконтроллеров семейства Tiny. Порт позволяет одновременно выполнять операции над всеми выводами, входящими в его состав. Это такие операции как установка направления передачи данных, установка логических уровней на выводах и чтение состояния выводов. 
   Многие выводы микроконтроллеров AVR помимо основного назначения, имеют дополнительные функции, которые часто востребованы. Это обстоятельство осложняет использование порта в качестве параллельной шины данных, а иногда и делает полностью невозможным.

   Обойти эту проблему можно тремя способами:
- использовать микроконтроллер с избыточными ресурсами (с большим количеством портов и периферии),
- использовать внешние микросхемы расширители портов,
- программно реализовать виртуальные порты, составленные из выводов разных физических портов.

   В этом материале пойдет речь о программных виртуальных портах.

Дэн Сакс
 
   Использование символов для представления постоянных числовых величин — это одна  из основных рекомендаций, которую узнают большинство программистов в первую очередь.  Например, вместо того чтобы писать:
 
char buffer[256];
...
fgets(buffer, 256, stdin);
 
лучше описать символ, скажем buffer_size, представляющий размерность буфера, и использовать его вместо литеральной константы. 
 
char buffer[buffer_size];
...
fgets(buffer, buffer_size, stdin);
 
   Си и Си++ предлагают несколько способов описания таких символов. Итак, давайте их рассмотрим. 

   При программировании микроконтроллеров постоянно приходится работать с битами. Устанавливать их, сбрасывать,  проверять их наличие в том или ином регистре. В AVR ассемблере для этих целей существует целый ряд команд. Во-первых, это группа команд операций с битами – они предназначены для установки или сброса битов в различных регистрах микроконтроллера, а во-вторых, группа команд передачи управления – они предназначены для организации ветвлений программ. В языке Си естественно нет подобных команд, поэтому у начинающих программистов часто возникает вопрос, а как в Си работать с битами. Эту тему мы сейчас и будем разбирать.