Newsgroup: it.comp.programmare
Titolo: Interrupt della porta Seriale

Sto facendo, in C, un TSR per DOS 3.
Il TSR si deve attivare quando la seriale riceve dei dati. Controlla il
carattere ricevuto e, se coincide con quello che ho scelto io, simula la
pressione di invio sulla tastiera.
Il mio problema è il monitoraggio della seriale. Infatti penso che ci sia un
interrupt che viene attivato quando la seriale riceve dei dati, am non so
quale. Così, per il momento ho collegato il TSR all'Interrupt 0x1C, che
viene generato 18 volte al secondo dall'orologio di sistema. Ogni nove volte
che viene generato l'interrupt, il programma controlla se sulla seriale sono
presenti nuovi dati. Se ci sono li controlla. Purtroppo però questo sistema
occupa moltissimo il processore (che è un 386), e lavorarci diventa molto
difficile.
Quindi sono alla ricerca di questo benedetto interrupt che viene generato
quando la seriale riceve dei dati, ma finora non l'ho trovato. Mi sembra
strano che non ce ne sia uno. Vorrebbe dire che tutti i programmi devono
monitorare continuamente la seriale per vedere se ci sono nuovi dati, ma se
lo facessero sarebbero lentissimi, quindi non penso.
In conclusione, se qualcuno di voi conosce l'indirizzo di questo benedetto
Interrupt...
Grazie per l'aiuto.

Interrupt...
allora, lavorando tu sotto DOS questo benedetto INTERRUPT é stato
mappato nel PIC8259A MASTER  quindi la linea IRQ3 per com2 e 4
e la linea IRQ4 per la com1 e la 3.
Ora il pic8259a in modalità reale genera per default interruzioni
a partire dall'interrupt 8 .. quindi 8 + 4 = 0C per com1 e 3
mentre 8+3 = 0B per com2 e 4....
ecco gli  interrupt software che devi hookare....
comunque, una conoscenza minima del PIC8259a non ti farebbe neanche
male
cod

quale. 
0x0B per la COM2, 0x0C per la COM1. Ma temo di non starti facendo un
favore: non e' *affatto* cosi' semplice.
In C dovresti fare qualcosa tipo:
	#define PORT	0x3F8h
	// *MIN* SPEED = 1200 BAUD!
	#define BAUD	9600
	disable();
	outb(PORT + 3, 0x80);
	outb(PORT + 1, 0x00);	
	outb(PORT,115200/BAUD);
	setvect(0x0B, myInterrupt);
	outb(PORT + 3, 0x03);
	outb(0x21, inb(0x21)&(~(2<<3)));	// Bit 2, mi pare...?
	outb(PORT + 3, inb(PORT + 3)&0x7F);
	outb(PORT + 1, 0x01);
	outb(PORT + 4, 0x02);
	enable();
 
poi myInterrupt dovrebbe preoccuparsi di resettare il PIC e leggere
i dati dall'hardware:
	byte = inb(PORT);
	outb(0x20, 0x20);
 
Probabilita' che funzioni: una su duemila.
Leggi il Serial-Programming-HOWTO, che e' meglio.
Leonardo
-- 
".signature": bad command or file name

Ho provato ad attaccarmi all'INT 0x0C, come mi hai suggerito, ma non
funziona.
L'interrupt dovrebbe essere attivato ogni volta che la COM 1 riceve
qualcosa, e invece non viene attivato.
Le prove le ho fatte collegando il mio PC ad un portatile con cavo null
modem, entrambi sulla COM1.
Sul PC da tavolo ho attivato Hyperterminal collegandolo alla COM1 e con le
impostazioni di 9600 bps, 8 bit di dati, 1 bit stop, no parità.
Sul portatile ho fatto partire il dos con un vecchio dischetto e poi ho
fatto partire il programma in C di cui trovi sotto il sorgente.
Il programma collega la routine ScriviInvio all'INT 0x0C. Ogni volta che
viene attivata, la routine manda un carattere sulla seriale (facendo varie
prove ho visto che senza inviare un carattere la porta non è in grado di
riceverli, non so perchè), poi legge un carattere ricevuto. Se è 'r', allora
simula la pressione di Invio.
La ScriviInvio è giusta, infatti ho provato a generare l'interrupt 0x0C
facendo un altro programmino di prova che lo attiva con l'istruzione
geninterrupt(0x0C) e funziona. Tuttavia, anche se gli invio tante 'r'
tramite Hyperterminal, la funzione non viene attivata. Se invece genero
artificialmente l'interrupt, legge la 'r' e funziona. Questo mi fa pensare
che l'INT 0x0C non venga attivato.
Il che però è strano, perchè sia tu, sia un sito internet che ho visto, sia
l'altra persona che mi ha risposto dicono che quello è l'INT giusto.
Qualche idea?
#include <stdio.h>
#include <stdlib.h>
#include <bios.h>
#include <dos.h>
#define COMINT 0x0C //interrupt della COM1
#define PORTA 0  //numero della COM1 per le funzioni del bios
void interrupt ScriviInvio()
{
    //invia un null sulla seriale (se no non va la ricezione);
     _AH=1;
     _AL=0;
     _DX=PORTA;
     geninterrupt(0x14);
     //riceve un carattere dalla seriale
     _AH=2;
     _DX=PORTA;
     geninterrupt(0x14);
     //se il carattere S r simula la pressione di Enter
     if(_AL=='r')
       {
 _CX = 0x1C0D;
 _AH = 0x05  ;
 geninterrupt(0x16);
       }
}
void main()
{
 //inizializza la com1 a 9600bps, 8 data bits, 1 stop bit, no parit.
 bioscom(0,0xE3,PORTA);
 setvect(COMINT, ScriviInvio);
 //va in TSR
 keep(0, (_SS + ((_SP + 16)/16) - _psp));
}//main

qualcosa, e invece non viene attivato.
hai provato ad abilitare l'IRQ4 sul pic8259a master ??
se non l'hai fatto é quello il problema...
trovi info sul pic8259a su 
www.programmazione.it
nel corso sviluppare un s.o.
cod

 cod
Sinceramente pensavo che fosse abilitato di default.
Comunque ho letto la pagina del tuo corso e, tra quella e il datasheet del
PIC 8259A scaricato dal sito della Intel ho modificato il sorgente del mio
programma C. Ho prima inizializzato i due pic, master e slave, e poi ho
mandato un OCW1 al master, dicendogli di abilitare tutti gli IRQ (in modo da
abilitare anche quello che mi interessa, IRQ4). Purtroppo però non funziona
ancora. Ho provato anche a cambiare un po' i vari settaggi delle
inizializzazioni, ma niente.
Comincia a venirmi un dubbio: la funzione del C per scrivere su un
indirizzo hardware è la outp(), vero?
Ti scrivo sotto il sorgente modificato e ti ringrazio se avrai la pazienza
di aiutarmi ancora, altrimenti grazie comunque.
#include <stdio.h>
#include <stdlib.h>
#include <bios.h>
#include <dos.h>
#define COMINT 0x0C //interrupt della COM1
#define PORTA 0  //numero della COM1 per le funzioni del bios
void interrupt ScriviInvio()
{
    //invia un null sulla seriale (se no non va la ricezione);
     _AH=1;
     _AL='c';
     _DX=PORTA;
     geninterrupt(0x14);
     //riceve un carattere dalla seriale
     _AH=2;
     _DX=PORTA;
     geninterrupt(0x14);
     //se il carattere S r simula la pressione di Enter
     if(_AL=='r')
       {
 _CX = 0x1C0D;
 _AH = 0x05  ;
 geninterrupt(0x16);
       }
}
void main()
{
 //inizializza la com1 a 9600bps, 8 data bits, 1 stop bit, no parit.
 bioscom(0,0xE3,PORTA);
 setvect(COMINT, ScriviInvio);
 disable();
 //inizializzazione master
 outp(0x20, 0x15);   //ICW1
 outp(0x21, 0x08);   //ICW2
 outp(0x21, 0x04);   //ICW3
 outp(0x21, 0x1F);   //ICW4
 //inizializzazione slave
 outp(0xA0, 0x15);   //ICW1
 outp(0xA1, 0x70);   //ICW2
 outp(0xA1, 0x01);   //ICW3
 outp(0xA1, 0x0B);   //ICW4
 outp(0x21, 0x00);    //OCW 1 sul PIC master: tutti gli IRQ attivi
 enable();


 outp(0x21, 0x00);    //OCW 1 sul PIC master: tutti gli IRQ attivi
senza offesa..... così non ne hai abilitato neanche 1!
sono tutti disabilitati.. cmq scusa per il ritardo, ma sono tornato a
casa oggi pomeriggio....
se avessi dato un'occhiata alla 3. puntatina di quel corsetto
avresti trovato di sicuro scritto che per abilitare un IRQ
bisogna settare il relativo bit (cioé porlo a 1)
tu lo hai posto a 0.. secondo te poteva funzionare?
buona fortuna
cod
p.s.
forse é meglio se continui a scrivere in privato

Qualche idea?
Prova a leggere i messaggi fino in fondo, mmm?
*plonk*
