PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ttyS0: led ansteuern (C )



jonasge
31-08-2002, 22:46
Hi,
irgendwie verarscht mich linux zur Zeit. -sorry bin schlecht drauf... :-(
Ich habe in meine ip-up das geschrieben:
touch /tmp/internet
und in meine ip-down das:
rm -r /tmp/internet
Jetzt habe ich eine LED an mein ttyS0 angeschlossen. GND und RTS.
Dann habe ich ein C-Programm geschrieben, das schaut ob die Datei vorhanden ist oder
nicht, wenn sie vorhanden ist, wird die LED angeschalten und wenn die Datei nicht
vorhanden ist, wird die LED ausgeschalten.
Dies funktioniert ja auch, ABER wenn ich mich ins Internet einwaehle, wird die LED
eingeschalten, aber immer nach 1 min und 30 sec schaltet sich die LED einfach wieder aus !!!
Obwohl die datei /tmp/internet noch vorhanden ist.
Wenn ich die datei jetzt manuell loesche und wieder erstelle, darauf reagiert mein PRogramm gar nicht mehr.

Was mache ich falsch ??


----
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#define PORT "/dev/ttyS0"
#define DATEI "/tmp/internet"
int main(int argc, char** argv)
{
FILE *file;
int currstat=0;
int laststat=0;
int fd = 0;
int i=4;
if((fd = open(PORT, O_RDWR | O_NDELAY)) < 0)
{
printf("Fehler: Device \"%s\" kann nicht geöffnet werden.\n", PORT);
return 2;
}

while (1)
{
usleep(75000);
laststat = currstat;
currstat = 0;
if ((file = fopen(DATEI, "r")) != NULL)
{
currstat |= TIOCM_RTS;
if (currstat != laststat)
{ ioctl(fd,TIOCMSET, &currstat); printf("\nan\n"); }
}
else
{
currstat &= ~TIOCM_RTS;
if (currstat != laststat)
{ ioctl(fd,TIOCMSET, &currstat); printf("\naus\n"); }
}
//printf("Lastst: %d Currstat: %d\r", laststat, currstat);


}

return 0;
}

--

gruss
Jonas

nobody0
01-09-2002, 00:36
Schwer zu sagen; ich würde erstmal in ungefähr jede 2. Zeile
printf("l %d\n",__LINE__);
schreiben und mal sehen, wo das Programm ist, wenn es nicht mehr richtig funktioniert.

nobody0
01-09-2002, 00:44
Vielleicht solltest Du mal ioctl nehmen, so wie bei diesem heartbeat-Programm, das über das Tastatur-Blinken anzeigt, dass der Kernel (u. das Programm) noch läuft (funktioniert sehr zuverlässig, sollte möglichst mit nice --adjustment=19 gestartet werden insbes. dann, wenn die Tastatur machmal nicht angeschlossen ist):

/*
* heatbeat.c -- flash NumLock in an hearthbeat fashion, usually without options.
*
* Tested with 1.2 on the x86
* Tested with 2.0 on the x86, Alpha, Sparc
*
* From the book LNUX DEVICE DRIVER (O'Reilly).
* Works even with USB-Keyboards and also with PS/2-Keyboards (eben with both at the same time).
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/kd.h>

int main(int argc, char **argv)
{
char led;
int chosenled = 1;
char hearth[]={1,0,1,1,0,0,0,0,0,0,0,0,0};
int udelay = 100000;
int load = 0;
char *prgname = argv[0];
FILE *f;

if (argc > 1 && isdigit(argv[1][0])) { /* the time delay */
udelay = 1000 * atoi(argv[1]);
if (udelay < 1000)
fprintf(stderr, "%s: delay too short\n", prgname);
else {
argv++; argc--;
}
}

nice(19); /* in case it succeeds... */

udelay *= 100; /* prepare for a later division */

if (argc > 1 && strlen(argv[1]) == 1) {
argv++, argc--;
if (tolower(argv[0][0]) == 's') chosenled = 1; /* scroll lock */
else
if (tolower(argv[0][0]) == 'n') chosenled = 2; /* num lock */
else
if (tolower(argv[0][0]) == 'c') chosenled = 4; /* caps lock */
else {
fprintf(stderr, "%s: unknown led '%s'\n", prgname, argv[1]);
argc++;
}
}
if (argc>1) {
prgname, prgname);
exit(1);
}



/* ok, now do your loop */

for (;;) {
int consolefd=open("/dev/tty0",O_RDONLY);

int i;
f=fopen("/proc/loadavg", "r");
if (f) {
fscanf(f, "%d.%d", &load, &i);
fclose(f);
} else {
load = i = 0;
}
load = 100 + load * 100 + i;

for (i=0; i < sizeof(hearth)/sizeof(hearth[0]); i++) {
if (ioctl(consolefd, KDGETLED, &led)
|| ioctl(consolefd, KDSETLED,
(led & ~chosenled) | chosenled * hearth[i])) {
fprintf(stderr, "%s: ioctl(): %s\n", prgname, strerror(errno));
exit(2);
}
usleep(udelay/load);
}
close(consolefd);
}
exit(0); /* never happen */
}


Das kann natürlich nur root ausführen ...

jonasge
01-09-2002, 08:32
HI !!
Danke fuer deine Denkanstoesse!! :-)
Jetzt geht es.
Wenn ich die Datei /tmp/internet erfolgreich oeffne, dann sollte ich die auch wieder
schliessen, sonst hat wird sie ja immer wieder geoeffnet, und das ergab den Fehler.
Nochmals danke :-)
Jetzt muss nurnoch das mit den Buttons am gameport funkten und dann brauche ich
noch ein paar Teile und mein ganzer Stolz ist fertig. :-)

Hier nochmals der richtige Code:


#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#define PORT "/dev/ttyS0"
#define DATEI "/tmp/internet"
int main(int argc, char** argv)
{
FILE *file;
int currstat=0;
int laststat=0;
int fd = 0;
int i=4;
if((fd = open(PORT, O_RDWR | O_NDELAY)) < 0)
{
printf("Fehler: Device \"%s\" kann nicht geöffnet werden.\n", PORT);
return 2;
}
while (1)
{
usleep(75000);
laststat = currstat;
currstat = 0;
if ((file = fopen(DATEI, "r")) != NULL)
{
currstat |= TIOCM_RTS;
fclose(file);
}
else
{
currstat &= ~TIOCM_RTS;
}
if (currstat != laststat)
{
ioctl(fd,TIOCMSET, &currstat);
}

}

return 0;
}




Gruss
Jonas :-)

mithras
02-09-2002, 10:38
das ganze hört sich überaus interessant an, nur leider verstehe ich net so ganz was genau du da ansteuerst!
kannst mich mal bitte etwas aufklären!?

jonasge
02-09-2002, 12:14
Hi,
was hört sich interessant an?
Das Programm starte ich beim Systemstart, und dieses check alle 75 ms ob die Datei /tmp/internet vorhanden ist, wenn ja wird die LED angeschalten.
Bzw. Es ist eine LED die grün/rot anzeigen kann. Wenn ich im Internet bin leuchtet die LED rot, wenn ich nicht im I-Net bin leuchtet die LED grün.
Mehr ist das nicht.

Simpel, aber doch genial, hat nicht jeder. :)

Noch fragen ?


Gruss
Jonas ->der wieder happy ist :D

P.S. Kennt jemand eine Bauanleitung fuer einen ANALOGEN Joystick ?

mithras
02-09-2002, 20:55
welche led, wie steurest du die?

jonasge
02-09-2002, 21:36
Hi,
die LED ist an ttyS0 (COM 1 ) angeschlossen.
Genauer gesagt an Pin "RTS" und "GND". DIe Pinnummer weiss ich
gerade nicht auswendig, das findet du aber ueberall im Netz.

Die LED wird ein/aus -geschalten, mit dem obrigen C -Programm.
Wenn die Datei /tmp/internet vorhanden ist, wird die LED angeschalten.
Wenn die Datei nicht vorhanden ist, wird die LED ausgeschalten.
Mein Programm wird einfach compiliert (gcc led.c -o led) und dann
gestartet mit led &

Noch fragen ?

Gruss
Jonas

mithras
04-09-2002, 11:05
coole sache, hast du vielleicht ein paar links zu tuts parat die sich mit com-schnittstellen-programmierung befassen!

nobody0
04-09-2002, 14:46
Das Buch "Linux Gerätetreiber" (gibt´s auch in Englisch; die 2. Auflage sollte man zum 2.4.x-Kernel haben).
Am einfachsten ist der Parallelport, weil man mit einem einfachen Befehl wie outb(0x380,0xF0) oder in_byte=inb(0x378) TTL-Pulse direkt ausgeben oder einlesen kann.
Über den Status-Port bzw. die Status-Pins kann immer eingelesen werden, über den Controll-Port bzw. die Kontroll-Pins immer ausgegeben werden kann und über den Daten-Port bzw. die Daten-Pins zumindest eingelesen werden kann.
Dabei muss man natürlich vorsichtig sein, denn sonst kann man einen Parallelport weniger haben ...


Hier ist mal ein Beispiel-Programm:

/* pario.c
* Dient zum Auslesen der Standard-Parallelport-Register und kann z. B.
* verwendet werden um zu sehen, welche Werte in das Status-Register
* geschrieben wurden.
*
* This Program won't work on the sparc, where there's no concept of I/O space
* Tested with Linux 2.2 on the x86.
*
* important: this program won't work without the compiler-option -O or -02 ...
* and this program can only be run by a superuser (or another user after
* "chown root.root pario; chmod 4755 pario").
*
* It takes approx. 1,5us for one Parallel Port I/O (with an onboard Parallel Port).
*/

#include <stdio.h>
#include <errno.h> /* error codes */
#include <sys/io.h> /* or <asm/io.h> */
// #include <unistd.h> // getuid()


int main()
{
const unsigned int b=0x9800; /* parallel port base (e. g. 0x3bc, 0x378 or 0x278), a wrong value may cause serious damage */
unsigned char i=0;

// if (getuid()!=0)
// {
// printf("\a\n\nError: $UID==%d!=0 (you are not a superuser).\n\n",getuid());
// exit (-EPERM);
// }
iopl(3); /* allows access to all I/O-Ports, ioperm doesen't work above the 0x3ff-Limit */
outb(0x2b,b+2); /* read (does normally work only for the status register) */
i=inb(b+1);
printf("Der Wert, der von Port 0x%hx (Status-Register des Parallelports) soeben gelesen wurde ist: 0x%hx\n\n",b+1,i);
i=inb(b);
printf("Der Wert, der von Port 0x%hx (Daten-Register des Parallelports) soeben gelesen wurde ist: 0x%hx\n\n",b,i);
i=inb(b+2);
printf("Der Wert, der von Port 0x%hx (Kontroll-Register des Parallelports) soeben gelesen wurde ist: 0x%hx\n\n",b+2,i);
iopl(0); /* release region */
exit(0);
}

Statt den 0x9800 für eine PCI-Karte mit Parallelport muss man für den onboard normalerweise 0x378 nehmen (notfalls im BIOS nachsehen) und der IRQ ist egal.