» »

c++ serijski port

c++ serijski port

fogl ::

Zanima me, če ve kdo za kak programček, ki ti pošilje podatke na serijski port (pa da lahko določim protokol in hitrost).
lp, klemen

jype ::

Kaksen protokol? Saj serijski porti so RS232 protokol, a niso?

Na unixih je to razmeroma enostavno:

f = fopen("/dev/ttyS0", "r+");
fwrite(f, "to gre na serijski port\n");
fclose(f);

Ce zelis spreminjat hitrost, start bit, stop bits in parity, potem napisi man ioctl in preberi (mogoce ne pise v ioctl man page, tudi google zna pri tem pomagat).

fogl ::

Kot protokol sem mislil stop bit, start bit, število data bitov...

Našel sem programček na http://www.codeproject.com/system/cserialport.asp , ki naj bi funkcioniral (dobil je dobre ocene), meni pa vrže 90 napak.

Mi lahko nekdo pove kako se to spravi skupej da deluje?
lp, klemen

BigWhale ::

Ja... ce bi nam obelodanil kaj gre narobe...

fogl ::

Sedaj mi najde samo še eno napako in dva opozorila:

--------------------Configuration: SerialPort - Win32 Unicode Debug--------------------
Compiling resources...
Compiling...
app.cpp
c:\documents and settings\klemen\desktop\serial port\kl\cserialport_src\app.cpp(103) : warning C4189: 'dwRead' : local variable is initialized but not referenced
SerialPort.cpp
c:\documents and settings\klemen\desktop\serial port\kl\cserialport_src\serialport.cpp(395) : warning C4189: 'dwBytesWritten' : local variable is initialized but not referenced
StdAfx.cpp
Linking...
xilink6: executing 'C:\PROGRA~1\MICROS~3\VC98\Bin\link.exe'
LINK : fatal error LNK1104: cannot open file "mfc42ud.lib"
Error executing xilink6.exe.

SerialPort.exe - 1 error(s), 2 warning(s)

Kaj to pomeni, od kje mu ta fajl?
lp, klemen

fx ::

jype jaz sem uporabil, to kar si napisal, samo nevem kako naj deklariram f, ker mi prevajalnik javi napako, ker ni deklariran.

lp

"Naj živ Unix"

BigWhale ::

FILE *f;

fx ::

Mene pa zdaj zanima zakaj mi prevajalnik javlja napako, še pa sem tako naredil, kot mora biti, vse sem preveril in je ne najdem:

/usr/include/stdio.h: In function `void Send(int)':
/usr/include/stdio.h:609: error: too few arguments to function `size_t
fwrite(const void*, unsigned int, unsigned int, FILE*)'
slo_tech.cpp:64: error: at this point in file

to pa je koda:
void Send(int number)
{
  FILE *x;
  x = fopen("/dev/ttyS0", "r+");
  fwrite(x, number);
  fclose(x);
  cout << "hex = " << hex << number << endl;
  cout << "dec = " << dec << number << endl;
}

lp

<b>"Naj živi UNIX"</b>

Zgodovina sprememb…

  • spremenil: fx ()

OwcA ::

Saj ti lepo pove, premalo (in za povrh še v napačnem redu) argumentov podaš fwrite().
Otroška radovednost - gonilo napredka.

fx ::

int serial_setspeed(int fd)
{
    struct termios tc;
    tcgetattr(fd, &tc);
    cfsetspeed(&tc, B2400);
    tcsetattr(fd, TCSANOW, &tc);
    return 0;
}

void Send(int number)
{
  serport = open("/dev/ttyS0", O_RDWR);
  serial_setspeed(serport);
  write(serport, &number, sizeof(number));
  close(serport);
}


To kodo je napisal trs, mislim da ga poznate iz irc, samo ga zdaj nemorem dobiti. In me zanima kako bi nastavo v tem podatkovni bit, parnost in zakljiučni bit.

lp

"Naj živi UNIX"

fx ::

Da ne boste mislili da nisem prebal ioctl page, sem samo to je tako splošno da si jaz nemorem nič pomagati.

lp

"Naj živi UnIX"

Vesoljc ::

special bite (pariteta, zakljucni, itd...) so (kolikor je to meni jasno) vkljuceni v sporocilo, ki ga posljes. v tvojem primeru je to sporocilo dolgo 32bitov (int). imas torej vsaj dve moznosti, povecas velikost (64), ali pa zmanjsas "svoje" sporocilo, ki je v biti int. ko tako dobis prostor za dodatne bite, jih le-te vkljucis v spremenljivko sz pomocjo bitnih operacij (go google for bitwise operations).

pa se ena stvar: ko reces send, ji podas parameter po vrednosti. ustvari se zacasna spremenljivka znotraj tvoje funkcije, ki se ji pripise vrednost podanega parametra. zatorej sklicevanje na "&number" ni najbolj "cisto", ceprav v tem primeru verjetno dela...
Abnormal behavior of abnormal brain makes me normal...

fx ::

#include <unistd.h>
#include <fcntl.h>
#include <termios.h>

#include <string.h>
#include <errno.h>
#include <stdio.h>

#define SET_MASK(var, mask, bits) var = ((var) & ~(mask)) | ((bits) & (mask))
#define SET_BITS(var, mask) var |= ~(mask)
#define CLR_BITS(var, mask) var &= ~(mask)

/*
 * serial_setparam:
 *      fd          - this is the file descriptor of the serial port
 *      baudrate    - the desired baud rate, currently only 2400 bauds is
 *                    supported
 *      bits        - bit size, valid values are from 5 to 8 bits.
 *      parity      - this can be either 'N', 'E' or 'O' with the following
 *                    meanings:
 *                          'N' - NO PARITY
 *                          'E' - EVEN PARITY
 *                          'O' - ODD PARITY
 *      stopbits    - either 1 or 2, representing the number of stop bits
 *      softflow    - boolean, 0 for hardware flow control, 1 for software
 */
int serial_setparam(int fd, int baudrate, int bits, char parity, int stopbits, int softflow)
{
    struct termios tc;
    int    retval;

    /* GET ATTRIBUTES */
    retval = tcgetattr(fd, &tc);
    if (retval != 0)
    {
        fprintf(stderr, "tcgetattr() failed: %s\n", strerror(errno));
        return 1;
    }

    /* SET BAUD RATE */
    /* XXX: This sucks ;) */
    if (baudrate != 2400)
    {
        fprintf(stderr, "Unsupported baud rate %d\n", baudrate); 
        return 1;
    }

    retval = cfsetspeed(&tc, B2400);
    if (retval != 0)
    {
        fprintf(stderr, "cfsetspeed() failed: %s\n", strerror(errno));
        return 1;
    }

    /* CLEAR ALL FLAGS */
    CLR_BITS(tc.c_cflag, PARENB | PARODD | CSIZE | CSTOPB);

    /* SET BITS */
    switch (bits)
    {
        case 5:
            SET_BITS(tc.c_cflag, CS5);
            break;

        case 6:
            SET_BITS(tc.c_cflag, CS6);
            break;

        case 7:
            SET_BITS(tc.c_cflag, CS7);
            break;

        case 8:
            SET_BITS(tc.c_cflag, CS8);
            break;

        default:
            fprintf(stderr, "Unsupported bit size: %d\n", bits);
            return 1;
    }
    /* SET PARITY */
    switch (parity)
    {
            /* Disable parity */
            case 'N':
                /* Nothing to do */
                break;

            /* Enable parity, EVEN */
            case 'E':
                SET_BITS(tc.c_cflag, PARENB);
                break;

            /* Enable parity, ODD */
            case 'O':
                SET_BITS(tc.c_cflag, PARENB | PARODD);
                break; 

            default:
                fprintf(stderr, "Unsupported parity: it souhld be 'N' - none, 'E' -even, 'O' - odd\n");
                return 1;
    }

    /* SET STOP BITS */
    switch (stopbits)
    {
        case 1:
            /* Nothing to do */
            break;

        case 2:
            SET_BITS(tc.c_cflag, CSTOPB);
            break;

        default:
            fprintf(stderr, "Unsupporte stopbits number %d, use either 1 or 2\n", stopbits);
            return 1;
    }

    /*
     * ADDITIONAL STUFF: I'm not really sure why is this needed, I just copied
     * the stuff from minicom
     */

    /* Set line to RAW, NOECHO mode */
    tc.c_iflag = IGNBRK; /* IGNBRK, ignore break condition */
    tc.c_lflag = 0;
    tc.c_oflag = 0;
    /* CLOCAL, ignore modem status line. CREAD, enable receiver, CRTSCTS, CTS
     * flow control of output */
    SET_BITS(tc.c_cflag, CLOCAL | CREAD | CRTSCTS);

    tc.c_cc[VMIN]  = 1; /* Minimum bytes recevied    */
    tc.c_cc[VTIME] = 5; /* Read delay in 0.1 seconds */

    /* Software flow control */
    if (softflow)
    {
        SET_BITS(tc.c_iflag, IXON | IXOFF);
    }
    else
    {
        CLR_BITS(tc.c_iflag, IXON | IXOFF | IXANY);
    }

    /* FINALLY, SET ATTRIBUTES */
    retval = tcsetattr(fd, TCSANOW, &tc);
    if (retval != 0)
    {
        fprintf(stderr, "tcsetattr() failed: %s\n", strerror(errno));
        return 1;
    }

    return 0;
}

int main(void)
{
    int retval;
    int serial;
    int ii;

    serial = open("/dev/ttys0", O_RDWR);
    if (serial < 0)
    {
        fprintf(stderr, "cannot open /dev/ttys0: %s\n", strerror(errno));
        return 1;
    }

    /* Set serial port parameters: 2400 baud, None parity, 1 stop bit, no
     * software flow control */
    retval = serial_setparam(serial, 2400, 8, 'N', 1, 0);
    if (retval != 0)
    {
        fprintf(stderr, "serial_setparam() failed, exiting ...\n");
        return 1;
    }

    for (ii = 0; ii < 99; ii++)
    {
        char c;

        c = ii;
        retval = write(serial, &c, sizeof(c));
        if (retval < 0)
        {
            fprintf(stderr, "write() failed: %s\n", strerror(errno));
            return 1;
        }

        sleep(1); /* 1 second delay between writes */
    }

    close(serial);

    return 0;
}



Zgoraj je koda, katero je zopet napisal trs, je zanimivo da zopet ne dela.

Namestil sem si minicom nastavil 2400 8N1 in deluje, a v programu pa ne deluje. Zdaj pa več ne vem kaj je narobe.
Zato bi prosil če bi kdo kodo preizkusil. A v linuxu tudi moram dodano nastaviti hitros, itd kot v win ali ni treba.

lp

"Naj živi UNIX"

Zgodovina sprememb…

  • spremenil: fx ()

trs ::

Hmm... zanimivo, da ti je prvic delalo, pol pa je kar nehalo. Lahko pastas tocno kaj ti izpise ta program ko ga startas ... error, karkoli?

lp,
trs

fx ::

Program se lepo prevede in ga zaženem, a neboš verjel nič ne izpiše nobenega errorja ven ne vrže nič, lahko pišeš cifre tlačiš enter in nič razen če pritisneš ctrl + c da zaključiš z programom to pa je vse.

lp

"Naj živi UNIX"

fogl ::

Demo programček (ta naj bi deloval), ki je bil poleg knjižnice za serijski port mi javi napake:
ChildView.obj : error LNK2001: unresolved external symbol "public: static unsigned int const CSerialWnd::mg_nDefaultComMsg" (?mg_nDefaultComMsg@CSerialWnd@@2IB)
ChildView.obj : error LNK2001: unresolved external symbol "public: virtual long __thiscall CSerialWnd::Open(unsigned short const *,struct HWND__ *,unsigned int,long,unsigned long,unsigned long)" (?Open@CSerialWnd@@UAEJPBGPAUHWND__@@IJKK@Z)
ChildView.obj : error LNK2001: unresolved external symbol "protected: virtual void __thiscall CSerialWnd::OnEvent(enum CSerial::EEvent,enum CSerial::EError)" (?OnEvent@CSerialWnd@@MAEXW4EEvent@CSerial@@W4EError@3@@Z)
ChildView.obj : error LNK2001: unresolved external symbol "public: virtual long __thiscall CSerialEx::StopListener(unsigned long)" (?StopListener@CSerialEx@@UAEJK@Z)
...
A kdo ve v čem je problem?
lp, klemen

BigWhale ::

Nekaj se ne linka prav...

fogl ::

Kaj sploh pomeni da se neki linka, kaj prevajalnik takrat dela? Kaj lahko spremenim?
lp, klemen

BigWhale ::

Prevajalnik takrat ne pocne nicesar vec, takrat stopi v akcijo linker... oziroma povezovalnik ;)

BigWhale ::

Naredi pa to, da ti iz polno .o datotek, ki so ze prevedene .c/.cpp/.whatever naredi izvrsno datoteko.

fogl ::

Zdej sem našel odgovor zakaj pride do tezav pri linkanju:
I had a similar problem when I was playing with CSerial for the first time. All code examples are included in Serial.dsw and have dependencies. Try to open that file in your VC++. Then you'll find that all projects depend on Serial.dsp (small short-cut like icon) - that's your missing 'resource'. Compiling the examples from Serial.dsw should work.
Ampak meni še vedno ni jasno kaj bi moral narediti :( Bi lahko kdo to poskusi, vse je tukaj, rad bi zagnal demo programček SerialTestMFC.
lp, klemen

fx ::

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>

int main()
{

  int fd;

  fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);
  if (fd == -1)
  {
    perror ("open_port: Unable to open /dev/ttyS0 - ");
    exit(1);
  }
  else
   fcntl(fd, F_SETFL, 0);

  struct termios options;

  tcgetattr(fd, &options);

  cfsetispeed(&options, B9600); //vhodna hitraost
  cfsetospeed(&options, B9600); //izhodna hitrsot

  options.c_cflag |= (CLOCAL | CREAD);
  //Zacetek brez paritete 8N1
  options.c_cflag &= ~PARENB;
  options.c_cflag &= ~CSTOPB;
  options.c_cflag &= ~CSIZE;
  options.c_cflag |= CS8;
  //Konec brez paritete 8N1

  options.c_cflag |= CRTSCTS;
  options.c_lflag |= (ICANON | ECHO | ECHOE);

  //Zacetek Input Options
  options.c_iflag |= (INPCK | ISTRIP);
  options.c_iflag |= (IXON | IXOFF | IXANY);
  //Konec Input Options

  //Zacetek Output Options
  options.c_oflag |= OPOST;
  //Konec Output Options
  options.c_cc[VMIN] = 0;  //sprejem vse znake
  options.c_cc[VTIME] = 10; //cakalani cas na podatek
  tcsetattr(fd, TCSANOW, &options);

  int n;

  n = write(fd, "ATZ\r", 4);
  if (n < 0)
    fputs("Write() of 4 byte failed!\n", stderr);
  close(fd);

  return (0);
}



Zgoraj je koda, ki sem jo sestavil s pomočjo tega linka in mi zadeva na drugi PC ne pošlje ukaza ATZ. Kabel je dobro narejen, saj sem ga preveril s pomočjo HT na dveh PC. Prosim za pomoč.
Nastavitve so tako - 9600 8N1 pa XON/XOFF nazdor.

lp

"UNIX & C++"

fx ::

Kaj nihče mi ne more pomagati?

lp

"UNIX & C++"Kaj nihče mi ne more pomagati?

Gundolf ::

Pojma nimam o serijskih portih. Najdi knjižnico, ki zna delati prav to - komunicirati prek COM.

CCfly ::

"My goodness, we forgot generics!" -- Danny Kalev

fx ::

jype kako pa so nastavitve pri tvoji možnosti?
f = fopen("/dev/ttyS0", "r+");
fwrite(f, "to gre na serijski port\n");
fclose(f);

lp

"UNIX & C++"


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Shell scripta

Oddelek: Programiranje
61431 (1035) BigWhale
»

[C] Kazalec tipa char na podatke iz datoteke

Oddelek: Programiranje
61123 (1084) Matako
»

c++ vstavljanje knjižnice v kodo

Oddelek: Programiranje
161612 (1271) SasoS
»

c++ datoteke

Oddelek: Programiranje
464030 (3519) Vesoljc
»

LPT porti in linux...

Oddelek: Operacijski sistemi
152484 (2291) Trojaner

Več podobnih tem