C++ - sygnaly i przerwania - czytanie portu rs232

Potrzebujesz pomocy z C, C++, perl, python, itp.
muzic
Posty: 1
Rejestracja: 18 lipca 2008, 10:46

C++ - sygnaly i przerwania - czytanie portu rs232

Post autor: muzic »

Witam wszystkich.

Siedze juz od kilku dni nad jednym problem, przeszukalem wszystko co bylo mozliwe do znalezienia ale rozwiazania brak.

Jestem zielony jesli idzie o Linuksa.

Mam do napisania program czytajacy port szeregowy (rs232), ktory bedzie dzialal tak, ze w momencie pojawienia sie czegos na RSie wystawiane jest przerwanie/sygnal, ktory spowoduje czytanie danych z RS232

Napisalem dzialajacy program ale niestety sytuacja wyglada tak:
jezeli czytam bezposrednio (bez syganlow) z RSa to wszystko ladnie odbiera, natomiast gdy wlaczam obsluge sygnalu polowa danych zostaje zgubiona np.: zamiast 20bajtow obieram 9.

Z gory dziekuje za pomoc. Moze ktos ma inny pomysl na napisanie tego programu np. z obsluga przerwan, albo doradzi co robie zle lub jak powinienem to napisac.

Pozdrawiam.
muzic

Ponizszy kod prezentuje program w ktorym wyraznie widac gubienie sygnalow w przypadku obslugi sygnalow:

Kod: Zaznacz cały

#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <iostream>
#include <sys/signal.h>
//----------------------------------------------------
#define BAUDRATE B57600					//[RS232] ustawienie predkosci transmisji
#define MODEMDEVICE "/dev/ttyS0"		//[RS232] sciezka odstepu do RS232
#define _POSIX_SOURCE 1					//ustawienie kodu zgodnego z POSIX
#define O_BINARY    0x8000
#define FALSE 0
#define TRUE 1 
//----------------------------------------------------
volatile int STOP=FALSE;
void signal_handler_IO (int status);    //definicja procedury obsługi przerwania/sygnalu
int wait_flag=TRUE;                     //flaga przerwania/sygnalu: TRUE - brak przerwania FALSE - przyszlo przerwanie
int fd, res;
unsigned char buf[255];					//zmienna trzymajaca wartosc odczytana z RS232
int przer=0;							// [TMP-DEL]

struct sigaction saio;               	//Struktura do obslugi konkretnego przerwania: SAIO
struct termios oldtio,newtio;			//Struktury do przechowywania informacji związanych z urządzeniami terminalowymi.
//----------------------------------------------------
int main()
{
    std::cout<<"START PROGRAMU"<<std::endl;
//----------------------------------------------------
//  Otwórz urządzenie: 
//	O_RDWR 		- do odczytu i zapisu, 
//	O_NOCTTY 	- brak kontroli polaczenia [zabezpieczenie przed CTRL-C], 
//	O_BINARY 	- tryb binarny, 
//	O_NONBLOCK 	- tryb nie blokujacy, zadne operacje (pisania, czekanie na dane) nie zablokuja procesu 
//----------------------------------------------------
   fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);	
   if (fd <0) {perror(MODEMDEVICE); exit(-1); }							//nie powiodlo sie otwarcie urzadzenia to ERROR
   
//----------------------------------------------------  		 
// ZAINICJUJ OBSLUGE PRZERWAN / SYGNALOW
//----------------------------------------------------
  
   saio.sa_handler = signal_handler_IO;									//inicjuje przerwanie dla RS232
   sigemptyset(&saio.sa_mask);   										//wyczysc ustawienia 	//PRZEDTEM: saio.sa_mask = 0;
   saio.sa_flags = 0;													//wyzeruj flage przerwania
   saio.sa_flags = SA_NODEFER;
   saio.sa_restorer = NULL;												//
  sigaction(SIGIO,&saio,NULL);											//zaladuj nowe ustawienia

//----------------------------------------------------
   fcntl(fd, F_SETOWN, getpid());										//pozwól procesowi otrzymać sygnał SIGIO
   fcntl(fd, F_SETFL, FASYNC);	 										//przelacz gniazdo fd w tryb asynchronicznego powiadamiania o gotowości do zapisu/odczytu. Domyślnie wysylany sygnał SIGIO
//   fcntl(fd,F_SETFL,FNDELAY);
   tcgetattr(fd,&oldtio);												//zapisz dotychczasowe ustawienia portu [oldtio]
   bzero(&newtio, sizeof(newtio));										//wyczyść strukturę na ustawienia portu [newtio]

//----------------------------------------------------
//USTAWIENIA RS232 
//	BAUDRATE - Ustaw prędkośc, 
//	CRTSCTS - ustaw sprzętową kontrolę transmisji, 
//	CS8 - 8n1 (8bitów ,bez kontroli parzystości,1 bit stopu), 
//	CLOCAL - połączenie lokalne - nie kontroluje modemu, 
//	CREAD - włącz odbieranie znaków
//----------------------------------------------------
	newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
    newtio.c_iflag = IGNPAR ;   										//IGNPAR - ignoruj bajty z błędami parzystości, ICRNL : przetłumacz CR na LN [ENTER]
    newtio.c_oflag = 0;													//port zorientowany bajtowo (RAW)
    newtio.c_lflag = 0;													//nie ukladaj odebranych danych w wiersze [brak obslugi nowej linii, konca wiersza itp] ICANON - wlacza ukladanie
    newtio.c_cc[VINTR]    = 0;											//Ctrl-c -przerwij	 	: 0 - wylacz, 1 - wlacz [jesli wlaczone ISIG]							
    newtio.c_cc[VQUIT]    = 0;      									//konczenie pracy	 	: 0 - wylacz, 1 - wlacz [jesli wlaczone ISIG]
    newtio.c_cc[VERASE]   = 0;      									//kasowanie 			: 0 - wylacz, 1 - wlacz [jesli wlaczone ICANON] 
    newtio.c_cc[VKILL]    = 0;      									//kasowanie wiersza 	: 0 - wylacz, 1 - wlacz [jesli wlaczone ICANON]
    newtio.c_cc[VEOF]     = 1;      									//koniec pliku			: 0 - wylacz, 1 - wlacz [jesli wlaczone ICANON] 
    newtio.c_cc[VTIME]    = 0;      									//odczytane dane beda dostępne, po upływie [VTIME] (VTIME x 0,1s) 	[jesli wylaczone ICANON]
    newtio.c_cc[VMIN]     = 1;      									//odczytane dane beda dostępne, gdy długość kolejki = [VMIN]		[jesli wylaczone ICANON]  
    newtio.c_cc[VSWTC]    = 0;      									//
    newtio.c_cc[VSTART]   = 0;      									//rozpoczecie pisania 	: 0 - wylacz, 1 - wlacz
    newtio.c_cc[VSTOP]    = 0;      									//zatrzymanie pisania 	: 0 - wylacz, 1 - wlacz
    newtio.c_cc[VSUSP]    = 0;      									//zawieszenie 			: 0 - wylacz, 1 - wlacz
    newtio.c_cc[VEOL]     = 0;      									//koniec wiersza 		: 0 - wylacz, 1 - wlacz
    newtio.c_cc[VREPRINT] = 0;      									//powtorz wiersz 		: 0 - wylacz, 1 - wlacz
    newtio.c_cc[VDISCARD] = 0;      									//	
    newtio.c_cc[VWERASE]  = 0;      									//kasowania słowa 		: 0 - wylacz, 1 - wlacz
    newtio.c_cc[VLNEXT]   = 0;      									//
    newtio.c_cc[VEOL2]    = 0;      									//koniec wiersza 2		: 0 - wylacz, 1 - wlacz
    tcflush(fd, TCIFLUSH);												//porzuć dane otrzymane do bufora ale nie odczytane (przez read() itd)
    tcsetattr(fd,TCSANOW,&newtio);										//uaktywnij nowe ustawienia

	while (STOP==FALSE) {
            res = read(fd,buf,1);
            buf[res]=0;             // set end of string, so we can printf 
            std::cout << "	Odczyt normal: " << (int)buf[0]<< std::endl;
            //std::cout << "	Przer: " << przer<< std::endl;	
            if (buf[0]=='z') STOP=TRUE;
         } 
//	fcntl(0, F_SETFL, tem);
    tcsetattr(fd,TCSANOW,&oldtio);
    std::cout<<"KONIEC PROGRAMU"<<std::endl;

  return 0;
}

void signal_handler_IO (int status)
{
	wait_flag = FALSE;
	printf("SIGIO signal.\n");
	przer++;
}
ODPOWIEDZ