Здравствуйте, _Mandor_, Вы писали:
_M_>Как сделать?
_M_>Дайте пример.
_M_>И запись тоже
Вот то, чем я пользуюсь (будет работать под DOS16 и под DOS32).
Извините за размер.
Есть еще один вариант работы с COM-портом, если нужен, могу выслать на почту (только для DOS16).
Пример работы c функциями:
InstallCom(1,115200,8,0,1); //настраиваем параметры порта
ClearCom(1); //очищаем входной буфер
//постоянно читаем данные из порта и выводим на экран
while(1)
{
while(DataSizeInCom(1))
printf("%c",ReadCom(1));
}
Заголовочный файл :
/* serial.h */
/* работа с последовательным портом для PC x86 */
#if !defined _SERIAL_H_
#define _SERIAL_H_
/* input buffer size*/
#define IN_BUF_SIZE 1024
#define __interrupt interrupt
#define __far far
#define __PARAM ...
#define NoError 0
#define ChkSumErr -1
#define TimeOut -2
void InstallCom1(long baud,int nbit,int parity,int stopbit); //установка параметров порта
void RestoreCom1(); //закрытие порта
int IsCom1(); //проверка наличия данных в буфере порта
void ToCom1(int data); //отправка байта в порт
int ReadCom1(); //чтение байта из входного буфера
void ClearCom1(); //очистка входного буфера
int DataSizeInCom1(); //размер данных во входном буфере
void __interrupt __far SerialISR1(__PARAM); //ф-ия обработки прерывания
void InstallCom2(long baud,int nbit,int parity,int stopbit); //установка параметров порта
void RestoreCom2(); //закрытие порта
int IsCom2(); //проверка наличия данных в буфере порта
void ToCom2(int data); //отправка байта в порт
int ReadCom2(); //чтение байта из входного буфера
void ClearCom2(); //очистка входного буфера
int DataSizeInCom2(); //размер данных во входном буфере
void __interrupt __far SerialISR2(__PARAM); //ф-ия обработки прерывания
// функции для работы с модулями 7000
int SndRcvCom1(char *cmd, char * resp,char chksum,int timeout);//отправка команды/прием ответа
int SndRcvCom2(char *cmd, char * resp,char chksum,int timeout);//отправка команды/прием ответа
// функции для ICOP-6070
void Set485DirToTransmit2();//включить порт RS485 на передачу
void Set485DirToReceive2(); //включить порт RS485 на прием
//общие функции
void InstallCom(int port, long baud, int nbit, int parity, int stopbit);
void RestoreCom(int port);
int IsCom(int port);
void ToCom(int port, int data);
int ReadCom(int port);
void ClearCom(int port);
int DataSizeInCom(int port);
void ToComStr(int port, char * str);
void ToComBufn(int port, char * buf, int size);
#endif //_SERIAL
CPP-шник:
/* serial.cpp */
#include "serial.h"
#include <dos.h>
//#include <i86.h>
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
/* baud */
#define BR_110 0x410
#define BR_150 0x300
#define BR_300 0x180
#define BR_600 0xC0
#define BR_1200 0x60
#define BR_2400 0x30
#define BR_4800 0x18
#define BR_9600 0xC
#define BR_19200 0x6
#define BR_38400 0x3
#define BR_57600 0x2
#define BR_115200 0x1
/* nbit */
#define bit_5 0x00
#define bit_6 0x01
#define bit_7 0x02
#define bit_8 0x03
/* parity */
#define NoParity 0x00
#define Odd 0x08
#define Even 0x18
/* stopbit */
#define OneStopBit 0x00
#define TwoStopBit 0x04
static char InBuf1[IN_BUF_SIZE];
static int wrcount1, rdcount1;
static char InBuf2[IN_BUF_SIZE];
static int wrcount2, rdcount2;
static void __interrupt __far (* oldvectCom1)(__PARAM);
static void __interrupt __far (* oldvectCom2)(__PARAM);
#define PORT1 0x3F8
#define INTVECT1 0xC
#define PORT2 0x2F8
#define INTVECT2 0xB
void __interrupt __far SerialISR1(__PARAM)
{// получено прерывание от порта
while( inp(PORT1+5) & 0x01 )
{
if( wrcount1 >= IN_BUF_SIZE )
{
wrcount1 = 0;
rdcount1 = 0;
}
InBuf1[wrcount1++] = (char)inp(PORT1);
}
outp(0x20,0x20);
};
void InstallCom1(long baud,int nbit,int parity,int stopbit)
{
outp(PORT1+1,0); //запрещаем прерывания от UART
oldvectCom1 = _dos_getvect(INTVECT1); //получаем старый вектор прерывания
_dos_setvect(INTVECT1,SerialISR1); //устанавливаем новый вектор прерывания
outp(PORT1+3,0x80); //устанавливаем режим загрузки делителя
//скорость передачи
switch( baud )
{
case 110L: baud = BR_110; break;
case 150L: baud = BR_150; break;
case 300L: baud = BR_300; break;
case 600L: baud = BR_600; break;
case 1200L: baud = BR_1200; break;
case 2400L: baud = BR_2400; break;
case 4800L: baud = BR_4800; break;
case 9600L: baud = BR_9600; break;
case 19200L: baud = BR_19200; break;
case 38400L: baud = BR_38400; break;
case 57600L: baud = BR_57600; break;
case 115200L: baud = BR_115200; break;
default: baud = BR_9600;
}
outp(PORT1+0, baud & 0xFF ); //загружаем младший байт делителя
outp(PORT1+1,baud>>8); //загружаем старший байт делителя
//кол-во бит
switch( nbit )
{
case 5: nbit = bit_5; break;
case 6: nbit = bit_6; break;
case 7: nbit = bit_7; break;
case 8: nbit = bit_8; break;
default: nbit = bit_8;
};
//четность
switch( parity )
{
case 0: parity = NoParity; break;
case 1: parity = Odd; break;
case 2: parity = Even; break;
default: parity = NoParity;
};
//стоп-биты
switch( stopbit )
{
case 1: stopbit = OneStopBit; break;
case 2: stopbit = TwoStopBit; break;
default: stopbit = OneStopBit;
};
outp(PORT1+3,nbit|parity|stopbit); //настраиваем формат передачи: кол-во бит/паритет/стоп-бит
outp(PORT1+2,0x07); //буфер FIFO - 1 байт, включаем буфер
outp(PORT1+4,0x0B); //устанавливаем линии RTS, DTR, OUT1
outp(0x21,inp(0x21)&0xEF); //настраиваем регистр маски прерываний контроллера прер-й
outp(PORT1+1,0x01); //разрешаем контроллеру UART прерывание по приему байта
};
void RestoreCom1()
{
outp(PORT1+1,0); //запрещаем прерывания от UART*/
outp(0x21,(inp(0x21)|0x10)); //маскируем линию запроса прерывания
if( oldvectCom1 )
_dos_setvect(INTVECT1, oldvectCom1); //возвращаем старый вектор прерывания
};
int IsCom1()
{
return ( wrcount1 > rdcount1 );
};
int ReadCom1()
{
if( wrcount1 > rdcount1 )
return InBuf1[rdcount1++];
return -1;
};
void ToCom1(int data)
{
while( !(inp(PORT1+5) & 0x20) );//ждем отправки байта
outp(PORT1+0,data);//отправляем байт
};
void ClearCom1()
{
wrcount1 = rdcount1 = 0;
};
int DataSizeInCom1()
{
return (wrcount1 - rdcount1);
};
void __interrupt __far SerialISR2(__PARAM)
{//получено прерывание от порта
while( inp(PORT2+5) & 0x01 )
{
if( wrcount2 >= IN_BUF_SIZE )
{
wrcount2 = 0;
rdcount2 = 0;
}
InBuf2[wrcount2++] = (char)inp(PORT2);
}
outp(0x20,0x20);
};
void InstallCom2(long baud,int nbit,int parity,int stopbit)
{
outp(PORT2+1,0); //запрещаем прерывания от UART
oldvectCom2 = _dos_getvect(INTVECT2);//получаем старый вектор прерывания
_dos_setvect(INTVECT2,SerialISR2); //устанавливаем новый вектор прерывания
outp(PORT2+3,0x80); //устанавливаем режим загрузки делителя
//скорость передачи
switch( baud )
{
case 110L: baud = BR_110; break;
case 150L: baud = BR_150; break;
case 300L: baud = BR_300; break;
case 600L: baud = BR_600; break;
case 1200L: baud = BR_1200; break;
case 2400L: baud = BR_2400; break;
case 4800L: baud = BR_4800; break;
case 9600L: baud = BR_9600; break;
case 19200L: baud = BR_19200; break;
case 38400L: baud = BR_38400; break;
case 57600L: baud = BR_57600; break;
case 115200L: baud = BR_115200; break;
default: baud = BR_9600;
}
outp(PORT2+0, baud & 0xFF ); //загружаем младший байт делителя
outp(PORT2+1,baud>>8); //загружаем старший байт делителя
//кол-во бит
switch( nbit )
{
case 5: nbit = bit_5; break;
case 6: nbit = bit_6; break;
case 7: nbit = bit_7; break;
case 8: nbit = bit_8; break;
default: nbit = bit_8;
};
//четность
switch( parity )
{
case 0: parity = NoParity; break;
case 1: parity = Odd; break;
case 2: parity = Even; break;
default: parity = NoParity;
};
//стоп-биты
switch( stopbit )
{
case 1: stopbit = OneStopBit; break;
case 2: stopbit = TwoStopBit; break;
default: stopbit = OneStopBit;
};
outp(PORT2+3,nbit|parity|stopbit); //настраиваем формат передачи: бит/паритет/стоп-бит
outp(PORT2+2,0x7); //буфер FIFO - 1 байт, включаем буфер
outp(PORT2+4,0x0B); //устанавливаем линии RTS, DTR, OUT1
outp(0x21,inp(0x21)&0xF7); //настраиваем регистр маски прерываний контроллера прер-й
outp(PORT2+1,0x01); //разрешаем контроллеру UART прерывание по приему байта
};
void RestoreCom2()
{
outp(PORT2+1,0);//запрещаем прерывания от UART*/
outp(0x21,(inp(0x21)|0x10));//маскируем линию запроса прерывания
if( oldvectCom2 )
_dos_setvect(INTVECT2, oldvectCom2);//возвращаем старый вектор прерывания
};
int IsCom2()
{
return ( wrcount2 > rdcount2 );
};
int ReadCom2()
{
if( wrcount2 > rdcount2 )
return InBuf2[rdcount2++];
return -1;
};
void ToCom2(int data)
{
while( !(inp(PORT2+5) & 0x20) );
outp(PORT2+0,data);
};
void ClearCom2()
{
wrcount2 = rdcount2 = 0;
};
int DataSizeInCom2()
{
return (wrcount2 - rdcount2);
};
void Set485DirToTransmit2()
{
outp( PORT2+4, inp(PORT2+4) | 0x02 );//устанавливаем линию RTS
}
void Set485DirToReceive2()
{
outp( PORT2+4, inp(PORT2+4) & 0xFD );//сбрасываем линию RTS
}
//функции для работы с модулями 7000
//отправка команды/прием ответа
int SndRcvCom1(char *cmd, char * resp,char chksum,int timeout)
{
unsigned char sum = 0;
char sumstr[2];
if( chksum )
{
for( int i = 0; i < strlen(cmd); i++ )
sum += cmd[i];
sprintf(sumstr,"%02X",sum);
}
//отправка команды
for( int byte = 0; byte < strlen(cmd); byte++ )
ToCom1(cmd[byte]);
if( chksum )
{
ToCom1(sumstr[0]);
ToCom1(sumstr[1]);
}
ToCom1('\r');
//
clock_t start_time = clock(), end_time;
//ждем появления данных
int counter = 0;
char ch;
do
{
while( !IsCom1() )
{
end_time = clock();
if( (end_time - start_time) >= timeout ) return TimeOut;
}
ch = (char)ReadCom1();
resp[counter++] = ch;
}
while( ch != '\r' );
if( counter )
{
counter--;
resp[counter] = 0;
}
if( chksum )
{
if( strlen(resp) < 2 ) return ChkSumErr;
sum = 0;
for( int i = 0; i < strlen(resp)-2; i++ )
sum += resp[i];
if( sum == (unsigned char)strtoul(resp+strlen(resp)-2,0,16) )
{
resp[strlen(resp)-2] = 0;
return NoError;
}
else
{
return ChkSumErr;
}
}
return NoError;
}
/* отправка команды/прием ответа */
int SndRcvCom2(char *cmd, char * resp,char chksum,int timeout)
{
unsigned char sum = 0;
char sumstr[3];
if( chksum )
{
for( int i = 0; i < strlen(cmd); i++ )
sum += cmd[i];
sprintf(sumstr,"%02X",sum);
}
//отправка команды
for( int byte = 0; byte < strlen(cmd); byte++ )
ToCom2(cmd[byte]);
if( chksum )
{
ToCom2(sumstr[0]);
ToCom2(sumstr[1]);
}
ToCom2('\r');
//
clock_t start_time = clock(), end_time;
//ждем появления данных
int counter = 0;
char ch;
do
{
while( !IsCom2() )
{
end_time = clock();
if( (end_time - start_time) >= timeout ) return TimeOut;
}
ch = (char)ReadCom2();
if( resp )
resp[counter++] = ch;
}
while( ch != '\r' );
if( counter )
{
counter--;
resp[counter] = 0;
}
if( chksum )
{
if( strlen(resp) < 2 ) return ChkSumErr;
sum = 0;
for( int i = 0; i < strlen(resp)-2; i++ )
sum += resp[i];
if( sum == (unsigned char)strtoul(resp+strlen(resp)-2,0,16) )
{
resp[strlen(resp)-2] = 0;
return NoError;
}
else
{
return ChkSumErr;
}
}
return NoError;
}
void InstallCom(int port, long baud, int nbit, int parity, int stopbit)
{
switch( port )
{
case 1: InstallCom1(baud, nbit, parity, stopbit);break;
case 2: InstallCom2(baud, nbit, parity, stopbit);break;
default: InstallCom1(baud, nbit, parity, stopbit);break;
}
};
void RestoreCom(int port)
{
switch( port )
{
case 1: RestoreCom1();break;
case 2: RestoreCom2();break;
default: RestoreCom1();break;
}
};
int IsCom(int port)
{
switch( port )
{
case 1: return IsCom1();
case 2: return IsCom2();
default: return IsCom1();
}
};
void ToCom(int port, int data )
{
switch( port )
{
case 1: ToCom1(data); break;
case 2: ToCom2(data); break;
default: ToCom1(data); break;
}
};
int ReadCom(int port)
{
switch( port )
{
case 1: return ReadCom1();
case 2: return ReadCom2();
default: return ReadCom1();
}
};
void ClearCom(int port)
{
switch( port )
{
case 1: ClearCom1(); break;
case 2: ClearCom2(); break;
default: ClearCom1(); break;
}
};
int DataSizeInCom(int port)
{
switch( port )
{
case 1: return DataSizeInCom1();
case 2: return DataSizeInCom2();
default: return DataSizeInCom1();
}
};
void ToComStr(int port, char * str)
{
for( int i = 0; i < strlen(str); i++)
ToCom(port,str[i]);
};
void ToComBufn(int port, char * buf, int size)
{
for( int i = 0; i < size; i++)
ToCom(port,buf[i]);
};