Serial communication
-
Hello.. I'm a beginner with Visual C++.. (have only done very very basic C++ programming).. I'm trying to communicate with a microcontroller using serial communication.. I tried to do it from scratch using the Windows functions..this is what my code looks like..
#include "stdafx.h" int _tmain() { HANDLE h = CreateFile("COM3", GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if (h == 0) { printf("Can't open com port (1)\n"); return 1; } DCB dcb; memset(&dcb, 0, sizeof(DCB)); dcb.DCBlength = sizeof(DCB); dcb.BaudRate = 19200; dcb.fBinary = TRUE; dcb.fParity = FALSE; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; BOOL result = SetCommState(h, &dcb); if (!result) { printf("Can't set com port state(2)\n"); return 1; } if (result) printf("Have Set com port state\n"); char buffer[100]; DWORD bytesRead = 0; while (true) { printf("In while\n"); memset(buffer, 0, sizeof(buffer)); if (ReadFile(h, buffer, sizeof(buffer)-1, &bytesRead, 0)) { printf("Read file has a result\n"); if (bytesRead != 0) { printf("Got some bytes\n"); printf ("%s", buffer); } else { printf("No bytes read\n"); } } else { printf("Readfile didnt give proper result \n"); } Sleep(200); } // Close session CloseHandle(h); return 0;
he micro is continously sending characters to the serial port.. when i run the program.. the port does gets initialized properly (debug statement printed ) then some characters are recieved but they are unintelligble.. i've checked the speed and all other settings for the com port and they are the same as the micro and the micro's usart is working fine.. can anyone see why i'm getting garbage.. Thank you for the help.. -
Hello.. I'm a beginner with Visual C++.. (have only done very very basic C++ programming).. I'm trying to communicate with a microcontroller using serial communication.. I tried to do it from scratch using the Windows functions..this is what my code looks like..
#include "stdafx.h" int _tmain() { HANDLE h = CreateFile("COM3", GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if (h == 0) { printf("Can't open com port (1)\n"); return 1; } DCB dcb; memset(&dcb, 0, sizeof(DCB)); dcb.DCBlength = sizeof(DCB); dcb.BaudRate = 19200; dcb.fBinary = TRUE; dcb.fParity = FALSE; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; BOOL result = SetCommState(h, &dcb); if (!result) { printf("Can't set com port state(2)\n"); return 1; } if (result) printf("Have Set com port state\n"); char buffer[100]; DWORD bytesRead = 0; while (true) { printf("In while\n"); memset(buffer, 0, sizeof(buffer)); if (ReadFile(h, buffer, sizeof(buffer)-1, &bytesRead, 0)) { printf("Read file has a result\n"); if (bytesRead != 0) { printf("Got some bytes\n"); printf ("%s", buffer); } else { printf("No bytes read\n"); } } else { printf("Readfile didnt give proper result \n"); } Sleep(200); } // Close session CloseHandle(h); return 0;
he micro is continously sending characters to the serial port.. when i run the program.. the port does gets initialized properly (debug statement printed ) then some characters are recieved but they are unintelligble.. i've checked the speed and all other settings for the com port and they are the same as the micro and the micro's usart is working fine.. can anyone see why i'm getting garbage.. Thank you for the help..Hi, Can you check this with Hyperterminal tool provided along with the operating systems?. If hyperterminal prints the right characters send by the microcontroller then we can dig into your code... Could you please do this?? And also check whether the characters sent by the microcontroller are ascii or unicode complaint.. " Action without vision is only passing time, Vision without action is merely day dreaming, But vision with action can change the world " - Words from Nelson Mandela Thanks & Regards, Gopalakrishnan
-
Hi, Can you check this with Hyperterminal tool provided along with the operating systems?. If hyperterminal prints the right characters send by the microcontroller then we can dig into your code... Could you please do this?? And also check whether the characters sent by the microcontroller are ascii or unicode complaint.. " Action without vision is only passing time, Vision without action is merely day dreaming, But vision with action can change the world " - Words from Nelson Mandela Thanks & Regards, Gopalakrishnan
-
Hello.. I'm a beginner with Visual C++.. (have only done very very basic C++ programming).. I'm trying to communicate with a microcontroller using serial communication.. I tried to do it from scratch using the Windows functions..this is what my code looks like..
#include "stdafx.h" int _tmain() { HANDLE h = CreateFile("COM3", GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if (h == 0) { printf("Can't open com port (1)\n"); return 1; } DCB dcb; memset(&dcb, 0, sizeof(DCB)); dcb.DCBlength = sizeof(DCB); dcb.BaudRate = 19200; dcb.fBinary = TRUE; dcb.fParity = FALSE; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; BOOL result = SetCommState(h, &dcb); if (!result) { printf("Can't set com port state(2)\n"); return 1; } if (result) printf("Have Set com port state\n"); char buffer[100]; DWORD bytesRead = 0; while (true) { printf("In while\n"); memset(buffer, 0, sizeof(buffer)); if (ReadFile(h, buffer, sizeof(buffer)-1, &bytesRead, 0)) { printf("Read file has a result\n"); if (bytesRead != 0) { printf("Got some bytes\n"); printf ("%s", buffer); } else { printf("No bytes read\n"); } } else { printf("Readfile didnt give proper result \n"); } Sleep(200); } // Close session CloseHandle(h); return 0;
he micro is continously sending characters to the serial port.. when i run the program.. the port does gets initialized properly (debug statement printed ) then some characters are recieved but they are unintelligble.. i've checked the speed and all other settings for the com port and they are the same as the micro and the micro's usart is working fine.. can anyone see why i'm getting garbage.. Thank you for the help..We need more beginners like you. You have good instincts as to how to figure out what the problem is. (You also have the option of using the TRACE() marcos, as well as printf(), in order to print debugging resutls). Unfortunaley your code is good enough that it should probably be working. It does need improvement, but that's not the problem. What the problem is I do not know and I've written severial serial communications programs. In otherwords, I'd have to be degugging it. SOME COMMENTS: 1) CreateFile() doesn't return 0 on failure, it returns INVALID_HANDLE_VALUE (which is equal to -1). All this tells us it that even thou your code does not know if it failed to open a port, it has succeded because you are receiving data. (Oh, if it did fail you code would report that it fail to open port 1 not 3). 2) Use: if(result) {...} else {...}. Not: if(result) {...} if(!resutl) {...} 3) If ReadFile() succededs then bytesRead should not be 0, so checking for it makes no since. GARBAGE IS A RELITIVE TERM: 1) Your code implies that you are expecting to receive (ASCII) text. If that is not what the microcontroller is returning, then it will look like garbage. 2) What are you expecting to receive from the microcontroller? FYI: I assume you know that you are writting C code and not C++ code. (It has no effect on your problem or its solution). INTP "The more help VB provides VB programmers, the more miserable your life as a C++ programmer becomes." Andrew W. Troelsen
-
Hello.. I'm a beginner with Visual C++.. (have only done very very basic C++ programming).. I'm trying to communicate with a microcontroller using serial communication.. I tried to do it from scratch using the Windows functions..this is what my code looks like..
#include "stdafx.h" int _tmain() { HANDLE h = CreateFile("COM3", GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if (h == 0) { printf("Can't open com port (1)\n"); return 1; } DCB dcb; memset(&dcb, 0, sizeof(DCB)); dcb.DCBlength = sizeof(DCB); dcb.BaudRate = 19200; dcb.fBinary = TRUE; dcb.fParity = FALSE; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; BOOL result = SetCommState(h, &dcb); if (!result) { printf("Can't set com port state(2)\n"); return 1; } if (result) printf("Have Set com port state\n"); char buffer[100]; DWORD bytesRead = 0; while (true) { printf("In while\n"); memset(buffer, 0, sizeof(buffer)); if (ReadFile(h, buffer, sizeof(buffer)-1, &bytesRead, 0)) { printf("Read file has a result\n"); if (bytesRead != 0) { printf("Got some bytes\n"); printf ("%s", buffer); } else { printf("No bytes read\n"); } } else { printf("Readfile didnt give proper result \n"); } Sleep(200); } // Close session CloseHandle(h); return 0;
he micro is continously sending characters to the serial port.. when i run the program.. the port does gets initialized properly (debug statement printed ) then some characters are recieved but they are unintelligble.. i've checked the speed and all other settings for the com port and they are the same as the micro and the micro's usart is working fine.. can anyone see why i'm getting garbage.. Thank you for the help..There are two things at the top of my head: flow control and timeouts. In most cases when you are beginning to communicate with a MC or similar you don't need any flow control and you would select "None" in Hyperterminal. In your code this would mean the following setting that you have omitted:
dcb.fDtrControl = DTR_CONTROL_ENABLE; dcb.fRtsControl = RTS_CONTROL_ENABLE;
Since you have fillled the DCB struct with zeros, the HW signals DataTerminalReady and RequestToSend will be inactive. Depending on connected hardware this could have various results from no communication to no impact at all. Regarding timeouts you may want to read about it in MSDN under the documentation for the ::SetCommTimeouts function. Tip of the day: use PortMon! I have found PortMon to be extremely helpful in situations like the one you are describing. PortMon is freeware and can be downloaded at http://www.sysinternals.com/utilities/portmon.html[^] With PortMon it's easy to determine how the port is setup and see what is sent and received in either hex or ASCII. Make sure that the setup sequence looks the same for both your app and HT since HT seems to be working. Hope this helps -- Roger -
There are two things at the top of my head: flow control and timeouts. In most cases when you are beginning to communicate with a MC or similar you don't need any flow control and you would select "None" in Hyperterminal. In your code this would mean the following setting that you have omitted:
dcb.fDtrControl = DTR_CONTROL_ENABLE; dcb.fRtsControl = RTS_CONTROL_ENABLE;
Since you have fillled the DCB struct with zeros, the HW signals DataTerminalReady and RequestToSend will be inactive. Depending on connected hardware this could have various results from no communication to no impact at all. Regarding timeouts you may want to read about it in MSDN under the documentation for the ::SetCommTimeouts function. Tip of the day: use PortMon! I have found PortMon to be extremely helpful in situations like the one you are describing. PortMon is freeware and can be downloaded at http://www.sysinternals.com/utilities/portmon.html[^] With PortMon it's easy to determine how the port is setup and see what is sent and received in either hex or ASCII. Make sure that the setup sequence looks the same for both your app and HT since HT seems to be working. Hope this helps -- RogerHello all.. Thank you for the replies.. Right now i'm sitting with the problem that the program on the PC is SOMETIMES getting the expected data from the micro but sometimes it gets the unintelligble characters.. I've noticed that for instance if i run the program and its gets garbage.. then i close it and wait a bit,run it a coupla times and then it gets the right stuff once.. then if i run it again it'll give garbage again.. and for the next coupla times it'll just give garbage.. then after a coupla tries it'll give the right stuff after some time ??!!! In my code.. I use CloseHandle() to close the serial connection.. but i've noticed that after running the program and exiting it and then using the a terminal program such as HyperTerminal.. then HyperTerminal has trouble getting the characters from the serial port.. but after giving some time then HyperTerminal starts getting the characters properly.. The program always garbage when the micro starts sending characters to it (at power up).. and then has to be run a coupla times before it'll give the right output once.. Is there any other method to close the serial connection properly ? I know my description above is not very technical but I'm a beginner and am trying to give as much info as I can make sense of in this program.. Thank you for your help.. Aditi P.S. I did put in the DTR and RTS control ENABLE lines in the code as suggested by Roger.. but it still behaves the same way..
-
Hello all.. Thank you for the replies.. Right now i'm sitting with the problem that the program on the PC is SOMETIMES getting the expected data from the micro but sometimes it gets the unintelligble characters.. I've noticed that for instance if i run the program and its gets garbage.. then i close it and wait a bit,run it a coupla times and then it gets the right stuff once.. then if i run it again it'll give garbage again.. and for the next coupla times it'll just give garbage.. then after a coupla tries it'll give the right stuff after some time ??!!! In my code.. I use CloseHandle() to close the serial connection.. but i've noticed that after running the program and exiting it and then using the a terminal program such as HyperTerminal.. then HyperTerminal has trouble getting the characters from the serial port.. but after giving some time then HyperTerminal starts getting the characters properly.. The program always garbage when the micro starts sending characters to it (at power up).. and then has to be run a coupla times before it'll give the right output once.. Is there any other method to close the serial connection properly ? I know my description above is not very technical but I'm a beginner and am trying to give as much info as I can make sense of in this program.. Thank you for your help.. Aditi P.S. I did put in the DTR and RTS control ENABLE lines in the code as suggested by Roger.. but it still behaves the same way..
Have you compared the setup sequences for your app and HyperTerminal with PortMon? Any diffs? Aditi484 wrote: In my code.. I use CloseHandle() to close the serial connection.. ::CloseHandle() is the proper call to make. If you are referring to the code you posted in your first mail you'll never reach ::CloseHandle() since it's outside the while-loop. This should make HT complain about the port being busy. How do you exit your application? Terminating it with ? Is it a real RS232 connection you're using or is it some simulated serial connection over USB? It might be helpful if you could log the setup sequence with PortMon and cut it out and send it in your next post. -- Roger
-
Have you compared the setup sequences for your app and HyperTerminal with PortMon? Any diffs? Aditi484 wrote: In my code.. I use CloseHandle() to close the serial connection.. ::CloseHandle() is the proper call to make. If you are referring to the code you posted in your first mail you'll never reach ::CloseHandle() since it's outside the while-loop. This should make HT complain about the port being busy. How do you exit your application? Terminating it with ? Is it a real RS232 connection you're using or is it some simulated serial connection over USB? It might be helpful if you could log the setup sequence with PortMon and cut it out and send it in your next post. -- Roger
Hello.. I just used PortMon and the setup is right between the app and hyperterminal.. I'm using a normal serial port... Below is the log of what PortMmon recorded..
4 0.00006984 comm console.ex IRP_MJ_CREATE Serial1 SUCCESS Options: Open 5 0.00000559 comm console.ex IOCTL_SERIAL_GET_BAUD_RATE Serial1 SUCCESS 6 0.00000196 comm console.ex IOCTL_SERIAL_GET_LINE_CONTROL Serial1 SUCCESS 7 0.00000196 comm console.ex IOCTL_SERIAL_GET_CHARS Serial1 SUCCESS 8 0.00000168 comm console.ex IOCTL_SERIAL_GET_HANDFLOW Serial1 SUCCESS 9 0.00000950 comm console.ex IOCTL_SERIAL_SET_BAUD_RATE Serial1 SUCCESS Rate: 19200 10 0.00000587 comm console.ex IOCTL_SERIAL_SET_RTS Serial1 SUCCESS 11 0.00000559 comm console.ex IOCTL_SERIAL_SET_DTR Serial1 SUCCESS 12 0.00000531 comm console.ex IOCTL_SERIAL_SET_LINE_CONTROL Serial1 SUCCESS StopBits: 1 Parity: NONE WordLength: 8 13 0.00000391 comm console.ex IOCTL_SERIAL_SET_CHAR Serial1 SUCCESS EOF:0 ERR:0 BRK:0 EVT:0 XON:0 XOFF:0 14 0.00000531 comm console.ex IOCTL_SERIAL_SET_HANDFLOW Serial1 SUCCESS Shake:1 Replace:40 XonLimit:0 XoffLimit:0 15 0.00819546 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 16 0.00986215 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 17 0.00978951 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 18 0.00971129 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 19 0.00959787 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 20 0.00904864 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 21 0.00977275 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 22 0.00979733 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 23 0.00865725 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 24 0.00866004 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 25 0.00002375 comm console.ex IRP_MJ_READ Serial1 SUCCESS Length 99: .*W...............M.................M.................M......... 26 0.00002375 comm console.ex IRP_MJ_READ Serial1 SUCCESS Length 99: .........M.................M.................M.................M 27 0.00002319 comm console.ex IRP_MJ_READ Serial1 SUCCESS Length 99: M.................M.................M.................M......... 28 0.00002347 comm console.ex IRP_MJ_READ Serial1 SUCCESS Length 99: .........M.................M.................M.................M 29 0.00002570 comm console.ex IRP_MJ_READ Serial1 SUCCESS Length 99: M.................M.................M.................M......... 30 0.00002542 comm console.ex IRP_MJ_READ Seri
-
Hello.. I just used PortMon and the setup is right between the app and hyperterminal.. I'm using a normal serial port... Below is the log of what PortMmon recorded..
4 0.00006984 comm console.ex IRP_MJ_CREATE Serial1 SUCCESS Options: Open 5 0.00000559 comm console.ex IOCTL_SERIAL_GET_BAUD_RATE Serial1 SUCCESS 6 0.00000196 comm console.ex IOCTL_SERIAL_GET_LINE_CONTROL Serial1 SUCCESS 7 0.00000196 comm console.ex IOCTL_SERIAL_GET_CHARS Serial1 SUCCESS 8 0.00000168 comm console.ex IOCTL_SERIAL_GET_HANDFLOW Serial1 SUCCESS 9 0.00000950 comm console.ex IOCTL_SERIAL_SET_BAUD_RATE Serial1 SUCCESS Rate: 19200 10 0.00000587 comm console.ex IOCTL_SERIAL_SET_RTS Serial1 SUCCESS 11 0.00000559 comm console.ex IOCTL_SERIAL_SET_DTR Serial1 SUCCESS 12 0.00000531 comm console.ex IOCTL_SERIAL_SET_LINE_CONTROL Serial1 SUCCESS StopBits: 1 Parity: NONE WordLength: 8 13 0.00000391 comm console.ex IOCTL_SERIAL_SET_CHAR Serial1 SUCCESS EOF:0 ERR:0 BRK:0 EVT:0 XON:0 XOFF:0 14 0.00000531 comm console.ex IOCTL_SERIAL_SET_HANDFLOW Serial1 SUCCESS Shake:1 Replace:40 XonLimit:0 XoffLimit:0 15 0.00819546 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 16 0.00986215 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 17 0.00978951 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 18 0.00971129 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 19 0.00959787 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 20 0.00904864 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 21 0.00977275 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 22 0.00979733 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 23 0.00865725 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 24 0.00866004 comm console.ex IRP_MJ_READ Serial1 TIMEOUT Length 0: 25 0.00002375 comm console.ex IRP_MJ_READ Serial1 SUCCESS Length 99: .*W...............M.................M.................M......... 26 0.00002375 comm console.ex IRP_MJ_READ Serial1 SUCCESS Length 99: .........M.................M.................M.................M 27 0.00002319 comm console.ex IRP_MJ_READ Serial1 SUCCESS Length 99: M.................M.................M.................M......... 28 0.00002347 comm console.ex IRP_MJ_READ Serial1 SUCCESS Length 99: .........M.................M.................M.................M 29 0.00002570 comm console.ex IRP_MJ_READ Serial1 SUCCESS Length 99: M.................M.................M.................M......... 30 0.00002542 comm console.ex IRP_MJ_READ Seri
The port seems to be setup good enough. To put it in short terms: I suspect that your MC doesn't do what you think it does. I tried running the code you've written and it works. It receives the bytes sent to the port and writes them to the console window. Note that calling ::ReadFile in non-overlapped mode will be a blocking call. You decide for how long it should block and when to timeout and what for by a call to ::SetCommTimeouts after calling ::SetCommState. Regarding ::CloseHandle() it cannot be called in the code you've written. The call to ::CloseHandle() is on the other side of an endless loop. Since you are running the app as a console app it is the responsability of the console to terminate the program running in the console, if it's possible, when you close the console window. I suspect a call to _endthread() that will end your app and that would let the run-time system reclaim allocated resources such as the port since there is only one thread in your app. As a result of that you will see the cleanup and close statements in PortMon. HyperTerminal might complain if the MC is malfunctioning or is not setup the same as HT, e.g. uses the wrong baudrate or uses two stopbits instead of one. But this is not unique for HT, your app should react the same way by getting nonsense. If I were you I would get an oscilloscope or logic analyser to see what's really going on with the RxD and TxD lines. -- Roger
-
The port seems to be setup good enough. To put it in short terms: I suspect that your MC doesn't do what you think it does. I tried running the code you've written and it works. It receives the bytes sent to the port and writes them to the console window. Note that calling ::ReadFile in non-overlapped mode will be a blocking call. You decide for how long it should block and when to timeout and what for by a call to ::SetCommTimeouts after calling ::SetCommState. Regarding ::CloseHandle() it cannot be called in the code you've written. The call to ::CloseHandle() is on the other side of an endless loop. Since you are running the app as a console app it is the responsability of the console to terminate the program running in the console, if it's possible, when you close the console window. I suspect a call to _endthread() that will end your app and that would let the run-time system reclaim allocated resources such as the port since there is only one thread in your app. As a result of that you will see the cleanup and close statements in PortMon. HyperTerminal might complain if the MC is malfunctioning or is not setup the same as HT, e.g. uses the wrong baudrate or uses two stopbits instead of one. But this is not unique for HT, your app should react the same way by getting nonsense. If I were you I would get an oscilloscope or logic analyser to see what's really going on with the RxD and TxD lines. -- Roger
Thank you for your reply.. Sorry i'm only getting back now.. I was busy tweaking the code and the MC to see where the problem was.. turns out it was the MC.. there was problems with synchronization when talking to the PC.. Thank you all for your time to help.. I've sure have learnt some pointers from the replies..