ЖУРНАЛ СТА №2/1998
лей ввода-вывода не использует пре- рываний, в системе возможны только два типа прерываний: от таймера-сто- рожа и от коммуникационных портов (табл. 1). Распределение памяти в контролле- ре показано в табл. 2. Как видно из сказанного, програм- мирование устройства требует некото- рого навыка и учета аппаратных осо- бенностей. Например, пользователям языка программирования С++ (и ана- логичных) придется забыть о функции «delay()» и пользоваться некими экви- валентами (см. функцию «delay1()» из примера, приведенного далее). Предвижу возмущение опытных программистов, но, поверьте мне, таки- ми же методами пользовались и разра- ботчики библиотек, поставляемых вместе с ADAM-5510. К сожалению, объем данной статьи не позволяет по- говорить о библиотеках более подроб- но. Скажу только одно. Библиотеки хо- рошо документированы и поставляют- ся вместе с исходными текстами. Поль- зователю, желающему быстро напи- сать работоспособную программу, они, безусловно, окажут хорошую помощь, а опытному программисту они доста- вят немало веселых минут (особенно в части функций, работающих с модуля- ми аналогового ввода). Надеюсь, что модификация вами библиотечных функций не станет для вас самоцелью, а лишь поможет получше узнать специ- фику оборудования. Иногда полезно помнить, что несколько миллисекунд процессорного времени несоизмери- мо в денежном отношении с несколь- кими рабочими днями квалифициро- ванного программиста. Здесь я позволю себе привести при- мер законченной программы, превра- щающей ADAM-5510 в отказоустойчи- вый будильник (пример 1). Здесь иллю- стрируются способы работы с систем- ным таймером, таймером-сторожем, консолью и устройствами ввода-выво- да (в данном случае — модулем релей- ного вывода ADAM-5060). К числу курьезных несоответствий документации на библиотеки стоит от- нести тот факт, что функция считыва- ния сетевого адреса, устанавливаемого внешними переключателями, возвра- щает результат в инверсном коде. Но не стоит судить строго подобные огрехи в бесплатном (!) и хорошо доку- ментированном программном обеспе- чении. Главное все-таки в ADAM-5510 — это то, что сама аппаратура получилась довольно надежной, сбалансирован- ной и открытой для пользователя. Про- изводительность процессора и ско- рость локальной шины, к которой под- ключены модули, позволяет опытному пользователю решать на нем такие за- дачи, о которых нельзя было и мечтать, работая с системами ADAM предыду- щих поколений. Например, классическая тестовая за- дача опроса 64 цифровых каналов вво- да на предмет подсчета поступающих импульсов (с определением фронта, защитой от дребезга, накоплением по- лученных значений в 32-разрядных пе- ременных и с обслуживанием сторо- жевого таймера), написанная на ТС++ v.3.0 с использованием поставляемых библиотек, заняла около 10 кбайт кода и позволила делать около 1700 циклов в секунду. Но что делать, если пользователь не хочет знать ничего из описанного и тем более из неописанного? Если вид программы, написанной на Си, вызы- вает у него сожаление о бесцельно про- житых годах, а перспектива копаться в чужих исходных текстах – активное нежелание бесцельно потратить время и деньги на зарплату программистам? 9 2/98 ОБЗОР АППАРАТНЫЕ СРЕДСТВА Таблица 1. Доступные прерывания Источник прерывания Адрес вектора Немаскируемое прерывание (NMI) 02h Прерывание от COM1 0Ch Прерывание от COM2 0Eh Таблица 2. Карта памяти ADAM-5510 0xF8000 — 0xFFFFF Отладочный монитор 0xF6C00 — 0xF7FFF Мини-BIOS 0xCC000 Начальный адрес флэш-диска (около 171 K) 0xC0000 Начальный адрес ROM-DOS (около 48 K) 0x40000 — 0xBFFFF Не используется 0x00400 — 0x3FFFF ОЗУ, доступное для программ 0x00000 — 0x003FF Системная область 0x003F8 — 0x003FF COM1 0x002F8 — 0x002FF COM2 0x00070 — 0x00071 Часы реального времени #include <time.h> #include <adam5510.h> #define FALSE 0 #define TRUE 1 #define ESC 27 void delay1(void); void main(void) { int key; struct dostime_t t; wdt_enable(); // Инициализация сторожевого // таймера led_init(); // Инициализация порта, уп // равляющего светодиодами if (!io_init()) // Инициализация устройств // вводавывода { printf(«Устройства вводавывода не обнаруже ны\n»); // Вывод на консоль exit(0); } while (TRUE) { if (kbhit()) if ((key = getch()) == ESC) break; wdt_clear(); // Сброс таймерасторожа _dos_gettime(&t); // Считывание показаний сис // темного таймера printf(«@$Текущее время:%2d:%02d:%02d.%02d\n», t.hour, t.minute, t.second, t.hsecond); if (t.hour==8) { if (t.minute==30) io_set_do(0,0x00f); // Если 8:30 – включение // «будильника» if (t.minute==31) io_set_do(0,0x0000); // Если уже 8:31 выключение } // Далее следует бессмыслен // ное мигание светодиодами… led1(1); led2(0); led3(0); led4(0); delay1(); led1(0); led2(1); led3(0); led4(0); delay1(); led1(0); led2(0); led3(1); led4(0); delay1(); led1(0); led2(0); led3(0); led4(1); delay1(); } } void delay1(void) // А это, извините, задержка… { int i,j; for (i=0;i<500;i++) for (j=0;j<200;j++); } Пример 1
Made with FlippingBook
RkJQdWJsaXNoZXIy MTQ4NjUy