Сафоненко Практикум по интерфейсам последователной передачи 2012
.pdfПример программирования
Рассмотрим пример программирования порта на языке C++ в ОС MS-DOS. В этом примере будут представлены режимы работы: дуплексный, полудуплексный, симплексный (в режиме передачи и
врежиме приема данных). Первоначально будет создан класс для отображения данных MyWindow и два объекта класса для ввода и вывода данных InWin и OutWin. Так как возможно, что система использовала до нас вектор прерывания порта, мы сначала сохраним его в переменную (чтобы в конце работы вернуть все назад) и только потом установим наш обработчик прерываний. Чтение и запись
впорты будем производить с помощью функций из dos.h inportb и outportb. Функция inportb возвращает байт данных из указанного порта, а outportb в качестве аргументов получает, помимо адреса порта, байт данных, который необходимо записать в указанный порт. Для получения и изменения векторов прерывания используются функции getvect и setvect из библиотеки dos.h.
#include <dos.h> #include <stdio.h> #include <conio.h>
#define PORT1 0x3F8 /* Базовый адрес для СОМ1*/ #define INTVECT 0x0C
/* */ |
|
/* COM1 0x3F8 |
*/ |
/* COM2 0x2F8 |
*/ |
/* COM3 0x3E8 |
*/ |
/* COM4 0x2E8 |
*/ |
//Объявление классаокна class MyWindow{
int xl,yl; //Координаты левого верхнего угла int xr,yr; //Координаты правого верхнего угла int xcur,ycur; //Позиция курсора
int textc,textb; //Цветовые параметры public:
41
MyWindow(){
//Конструктор класса, параметрыокна по
умолчанию
xl=1;yl=1;xr=1;yr=1;
xcur=1;ycur=1;
textc=LIGHTGRAY;
textb=BLACK;
}
int outsym(unsigned char c){ //Выводсимвола вокно window(xl+1,yl+1,xr-1,yr);
textcolor(textc);
textbackground(textb);
gotoxy(xcur,ycur);
if (c==13){ //символ перевода курсорана новуюстроку cprintf("\r\n");
}
else{
cprintf("%c",c);
}
xcur=wherex();ycur=wherey(); return 0;
}
int changecolor(int c, int b){
//Изменение цветовых параметровокна textc=c;
textb=b; return 0;
}
int changecoord(int x1,int y1, int x2, int y2){ //Изменение координат окна xl=x1;xr=x2;yl=y1;yr=y2;
return 0;
}
42
int clear(void){ //Очисткаокна
window(xl+1,yl+1,xr-1,yr); textcolor(textc);
textbackground(textb);
xcur=0;ycur=0;
clrscr(); return 0;
}
};
class MyWindow InpWin,OutWin; //Создадимдва //объектакласса MyWindow
int bufferin = 0; // Номер символа буфере полученных данных int bufferout = 0;// Номер символа в буфере отправленных данных
char ch; |
|
char buffer[1025]; |
//Буфер |
int DTR=0; |
//Значение сигналаDTR |
//Сохраняем старый обработчик прерываний void interrupt (*oldport1isr)(...);
//Обработчикпрерываний void interrupt PORT1INT(...){
unsigned char c,c1=0;
c1= inportb(PORT1+6); //Чтение
//регистра состояния COM-порта
c = inportb(PORT1+2); //Чтение регистраидентификации //прерываний
if ((c&4)&&!(c&2)){//анализ причины прерываний //входной регистр получил символ
buffer[bufferin] = inportb(PORT1); //Чтение символа bufferin++;
if (bufferin == 1024)//буфер переполнен bufferin = 0;
}else{
//Если сработало прерывание по сигналу DTR
43
if(c1&32){
DTR=1; //DTR установимв единицу (xx1xxxxx)
}else{
DTR=0; //DTR установим в ноль(xx0xxxxx)
}
}
outportb(0x20,0x20); //Стандартное завершение Обработчика прерываний
}
void Duplex(void){
//Дуплексный режим
char c; clrscr();
gotoxy(2,1);cprintf("MODE: Duplex"); gotoxy(10,2);cprintf("Input information:"); gotoxy(10,13);cprintf("Output information:"); //Настройки окна получаемой информации
InpWin.changecoord(1,2,80,12);
InpWin.changecolor(BLUE,LIGHTGRAY);
InpWin.clear();
//Настройки окна переданной информации
OutWin.changecoord(1,13,80,24);
OutWin.changecolor(RED,LIGHTGRAY);
OutWin.clear();
do{
if (bufferin != bufferout){
//Выводимсимвол наэкран ch = buffer[bufferout];
bufferout++;
if (bufferout == 1024) bufferout = 0; InpWin.outsym(ch);
}
if (kbhit()){
//Чтение кода нажатой клавиши
44
c = getch();// имитаторввода данных впорт outportb(PORT1, c);//отсылаем символ OutWin.outsym(c);
}
}while (c!=27); //завершение по клавише <ESC> return;
}
void HDuplex(void)
{
//Полудуплексный режим
char c; clrscr();
gotoxy(2,1);cprintf("MODE: Half-Duplex. Press <ENTER> to begin/end session");
gotoxy(10,2);cprintf("Input information:"); gotoxy(10,13);cprintf("Output information:"); //Настройки окна принятойинформации
InpWin.changecoord(1,2,80,12);
InpWin.changecolor(BLUE,LIGHTGRAY);
InpWin.clear();
//Настройки окна переданной информации
OutWin.changecoord(1,13,80,24);
OutWin.changecolor(RED,LIGHTGRAY);
OutWin.clear();
do{
if(DTR){
//Если установленDTR, то получаем символы do{
if (bufferin != bufferout){ ch = buffer[bufferout]; bufferout++;
if (bufferout == 1024) bufferout = 0;
45
inport(PORT)
InpWin.outsym(ch);
}
}while(DTR); //выполняем цикл покаустановлен
//DTR
}
if (kbhit()){
c = getch();
}
if(c==13){
//Если нажата клавиша <ENTER> начинаем вывод в
//COM-порт
outportb(PORT1+4,0x09); //Включение DTR do{
c=getch();
outportb(PORT1, c);//передать символ в линию OutWin.outsym(c);
}while(c!=13); //<ENTER> – начало/ //окончание ввода
outportb(PORT1+4,0x08); //ВыключениеDTR c=0;
}
}while (c !=27); return;
}
void SimplexM(void)
{
//Симплексный режим: отправка данных char c;
clrscr();
gotoxy(2,1);cprintf("MODE: Simplex (master)"); gotoxy(10,2);cprintf("Input information:"); gotoxy(10,13);cprintf("Output information:"); //Настройки окна получаемой информации
InpWin.changecoord(1,2,80,12);
46
InpWin.changecolor(BLUE,LIGHTGRAY);
InpWin.clear();
//Настройки окна переданной информации
OutWin.changecoord(1,13,80,24);
OutWin.changecolor(RED,LIGHTGRAY);
OutWin.clear();
do{
if (kbhit()){
c = getch(); outportb(PORT1, c); OutWin.outsym(c);
}
//Ввод и отправка введенных символов, до тех //пор, пока не нажат <ESC>
}while (c !=27); return;
}
void SimplexS(void){
//Симплексный режим: получение данных
char c; clrscr();
gotoxy(2,1);cprintf("MODE: Simplex (slave)"); gotoxy(10,2);cprintf("Input information:"); gotoxy(10,13);cprintf("Output information:"); //Настройки окна получаемой информации
InpWin.changecoord(1,2,80,12);
InpWin.changecolor(BLUE,LIGHTGRAY);
InpWin.clear();
//Настройки окна переданной информации
OutWin.changecoord(1,13,80,24);
OutWin.changecolor(RED,LIGHTGRAY);
OutWin.clear();
do{
if (bufferin != bufferout){
47
ch = buffer[bufferout]; bufferout++;
if (bufferout == 1024) bufferout = 0;
InpWin.outsym(ch);
}
if (kbhit())
{
c = getch();
}
}while (c !=27); return;
}
void main(void){ //Основная функция int c;
int c1; textcolor(LIGHTGRAY); textbackground(BLACK); clrscr();
outportb(PORT1 + 1 , 0); //Отключаем прерывания oldport1isr = getvect(INTVECT); //Сохраняем адрес
//старого обработчика
setvect(INTVECT, PORT1INT); //Устанавливаем новый
//обработчик
//Инициализация COM-порта
outportb(PORT1 + 3 , 0x80); //Настройка скорости outportb(PORT1 + 0 , 0x0C); //9600 bps outportb(PORT1 + 1 , 0x00);
outportb(PORT1 + 3 , 0x03); //Окончание настройки outportb(PORT1 + 4 , 0x08); //Выбор линии OUT2 outportb(0x21,(inportb(0x21) & 0xEF)); //Разрешаемпрерывания
процессора
48
/* COM1 (IRQ4) – 0xEF */ /* COM2 (IRQ3) – 0xF7 */ /* COM3 (IRQ4) – 0xEF */ /* COM4 (IRQ3) – 0xF7 */
outportb(PORT1 + 1 , 0x09); //РазрешитьПрерывание по
//событиям готовности данных и DTR do{
window(1,1,80,24);
textcolor(LIGHTGRAY);
textbackground(BLACK);
clrscr();
printf("Choose mode:\n1. Duplex\n2. Half-Duplex\n3. Simplex (master)\n4. Simplex (slave)");
printf("\nPress <ESC> to quit"); c=getch();
switch(c){
case '1':Duplex();break; case '2':HDuplex();break; case '3':SimplexM();break; case '4':SimplexS();break;
}
}while(c!=27);//Завершение по клавише Escape outportb(PORT1 + 1 , 0); //Выключаем прерывания outportb(0x21,(inportb(0x21) | 0x10));
/* COM1 (IRQ4) – 0x10 */ /* COM2 (IRQ3) – 0x08 */ /* COM3 (IRQ4) – 0x10 */ /* COM4 (IRQ3) – 0x08 */
setvect(INTVECT, oldport1isr); //Восстанавливаем
//старый обработчик textbackground(BLACK); clrscr();
return;
}
49
Глава 2. МЕТОДИКА ПРОГРАММИРОВАНИЯ В СРЕДЕ MATLAB
Арбитраж в интерфейсах. Программные и аппаратные механизмы реализации алгоритмов арбитража. Критерии качества интерфейса и сравнительные характеристики методов арбитража передачи
Интерфейс использует буферизацию данных с целью согласования пропускной способности приемника и передатчика. В табл. 4 приведены характеристики современных буферных устройств для схем UART. В первых схемах передатчик имел два байта очереди и один байт имел приемник.
Другой механизм, который позволяет избежать потери данных в случае занятости приемника, предполагает использование сигналов квитирования. С этой целью стандарт предусматривает использование сигналов RTS–CTS, DTR–DSR и систему прерываний.
Интерфейс имеет возможность работать в режиме коммутации пакетов и в режиме коммутации соединений. Выбор и включение типа управления выполняется с помощью свойства FlowControl. Оно позволяет выбрать один из двух методов управления передачей: режим коммутации соединений (hardware– аппаратный, англ.) и коммутации пакетов (software , программный, англ.).
При выборе аппаратного метода, управление происходит с использованием сигналов RTS–CTS, DTR–DSR. Для этого метода необходимо произвести соединение устройств по схеме рис. 9. В этом случае допускается реальный контроль скорости передачи в канале.
Пример: соединим порты по схеме рис. 9 Установим:
>> com1.flowcontrol='hardware';
Бит CTS занят обслуживанием механизма управления передачи. Занять его еще чем-либо невозможно. Устройство, подключенное к порту, может приостанавливать передачу по необходимости, устанавливая бит RTS, при этом бит CTS порта устанавливается в то же значение (так как он соединен с битом RTS устройства) и сигнали-
50