Скачать 1.44 Mb.
|
3.3.6. Использование прерываний в программе на языке С Пример программы на языке С для процессорной системы «DЕ2-70 Media Computer», в которой используются прерывания, приведен в листинге 11. Эта программа выполняет точно такие же действия, что и программа, описанная в предыдущем разделе. Для разрешения прерываний процессорной системы в программе в листинге 11 используется макрос, который обеспечивает доступ к регистрам состояния и регистрам управления процессора Nios II. Набор таких макросов, которые могут быть использованы в любой программе на С, приведен в листинге 12. Обработчики сброса и исключений для основной программы, представленной в листинге 11, приведены в листинге 13. Первая функция называется the_reset. Она обеспечивает простой механизм сброса посредством выполнения перехода к основной программе. Функция the_exception представляет обработчик общих исключений, который может быть использован в любой программе. Он включает код на языке ассемблер для того, чтобы проверить, является ли прерывание внешним, и если да, то вызывает программу, названную interrupt_hundler. Эта программа затем может выполнить какие-либо действия, необходимые для некоторого приложения. Фрагмент кода в листинге 13 interrupt_hundler во-первых определяет какое прерывание произошло, посредством использования макроса из листинга 12, который читает содержимое регистра произошедших прерываний. Программа обслуживания прерываний, которая вызывается интервальным таймером, приведена в листинге 14 и программа обслуживания прерываний от кнопок приведена в листинге 15. Файлы с исходными кодами рассмотренных программ распространяются как часть AMP. Они могут быть найдены в разделе «Sample programs» под именем Interrupt Example. Листинг 11. Пример программы на С, в которой используются прерывания #include "nios2_ctrl_reg_macros.h" #include "key_codes.h" volatile int key_pressed = KEY2; volatile int pattern = 0x0000000F; /***************************************************************************** * Эта программа демонстрирует использование прерываний на стенде * DE2-70 Media Computer. Вначале запускается таймер, который генерирует * прерывания каждые 33 мс. Затем разрешаются прерывания от таймера и кнопок. * Процедура обработки прерывания таймера отображает текст на 7-сегментных * индикаторах и сдвигает его влево или вправо. Направление сдвига определяется * кнопками. При нажатии кнопки key1 текст сдвигается вправо, при нажатии * key2 – влево, при нажатии key3 изменяется текст, используя данные с переключателей. *****************************************************************************/ int main(void) { volatile int * interval_timer_ptr = (int *) 0x10002000; //базовый адрес интервального таймера volatile int * KEY_ptr = (int *) 0x10000050; //базовый адрес кнопок /* устанавливаем период срабатывания интервального таймера */ int counter = 0x190000; // 1/(50 MHz) x (0x190000) = 33 msec *(interval_timer_ptr + 0x2) = (counter & 0xFFFF); *(interval_timer_ptr + 0x3) = (counter >> 16) & 0xFFFF; /* запускаем таймер и разрешаем формирование прерываний от него */ *(interval_timer_ptr + 1) = 0x7; // STOP = 0, START = 1, CONT = 1, ITO = 1 *(KEY_ptr + 2) = 0xE; //разрешаем формирование прерываний от трех кнопок NIOS2_WRITE_IENABLE( 0x3 ); //разрешаем прерывания Nios II процессора от кнопок и таймера NIOS2_WRITE_STATUS( 1 ); //разрешаем прерывания Nios II процессора while(1); //бесконечный цикл } Листинг 12. Макросы для доступа к регистрам состояния и управления Nios II #ifndef __NIOS2_CTRL_REG_MACROS__ #define __NIOS2_CTRL_REG_MACROS__ /*****************************************************************************/ /* Макросы для доступа к управляющим регистрам */ /*****************************************************************************/ #define NIOS2_READ_STATUS(dest) \ do { dest = __builtin_rdctl(0); } while (0) #define NIOS2_WRITE_STATUS(src) \ do { __builtin_wrctl(0, src); } while (0) #define NIOS2_READ_ESTATUS(dest) \ do { dest = __builtin_rdctl(1); } while (0) #define NIOS2_READ_BSTATUS(dest) \ do { dest = __builtin_rdctl(2); } while (0) #define NIOS2_READ_IENABLE(dest) \ do { dest = __builtin_rdctl(3); } while (0) #define NIOS2_WRITE_IENABLE(src) \ do { __builtin_wrctl(3, src); } while (0) #define NIOS2_READ_IPENDING(dest) \ do { dest = __builtin_rdctl(4); } while (0) #define NIOS2_READ_CPUID(dest) \ do { dest = __builtin_rdctl(5); } while (0) #endif Листинг 13. Обработчики сброса и исключений на С #include "nios2_ctrl_reg_macros.h" void main(void); void interrupt_handler(void); void interval_timer_isr(void); void pushbutton_ISR(void); /* глобальные переменные */ extern int key_pressed; /* Код на языке ассемблер, выполняющийся при сбросе процессора */ void the_reset (void) __attribute__ ((section (".reset"))); void the_reset (void) /************************************************************************************ * Обработчик сброса ***********************************************************************************/ { asm (".set noat"); asm (".set nobreak"); asm ("movia r2, main"); //вызывается основная программа на С asm ("jmp r2"); } /* Код на языке ассемблер, выполняющийся при возникновении прерывания или исключения*/ void the_exception (void) __attribute__ ((section (".exceptions"))); void the_exception (void) /******************************************************************************* * Обработчик исключений ******************************************************************************/ { asm ( ".set noat" ); asm ( ".set nobreak" ); asm ( "subi sp, sp, 128" ); asm ( "stw et, 96(sp)" ); asm ( "rdctl et, ctl4" ); asm ( "beq et, r0, SKIP_EA_DEC" ); //прерывания не внешние asm ( "subi ea, ea, 4" ); //декрементируем регистр ea на 1 команду asm ( "SKIP_EA_DEC:" ); asm ( "stw r1, 4(sp)" ); //сохраняем содержимое всех регистров в стеке asm ( "stw r2, 8(sp)" ); asm ( "stw r3, 12(sp)" ); asm ( "stw r4, 16(sp)" ); asm ( "stw r5, 20(sp)" ); asm ( "stw r6, 24(sp)" ); asm ( "stw r7, 28(sp)" ); asm ( "stw r8, 32(sp)" ); asm ( "stw r9, 36(sp)" ); asm ( "stw r10, 40(sp)" ); asm ( "stw r11, 44(sp)" ); asm ( "stw r12, 48(sp)" ); asm ( "stw r13, 52(sp)" ); asm ( "stw r14, 56(sp)" ); asm ( "stw r15, 60(sp)" ); asm ( "stw r16, 64(sp)" ); asm ( "stw r17, 68(sp)" ); asm ( "stw r18, 72(sp)" ); asm ( "stw r19, 76(sp)" ); asm ( "stw r20, 80(sp)" ); asm ( "stw r21, 84(sp)" ); asm ( "stw r22, 88(sp)" ); asm ( "stw r23, 92(sp)" ); asm ( "stw r25, 100(sp)" ); // r25 = bt asm ( "stw r26, 104(sp)" ); // r26 = gp asm ( "stw r28, 112(sp)" ); // r28 = fp asm ( "stw r29, 116(sp)" ); // r29 = ea asm ( "stw r30, 120(sp)" ); // r30 = ba asm ( "stw r31, 124(sp)" ); // r31 = ra asm ( "addi fp, sp, 128" ); asm ( "call interrupt_handler" ); //вызываем процедуру обработки прерывания asm ( "ldw r1, 4(sp)" ); //восстанавливаем содержимое всех регистров asm ( "ldw r2, 8(sp)" ); asm ( "ldw r3, 12(sp)" ); asm ( "ldw r4, 16(sp)" ); asm ( "ldw r5, 20(sp)" ); asm ( "ldw r6, 24(sp)" ); asm ( "ldw r7, 28(sp)" ); asm ( "ldw r8, 32(sp)" ); asm ( "ldw r9, 36(sp)" ); asm ( "ldw r10, 40(sp)" ); asm ( "ldw r11, 44(sp)" ); asm ( "ldw r12, 48(sp)" ); asm ( "ldw r13, 52(sp)" ); asm ( "ldw r14, 56(sp)" ); asm ( "ldw r15, 60(sp)" ); asm ( "ldw r16, 64(sp)" ); asm ( "ldw r17, 68(sp)" ); asm ( "ldw r18, 72(sp)" ); asm ( "ldw r19, 76(sp)" ); asm ( "ldw r20, 80(sp)" ); asm ( "ldw r21, 84(sp)" ); asm ( "ldw r22, 88(sp)" ); asm ( "ldw r23, 92(sp)" ); asm ( "ldw r24, 96(sp)" ); asm ( "ldw r25, 100(sp)" ); // r25 = bt asm ( "ldw r26, 104(sp)" ); // r26 = gp asm ( "ldw r28, 112(sp)" ); // r28 = fp asm ( "ldw r29, 116(sp)" ); // r29 = ea asm ( "ldw r30, 120(sp)" ); // r30 = ba asm ( "ldw r31, 124(sp)" ); // r31 = ra asm ( "addi sp, sp, 128" ); //увеличиваем адрес указателя стека asm ( "eret" ); //выходим из обработчика прерывания } /***************************************************************************** *Процедура обработки прерываний *****************************************************************************/ void interrupt_handler(void) { int ipending; NIOS2_READ_IPENDING(ipending); //читаем содержимое бита ipending if ( ipending & 0x1 ) //если было обнаружено прерывание от таймера { interval_timer_isr( ); //вызываем процедуру обработки прерываний от таймера } if ( ipending & 0x2 ) // если было обнаружено прерывание от кнопок { pushbutton_ISR( ); //вызываем процедуру обработки прерываний от кнопок } return; } Листинг 14. Программа обслуживания прерываний от интервального таймера #include "key_codes.h" extern volatile int key_pressed; extern volatile int pattern; /***************************************************************************** * Процедура обработки прерываний от интервального таймера ******************************************************************************/ void interval_timer_isr( ) { volatile int * interval_timer_ptr = (int *) 0x10002000; //базовый адрес таймера volatile int * HEX3_HEX0_ptr = (int *) 0x10000020; //адрес HEX3_HEX0 volatile int * HEX7_HEX4_ptr = (int *) 0x10000030; //адрес HEX7_HEX4 *(interval_timer_ptr) = 0; //Сбрасываем прерывания *(HEX3_HEX0_ptr) = pattern; // вывод заготовки на HEX3_HEX0 *(HEX7_HEX4_ptr) = pattern; // вывод заготовки на HEX7_HEX4 /* сдвигаем текст на 7-сегментных индикаторах */ if (key_pressed == KEY2) //если была нажата кнопка KEY2, то сдвигаем текст влево if (pattern & 0x80000000) pattern = (pattern << 1) | 1; else pattern = pattern << 1; else if (key_pressed == KEY1) //если была нажата кнопка KEY1, то сдвигаем текст вправо if (pattern & 0x00000001) pattern = (pattern >> 1) | 0x80000000; else pattern = (pattern >> 1) & 0x7FFFFFFF; return; } Листинг 15. Программа обслуживания прерываний от кнопок #include "key_codes.h" extern volatile int key_pressed; extern volatile int pattern; /***************************************************************************** Процедура обработки прерываний от кнопок ******************************************************************************/ void pushbutton_ISR( void ) { volatile int * KEY_ptr = (int *) 0x10000050; //базовый адрес кнопок volatile int * slider_switch_ptr = (int *) 0x10000040; //базовый адрес переключателей int press; press = *(KEY_ptr + 3); // Читаем содержимое регистра edge-capture *(KEY_ptr + 3) = 0; // Сбрасываем регистр edge-capture if (press & 0x2) //если была нажата кнопка KEY1 key_pressed = KEY1; else if (press & 0x4) //если была нажата кнопка KEY2 key_pressed = KEY2; else //если была нажата кнопка KEY3 pattern = *(slider_switch_ptr); //определяем какие переключатели //установлены в верхнее положение return; } 3.4. Мультимедийные компоненты процессорной системы Этот раздел описывает аудиопорт, видеопорт, аудио/видео конфигурационный модуль, LCD дисплей 16*2, и PS/2 порт. 3.4.1. Аудиопорт Процессорная система «DЕ2-70 Media Computer» включает аудиопорт, который соединён с микросхемой аудиокодека (Coder/Decoder) на плате DE2-70. По умолчанию аудиокодек настроен на скорость оцифровки 48К образцов в секунду. Аудиопорт обеспечивает возможность ввода аудиоинформации через разъём микрофона на стенде DE2-70 и возможность вывода аудиоинформации через выходной разъём. Аудиопорт включает 4 буфера FIFO, которые используются для хранения вводимых и выводимых данных. Вводимые данные сохраняются в левом и правом каналах читаемых буферов FIFO, а выводимые данные хранятся в левом и правом каналах записываемых буферов FIFO. Все буферы FIFO имеют максимальную глубину 128 32-битных слов. Программируемый интерфейс аудиопорта состоит из четырех 32-битных регистров, как показано на рис. 3.16. Регистр управления имеет адрес 0x10003040. Для получения информации о состоянии аудиопорта его необходимо прочитать, а для того, чтобы выполнить управляющие установки - записать. Бит RE этого регистра обеспечивает возможность прерывания процессорной системы для ввода данных. Установка этого бита в 1 позволит контроллеру аудиопорта сформировать прерывание процессора, когда читаемый буфер FIFO заполнится на 75% или более. Причем бит RI в этом случае установится в единицу, чтобы указать, что прерывание произошло. Сигнал прерывания снимется после извлечения данных из читаемых буферов FIFO до тех пор, пока их заполнение станет менее 75% процентов. Бит WE реализует возможность прерывания процессорной системы при выводе данных. Установка этого бита в 1 позволит аудио контроллеру сформировать сигнал прерывания, когда в записываемых буферах FIFO останется менее 25% свободного места. При этом бит WI установится в 1, чтобы указать, что прерывание произошло. Потом он может быть очищен путём освобождения записываемых буферов более, чем на 25%. Биты CR и СW, показанные на рис. 3.16, предназначены для очистки буферов записи и чтения, соответственно. Функция очистки активируется посредством установки бит CR и СW в единицу. Функция остаётся активной до тех пор, пока соответствующие биты не будут сброшены в 0. Рис. 3.16 – Регистры аудиопорта Доступный по чтению регистр Fifospace показан на рис. 3.16. Он содержит четыре 8 - битных поля. Поля RARC и RALC отображают число слов, хранимых в настоящий момент времени в правом и левом входных буферах FIFO, соответственно. Поля WSRC и WSLC показывают число слов, доступных для заполнения в текущий момент времени, в правом и левом выходных буферах FIFO. После очистки всех буферов FIFO аудиопорта, величины, содержащиеся в Fifospace, станут следующими RARC=RALC=0 и WSRC=WSLC=128. Информация из регистров Left data и Right data считывается процессором для выполнения записи аудиоинформации в буферы FIFO ввода, и записывается - для вывода аудио. Когда данные читаются из этих регистров, то они извлекаются из вершины читаемых буферов FIFO, и когда данные записываются в эти регистры, они загружаются в записываемые буфера FIFO. Фрагмент кода на языке С, который использует аудиопорт, показан в листинге 16. Код проверяет, когда глубина правого или левого порта FIFO превысит 75% полноты и передаёт данные из этих FIFO в буферную память. Этот код входит в состав приложения AMP в раздел «Sample programs» под именем «Media». Листинг 16. Пример кода, который использует аудиопорт volatile int * audio_ptr = (int *) 0x10003040; //адрес аудиопорта /* Используется для аудио записи/воспроизведения */ int fifospace, leftdata, rightdata; int record = 0, play = 0, buffer_index = 0; int left_buffer[BUF_SIZE]; int right_buffer[BUF_SIZE]; … fifospace = *(audio_ptr + 1); // читаем fifospace регистр if ( (fifospace & 0x000000FF) > 96 ) // проверяем значение поля RARC { // Сохраняем данные из аудио буферов while ( (fifospace & 0x000000FF) && (buffer_index < BUF_SIZE) ) { left_buffer[buffer_index] = *(audio_ptr + 2); //сохраняем аудиоданные right_buffer[buffer_index] = *(audio_ptr + 3); ++buffer_index; fifospace = *(audio_ptr + 1); // читаем fifospace регистр } } … 3.4.2. Порт вывода видеоданных Процессорная система «DЕ2-70 Media Computer» включает порт вывода видеоинформации с соответствующим VGA-контроллером, который может быть соединён со стандартным VGA-монитором. VGA- контроллер поддерживает разрешение 640*480. Картинка, которая отображается VGA контроллером, получается из двух источников, графического буфера и символьного буфера. 3.4.2.1. Графический видеобуфер Графический видеобуфер содержит значения величин цвета пикселей изображения для отображения VGA контроллером на мониторе. Как показано на рис. 3.17, видеобуфер обеспечивает разрешение 320*240 пикселей. Каждый пиксель имеет координаты Х и У. Причем, координата (0,0) соответствует левому верхнему углу изображения. Так как VGA контроллер поддерживает разрешение экрана 640*480, каждый пиксель из видеобуфера дублируется в двух направлениях, когда эти пиксели отображаются на VGA мониторе. Рис. 3.17 – Координаты графического буфера Рис. 3.18 показывает формат задания цвета пикселей. Так, цвет каждого пикселя задается 16 – битным полусловом с 5 битами для задания голубого и красных компонентов и 6 битами для зелёного цвета. Рис. 3.18 – Кодирование пикселей Как показано на рис. 3.19, пиксели адресуются в памяти посредством использования комбинации базового адреса и смещения X,Y. Рис. 3.19 – Адресация в графическом буфере В процессорной системе «DE2-70 Media Computer» базовый адрес 0х08000000 графического буфера соответствует начальному адресу статической памяти, установленной на плате. В соответствии с этой схемой, пиксель с координатами (0,0) имеет адрес 0х08000000, пиксель (1,0) имеет адрес базовый +00000000_00000001_0=0х08000002, пиксель (0,1) имеет адрес базовый + 00000001_000000000_0=0х08000400 и пиксель с координатами (319,239) имеет адрес базовый + 11101111_100111111_0= 0х0803BE7E. Графический буфер включает программный интерфейс в форме набора регистров. Эти регистры представлены на рис 3.20. Рис. 3.20 – Регистры видеопорта Регистр с именем Buffer доступен только для чтения. Он содержит базовый адрес первого пикселя видеокадра, отображаемого в текущий момент времени. Регистр BackBuffer позволяет менять начальный адрес отображаемого кадра под программным управлением. Он доступен для записи и чтения. Чтобы изменить отображаемый на экране кадр, вначале необходимо записать его адрес в BackBuffer. Затем выполнить операцию записи в регистр Buffer. Записываемое значение не используется контроллером. Вместо этого контроллер интерпретирует операцию записи в регистр Buffer как требование поменять содержимое регистров Buffer и BackBuffer. Переключение не выполняется немедленно. Переключение будет выполнено после того, как контроллер DMA выполнит вывод последнего пикселя текущего кадра. Пока контроллер не сделает этого, бит S в регистре Status будет установлен в единицу, и лишь после завершения вывода текущего кадра произойдет переключение кадров и бит S сбросится в ноль. Регистр Resolution является только читаемым. Он содержит в разрядах 15-0 разрешение экрана по оси Х, и в разрядах 31-16 разрешение по оси У, соответственно. Регистр Status доступен только для чтения. Он отражает информацию о состоянии контроллера DMA. Поля, содержащиеся в этом регистре, представлены на рис. 3.21. Рис. 3.21 – Поля регистра Status видеопорта 3.4.2.2. Символьный буфер Символьный буфер для порта вывода видеоданных содержится в оперативной памяти, реализованной внутри кристалла FPGA. Как показано на рис. 3.22 буфер обеспечивает разрешение 60 строк по 80 символов, где каждой строке соответствует координата У, а каждому символу в строке – координата Х. Каждый символ отображается на VGA мониторе блоком 8*8 пикселей. Этот блок называется знакоместом. Символы хранятся в каждой позиции символьного буфера, как показано на рис. 3.22. Для их представления используются ASCII коды. Рис. 3.22 – Координаты символьного буфера Рис. 3.23 – Адресация в символьном буфере Когда символы отображаются на VGA мониторе, контроллер автоматически генерирует соответствующие наборы пикселей для каждого символа, используя встроенный шрифт. Рис. 3.23 содержит схему адресации символов внутри буфера. Для адресации символов в памяти используется комбинация базового адреса и смещения по оси Х и У. Базовый адрес символьного буфера равен 0х09000000. В соответствии со схемой адресации, символ, отображаемый на экране в позиции с координатами (0,0), хранится по адресу 0х09000000, символ с координатами (1,0) хранится по адресу базовый + 000000_0000001=0х09000001. Символ с координатами (0,1) хранится по адресу базовый + 000001_0000000=0х09000080 и символ с координатами (79,59) хранится по адресу базовый + 111011_ 1001111=0х09001DCF. 3.4.2.3. Использование порта вывода видеоданных в программе на языке С Фрагмент программы на языке С, в котором используются графический и символьный буферы, показан в листинге 17. Первый цикл while изображает прямоугольник в графическом буфере, используя цвет pixel_color. Прямоугольник задается координатами двух противоположных углов (x1,y1) и (x2,y2). Второй цикл while записывает символьную строку text_ptr, с нулевым байтом в конце, в символьный буфер, начиная с координаты (x,y). Представленный в листинге 17 фрагмент программы включен в образцы программ приложения AMP под именем Media. 3.4.3. Модуль конфигурации аудио/видеопортов Модуль конфигурации аудио/видеопортов управляет установками, которые влияют на работу аудио и видеопортов. Модуль конфигурации аудио/видео автоматически конфигурирует и инициализирует эти порты, когда выполняется сброс процессорной системы. Для типового использования процессорной системы нет необходимости модифицировать эти установки. Если такая потребность всё таки появиться, то в этом случае необходимо обратиться к документации по модулю конфигурации аудио/видеопортов, доступной на сайте фирмы Altera[3] и эти установки изменить. Листинг 17. Пример программы, в котором используется выходной видеопорт void VGA_text (int, int, char *); void VGA_box (int, int, int, int, short); int main(void) { volatile int * green_LED_ptr = (int *) 0x10000010; /* Тексты для вывода на экран монитора и lcd дисплей */ char text_top_row[40] = "Altera DE2-70\0"; char text_bottom_row[40] = "Media Computer\0"; /* Выводит текстовые строки на экран монитора */ VGA_text (35, 29, text_top_row); VGA_text (35, 30, text_bottom_row); VGA_box (34*4, 28*4, 50*4, 32*4, 0x187F); } /******************************************************************************* * Вывод строки на экран монитора *******************************************************************************/ void VGA_text(int x, int y, char * text_ptr) { int offset; volatile char * character_buffer = (char *) 0x09000000; // адрес символьного буфера VGA offset = (y << 7) + x; //Вычисляем смещение в памяти while ( *(text_ptr) ) { *(character_buffer + offset) = *(text_ptr);// Записываем в символьный буфер значение ++text_ptr; ++offset; } } /******************************************************************************* * Рисование на экране монитора прямоугольника *******************************************************************************/ void VGA_box(int x1, int y1, int x2, int y2, short pixel_color) { int offset, row, col; volatile short * pixel_buffer = (short *) 0x08000000; // адрес пиксельного буфера VGA for (row = y1; row <= y2; row++) { col = x1; while (col <= x2) { offset = (row << 9) + col; //Вычисляем смещение пиксельном буфере *(pixel_buffer + offset) = pixel_color; // Устанавливаем цвет пиксела ++col; } } } 3.4.4. Порт LCD дисплея Процессорная система «DE2-70 Media Computer» включает порт, соединённый с жидкокристаллическим дисплеем LCD на плате DE2-70. Дисплей включает память для хранения символьных данных. Как показано на рис. 3.24, общая ёмкость памяти составляет 40х2=80 символов. Первые 16 символов, хранимых в каждой строке этой памяти, видимы на экране, а оставшиеся 24 символа не видимы на экране. Каждая ячейка в памяти может быть доступна с помощью координат (x,y) в семиразрядном адресе, как показано на рис. 3.25. В соответствии с этой схемой, верхняя и нижняя строки дисплея начинаются с адресов 0х00 и 0х40, соответственно, как показано на рис. 3.24. Программируемый интерфейс для LCD дисплея показан на рис. 3.26. Он включает регистр команд, который используется для управления дисплеем LCD и регистр данных, который используется для отправки символьных данных для отображения их на дисплее. Данные могут быть отправлены на дисплей, как ASCII коды, которые автоматически преобразуются дисплеем LCD в отображаемые символы, используя встроенный шрифт. Некоторые из команд, поддерживаемых символьным дисплеем, показаны в таблице 3.2. Первая команда, которая идентифицируется посредством установки бита 7 регистра управления в единицу, используется для установки курсора в заданное положение. Семиразрядное поле адреса задает координаты курсора. После того, как положение курсора будет задано, символ может быть отображен в этой позиции экрана LCD посредством записи его ASСII кода в регистр данных. Рис. 3.24 – 16х2 символьный дисплей Рис. 3.25 – Адресация символьного дисплея Рис. 3.26 – Регистры LCD дисплея После завершения операции записи данных в регистр данных, символьный дисплей автоматически перемещает положение курсора на одну позицию вправо. Последовательность символов может быть выведена на дисплей посредством записи каждого символа последовательно в регистр данных LCD. Как показано на рис. 3.24, символьный дисплей включает 40 позиций в каждой строке. Когда курсор достигнет адреса 0х0F в верхней строке, следующие 24 символа сохраняются в позициях, которые не видимы на экране. После записи 40 символов в верхнюю строку, положение курсора переместиться на нижнюю строку по адресу 0х40. После заполнения нижней строки, курсор переместиться назад по адресу 0х00 в начало верхней строки. Жидкокристаллический дисплей LCD обладает способностью сдвигать своё содержимое на одну позицию влево или вправо. Как показано в табл. 3.2 команда для сдвига влево - 0х18, а команда для сдвига вправо - 0х1С. Выполнение этих команд приведет к одновременному сдвигу двух строк на экране на одну позицию. Когда символы выдвигаются за пределы строки вправо, они циклически помещаются в её начало. Аналогично в другую сторону. Для выключения мерцания курсора на дисплее используется команда 0х0С. Для включения – команда 0х0F. Дисплей может быть очищен и курсор установлен в начало верхней строки, посредством использования команды 0х01. Фрагмент программы на языке С, в котором используется LCD дисплей, приведён в листинге 18. Программа вначале устанавливает курсор в положение (x,y), затем записывает строку, оканчивающуюся нулевым байтом, для отображения на символьном дисплее. Этот фрагмент входит в состав программы «Media», о которой упоминалось ранее. Таблица 3.2 Команды LCD дисплея
Листинг 18. Фрагмент кода, в котором используется LCD дисплей volatile char *LCD_display_ptr = (char *) 0x10003050; //базовый адрес lcd дисплея int x, y; char *text_ptr; char instruction; … instruction = x; if (y!=0) instruction |=0x40; //записываем значение позиции курсора (начало нижней строки) instruction |=0x80; //команда установки курсора *(LCD_display_ptr) = instruction; //записываем команду по адресу lcd дисплея while(*(text_ptr)) { *(LCD_display_ptr+1) = *(text_ptr); //выводим символ на дисплей ++text_ptr; } 3.4.5. Порт PS/2 Процессорная система «DE2-70 Media Computer» включает два PS/2 порта, которые могут быть соединены со стандартными клавиатурой и мышью. Каждый порт содержит 256 байтный FIFO буфер, который хранит данные, получаемые из PS/2 устройства. Программный интерфейс PS/2 порта состоит из двух регистров, как показано на рис. 3.27. Рис. 3.27 – Регистры РS/2 порта Регистр данных можно считывать и записывать. Если в считанном из регистра данных слове 15-ый бит (RVALID) равен 1, то это означает, что данные в буфере чтения FIFO присутствовали. Следовательно, они могут быть взяты из младших восьми разрядов считанного из регистра данных слова. В это же время, считанное из поля RAVAIL значение, будет отображать число оставшихся в буфере FIFO символов, с учетом только что прочитанного. Каждый раз после чтения символа из буфера FIFO, поле RAVAIL автоматически уменьшается на единицу. Запись в регистр данных может быть использована для отправки команды, представленной в младшем байте, в PS/2 устройство. Регистр управления может быть использован для разрешения прерываний процессора от PS/2 порта, посредством установки поля RE в 1. Когда это поле установлено, PS/2 порт будет формировать запрос прерывания, если RAVAIL больше 0. Об этой ситуации будет сигнализировать разряд RI, который будет установлен в 1. Этот разряд может быть очищен посредством чтения из PS/2 порта. Бит CE в регистре управления используется для указания ошибки, если она возникает при отправке команды в PS/2 устройство. Фрагмент программы на языке С, в котором используется PS/2 порт, приведён в листинге 19. Программа читает содержимое регистра данных, затем выделяет бит RVALID и, если он установлен, то сохраняет данные. В противном случае ожидает установки этого бита. Последние три байта данных, полученных от PS/2 порта, сохраняются в переменных byte1, byte2, byte3. Рассмотренный фрагмент является составной частью большей программы Media, входящей в приложение Altera Monitor Program. Листинг 19. Фрагмент программы, в котором используется PS/2 порт volatile int *PS2_ptr = (int *) 0x10000100; //базовый адрес PS/2 порта int PS2_data, RVALID; char byte1=0, byte2=0, byte3=0; … PS2_data = *(PS2_ptr); //читаем содержимое регистра данных PS/2 порта RVALID = PS2_data & 0x8000; //извлекаем бит RVALID if (RVALID) //если в буфере имеются новые данные { /*Сохраняем последние 3 байта данных*/ byte1 = byte2; byte2 = byte3; byte3 = PS2_data & 0xFF; } … 3.4.6. Второй PS/2 порт Процессорная система «DE2-70 Media Computer» включает второй PS/2 порт, что позволяет использовать в ней одновременно и клавиатуру и мышь. Для этого понадобится соединитель Y-типа, через который можно подсоединить к стенду клавиатуру и мышь. Второй PS/2 порт имеет такие же регистры, как и первый, только адрес его регистра данных 0x10000108 и адрес регистра управления 1x000010C. 3.4.7. Блок арифметики с плавающей запятой Процессор Nios II в «DE2-70 Media Computer» использует аппаратную поддержку для реализации арифметических операций с плавающей запятой: сложения, вычитания, умножения и деления. Чтобы использовать эту поддержку, переменные в программах должны быть объявлены типа float. Простой пример такой программы приведён в листинге 20. Когда компилируется эта программа, компилятору необходимо передать специальный аргумент: –mcustom-fpu-cfg=60-2, чтобы проинструктировать его использовать аппаратную поддержку. Листинг 20. Пример программы, в котором используются переменные с плавающей запятой /* Данная программа демонстрирует использование чисел с плавающей запятой * * Она выполняет следующее: * 1. Считывает 2 числа с плавающей запятой из терминального окна * 2. Выполняет над считанными числами операции сложения, вычитания, умножения и * деления и выводит результаты в терминальное окно */ int main(void) { float x, y, add, sub, mult, div; while(1) { printf ("Enter FP values X Y:\n"); scanf ("%f", &x); //считываем 1 число printf ("%f ", x); //выводим его в терминальном окне scanf ("%f", &y); //считываем 2 число printf ("%f\n", y); //выводим его в терминальном окне add = x + y; sub = x - y; mult = x * y; div = x / y; printf ("X + Y = %f\n", add); //выводим в терминальное окно результаты printf ("X - Y = %f\n", sub); printf ("X * Y = %f\n", mult); printf ("X / Y = %f\n", div); } } 3.5. Модификация процессорной системы «DE2-70 Media Computer» С помощью средства SOPC Builder приложения Quartus II можно модифицировать процессорную систему «DE2-70 Media Computer». Подробное описание выполняемых для этого действий содержится в части 1 настоящего учебного пособия, а также в [5]. Чтобы модифицировать систему, необходимо иметь все её файлы с исходными кодами. Процессорная система «DE2-70 Media Computer» доступна в двух версиях, с использованием языка Verilog или VHDL. Также необходимо установить исходные коды для контроллеров периферийных устройств ввода/вывода. Эти устройства предоставлены в форме ядер интеллектуальной собственности (IP) и включены в пакет, доступный в разделе университетской программы Altera University Program IP Cores. Табл. 3.3 содержит имена IP ядер, которые используются в процессорной системе. Соответствующие файлы проекта «DE2-70 Media Computer» могут быть открыты в пакете Quartus II. Каждое ядро имеет ряд установок, которые назначаются в SOPC Builder, и включает спецификацию, содержащую подробную документацию. Таблица 3.3 IP- ядра, используемые в процессорной системе. Шаги необходимые для модификации системы. 1) Инсталлируйте IP ядра с сайта Altera.com. 2) Скопируйте исходные файлы проекта для «DE2-70 Media Computer» из раздела университетской программы на сайте. Эти файлы могут быть найдены в разделе Design Examples. 3) Откройте файл DE2-70_Media_Computer.qpf. При этом произойдет открытие проекта процессорной системы «DE2-70 Media Computer» с помощью пакета Quartus II. 4) Запустите SOPC Builder и модифицируйте процессорную систему, как описано в разделе 1 настоящего пособия. 5) Выполните генерацию модифицированной системы, используя соответствующую кнопку SOPC Builder. 6) Может понадобиться модифицировать Verilog или VHDL код верхнего уровня (DE2-70_Media_System.v/vhd), если потребуется добавить или удалить некоторую периферию из системы. 7) Скомпилируйте проект в Quartus II. 8) Загрузите модифицированную процессорную систему в кристалл ПЛИС на плате. 3.6. Реализация процессорной системы «DE2-70 Media Computer» после включения питания стенда Процессорная система «DE2-70 Media Computer» может быть автоматически реализована в стенде после включения его питания. Для этого необходимо сохранить в энергонезависимой конфигурационной памяти, содержащейся на плате, файл конфигурирования процессорной системы, имеющий расширение .pof. Если файл программирования имеет формат .sof, то его вначале необходимо преобразовать с помощью Quartus II в формат .pof. После чего, пользователю необходимо запустить Programmer и включить в нем режим программирования Active Serial Programming. Приложение Programmer попросит указать устройство, в которое будет загружена конфигурация. Таким устройством на стенде DE2-70 является EPCS16. Перед непосредственным программированием следует передвинуть переключатель “RUN/PROG” стенда в положение PROG. После завершения программирования следует перевести переключатель в положение RUN, выключить и повторно включить стенд. 3.7. Адресное пространство процессорной системы Таблица 3.4 содержит карту памяти процессорной системы «DE2-70 Media Computer». Таблица 3.4 Карта памяти процессорной системы. |
Учебное пособие Москва Издательство Московского государственного... Рекомендовано к изданию Редакционно-издательским советом университета в качестве учебного пособия для студентов направления 230100... |
Учебное пособие Издательство Иркутского государственного технического университета 2012 Тимофеева С. С. Защита литосферы и обращение с опасными отходами : учеб пособие. – Иркутск : Изд-во Иргту, 2012. – 159 с |
||
Учебное пособие Издательство Иркутского государственного технического университета 2012 Тимофеева С. С. Защита литосферы и обращение с опасными отходами : учеб пособие. – Иркутск : Изд-во Иргту, 2012. – 159 с |
2015 удк 378 вестник рыбинского государственного авиационного технического... ... |
||
2015 удк 378 вестник рыбинского государственного авиационного технического... ... |
Учебное пособие «Основы современной социологии» Год издания: 2001... Григорьев С. И., Растов Ю. Е. Основы современной социологии. Учебное пособие. Барнаул: Издательство Алтайского государственного университета,... |
||
Учебное пособие (Краткий курс) Москва Издательство Российского университета дружбы народов Учебное пособие предназначено для студентов, обучающихся в магистратуре и специализирующихся по защите растений |
Учебное пособие Москва Издательство Российского Университета дружбы народов 1998 ... |
||
Учебное пособие Часть 1 Р89 Русский язык и культура речи для студентов-нефилологов. Ч. 1: учебное пособие/ Колпакова Л. В., Максименко Е. В., Михайлова О.... |
Рабочая программа размещена на сайте Университета http :// utmn ru... Н. В. Бакша, А. А. Данилюк. Корпоративная социальная ответственность: учебное пособие. Тюмень: Издательство Тюменского государственного... |
||
Учебное пособие Издание третье, исправленное и дополненное Москва... Б 17 Литературное редактирование: Учеб пособие., изд. 3 – М.: Рудн, 2010. – 249 с |
Учебное пособие. М.: Издательство Московского университета, 2004 «Вся Россия», «Моя провинция», «Новости – время местное» и др Представлены также некоторые особенности совместной работы журналистов... |
||
Учебное пособие Часть II РФ, заведующая кафедрой детских болезней лечебного факультета I московского Государственного Медицинского университета им. И. М.... |
Учебное пособие Издательство Иркутского государственного технического университета 2014 Курышова И. В. История и теория местного самоуправления : учеб пособие. – Иркутск : Изд-во Иргту, 2014. – 112 с |
||
Методические рекомендации по подготовке и защите выпускной квалификационной... Печатается по решению Ученого совета Московского государственного медико-стоматологического университета им. А. И. Евдокимова (г.... |
Бурлюкина Е. В., Васильченко Н. Г. Экономика отрасли Учебное пособие... Рецензенты: Кафедра «Экономики и управления предприятием» Московского государственного университета инженерной экологии, зав кафедрой:... |
Поиск |