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
Moderatorzy:Jacek Bogusz, Moderatorzy
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!
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!
-
- -
- Posty:651
- Rejestracja:13 sty 2005, o 18:38
- Lokalizacja:Krasnystaw
- Kontaktowanie:
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.
-
- -
- Posty:651
- Rejestracja:13 sty 2005, o 18:38
- Lokalizacja:Krasnystaw
- Kontaktowanie:
Kod jest chyba uniwersalny..
uart.h
uart.cpp
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).
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();
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).
-
- -
- Posty:651
- Rejestracja:13 sty 2005, o 18:38
- Lokalizacja:Krasnystaw
- Kontaktowanie:
-
- -
- Posty:651
- Rejestracja:13 sty 2005, o 18:38
- Lokalizacja:Krasnystaw
- Kontaktowanie:
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
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..
Probowalem tez:
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!
[ 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);
}
}
Kod: Zaznacz cały
while(1)
{
do {} while(!RI);
c = SBUF;
RI = 0;
//++c; - opcja
do {} while(!TI);
SBUF = c;
TI = 0;
}
- Załączniki
-
- screen2.JPG (7.1KiB)Przejrzano 8305 razy
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 :
Obsugę UARTu na uC zawsze pisze sam, nie korzystam z funkcji bibliotecznych, bo jak widać sprawiają sporo problemów.
Kod: Zaznacz cały
while(1)
{
do {} while(!RI);
c = SBUF;
RI = 0;
//++c; - opcja
SBUF = c;
do {} while(!TI);
TI = 0;
}
-
- -
- Posty:651
- Rejestracja:13 sty 2005, o 18:38
- Lokalizacja:Krasnystaw
- Kontaktowanie:
Kto jest online
Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 82 gości