Как можно определить текущую скорость передачи последовательного порта на контроллере UART 16550A в MS-DOS?
Как определить скорость передачи данных контроллера последовательного порта в MS-DOS с помощью C
Ответы (1)
Скорость передачи данных можно рассчитать, получив делитель. Это делается путем установки флага делителя путем отправки 0x80 на порт базовый адрес+3. Затем делитель извлекается путем считывания 16-битного значения из порта базовый адрес, который может определить скорость передачи на основе частоты кристалла на микросхеме UART. Различные таблицы зависимости частоты от скорости передачи данных можно найти в Книге данных по элементам микросвязи< /а>
Пример. Запустите это без параметров командной строки, чтобы получить список всех последовательных портов, установленных с COM1-COM4, их базовый адрес и скорость передачи данных.
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
int detect_UART(unsigned baseaddr)
{
// This function returns
// -1 if no UART is installed
// 0 - 8250
// 1 - 16450
// 2 - 16550 w/o SCR
// 3 - 16550
// 4 - 16550A w/o SCR
// 5 - 16550A
unsigned char x, scr=1;
// First step: see if the LCR is there
outp(baseaddr+3, 0x1B);
if (inp(baseaddr+3) != 0x1B) return -1;
outp(baseaddr+3,0x03);
if (inp(baseaddr+3) != 0x03) return -1;
// next thing to do is look for the scratch register
outp(baseaddr+7,0x55);
if (inp(baseaddr+7) != 0x55) scr=0;
outp(baseaddr+7,0xAA);
if (inp(baseaddr+7) != 0xAA) scr=0;
// then check if there's a FIFO
outp(baseaddr+2,0x01);
x=inp(baseaddr+2);
outp(baseaddr+2,0x00); // some old fashioned software relies on this
if (!(x&0x80)) return scr;
if (!(x&0x40)) return 2+scr;
return 4+scr;
}
void check_type(unsigned baseaddr)
{
char *uart[]={"COM1","COM2","COM3","COM4","UART"};
char *type[]={"not installed",
"8250","16450",
"16550 w/o SCR","16550",
"16550A w/o SCR","16550A"};
int i;
for (i=0;i<4;i++)
{
if ((unsigned)peek(0x40,2*i)==baseaddr) break;
}
if (baseaddr==0) i=4;
printf(" %s with base address %03X is %-14s\n",
uart[i], baseaddr, type[1+detect_UART(baseaddr)]);
}
void main(int argc,char *argv[])
{
int i,divisor;
printf("UARTs detect routine\n");
if (argc<2)
{
for(i=0;i<4;i++)
{
register baseaddr=peek(0x40,2*i);
if (baseaddr!=0)
{
check_type((unsigned)baseaddr);
outp(baseaddr+3,0x80);
divisor = inpw(baseaddr);
printf("Divisor = %i\n",divisor);
// assumes 1.8432 MHz crystal
switch (divisor)
{
case 2304:
printf("Baud Rate = 50\n");
break;
case 1536:
printf("Baud Rate = 75\n");
break;
case 1047:
printf("Baud Rate = 110 +/- 0.026 percent\n");
break;
case 857:
printf("Baud Rate = 134.5 +/- 0.058 percent\n");
break;
case 768:
printf("Baud Rate = 150\n");
break;
case 384:
printf("Baud Rate = 300\n");
break;
case 192:
printf("Baud Rate = 600\n");
break;
case 96:
printf("Baud Rate = 1200\n");
break;
case 64:
printf("Baud Rate = 1800\n");
break;
case 58:
printf("Baud Rate = 2000 +/- 0.69 percent\n");
break;
case 48:
printf("Baud Rate = 2400\n");
break;
case 32:
printf("Baud Rate = 3600\n");
break;
case 24:
printf("Baud Rate = 4800\n");
break;
case 16:
printf("Baud Rate = 7200\n");
break;
case 12:
printf("Baud Rate = 9600\n");
break;
case 6:
printf("Baud Rate = 19200\n");
break;
case 3:
printf("Baud Rate = 38400\n");
break;
case 2:
printf("Baud Rate = 56000 +/- 2.86 percent\n");
break;
}
outp(baseaddr+3,0x0);
}
}
}
else
{
for (i=1;i<argc;i++)
{
char *end;
check_type((unsigned)strtol(argv[i],&end,16));
}
}
printf("\n");
}
person
Malcolm McCaffery
schedule
01.12.2020