Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Разработка ПО на языке Си для микроконтроллера AT91SAM7S.pdf
Скачиваний:
120
Добавлен:
18.05.2014
Размер:
838.69 Кб
Скачать

5Структуры

Структуры являются механизмом, позволяющим формировать новые типы

данных из имеющихся. Структуры используются при необходимости группировки нескольких переменных для работы с ними как с единой переменной. Объявление структур производится с использованием ключевого слова struct, обычно его совмещают с объявлением нового типа, используя также ключевое слово typedef.

typedef-выражение не создаёт новый тип, а создаёт для имеющегося типа дополнительное имя. После слова typedef указывается существующий тип, а за ним новое имя для данного типа. typedef можно применять не только для объявления структур, но также для других типов, в том числе для указателей.

После объявления типа структуры его можно использовать для создания переменных этого типа (объектов структуры), массивов, а также указателей. Обращение к элементам структуры производится с использованием операторов доступа к членам структуры: «.» (точка) для обычных переменных и «->» для указателей. Пример использования структур см. в листинге 11.

Листинг 11. Пример использования структур.

// Объявление нового типа - структуры Result typedef struct

{

// Члены структуры unsigned char channel; float value;

} Result;

// Объявление нового имени для указателя на структуру typedef Result* ResultPtr;

int main (void)

{

//Создание переменной типа Result Result res;

//Обращение к переменным внутри структуры res.channel = 0;

res.value = 2.5;

//Создание массива элементов типа Result Result resultArray[10];

22

//Обращение к переменным внутри структуры resultArray[2].channel = 5;

(*(resultArray + 2)).value = 3.9;

//Указатель на структуру

ResultPtr pointerToResult = &res;

// Обращение к членам структуры через указатель pointerToResult->channel = 1; // Было 0, станет 1 pointerToResult->value = 3.5; // Было 2.5, станет 3.5

}

5.1Работа с регистрами ввода-вывода через структуры данных

Вмикропроцессорной архитектуре ARM7 отсутствует отдельное адресное пространство для регистров ввода-вывода, через которые можно было бы взаимодействовать с периферийным оборудованием. Вместо этого регистры ввода-вывода отображаются в определённых областях единого адресного пространства (для AT91SAM7 – в верхних адресах памяти). Это означает, что программное чтение соответствующих ячеек памяти приводит к выполнению операции ввода, а запись – к операции вывода. Такой подход называется «Memory-Mapped I/O» (ввод-вывод, отражённый в память).

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

Для групп регистров, близких по назначению, в системных заголовочных файлах (о заголовочных файлах см. в п. 12.1.2), поставляемых производителем микроконтроллеров, определены такие структуры и созданы указатели на эти структуры, инициализированные адресом, начиная с которого в памяти располагаются регистры периферийных устройств4.

Это позволяет работать с регистрами ввода-вывода как с именованными

3Переменные, составляющие структуру всегда располагаются в порядке объявления. Однако, в общем случае в зависимости от конкретных типов этих переменных, версии и настроек компилятора, элементы могут выравниваться в памяти, так что между ними будут промежутки размером до нескольких байт. Поэтому для произвольной структуры предугадать смещение каждого элемента относительно начала структуры сложно.

4Все регистры периферийных устройств являются 32-разрядными, поэтому элементы структур имеют тип unsigned int, и на 32х-разрядной архитектуре выравниваются естественным образом без образования промежутков.

23

элементами структур, что делает исходный код более понятным за счёт использования символических имён регистров, исключает необходимость указания адреса конкретного регистра. Присвоение нового значения переменной-члену структуры приводит к записи этого значения в регистр (операция вывода), а использование значения этой переменной – к чтению из регистра (операция ввода). Пример приведён в листинге 12.

Листинг 12. Использование структур для работы с регистрами ввода-вывода.

//Подключение (встраивание) заголовочного файла с описанием структур и

//необходимых типов данных.

#include "Board.h"

//Указатель на структуру, предназначенную для управления контроллером

//параллельного ввода-вывода (PIO)

static AT91PS_PIO pioa = AT91C_BASE_PIOA;

void setUp (void)

{

//Указываем, что ножками, к которым подключены светодиоды

//управляет PIO, а не встроенная периферия (операция вывода). pioa->PIO_PER = 0x00060000; // PIO Enable Register

//Настройка ножек как выходов (операция вывода).

pioa->PIO_OER = 0x00060000; // PIO Output Enable Register

// Прочитать состояния ножек (ввод)

unsigned int pinStatus = pioa->PIO_PDSR; //Pin Data Status Register

...

}

При работе с регистрами ввода-вывода следует помнить, что не все регистры поддерживают ввод и вывод. Некоторые из них рассчитаны только на ввод (т. е. чтение из регистра), а некоторые – только на вывод (запись в регистр).

24