Цитата(ReAl @ Sep 10 2010, 15:43)

p.s[0] Отличная иллюстрация того, что программисты на С борятся с аппаратурой (вручную маски битов собирают), а программисты на С++ борятся с компилятором (заставляют его делать тупую работу).
Позволю себе добавить, что отличная, но однобокая иллюстрация. Автор абсолютно не упоминает о возможности описания проекта на языках с гораздо более гибкими и удобными конструкциями. Ведь никто не обязывает втискивать себя в прокрустово ложе препроцессора C или шаблонов C++. Современные скриптовые языки вроде ruby или python позволяют эффективно описать проект (причем не только МК но и всю периферию) и автоматически сгенерировать все требуемые макроопределения, функции, файлы конфигурации и документации, причем генератор легко может учитывать особенности целевого компилятора или ассемблера. При этом сложность описания не ограничивается парой портов.
Приведу усеченный пример:
Код
require 'atmega162'
require 'unitimer'
M = ATMega162.new
M.device_name = "My Super Device"
M.clksrc = :FAST_CRYSTAL
M.clkfreq = 14.3e6
M.bldr_size = 2048
M.hw_version = [1, 2]
M.fw_version = [1, 1]
#
# Pins configuration
#
M.dp :A, 0, :KBDR0, :IN, :PULLUP :desc => "kbd row 0"
M.dp :A, 1, :KBDR1, :IN, :PULLUP :desc => "kbd row 1"
...
M.dp :C, 0, :LED_A, :OUT, :INIT1, :desc => "Display1, seg A"
M.dp :C, 1, :LED_E, :OUT, :INIT1, :desc => "Display1, seg E"
M.dp :C, 2, :LED_C, :OUT, :INIT1, :desc => "Display1, seg C"
M.dp :C, 3, :LED_F, :OUT, :INIT1, :desc => "Display1, seg F"
M.dp :C, 4, :LED_B, :OUT, :INIT1, :desc => "Display1, seg B"
M.dp :C, 5, :LED_D, :OUT, :INIT1, :desc => "Display1, seg D"
M.dp :C, 6, :LED_G, :OUT, :INIT1, :desc => "Display1, seg G"
M.dp :C, 7, :LED_H, :OUT, :INIT1, :desc => "Display1, seg H"
#
# define pins group for display segements
#
M.dg :LED_SEGMENTS, 8, [:LED_A, :LED_B, :LED_C, :LED_D, :LED_E, :LED_F, :LED_G, :LED_H]
#
# unitimer configuration, period 20uS, mode - OCR
#
M.unitimer(20e3, :OCR)
M.UT.add "05S", 500e3, :timer_05s_handler
M.UT.add "LED", 200, :led_timer
M.UT.add "MODBUS", :MODBUS_TIMER_TICK, :mb_timer
...
M.sources=%@
main.c
leds.c
control.c
heater.c
@
Функциональность объекта ATMega162 имеющего общим предком семейство МК АВР понимает не только определения портов и групп битов, но и может быть расширена за счет подключения дополнительных модулей как unitimer в этом примере. Так, аналогичные расширения имеются для шин Modbus, Microlan, pcuart, пресловутого 44780, sed1520. Более того, поскольку уже все описано на языке высокого уровня, генератор учитывает конфигурацию фьюзов и генерирует соответствующие секции Makefile'ов учитывая особенности AvReal или avrdude.
Значительным преимуществом данного подхода является и то, что вся конфигурация собрана в один или несколько однородных файлов, что резко снижает вероятность непреднамеренных ошибок.