Вопрос: Откомментировать программу для работы с портами

  • Автор темы -
  • Дата начала
Статус
Закрыто для дальнейших ответов.

Гость
#1
программа для двусторонней передачи и приема данных, вводимых с клавиатуры между двумя компьютерами через СОМ-порт (интерфейс RS-232C) с поддержкой буфера FIFO и возможностью управлять количеством передаваемых бит, количеством стоповых бит и битом паритета.

Код:
#include <stdio.h>
#include <fstream.h>
#include <dos.h>
#include <conio.h>
#include <string.h>

#define BYTE unsigned char
#define WORD unsigned short
#define PORT1 0x3f8
#define HIBYTE(w)	((BYTE)((WORD)(w)>>8))
#define LOBYTE(w)	((BYTE)(w))

WORD count_r=0;
WORD port_com;
BYTE irq_com;
BYTE byte;
BYTE old_mask_com;
BYTE vect_com;
int a0_com;
char buff [1024];
WORD str_len=0;
WORD send_index=0;
char ch=0;


char buff_in [1024];
int head = 0, tail = 0;

int rec_f = 0,
str_f = 0;
int ff=0;

void interrupt (*old_handler_com)(...);
void interrupt isr_com(...)
{
asm sti
BYTE line;
BYTE IIR = inportb(port_com + 2);
do
{
switch(IIR & 0x06)
{
//interrupt of modem
case 0:
inportb(port_com + 6);
break;
//interrupt of transiver ()ГаГо з )
case 2:
for(int i=0;((i<16)&&(send_index < str_len)); i++)
outportb(port_com, buff[send_index++]);
if(send_index == str_len)rec_f = 1;
break;
//received data available interrupt (IaEf-^)
case 4:
do
{
line = inportb(port_com+5);
if(line&1)
{
buff_in[head++] = inportb(port_com);
if(head == 1024)
head = 0;
}

}
while(line&1);
break;
//receiver line status interrupt
case 6:
inportb(port_com + 5);
break;
}
IIR = inportb(port_com + 2);
}
while(~IIR& 1);
if(a0_com)
outportb(0xa0, 0x20);
outportb(0x20, 0x20);
}

void enable_com(int port, int irq, WORD divisor, BYTE mode)
{
char mask[8]={1,2,4,8,16,32,64,128};
asm cli
port_com=port;
irq_com=irq;
vect_com=(irq<8)?(irq+0x08):(irq-0x08)+0x70;
outportb(port+1,0);
old_handler_com=getvect(vect_com);
setvect(vect_com, isr_com);
outportb(port + 3, 0x80);
outportb(port + 0, LOBYTE(divisor));
outportb(port + 1, HIBYTE(divisor));
outportb(port + 3, mode);
outportb(port + 2, 0xc7);	/* FIFO enable */
inportb (port + 2);
outportb(port + 4 ,0x0B); 	/* Turn on DTR, RTS, and OUT2 */
if(irq<8)
{
old_mask_com = inportb(0x21);
outportb(0x21 ,old_mask_com & ~mask[irq]);
a0_com = 0;
}
else
{
old_mask_com = inportb(0xa1);
outportb(0xa1, old_mask_com & ~mask[irq-8]);
a0_com = 1;
}
outportb(port + 1,0x03);
inportb(port+0);
inportb(port+2);
inportb(port+5);
asm sti
}

void disable_com()
{
asm cli
outportb(port_com + 1,0);
outportb(port_com + 4,0);
if(irq_com < 8)
{
outportb(0x21,inportb(0x21) | old_mask_com);
}
else
{
outportb(0xa1,inportb(0xa1) | old_mask_com);
}
setvect(vect_com, old_handler_com);
asm sti
}

void main()
{	  int st;
int par;
int kl;
int prt;
clrscr();
port_com=0x3f8;
irq_com=4;
enable_com(port_com, irq_com, 3, 0x3);
send_index=0;
str_len=0;
int i;
//	int lock=0;
printf("vvedite: 0 - dla otpravki 5 bit,\n		 1 - 6 bit,\n		 2 - 7 bit,\n		 3 - 8 bit\n");
scanf("%x", &kl);
printf("vvedite: 0 -dla odnogo stopovogo bita, 1 - dla dvyx >\n");
scanf("%x", &st);
printf("vvedite: 0 - kontrol' chetnosti ne ispolzuetsa,	 \n		 2 - kontrol' na nechetnost'\n		 3 - kontrol' na chetnoct'>\n ");
scanf("%x", &par);
prt=kl&3;
prt|=((int)st&1)<<2;
prt|=((int)par&3)<<3;
outportb(PORT1 + 3, prt);
printf("Vvedite peredavaimie dannie\n");
while(1)
{
if(rec_f)
{
send_index = 0;
str_len = 0;
rec_f = 0;
}
while(head != tail)
{
printf("%c",buff_in[tail++]);
if(tail == 1024)
tail = 0;
}

if(kbhit())
{
ch = getch();
buff[str_len++] = ch;
if(ch == 27) break;
else if(ch == 13)
{
str_len--;
printf("\n");
str_f = 1;
}
else
{
if(str_len == 1024) str_f=1;
}
printf("%c",ch);
}

if(str_f)
{
for(i=0; ((i<16)&&(send_index <= str_len)); i++)
outportb(port_com, buff[send_index++]);
if(send_index == str_len)rec_f = 1;
str_f = 0;
}


}
disable_com();
}
 

Гость
#2
да,это очень частично)
а может кто объяснить почему в функции void interrupt isr_com(...) только чётные(0,2,4,6) case ?
 

lazybiz

Well-Known Member
03.11.2010
1 339
0
#3
почему в функции void interrupt isr_com(...) только чётные(0,2,4,6) case ?
Читаем interrupt identification register:
inportb(port_com + 2);

Нас интересуют только биты 2 и 3 (IIR & 0x06):
00 - line status interrupt
01 - data available
10 - buffer empty
11 - modem status

Если заменить switch(IIR & 0x06) на switch((IIR >> 1) & 3), то в case-ах у тебя будет: 0, 1, 2 и 3 соответственно.
 

DarkKnight

Well-Known Member
01.08.2010
653
0
#5
2 чудо , Более комментариев не требуется??? Вам все понятно??? Объяснение Лэйза (lazybiz) более чем исчерпывающие?
Тему можно закрыть?
 

DarkKnight

Well-Known Member
01.08.2010
653
0
#7
2 чудо , Автор, так что тема уже не актуальна, комментарии Лэйза (lazybiz) исчерпыющие ???
Вопросов больше не имеете?
 
Статус
Закрыто для дальнейших ответов.