04_Использование_языков_высокого_уровня_Информ_материал_СПО_ч4 (1268620), страница 5
Текст из файла (страница 5)
Модели памятиМодель памяти определяет, какой по умолчанию тип памяти используется дляаргументов функций, автоматических переменных и декларации без явного указанияспецификатора типа памяти. Поддерживаются три модели памяти: SMALL (малая),COMPACT (компактная) и LARGE (большая).Исключая очень специально выбранные приложения, всегда используйте модель памятиSMALL, устанавливаемую по умолчанию.
В этом случае генерируется самый быстрый исамый эффективный код. Явным объявлением переменной со спецификатором типапамяти можно перекрыть тип памяти по умолчанию, навязываемую моделью памяти.Модель памяти SmallВ этой модели памяти все переменные по умолчанию размещаются во внутреннем ОЗУмикроконтроллеров семейства 8051. Данная модель обеспечивает очень эффективныйдоступ к переменным.Модель памяти CompactПри использовании компактной модели все переменные по умолчанию размещаются водной странице внешнего ОЗУ (это соответствует явному объявлению спецификаторатипа памяти PDATA). Эта модель может поместить максимум 256 байтов переменных.Ограничение объясняется используемым способом адресации, который являетсякосвенным через регистры R0 и R1.
Эта модель памяти не так эффективна как малаямодель, поэтому доступ к переменным не так быстр. Однако компактная модель болеебыстрая, чем большая модель.Модель памяти LargeВ большой модели все переменные по умолчанию размещаются во внешней памятиданных (до 64 кВ). Регистр DPTR используется для адресации. Доступ к памяти черезэтот регистр неэффективен, особенно для переменных с длиной 2 и более байтов. Этоттип механизма доступа к данным генерирует больший код, чем малая или компактнаямодель.Явно декларируемые типы памятиКаждой переменной может быть явно назначено специфицируемое пространство памятипо схеме:тип_данных тип_памяти имя_переменной [= значение];где тип_памяти = {code, data, idata, bdata, xdata, pdata}.Аргументы функций и автоматические переменные, которые не могут быть размещены врегистрах, т а к ж е хранятся в области памяти по умолчанию.
Тип памяти по умолчаниюопределяется управляющими директивами компилятора: SMALL, COMPACT и LARGE.Примеры:u8 data v1; // здесь data можно не писать, т.к. по умолчанию для// класса памяти small все переменные содержатся в// области datauintS_t data v1;uint8_t code mes[] = “Это пример";float xdata buff [100]; // 400 байтfloat idata x, y, z;uint8_t bdata flags; // переменная как байтовая или по отдельным//битам4.3.2. Новые типы данныхБитовый типЯзык Сх51 предоставляет тип данных bit, который может использоваться для декларациипеременных, списков аргументов и значений, возвращаемых функциями.
Переменныетипа bit декларируются также, как и другие типы данных Си, например:static bit flag = 0;bit func (bit fg){…….return (0);}Тип bit допускает только прямую адресацию, поэтому указателей на биты не может быть,соответственно, и битовых массивов не может существовать.Бит-адресуемые объектыБит-адресуемые объекты — это объекты, которые могут быть адресованы как байты иликак биты. В эту категорию попадают только объекты данных, которые занимают битадресуемое пространство внутренней памяти микроконтроллеров семейства 8051.Компилятор Сх51 помещает переменные, декларированные с типом памяти BDATA в этубит-адресуемую область. Например:int bdata ibase;char bdata a[4];Индивидуальные биты этих переменных могут быть прямо доступны и модифицированы.Для этого используйте ключевое слово sbit, чтобы декларировать новые переменные длядоступа к битам переменных, декларированных с BDATA.
Например:sbit bit0 = ibase^0; // где 0 — номер битаsbit bit15 = ibase^15;sbit a_bit0 = a[0]^0;sbit a_bit3_7 = a[3]^7;bit15 = 1; bit15 = 0;Представленные выше примеры представляют декларации, а не присваивание битампеременных ibase и а.Регистры специальных функцийЭти регистры используются для управления различными периферийными устройствамимикроконтроллеров. РСФ могут быть доступны как биты, байты и слова.В разных типах микроконтроллеров семейства 8051 число РСФ варьируется. Заметим, чтоимена РСФ в компиляторе Сх51 не определены.
Однако декларации для РСФпоставляются во включаемых файлах. Каждый файл содержит декларации для РСФ,соответствующих данной производной семейства микроконтроллеров 8051. КомпиляторСх51 обеспечивает доступ к РСФ с помощью типов данных: sfr, sfr16 и sbit.SFRРСФ декларируются таким же образом как другие переменные. Единственное отличие –тип данных специфицируется как sfr. Например:sfr Р0 = 0x80; // порт 0, адрес 80Нsfr РЗ = 0хВ0; // порт 3, адрес 0В0НЗдесь Р0-Р3 — декларированные имена РСФ. Любое имя может быть использовано в srfдекларации. Спецификация адреса после знака равенства должна быть числовойконстантой (выражение с операторами не допускается). Диапазон константы долженсоответствовать диапазону адресов РСФ (0x80 - 0xff).SFR16Многие новые производные микроконтроллеров семейства 8051 используют два РСФ споследовательными адресами для специфицирования 16-битовых значений.
Например,микроконтроллеры 8052 использует адреса 0хСС и 0xCD для младшего и старшегобайтов таймера-счетчика 2 (ТС2). Компилятор Сх51 предоставляет тип данных sfr16 длядоступа к двум РСФ как к одному 16-битовому РСФ. Доступ к 16-разрядному РСФвозможен только когда младший байт непосредственно предшествует старшему байту.Младший байт используется как адрес в декларациях sfr16. Например:sfr16 Т2 = 0хСС; // таймер 2: T2L = 0CCh, Т2Н = 0CDhДекларации sfr16 подчиняются тем же самым правилам, как и sfr-декларации.SBITЧасто в приложениях необходим доступ к индивидуальным битам бит-адресуемых РСФ.Компилятор Сх51 делает это возможным с помощью типа данных sbit. Любое имя можетбыть использовано в декларации sbit.
Выражение справа от знака равенства указываетабсолютный адрес бита для соответствующего имени. Имеются три варианта заданияадреса:sfr nsme^int const// определение бита регистра,//где nsme — имя регистра,//const — целочисленная константаsbit EA = IE^7;int constant constsbit EA= 0хА8^7;int constsbit EA = 0xAF;Размещение переменных по абсолютному адресуПеременные могут быть локализованы на абсолютные ячейки памяти, используяключевое слово _at_.тип [тип_памяти] имя_переменной _at_ константа;тип_памяти — тип памяти для переменной; если отсутствует в декларации, тоустанавливается по умолчанию; константа — адрес локализации переменной.Примеры:float х _at_ 50;int xdata a[200] _at_ 500;Абсолютный адрес, следующий за _at_ , должен удовлетворять физическим границампространства памяти для переменной.
Компилятор Сх51 проверяет недопустимый адрес.Следующие ограничения применимы к абсолютной локализации переменной:1) абсолютные переменные не могут быть инициализированы при описании;2) функции и переменные типа bit не могут размещаться по абсолютному адресу.УказателиОбобщенные или универсальные указатели (generic pointers) декларируются таким жеобразом, как стандартные указатели Си.
Эти указатели всегда хранятся в трех байтах:первый байт – тип памяти, второй – старший байт смещения и третий – младший байтсмещения. Обобщенные указатели могут быть использованы для доступа к любойпеременной, независимо от ее расположения в памяти. Однако код, генерируемый дляработы с обобщенными указателями, более громоздкий и менее быстрый, чем код,генерируемый для указателей, специфичных для конкретного типа памяти (memoryspecific pointers).
Если эффективность генерируемого компилятором кода важна, торекомендуется использовать типизированные указатели. Типизированные указателивсегда включают тип памяти в свою декларацию. Например:char data *str; // указатель на переменную типа char,// которая находится в dataПоскольку тип памяти известен во время компиляции, то в этом случае не нужен байт дляхранения кода типа памяти.
Типизированные указатели хранятся в одном байте (idata,data, bdata, pdata-указатели) или в двух байтах (code- и xdata-указатели).Кроме того можно указать тип памяти, где хранится сам типизированный указатель:char data *xdata str; // сам указатель будет храниться в//xdataОбъявления функцийКомпилятор Сх51 предоставляет ряд расширений для декларации стандартных Сифункций: специфицирование функции как процедуры обработки прерывания; выбор используемого банка регистров; выбор модели памяти; спецификация реентерабельности.Используется следующий стандартный формат декларации функции:возвращаемый_тип имя_функции([список формальных параметров])[{small | compact | large}][reentrant][interrupt n][using k]reentrant — указывает, что функция рекурсивная или реентерабельная; interrupt —указывает, что функция — обработчик прерывания; using — специфицируетиспользуемый функцией банк регистров.Пример:uintS_t sec;void ISR_TC0(void) interrupt 1 using 2{static uint16_t i= 0if (++i == 4000) { sec++; i = 0;}}Встроенные функцииКомпилятор Сх51 поддерживает ряд встроенных библиотечных функций (intrinsicfunction).
Невстроенные функции генерируют инструкции ACALL или LCALL, чтобыисполнить библиотечную подпрограмму. Встроенные функции генерируют машинный(in-line – линейный) код, чтобы исполнить библиотечную подпрограмму. Прикомпиляции вызов такой функции заменяется ее кодом. Генерируемый линейный кодмного быстрее и более эффективнее, чем вызов подпрограммы. Следующие функцииимеются во встроенной форме:Таблица 4.6. Встроенные функцииЦиклические сдвиги_crol__irol__lrol__cror__iror__lror_Команда NOPТестирование бита и его сброс_nop__testbit_Прототипы этих функций содержит заголовочный файл <intrins.h>.
Пример описанияфункции _nop_ в этом файле: void _nop_(void);4.4. Рекомендации по оформлению исходного текста программ4.4.1. КомментарииХорошее правило — это включать комментарии в процессе написания программы,именно в это время наиболее хорошо вникать в работу программы. Существует три типакомментариев: оглавление, вводные, пояснительные.Если программа большая по объему текста кода, то целесообразно в ее начале (главномфайле) помещать оглавление в виде комментариев.