Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
KOMAROV.DOC
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
1.32 Mб
Скачать

1.19.3. Эмуляция интерфейса rs-232 (смешанный вариант)

Задание: см. задание в п. 1.19.2. Главную часть программы рис. 1.17 (от метки start до метки init_uart) написать на языке С. Вызываемые подпрограммы написать на языке ассемблера.

Метод решения: использовать в качестве основы программу рис. 1.17.

Актуальность смешанного программирования объясняется тем, что сложные проекты проще реализовывать на языке высокого уровня, например, СИ. Но полностью выполненный на языке высокого уровня проект обладает большим объемом программы и относительно низким ее быстродействием. Эти недостатки можно существенно уменьшить, если функции (подпрограммы) писать на языке ассемблера, а их вызовы производить из программы, написанной на языке высокого уровня. Рассматриваемые ниже программы иллюстрируют такой подход.

Проект имеет имя AsyncMix и содержит шесть файлов: 218x_int_tab.asm – ASM файл векторов прерываний программы; 218x_hdr.asm – ASM файл пролога программы; 218x_exit.asm – ASM файл эпилога программы; async.c – СИ программа (рис. 1.18), uart.asm – ASM программа (рис. 1.19) и AsyncMix.ldf – линкерный файл (рис. 1.20). Первые три файла находятся в директории ..VisualDSP\218x\lib\crt_src.

//---------- Содержимое файла async.c

#include <Signal.h>

unsigned short ch; // принимаемый из UART символ

void (*dm handler)(dm int); // переменная, в которой хранится указатель

// на обработчик прерываний таймера

//---------- Функции, определенные в uart.asm

extern void init_uart(void);

extern void stop_uart(void);

extern unsigned short char_received(void);

extern unsigned short get_char(void);

extern void out_char(unsigned short);

extern void turn_rx_on(void);

extern void turn_rx_off(void);

extern void process_a_bit(int);

void main(void) {

handler = process_a_bit; // инициализация указателя на обработчик

// прерывания от таймера

// Запись адреса обработчика прерываний в таблицу векторов

// прерываний. Константа SIGTIMER определена в Signal.h

interrupt(SIGTIMER, handler);

init_uart(); // инициализация UART

turn_rx_on(); // разрешение приема из UART

while(1) {

ch = get_char(); // ожидание и прием символа из UART

out_char(ch); // эхо-возврат принятого символа

}

}

Рис. 1.18. СИ программа поддержки UART

Программа, представленная на рис. 1.18, функционально идентична фрагменту программы рис. 1.17, который начинается с метки start и заканчивается меткой init_uart. Все используемые функции определены в файле uart.asm, поэтому должны быть объявлены с классификатором extern. Функции, имеющие одинаковое имя на рисунках 1.17, 1.18, имеют одинаковое назначение.

К таким же функциям относятся get_char и get_char_ax1, а также out_char и out_char_ax1. Изменение имен get_char_ax1 и out_char_ax1 про­и­зошло для упрощения их записи, а также в связи с тем, что прямое указание регистра источника и назначения (ах1) теперь не актуально.

Единственной новой функцией является функция char_received(), которая возвращает TRUE, если символ принят из UART и FALSE в противном случае. Эту функцию удобно использовать перед вызовом функции get_char(), которая может зациклиться, если из последовательного канала не приходят данные.

//---------- Содержимое файла uart.asm

// Объявление экспортируемых имен функций, чтобы они стали

// доступными в других модулях проекта

.GLOBAL _init_uart, _stop_uart, _get_char, _out_char;

.GLOBAL _char_received, _turn_rx_on, _turn_rx_off;

.GLOBAL _process_a_bit;

{

Далее следуют строки программы рис. 1.17, начиная с #include <Reg2181.inc> и заканчивая строкой SECTION/PM UART_CODE. Строки jump start;… start: необходимо опустить, они находятся в файле 218x_int_tab.asm. Необходимо также опустить строки start:…jump next_byte;, они заменены С-программой (см. рис. 1.18).

}

_init_uart:

// Тело подпрограммы полностью идентично телу подпрограммы init_uart

// на рис. 1.17

rts

_stop_uart:

// Тело подпрограммы полностью идентично телу подпрограммы stop_uart

// на рис. 1.17

rts

_process_a_bit:

// Тело подпрограммы полностью идентично телу подпрограммы

// process_a_bit на рис. 1.17, только все команды rti необходимо заменить

// на команды rts

rts

invoke_UART_transmit:

// Тело подпрограммы полностью идентично телу подпрограммы

// invoke_UART_transmit на рис. 1.17

rts

_char_received:

ax1 = 1;

ax0=dm(flag_rx_no_word);

none=pass ax0;

if eq rts; // если символ из UART получен, то возвращаем 1

ax1 = 0; // в противном случае возвращаем 0

rts;

_get_char:

// Тело подпрограммы полностью идентично телу подпрограммы

// get_char_ax1 на рис. 1.17

rts;

_out_char:

ax0=dm(flag_tx_ready);

none=pass ax0;

if eq jump _out_char; // ожидание передачи предыдущего

// символа

// Формирование указателя (I6) на передаваемый параметр функции

I6 = I4; M5 = 1; MODIFY(I6, M5);

{Pop arg1}

AX1 = DM(I6, M5);

dm(user_tx_buffer)=ax1;

call invoke_UART_transmit; // выдача его в UART

rts;

_turn_rx_on:

// Тело подпрограммы полностью идентично телу подпрограммы

// turn_rx_on на рис. 1.17

rts;

_turn_rx_off:

// Тело подпрограммы полностью идентично телу подпрограммы

// turn_rx_off на рис. 1.17

rts;

Рис. 1.19. ASM программа поддержки UART

Программа рис. 1.19 практически полностью соответствует программе рис. 1.17. Отличие заключается в том, что экспортируемые имена предваряются подчеркиванием (соглашение языка С) и объявляются директивой GLOBAL. Небольшое отличие наблюдается в функции _out_char. Ее аналог out_char_ax1 принимает символ (для выдачи в UART) в регистре ах1, а _out_char – через программный стек Поэтому в индексном регистре I6 формируется указатель на выдаваемый символ, хранящийся в стеке.

Передаваемые в качестве параметров функции значения хранятся по следующим адресам: первый аргумент – в SP + 1, второй – в SP + 2 и т.д. SP хранится в индексном регистре I4, поэтому первым шагом при формировании указателя на передаваемый параметр является I6 = I4. Затем в модификационный регистр М5 записывается 1 и окончательно командой MODIFY(I6, M5); формируется указатель.

Простота адаптации уже написанных программ на ассемблере позволяет широко использовать их в программах на СИ. Необходимо только следить, чтобы соблюдались соглашения об доступных (scratch), сохраняемых (preserved) и предопределенных (dedicated) регистрах.

//---------- Содержимое файла AsyncMix.ldf

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]