Aktyw Forum

Zarejestruj się na forum.ep.com.pl i zgłoś swój akces do Aktywu Forum. Jeśli jesteś już zarejestrowany wystarczy, że się zalogujesz.

Sprawdź punkty Zarejestruj się

Problem z transmisja przez RS232 pod Windows

czarlz
-
-
Posty:6
Rejestracja:7 sty 2006, o 22:07
Lokalizacja:Wrocław
Kontaktowanie:
Problem z transmisja przez RS232 pod Windows

Postautor: czarlz » 7 sty 2006, o 22:16

Witam!
Sytuacja wyglada nastepujaco.. zrobilem uklad mikrokontrolera, zaprogramowalem, by odbijal znaki, ktore odbierze. Zatem po wyslaniu 'A' powinienem dostac 'A'. I tak jest w przypadku gdy korzystam z hyperterminala, a wiec uklad mikrokontrolera jest sprawny i to nie on jest powodem problemow (tak domniemam). Jezeli probuje wysylac znak przy uzyciu wlasnej aplikacji opartej o funkcjie API takie jak CreateFile, WriteFile oraz ReadFile odbieram go w dwoch kopiach, czyli wysylam 'A', dostaje 'A', dalej wysylam 'B', ale dostaje spowrotem 'A' i tak kazdy znak w dwoch kopiach. Jestem prawie pewien, ze wysylanie i odbieranie wykorzystuje ten sam bufor, a ja odbieram raz znak ktory chcialem wyslac, a drugi raz znak ktory wysyla mikrokontroler. Sytuacja taka jest opisana w ksiazce "RS232 praktyczne programowanie", gdzie autor zaleca stosowanie pomiedzy funkcjami WriteFile i ReadFile funkcji FlushFileBuffers, oprozniajacej bufor. Tak tez zrobilem, ale nie przynioslo to zadnego efektu. Okazalo sie, ze funkcja sie nie wykonuje, tj zwraca 0 lub FALSE. Uzywajac GetLastError otrzymalem kod bledu 50, jest to ERROR_NOT_SUPPORTED, czyli "The network request is not supported". Ma ktos moze pomysl, dlaczego tak jest? Od razu moze zaznacze, ze przy CreateFile dalem flage GENERIC_WRITE. Z gory dziekuje za pomoc i pozdrawiam!

a_antoniak
-
-
Posty:651
Rejestracja:13 sty 2005, o 18:38
Lokalizacja:Krasnystaw
Kontaktowanie:

Postautor: a_antoniak » 8 sty 2006, o 00:26

Samo GENERIC_WRITE? Daj kod (ujęty w tagi Code!) otwarcia, zapisu i odczytu.
Ostatnio zmieniony 8 sty 2006, o 00:28 przez a_antoniak, łącznie zmieniany 1 raz.

czarlz
-
-
Posty:6
Rejestracja:7 sty 2006, o 22:07
Lokalizacja:Wrocław
Kontaktowanie:

Postautor: czarlz » 8 sty 2006, o 00:28

Chciales chyba zapytac o GENERIC_WRITE... ale sa oba, tzn. GENERIC_WRITE i GENERIC_READ. W przypadku funkcji FlushFileBuffers znaczenie ma tylko GENERIC_WRITE i dlatego wspomnialem tylko o tym...

a_antoniak
-
-
Posty:651
Rejestracja:13 sty 2005, o 18:38
Lokalizacja:Krasnystaw
Kontaktowanie:

Postautor: a_antoniak » 8 sty 2006, o 00:31

szybki jestes :) odpowiedziales zanim zdazylem zmienic :). daj kod - bedzie prosciej

czarlz
-
-
Posty:6
Rejestracja:7 sty 2006, o 22:07
Lokalizacja:Wrocław
Kontaktowanie:

Postautor: czarlz » 8 sty 2006, o 00:39

Kod jest chyba uniwersalny..

uart.h

Kod: Zaznacz cały

#include <windows.h> #include <commctrl.h> #include <iostream> #include <conio.h> int SetupUart(char *Port="COM1",int baud=9600,int Bitsize=8,int StopBits=1,int Parity=NOPARITY); int WriteUart(unsigned char *buf, int len); int ReadUart(unsigned char *buf, int len); int CloseUart();
uart.cpp

Kod: Zaznacz cały

#include "UART.h" using namespace std; DCB PortDCB; COMMTIMEOUTS CommTimeouts; HANDLE hPort; /**************************************************************************** * SetupUart() * * This function initialises the serial port and opens it ready to send and * receive data. * * The default setup is: (define in Uart.h) * COM1 9600,8,1,NOPARITY * * Usage for default setup: SetupUart(); * Or usage for specific parameters: SetupUart("COM2",2400,8,1,NOPARITY); * * Parity can be: Bitsize can be: * EVENPARITY 5 - 8 * MARKPARITY * NOPARITY * ODDPARITY * SPACEPARITY * * Will return 0 if the function fails ******************************************************************************/ return 0; } int SetupUart(char *Port,int baud,int Bitsize,int StopBits,int Parity) { int STOPBITS; if(StopBits == 1) STOPBITS = ONESTOPBIT; // if(StopBits == 1.5) STOPBITS = ONE5STOPBITS; if(StopBits == 2) STOPBITS = TWOSTOPBITS; // Open the serial port. hPort = CreateFile (TEXT(Port), // Name of the port GENERIC_WRITE | GENERIC_READ, // Access (read-write) mode 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, NULL); // If it fails to open the port, return 0. if ( hPort == INVALID_HANDLE_VALUE ) { //We failed to open! return 0; } //Get the default port setting information. GetCommState (hPort, &PortDCB); // Change the settings. PortDCB.BaudRate = baud; // BAUD Rate PortDCB.ByteSize = Bitsize; // Number of bits/byte, 5-8 PortDCB.Parity = Parity; // 0-4=no,odd,even,mark,space PortDCB.StopBits = STOPBITS; // StopBits PortDCB.fNull = 0; // Allow NULL Receive bytes // Re-configure the port with the new DCB structure. if (!SetCommState (hPort, &PortDCB)) { // Could not create the read thread. CloseHandle(hPort); return 0; } // Retrieve the time-out parameters for all read and write operations // on the port. GetCommTimeouts (hPort, &CommTimeouts); memset(&CommTimeouts, 0x00, sizeof(CommTimeouts)); CommTimeouts.ReadIntervalTimeout = 10; CommTimeouts.ReadTotalTimeoutConstant = 10; CommTimeouts.WriteTotalTimeoutConstant = 10; // Set the time-out parameters for all read and write operations on the port. if (!SetCommTimeouts (hPort, &CommTimeouts)) { // Could not create the read thread. CloseHandle(hPort); return 0; } // Clear the port of any existing data. if(PurgeComm(hPort, PURGE_TXCLEAR | PURGE_RXCLEAR)==0) { CloseHandle(hPort); return 0; } return 1; //SERIAL SETUP OK } /**************************************************************************** * WriteUart() * * This function Writes data to the serial for receiving device * * Input: *buf - pointer to unsigned char array containing data * len - length of data to be sent * * Usage: WriteUart("HELLO COMS",strlen("HELLO COMS")); * * Will return 0 if the function fails ******************************************************************************/ int WriteUart(unsigned char *buf, int len) { DWORD dwNumBytesWritten; WriteFile (hPort, // Port handle buf, // Pointer to the data to write len, // Number of bytes to write &dwNumBytesWritten, // Pointer to the number of bytes written NULL); // Must be NULL if(dwNumBytesWritten > 0) return 1; //Transmission was success else return 0; //Error transmitting? } /**************************************************************************** * ReadUart() * * This function reads data from the serial port * * Input: *buf - pointer to unsigned char which will contain the received data * len - size of buffer for receiving data * * Usage: ReadUart(indatabuffer,sizeof(indatabuffer)); * * Will return 0 if no data available ******************************************************************************/ int ReadUart(unsigned char *buf, int len) { BOOL ret; unsigned long retlen; ret = ReadFile(hPort, // handle of file to read buf, // pointer to buffer that receives data len, // number of bytes to read &retlen, // pointer to number of bytes read NULL // pointer to structure for data ); if(retlen > 0) //If we have data return (int) retlen; //return the length else return 0; //else no data has been read } /**************************************************************************** * CloseUart() * * Closes connection to the serial port * ******************************************************************************/ int CloseUart() { CloseHandle(hPort); return 1; } int main() { unsigned char cZnak; if(!SetupUart("\\\\.\\COM2", 9600, 8, 1, 0)) { cout << "\nBlad otwarcia portu.\n"; } while(1) { cout << "\nPodaj znak: "; cin >> cZnak; if(!WriteUart(&cZnak, 1)) cout << "\nNic nie wyslano.\n"; Sleep(100); FlushFileBuffers(hPort); cout << GetLastError(); if(ReadUart(&cZnak, 1)) cout << "\nOtrzymano: " << cZnak; } CloseUart(); return 0; }

Dodam moze jeszcze (bo moze to ma znaczenie), ze korzystam z wirtualnego COM`a, wszystko podlaczone jest pod USB, a miedzy mikorokontrolerem a komputerem jest TUSB3410 (konwerter RS <-> USB).

a_antoniak
-
-
Posty:651
Rejestracja:13 sty 2005, o 18:38
Lokalizacja:Krasnystaw
Kontaktowanie:

Postautor: a_antoniak » 8 sty 2006, o 00:53

poczekaj - zmacham na kolanie prosta aplikacje, przetestuje (mam akurat pod Comem C167 - posluzy za "rozmowce" i sprawdzisz czy moj exec dziala). ok?

czarlz
-
-
Posty:6
Rejestracja:7 sty 2006, o 22:07
Lokalizacja:Wrocław
Kontaktowanie:

Postautor: czarlz » 8 sty 2006, o 01:19

Jasne, w takim razie czekam na kod..

a_antoniak
-
-
Posty:651
Rejestracja:13 sty 2005, o 18:38
Lokalizacja:Krasnystaw
Kontaktowanie:

Postautor: a_antoniak » 8 sty 2006, o 01:30

Sprawdzmy execa czy w ogole dziala. program wysyla 1 bajt (Query) i pokazuje dziesietnie pierwszy bajt odpowiedzi (w messageboxie) lub jej brak.
Załączniki
RS232_test_exe.zip
(1.33MiB)Pobrany 346 razy

czarlz
-
-
Posty:6
Rejestracja:7 sty 2006, o 22:07
Lokalizacja:Wrocław
Kontaktowanie:

Postautor: czarlz » 8 sty 2006, o 02:42

Sprawdzilem i... odbiera dokladnie to co wysylamy, ale jest jeden szkopul, mianowicie zaprogramowalem mk zeby po odebraniu zwiekszal znak o jeden i dopiero wysylal. Wtedy wysylajac 0, powinnismy dostac 1, a ja nadal dostaje 0. Wniosek jest taki, bo juz to wczesniej sprawdzalem, odbierajac 2 znaki a nie jeden: pierwszy znak jest dokladnie taki sam jak chcemy wyslac, zaryzykowalbym stwierdzeniem, ze jest to ten sam znak (!), dopiero drugi znak jest odpowiedzia ukladu. Sprobuje to zilustrowac na dolaczonym screenshocie..

[ Dodano: 08-01-2006, 02:25 ]
Moze gwoli scislosci pokaze tez kawalek kodu jakim zaprogramowalem ADuC847, bo o takim mikrokontrolerze jest mowa..

Kod: Zaznacz cały

void main(void) { char cZnak; while(1) { scanf("%c", &cZnak); //++cZnak; - opcja printf("%c", cZnak); } }
Probowalem tez:

Kod: Zaznacz cały

while(1) { do {} while(!RI); c = SBUF; RI = 0; //++c; - opcja do {} while(!TI); SBUF = c; TI = 0; }
Moze to tutaj tkwi blad? Ale czy wtedy hyperterminal dzialalby tak jak trzeba? Moze ktos ma inny pomysl na kod dla ADuC realizujacy echo? Dziekuje za zainteresowanie!
Załączniki
screen2.JPG
screen2.JPG (7.1KiB)Przejrzano 8304 razy

radzio
Moderator
Moderator
Posty:967
Rejestracja:13 maja 2003, o 10:33
Lokalizacja:Sosnowiec
Kontaktowanie:

Postautor: radzio » 8 sty 2006, o 09:10

Też kiedyś się z tym samym problemem męczyłem. Haczyk tkwi w automatyczym echu realizowanym przez funkcje odbioru danej z UARTu (getc i pośrednio scanf itp) - odebrany znak jest automatycznie wysyłany z powrotem do PC. Natomiast drugi kod podany przez Ciebie zadziałał po zamianie kolejności dwóch wierszy :

Kod: Zaznacz cały

while(1) { do {} while(!RI); c = SBUF; RI = 0; //++c; - opcja SBUF = c; do {} while(!TI); TI = 0; }
Obsugę UARTu na uC zawsze pisze sam, nie korzystam z funkcji bibliotecznych, bo jak widać sprawiają sporo problemów.

a_antoniak
-
-
Posty:651
Rejestracja:13 sty 2005, o 18:38
Lokalizacja:Krasnystaw
Kontaktowanie:

Postautor: a_antoniak » 8 sty 2006, o 10:30

Ot i problem wyjasnil sie :). ja tez pisze sam transmisje szeregowa :)

czarlz
-
-
Posty:6
Rejestracja:7 sty 2006, o 22:07
Lokalizacja:Wrocław
Kontaktowanie:

Postautor: czarlz » 9 sty 2006, o 07:26

Absolutne dzieki ! Stawiam piwo, jak cos to wysle tez poczta ;)

Wróć do „PLD/FPGA i inne zagadnienia techniki cyfrowej”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 67 gości