© Harry Broeders.
Deze pagina is bestemd voor studenten van de Haagse Hogeschool - Academie voor Technology, Innovation & Society Delft.
Een goede introductie over het programmeren van de seriële poort kun je vinden het door Robertson Bayer geschreven document Windows Serial Port Programming . Dit is voldoende voor MICPRG.
Het onderstaande Windows programma winserial.c verstuurt een 'S' via de seriële poort COM1 9600-7-E-1 en zet daarna alle binnenkomende karakters op het scherm totdat een 'Q' wordt ontvangen.
#include <stdio.h>
#include <windows.h>
HANDLE initCom(int comPortNumber) {
DCB dcb;
HANDLE hCom;
BOOL fSuccess;
char comPortName[20];
sprintf(comPortName, "\\\\.\\COM%d", comPortNumber);
hCom = CreateFileA(comPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hCom == INVALID_HANDLE_VALUE) {
MessageBoxA(0, "Fout: De seriële poort kan niet geopend worden!", "Fout", MB_OK | MB_ICONEXCLAMATION);
exit(-1);
}
fSuccess = GetCommState(hCom, &dcb);
if (!fSuccess) {
MessageBoxA(0, "Fout: De instellingen van de seriële poort kunnen niet gelezen worden!", "Fout", MB_OK | MB_ICONEXCLAMATION);
exit(-1);
}
dcb.fParity = TRUE;
dcb.BaudRate = CBR_9600;
dcb.ByteSize = 7;
dcb.Parity = EVENPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = FALSE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
fSuccess = SetCommState(hCom, &dcb);
if (!fSuccess) {
MessageBoxA(0, "Fout: De instellingen van de seriële poort kunnen niet aangepast worden!", "Fout", MB_OK | MB_ICONEXCLAMATION);
exit(-1);
}
return hCom;
}
char readCom(HANDLE hCom) {
char inBuffer[2] = " ";
unsigned long nBytesRead;
while (ReadFile(hCom, &inBuffer, 1, &nBytesRead, NULL) && nBytesRead == 0);
if (nBytesRead != 1) {
MessageBoxA(0, "Fout: De seriële poort kan niet uitgelezen worden!", "Fout", MB_OK | MB_ICONEXCLAMATION);
exit(-1);
}
return inBuffer[0];
}
void writeCom(HANDLE hCom, char c) {
char outBuffer[2] = " ";
unsigned long nBytesWritten;
outBuffer[0] = c;
WriteFile(hCom, &outBuffer, 1, &nBytesWritten, NULL);
if (nBytesWritten != 1) {
MessageBoxA(0, "Fout: De seriële poort kan niet beschreven worden!", "Fout", MB_OK | MB_ICONEXCLAMATION);
exit(-1);
}
}
void closeCom(HANDLE hCom) {
CloseHandle(hCom);
}
int main(void) {
HANDLE hCom;
char in;
hCom = initCom(1);
printf("Er wordt nu een S verstuurd.\n");
writeCom(hCom, 'S');
printf("Ontvangen karakters worden op het scherm gezet totdat een Q wordt ontvangen.\n");
do {
in = readCom(hCom);
if (in != 'Q') {
putchar(in);
}
} while (in != 'Q');
closeCom(hCom);
printf("\nEINDE.\n");
getchar();
return 0;
}
Het onderstaande ATmega32 programma avrserial.c wacht tot er een 'S' binnekomt via de seriële poort 9600-7-E-1 en verstuurt daarna de tekst "HalloQ" via de seriële poort.
#include <avr/io.h>
int main(void) {
char c;
// 9600-7-E-1
UCSRA = 0x00;
UCSRB = 0x18;
UCSRC = 0xA4;
UBRRH = 0;
UBRRL = 23;
while(1) {
while (~UCSRA & 1<<RXC);
if (UCSRA & (1<<FE | 1<<DOR | 1<<PE)) {
c = UDR;
while (~UCSRA & 1<<UDRE);
UDR = '?';
}
else {
c = UDR;
if (c == 'S') {
char s[] = "HalloQ";
int i;
for (i = 0; s[i] != '\0'; i++) {
while (~UCSRA & 1<<UDRE);
UDR = s[i];
}
}
}
}
return 0;
}
Als de "SPARE" seriële poort van het STK500 practicumbord verbonden wordt met COM1 van de PC dan geeft het windowsprogramma de volgende uitvoer:
Als de COM1 poort bezet is (door een ander programma) verschijnt de volgende foutmelding:
Alle details kun je vinden op de MSDN site (Microsoft Developers Network).
CreateFile
(CreateFileA
) en
MessageBox
(MessageBoxA
). Dit is nodig omdat de
Visual Studio compiler anders (standaard) de Unicode variant
van deze API (Application Programmers Interface) functies gebruikt. Windows
console applicaties ondersteunen echter geen Unicode, zie eventueel: http://msdn.microsoft.com/en-us/library/dd317752%28v=vs.85%29.aspx.
"\\\\.\\COMx"
terwijl "COMx"
ook zou werken (voor
x = 0..9). Als je echter COM10 of hoger wilt gebruiken dan
werkt "COMx"
niet en moet
je echt "\\\\.\\COMx"
gebruiken. Zie voor details: http://support.microsoft.com/kb/115831/en-us.
snprintf
in plaats van sprintf
te gebruiken om zeker te zijn dat er geen buffer overrun op kan treden,
zie: De gevaren van buffer
overrun! Microsoft Visual Studio 2010 bevat de functie snprintf echter
niet (en voldoet dus niet aan de C99 standaard!), zie http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010.