PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : serielle Schnittstelle mit C unter LInux



stochri
04.01.2006, 12:41
Hat schon mal jemand die serielle Schnttstelle unter Linux mit einem kleine C-Programm angesteuert? Oder weiss jemand, wie man das geschickt macht?
Ich würde gerne meine ASURO unter LInux fernsteuern.

Gruss,
stochri

izaseba
04.01.2006, 14:49
Hallo stochri,

Ich habe mich mal in c++ versucht, es ist ganz einfach die serielle Schnittstelle anzusprechen.
Ich hab da eine Klasse geschrieben, aber in C ist es auch ohne Problemme möglich:



#include "avr.h"
#include <iostream>

using namespace std;

avr::avr(void)
: fd_avr(-1)
{
}

avr::~avr(void)
{
closeDevice();
fd_avr = -1;
}

void avr::waitms(int ms)
{
struct timeval tv;
tv.tv_sec=0;
tv.tv_usec=ms*1000;
select(0, NULL, NULL, NULL, &tv);
}



int avr::open_port(void) {
if (fd_avr != -1) {
//Bereits geöffnet, will nicht nochmal öffen
return 1;
}
struct termios newtio;

fd_avr = open(DEVICE, O_RDWR | O_NOCTTY | O_NDELAY );
if (fd_avr == -1) {
perror(DEVICE);
return(-1);
}
else {
fcntl(fd_avr, F_SETFL, FNDELAY);
newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD ;
newtio.c_iflag = IGNPAR | ICRNL ;
newtio.c_oflag = 0;
newtio.c_lflag &= ~(ICANON);

tcflush(fd_avr, TCIOFLUSH);
tcsetattr(fd_avr,TCSANOW,&newtio);
return fd_avr;

}

}

int avr::write_port(unsigned char _byte){
if (fd_avr == -1) {
cout << "ERROR use avr::open() first" << endl;
return 0;
}
int a = write(fd_avr, &_byte ,1);
return a;
}
int avr::read_port(unsigned char * _byte) {
if (fd_avr == -1) {
cout << "ERROR use avr::open() first" << endl;
return 0;
}
int size = read(fd_avr,_byte,1);
return size ;
}

int avr::getfd()
{
return fd_avr;
}

bool avr::isOpen()
{
return (fd_avr != -1) ? true : false;
}

void avr::closeDevice()
{
if( isOpen() )
close(fd_avr);
fd_avr = -1;
}


Dazu der Header:



#ifndef _AVR_H_
#define _AVR_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <ctype.h>
#include <assert.h>
#define DEVICE "/dev/ttyS0"
#define BAUDRATE B9600

class avr
{
public:
avr(void);
~avr();
void waitms(int);
int open_port(void); // Serielle Schnittstelle öffnen
int write_port(unsigned char); //ein Byte schreiben
int read_port(unsigned char * _byte); //ein Byte lesen
int read_portBlocking(unsigned char * _byte);//Block lesen
int getfd(void); //liefert den Filedescriptor zurück
bool isOpen(void); //Ist der Port schon offen?
void closeDevice(); //Port schliessen
private:
int fd_avr; // Filedescriptor
};
#endif //_AVR_H_


Und ein kleines Testprogramm:



#include "avr.h"
#include <iostream>
using namespace std;

int main (void) {
avr * port = new avr();
unsigned char empfangen;
int a;
port->open_port();


while(1){
port->write_port(255);
port->write_port(1);
port->waitms(500);
port->write_port(254);
port->waitms(5);
port->write_port(1);
port->waitms(500);
port->write_port(255);
port->waitms(5);
port->write_port(0);
port->waitms(500);
port->write_port(254);
port->waitms(5);
port->write_port(0);
port->waitms(500);
port->write_port(253);
port->write_port(0);
port->read_port(&empfangen);
a = empfangen;
port->read_port(&empfangen);
if (empfangen == 0) {
cout << "Temperatur beträgt " << a << " Grad" << endl;
}else {
cout << "Temperatur beträgt " << a << ",5 Grad" << endl;

}
port->waitms(5);
}
return 0;
}


Ich hoffe, Du kommst damit klar.

das Testprogamm macht nichts anderes als als paar Werte an die Serielle zu schicken, womit der Avr seinerseits die Temperaturwerte schickt, die dann am Bildschirm angezeigt werden.

Wenn interesse besteht, suche ich den Link, wo das alles beschreiben ist, jetzt finde ich ihn nicht :-(

Gruß Sebastian

stochri
04.01.2006, 14:51
Hallo izaseba,
vielen Dank für die Info. Da hätte ich auch gleich noch eine Frage: Welches Entwicklungssystem verwendest Du? Oder machst Du alles aus der Kommandozeile?

Gruss,
stochri

izaseba
04.01.2006, 15:11
Ich arbeite sehr gerne in der Konsole, mit Emacs, einem sehr mächtigem Editor, und wenn Du lieber in X arbeiten möchtest und z.B. KDE sowieso drauf hast dann schaue Dir mal den QT Designer an, damit bekommst Du eine schöne Oberfläche, ala Delphi, aber wie gesagt, man braucht da die QT Bibliotheken, die sind ja auch mittlerweile für Windows verfügbar, womit Du plattformunabhängig programmierst.

Gruß Sebastian

izaseba
05.01.2006, 11:49
Noch ein kleiner Nachtrag,

Auf dieser (http://www.easysw.com/~mike/serial/serial.html#2_5) Seite findest Du alles was Du brauchst.
Ich hoffe, daß Dir das weiterhilft.

Gruß Sebastian

stochri
05.01.2006, 15:16
Hallo Izazeba,
im Moment probiere ich es noch auf die "theoretisch" einfache Art und Weise, nämlich mit der Kommandozeile. Aber aus irgendwelchen Gründen geht es nur mit root.

ww@Bigtower:~> echo 1 > /dev/ttyUSB0
bash: /dev/ttyUSB0: Keine Berechtigung

Ich kriege nicht raus, wo ich die Berechtigung für die Schnittstelle freigeben kann ( Suse10.0).
Kannst Du mir helfen?

Gruss,
stochri

izaseba
05.01.2006, 15:45
Hmmm,
Ich kenne mich mit Suse nicht aus,und weiß nicht, wie gut Deine Linux kenntnise sind, aber machmal ein


ls -l /dev/ttyUSB0


Ich hab noch eine normale serielle Schnittstelle und bei Gentoo sieht es so dann aus:



ls -l /dev/ttyS0

lrwxrwxrwx 1 root root 5 5. Jan 12:25 /dev/ttyS0 -> tts/0


Das heißt soviel, daß /dev/ttyS0 ein symbolischer Link auf /dev/tts/0 ist.

ein



ls -l /dev/tts/0
crw-rw---- 1 root tty 4, 64 5. Jan 12:25 /dev/tts/0



sagt mir dann aus, daß /dev/tts/0 dem root und der Gruppe tty
gehört.

Jetzt mußt Du nur noch feststellen, daß der Zielnutzer, auch Mitglied der Gruppe tty ist, und das geht bei Suse mit Yast oder Yast2, oder wie auch immer.

Aber, wie gesagt, bei Suse muß es nicht unbedingt tty sein, am besten prüfen.

Ich hoffe, daß es Dir weiterhilft.

Gruß Sebastian

stochri
05.01.2006, 17:29
Hallo Sebastian,
bei mir kommt dieses
crw-rw---- 1 root uucp 188, 0 2006-01-05 18:27 /dev/ttyUSB0

Ich hatte uccp mit yast schon freigegeben, aber die Berechtigung wurde erst beim Neustart des Computers aktuallisiert, das wusste ich nicht.
Jetzt gehts aber.

Vielen Dank,
stochri

izaseba
05.01.2006, 17:42
aber die Berechtigung wurde erst beim Neustart des Computers aktuallisiert, das wusste ich nicht.

Nein, es ist kein Windows, sorry habe vegessen zu sagen, daß Du Dich ab, und wieder anmelden sollst :oops:

Die Gruppenzugehörigkeit wird nur beim Anmelden ausgewertet...

Gruß Sebastian

stochri
05.01.2006, 21:20
Nein, es ist kein Windows, sorry habe vegessen zu sagen, daß Du Dich ab, und wieder anmelden sollst Embarassed

Jaja, aber eigentlich ist es ja gar nicht so unlogisch.

Ich habe mal einen neuen Thread für die ASURO-Linux-Fersteuerung aufgemacht:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=15726

Aber leider muss ich jedesmal minicom aufmachen, damit die Schnittstelle richtig initialisiert wird. Eigentlich sollte das mit setserial gehen.

Gruss,
stochri