1. Wstęp
Witam w kolejnym artykule poświęconemu komunikacji po porcie RS 232 lub mówiąc prościej COM. W artykule tym opisze program ściśle współpracującym układem Piotra Zysek. Na samym początku chcę zaznaczyć, że lekcja ta nie należy do łatwych (warto znać podstawy elektroniki oraz programowania). Większość z Was zapewne zdziwi się, że zajmujemy się RS 232 a nie np.: USB. Faktem jest ze ten ostatni wypiera port RS 232, ale znając podstawy komunikacji po COM'ie na pewno w przyszłości będzie łatwiej „przesiąść” się na szybszy, ale i bardziej skomplikowany USB. Zaznaczam również, że artykuł ten porusza tylko podstawowe informacje na temat komunikacji po porcie szeregowym. Temat jest ten bardzo obszerny i bardziej zaciekawionych tym tematem odsyłam do odpowiedniej literatury.
2. Przed transmisją danych.
Aby móc zacząć wysłać lub odbierać dane z urządzenia lub komputera należy wypełnić strukturę DCB (Device Control Block). W naszym przykładzie wypełnimy tylko część pól tej struktury, jeżeli ktoś jest zainteresowany całą strukturą to odsyłam do MSDN. Zanim zaczniemy transmisje należy otworzyć port. My zrobimy to za pomocą funkcji CreateFile (opis jej parametrów poniżej). W naszym przykładzie znajdzie się jeszcze kilka dodatkowych funkcji, które będę opisywał na bieżąco. Przykład nasz oparty jest na transmisji znak po znaku, ponieważ jest to metoda łatwiejsza do zrealizowania i częściej wykorzystywana do komunikacji z jakimś innym urządzeniem. W transmisji gdzie przesyłane są ciągi znaków należy zadbać o buforowanie danych i kilka innych rzeczy - tutaj nie będziemy się tym zajmować.
// Częściowy opis struktury DCB.
Częściowy opis struktury DCB |
|
DWORD DCBlength |
Wielkość struktury |
DWORD BaudeRate |
Prędkość transmisji danych dostępne wartości: CBR_110, CBR_300, CBR_600, CBR_1200, CBR_2400, CBR_4800, CBR_9600 itd.… |
DWORD fParity |
Wartość TRUE umożliwia sprawdzanie parzystości |
BYTE Parity |
Ustawienie parzystości dostępne wartości: EVENPARITY (parzysta), MARKPARITY (bit parzystości wynosi 1), NOPARITY (brak bitu parzystości), ODDPARITY (nieparzysta) |
BYTE StopBits |
Ustawienie bitu stopu dostępne wartości: ONESTOPBIT (jeden bit stopu), TWOSTOPBITS (dwa bity stopu) |
BYTE ByteSize |
Liczba bitów do wysyłania/odebrania danych (wartości: od 5 do 8) |
DWORD fDtrControl |
Kontrola linii DTR wartości: DTR_CONTROL_DISABLE (sygnał nieaktywny), DTR_CONTROL_ENABLE (sygnał aktywny), DTR_CONTROL_HANDSHAKE (szczegóły w MSDN) |
DWORD fRtsControl |
Jak wyżej z tym, że dotyczy linii RTS - przedrostki z powyższego przykładu (DTR) należy zastąpić RTS |
DWORD fOutxCtsFlow |
Umożliwia sprawdzanie sygnału na linii CTS, odnośnie wartości odsyłam do MSDN
|
DWORD fOutxDsrFlow |
Jak wyżej z tym, że dotyczy linii DSR |
DWORD fAbortOnError |
Wstrzymanie odbierania/wysyłania danych przy wykryciu błędu, dostępne wartości: TRUE (włączona), FALSE (wyłączona) |
DWORD fErrorChar |
Podczas błędu parzystości możemy zastąpić dane podanym tutaj znakiem - tylko przy ustawionym fParity na TRUE |
DWORD fNull |
Nie przyjmowanie złych lub uszkodzonych danych, wartość TRUE (włącza) lub FALSE (wyłącza) |
Jak wspomniałem wyżej, jest to tylko część struktury DCB, jeżeli ktoś jest zainteresowany całą to odsyłam do helpa. Po wypełnieniu tej struktury musimy jeszcze uzyskać uchwyt naszego portu oraz ustawić parametry naszej struktury.
Funkcja CreateFile pozwala nam utworzyć plik lub uchwyt do jakiegoś urządzenia (w naszym przypadku do portu RS 232). Prototyp tej funkcji wygląda tak:
CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDistribution, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
Opis wybranych parametrów funkcji CrateFile |
|
lpFileName |
W naszym przypadku będzie to numer portu podany, jako „COM1”, „COM2” itd. |
dwDesierdAccess |
Parametr ten ustawia możliwość wysyłania/odbierania danych, wartości:, GENERIC_READ, GENERIC_WIRTE połączenie tych dwóch parametrów (GENERIC_READ | GENERIC_WRITE) daje nam możliwość odbierania i wysłania danych. |
dwCreationDistribution |
Dla naszego przykładu ustawiamy tą wartość na OPEN_EXISTING, inne parametry to CREATE_NEW, CREATE_ALWAYS, OPEN_ALWAYS (jednak z tego, co się orientuje stosuje się je do pracy przy plikach) |
Funkcja zwraca nam uchwyt do naszego portu. Kiedy wiemy już, jak pobrać uchwyt do naszego portu i wypełnić strukturę DCB ustawimy nasze parametry za pomocą funkcji SetCommState(HANDLE hFile, LPDCB lpDCB). Dla nas parametrami są uchwyt portu uzyskany dzięki funkcji CreateFile oraz adres struktury DCB. Jeżeli uda nam się wypełnić odpowiednio strukturę i uzyskać uchwyt portu to potrafimy już nawiązać połączenie z urządzeniem. Należy jeszcze pamiętać, że po zamknięciu aplikacji należy zadbać również o zamknięcie już otwartego portu. Do tego celu posłuży nam funkcja CloseHandle(HANDLE hObject), parametrem jest uchwyt naszego portu.
Przykładowy kod:
Listing 1.0 // Komunikacja z portem RS 232 //
// wypełnianie struktury DCB
DCB dbc;
HANDLE hNumPort;
LPSTR NumCom = „COM1”;
hNumPort = CreateFile(NumCom, GENERIC_WRITE | GENERIC_READ, 0, NULL,
OPEN_EXISTING, 0, NULL);
dcb.DCBlength = sizeof(dcb);
dcb.BaudRate = CBR_9600;
dcb.fParity = FALSE;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.ByteSize = 8;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDsrSensitivity = FALSE;
dcb.fAbortOnError = FALSE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.fErrorChar = FALSE;
dcb.fNull = FALSE;
SetCommStat(hNumPort, &dcb);
3. Wysyłanie i odbieranie danych.
Doszliśmy w końcu do najbardziej (tak mi się wydaje) oczekiwanego paragrafu. Samo nawiązywanie połączenia na nic się nie przyda, kiedy nie potrafimy wysyłać lub odbierać danych do/z urządzenia. W celu wysłania lub odebrania danych musimy użyć kilka dodatkowych funkcji. Jak wspomniałem na początku będziemy się zajmować tylko wysyłaniem znaku i obieraniem jednego znaku - do tego posłuży nam funkcja TransmitCommChar (funkcja WriteFile(..) służy do wysłania ciągów znaków). Musimy również zdefiniować bufor na dane oraz te dane odczytać przy użyciu funkcji ReadFile(...). Kiedy nawiązaliśmy już połączenie wysyłamy znak do urządzenia, które w naszym przypadku powoduje zapalenie się danej LED'ki w układzie. TransmitCommChar(HANDLE hFile, char cChar) parametry powinny być jasne, ale dla przypomnienia napisze, że pierwszy z nich to uchwyt portu a drugi to znak jaki chcemy wysłać.
Natomiast odbiór danych jest już troszkę bardziej skomplikowany na początku musimy zdefiniować sobie jakiś bufor, który przechowa nam dane odbierane z urządzenia. Do odbioru danych wykorzystamy funkcje
ReadFiel(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped );
Opis parametrów funkcji ReadFile |
|
hFile |
Uchwyt portu |
lpBuffer |
Wskaźnik do bufora - do przechowywania danych |
nNumberOfBytesToRead |
Liczba bajtów do odebrania |
lpNumberOfBytesRead |
Rzeczywista liczba odebranych danych |
Parametr lpOverlapped dla naszych potrzeb ustawiany jest na NULL. Warto również zainteresować się strukturą COMSTAT, dzięki, której możemy zaoszczędzić sobie pracy przy określaniu wielkości bufora na dane odbierane. Podczas odczytywania danych musimy podać wielkość bufora i można to zrobić w łatwy sposób używając pola „cbInQue” struktury COMSTAT. Również użycie funkcji ClearCommError, która odnajduje informacje na temat błędów i aktualnego stanu transmisji w połączeniu ze strukturą COMSTAT może pomóc nam w usunięciu części błędów powstałych podczas komunikacji z portem szeregowym. Jeżeli zależy nam na monitorowaniu linii i chcemy odpowiednio zareagować na dany komunikat to możemy się posłużyć funkcją SetCommMask (opis, poniżej), która potrafi wychwycić na podstawie komunikatów interesujące nas zdarzenie.
Opis funkcji:
ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat);
Opis parametrów funkcji ClearCommError |
|
hFile |
Uchwyt portu (wartość zwracana przez CreateFile) |
lpErrors |
Zmienna odbierająca kod błędu. Kody błędów można znaleźć na MSDN |
lpStat |
Adres do struktury COMSTAT, jeżeli z niej nie korzystamy wartość tej pozycji równa jest NULL |
SetCommMask(HANDLE hFile, DWORD fdwEvtMask)
Opis parametrów funkcji SetCommMask |
|
hFile |
Uchwyt portu |
fdwEvtMask |
Identyfikator zdarzenia. Wszystkie wartości (w sumie 9) można znaleźć w MSDN |
Na zakończenie część kodu:
// Listing 1 Komunikacja z portem RS 232 //
#define BUFOR 32
DCB dcb;
HANDLE hNumPort;
char lpBuffor;
char data = 0x00 // znak wysyłany do urządzenia
dcb.DCBlength = sizeof(dcb);
dcb.BaudRate = CBR_9600;
dcb.fParity = FALSE;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.ByteSize = 8;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDsrSensitivity = FALSE;
dcb.fAbortOnError = FALSE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.fErrorChar = FALSE;
dcb.fNull = FALSE;
SetCommStat(hNumPort, &dcb);
SetCommMask(hNumPort, fdwEvtMask);
// wysyłanie znaku do urzadzenia
TransmitCommChar(hNumPort, data);
// odbieranie znaku z urządzenia
ReadFile(hNumPort, lpBuffor, nNumberOfBytesToRead, lpNumberOfBytesRead, NULL);
// zamykanie portu
CloseHandle(hNumPort);
W celu lepszego zrozumienia tego kodu najlepiej ściągnąć przykładowy programik do lekcji. Zawarty tam kod jest opisany bardziej szczegółowo i można zobaczyć co, w jakich komunikatach jest wywoływane (polecam)
4. Opis hardware do RS232
Fot.1. Układ do testowania łącza RS232[plik plytka.jpg]
Do sprawdzenia oprogramowania wysyłającego znak wykorzystamy prosty układ, który odebraną informację będzie przedstawiał na diodach LED. Układ odebrane słowo wysyła z powrotem do komputera, realizując tzw. ECHO. Schemat układu znajduje się na rys.1.
Rys.1. Schemat ideowy układu [plik RS232C.pdf]
Układ podzielono na dwa bloki. Pierwszy stanowi układ MAX232 (U2), który jest konwerterem napięć ze standardu RS232 na standard 0, +5V i odwrotnie. Kondensatory C8..C11 tworzą tzw. pompę napięcia przy konwersji napięć z 0, +5V na napięcie odpowiadającemu złączu RS232. Drugim blokiem jest mikroprocesor rodziny AVR AT90S8515 (U1), który pobiera informację z portu szeregowego komputera i zamienia ją na postać binarną zapalając tym samym diody LED (D1..D8). Rezystory R1..R8 ograniczają prąd płynący przez diody do wartości ok. 7,5mA. Kondensator C7 wykonuje RESET procesora w momencie włączenia zasilania, tak jak to się dzieje w zwykłym PC-cie. Generator do napędzania procesora (zegar) został zrealizowany na kwarcu Y1 i pojemnościach C5, C6. Częstotliwość zegara wynosi 8MHz. Kondensatory C3 i C4 blokują zasilanie przed zakłóceniami powstającymi na zasilaniu układów U1 i U2. Kondensatory C1 i C2 umożliwiają odfiltrowanie zasilania.
5. Zasilanie układu
Do zasilania układu należy użyć zasilacza stabilizowanego o napięciu +5V i prądzie ok.100mA, które należy podłączyć do złącza J1. Układ można zasilić z powodzeniem np. z płaskiej baterii 3R12, która dostarcza 4,5V.
6. Montaż
Montaż układu najlepiej przeprowadzić na płytce uniwersalnej, a połączenia wykonać za pomocą odcinków przewodów. Układy scalone najlepiej umieścić w podstawkach. Kondensatory C3 i C4 powinny być umieszczone najbliżej układów scalonych U1 i U2.
7. Spis elementów
Lp. |
Nazwa elementu |
Wartość/ typ |
Ozn. Na schemacie |
Ilość [szt] |
1. |
Układ scalony |
MAX232 |
U2 |
1 |
2. |
Mikroprocesor |
AT90S8515 |
U1 |
1 |
3. |
Dioda LED |
Czerwona |
D1..D8 |
8 |
4. |
Kwarc |
8MHz |
Y1 |
1 |
5. |
Kondensator |
100nF |
C1, C4, C3 |
3 |
6. |
Kondensator |
33pF |
C5, C6 |
2 |
7. |
Kondensator elektrolityczny |
10uF/16V |
C2 |
1 |
8. |
Kondensator elektrolityczny |
1uF/16V |
C7 |
1 |
9. |
Kondensator elektrolityczny |
4,7uF/16V |
C8..C11 |
4 |
10. |
Rezystor |
330ohm/0,125W |
R1..R8 |
8 |
11. |
Złącze CANNON DB9 męskie |
Do druku |
J2 |
1 |
12. |
Złącze zasilania |
ARK2 |
J1 |
1 |
13. |
Podstawka |
DIL40 |
|
1 |
14. |
Podstawka |
DIL16 |
|
1 |
8. Programowanie procesora
Po zmontowaniu układu pozostaje nam tylko zaprogramowanie procesora i jeśli układ został prawidłowo zmontowany, to po włączeniu zasilania układ pokaże nam, że żyje, mrugając diodami LED. Następnie układ przejdzie do oczekiwania na znak z portu RS232. Zaprogramowanie procesora można wykonać w dwojaki sposób. Można udać się z kodem wynikowym [RS232.hex] do kogoś, kto posiada programator, lub można wykonać własny programator niewielkim nakładem sił własny, którego schemat znajduje się na rys.2. [plik STK200.pdf]
9. Programator
Jest to schemat programatora typu STK200, schemat nie jest mojego autorstwa, został zaczerpnięty ze strony producenta procesorów rodziny AVR http://www.atmel.com i jako użytkownik tego programatora mogę go wszystkim polecić. Programator jest podłączany do portu równoległego drukarki LPT, a złącze ISP (In System Programming) do układu programowanego. System ISP charakteryzuje się tym, że można w każdej chwili działania układu zaprogramować procesor bez wyjmowania go jak to miało miejsce w starszym mikrokontrolerach np. serii 8051.
Rys.2. Schemat programatora ISP [plik STK200.pdf]
Jak można zauważyć układ nie jest w żaden sposób skomplikowany i zawiera tylko kilka elementów elektronicznych. Układ U1 jest „separatorem” pomiędzy układem AVR, a portem równoległym komputera w momencie, kiedy układ nie jest programowany. Zasilanie układu odbywa się poprzez złącze J2 ISP, które jest podłączane do programowanego systemu. Sygnały MISO, MOSI, SCK, RST podłączone są bezpośrednio do wyprowadzeń procesora i są to sygnały programujące. Dioda LED D2 zaświeca się podczas komunikacji procesora z programoterem.
10. Montaż programatora
Montaż jak w poprzednim przypadku najlepiej przeprowadzić na płytce uniwersalnej, a całość umieścić w obudowie - przejściówce DB25 - DB9. Mój programator został wykonany na obwodzie drukowanym specjalnie do tego przygotowanym. Zdjęcie wnętrza programatora można zobaczyć poniżej.
Fot.2. Programator ISP, po prawej widok zmontowanego układu na płytce drukowanej[plik prog_pcb.jpg]; po lewej układ zamknięty w obudowie[plik prog,JPG].
11. Podłączenie programatora
Sygnały z programatora należy podłączyć w następujący sposób:
Sygnał z programatora |
Nóżka procesora U1 |
MOSI |
6 |
MISO |
7 |
SCK |
8 |
RST |
9 |
+5V |
40 |
GND |
20 |
Najlepiej przewody z programatora przylutować wprost do nóżek procesora.
12. Program obsługi programatora ISP
Do czytania plików *.hex i obsługi będziemy używali oprogramowania PonyProg http://www.lancos.com/prog.html .Na tej stronie znajduje się pełny opis programu i są również różne nakładki językowe i platformy pod którymi działa to oprogramowanie. Nie będę się rozpisywał jak po kolei korzystać z tego narzędzia, bo to nie ma sensu. Odsyłam więc Was do strony.
13. Przewód łączący układ z komputerem
Przewód łączący układ z komputerem jest typowym przewodem zakończonym wtyczkami DB9 typu żeńskiego. Taki przewód był stosowany np. do połączenia dwóch kompów za pomocą portów COM. Schemat połączeń tego przewodu zamieszczono na rys.3.
Rys.3. Przewód RS232
14. Oprogramowanie mikrokontrolera
Oprogramowanie na mikrokontroler napisano w języku C w środowisku CodeVision. Program podzielono na dwa pliki: w set_hardware.h ustawiono część sprzętowa procesora, taką jak ustawienia portów, procedury obsługi przerwania wewnętrznego układu UART mikrokontrolera. Drugi plik rs232.c to procedury odbioru i wysyłania znaków. Poniżej zamieszczono listingi.
set_hardware.h
#define RXB8 1
#define TXB8 0
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7
#define FRAMING_ERROR (1<<FE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)
/******************************************************************************
UART
******************************************************************************/
/*********************************** RX ***************************************/
#define RX_BUFFER_SIZE 8 // rozmiar bufora UART'a
char rx_buffer[RX_BUFFER_SIZE]; // tablica bufora
unsigned char rx_wr_index,rx_rd_index,rx_counter;
bit rx_buffer_overflow; // flaga przeplnienia bufora
#pragma savereg- // nie zapisuj rejestrow z innych przerwan
/*########################### OBSLUGA PRZERWANIA #############################*/
interrupt [UART_RXC] void uart_rx_isr(void)
{
char status,data;
#asm
push r26
push r27
push r30
push r31
in r26,sreg
push r26
#endasm
status=USR;
data=UDR;
if ((status & (FRAMING_ERROR | DATA_OVERRUN))==0)
{
rx_buffer[rx_wr_index]=data;
if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
if (++rx_counter == RX_BUFFER_SIZE)
{
rx_counter=0;
rx_buffer_overflow=1;
};
};
#asm
pop r26
out sreg,r26
pop r31
pop r30
pop r27
pop r26
#endasm
}
/*########################## KONIEC OBSLUGI PRZERWANIA #######################*/
#pragma savereg+ // zezwolenie na zapis rejestrow
#ifndef _DEBUG_TERMINAL_IO_
#define _ALTERNATE_GETCHAR_
#pragma used+ // warning przy kompilacji
char getchar(void) // pobranie znaku z bufora
{
char data;
while (rx_counter==0);
data=rx_buffer[rx_rd_index];
if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#asm("cli") // zablokowanie przerwan
--rx_counter;
#asm("sei") // odblokowanie przerwan
return data;
}
#pragma used- // koniec warningu
#endif
/*********************************** TX ***************************************/
#define TX_BUFFER_SIZE 8 // wielkosc bufora wysylania
char tx_buffer[TX_BUFFER_SIZE]; // tablica bufora TX
unsigned char tx_wr_index,tx_rd_index,tx_counter;
#pragma savereg-
/*########################### OBSLUGA PRZERWANIA #############################*/
interrupt [UART_TXC] void uart_tx_isr(void)
{
#asm
push r26
push r27
push r30
push r31
in r26,sreg
push r26
#endasm
if (tx_counter)
{
--tx_counter;
UDR=tx_buffer[tx_rd_index];
if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0;
};
#asm
pop r26
out sreg,r26
pop r31
pop r30
pop r27
pop r26
#endasm
}
/*########################## KONIEC OBSLUGI PRZERWANIA #######################*/
#pragma savereg+ // zezwolenie na zapis rejestrow
#ifndef _DEBUG_TERMINAL_IO_
#define _ALTERNATE_PUTCHAR_
#pragma used+ // warning przy kompilacji
void putchar(char c) // znak do wyslania
{
while (tx_counter == TX_BUFFER_SIZE);
#asm("cli") // blokuj przerwania
if (tx_counter || ((USR & DATA_REGISTER_EMPTY)==0))
{
tx_buffer[tx_wr_index]=c;
if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;
++tx_counter;
}
else UDR=c;
#asm("sei") // teraz odblokuj
}
#pragma used- // koniec warningu
#endif
/******************************************************************************
Peryferia
******************************************************************************/
void set_hardware(void)
{
// port A jako wejscie
PORTA=0x00;
DDRA=0x00;
// B jako wyjscie
PORTB=0x00;
DDRB=0xFF;
// C jako wejscie
PORTC=0x00;
DDRC=0x00;
// port D jako wejscie
PORTD=0x00;
DDRD=0x00;
// inicjalizacja Tajmera T0
TCCR0=0x00;
TCNT0=0x00;
// inicjalizacja Tajmera T1
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Zewnetrzne przerwania wylaczone
GIMSK=0x00;
MCUCR=0x00;
// inicjalizacja przerwan od T0, T1
TIMSK=0x00;
// inicjalizacja UART'a
// 8 bitow, 1 bit stopu, bez parzystosci
// wlaczenie nasluchu i nadawania
// predkosc 9600bps
UCR=0xD8;
UBRR=0x33;
// komparator wylaczony
ACSR=0x80;
// odblokowanie przerwan
#asm("sei")
}
rs232.c
/******************************************************************************
proj: RS232
ver.: 1.0 alpha
date: 23.11.2003
autor: c2003 by Piotr Zysek
e-mail: zysiu@ckomp.net
www: http://zysiu.ckomp.net
Chip: AT90S8515
*******************************************************************************/
#include <90s8515.h>
#include <stdio.h>
#include <delay.h>
#include <.\\set_hardware.h>
#define xtal 8000000L // kwarc 8MHz
#define baud 9600 // predkosc transmisji
/******************************************************************************
Funkcje
******************************************************************************/
void blink (void) // demo-mruganie LED'ami
{
int i;
PORTB= 0xFE;
for (i=0; i <=7; i++)
{
PORTB = PORTB >>1; // przesuwanie w prawo
delay_ms(100); // czekaj chwile...
}
PORTB= 0x7F; // zapalenie ostatniej LED
for (i=0; i <=7; i++)
{
PORTB = PORTB <<1; // przesuwanie w lewo
delay_ms(100);
}
delay_ms(300);
PORTB=0xFF; // zgaszenie diod
}
void uart_RX(void) // obsluga UART'a
{
char data; // zmienna pomocnicza
data=~getchar(); // negujemy bajt dla diod LED
if (data!= PORTB) // jesli przyszedl nowy znak
{
PORTB=data; // ustaw odczytana wart. na diodach LED
putchar(~data); // wyslij ECHO, odzyskiwanie informacji
} // przez ponowna negacje
}
/******************************************************************************
Petla Glowna
******************************************************************************/
void main (void)
{
set_hardware(); // ustaw sprzet
blink(); // pomrugaj diodami
while (1)
{
uart_RX(); // wywolanie funkcji uart
};
}
Dokumentacja : AT90S8515 [plik AT90S8515.pdf]
MAX232 [plik MAX232.pdf]
Tym sposobem poznaliście podstawy podstaw :) komunikacji po porcie szeregowym. Ja sam dopiero się tego uczę, więc niedługo powinniście tu znaleźć więcej informacji dotyczącej komunikacji po porcie szeregowym i może USB. Artykuł ten powstał z dwóch części. Pierwszą część opracował Dawid Węgrzyn, dotyczącą komunikacji po porcie RS 232 z poziomu aplikacji, drugą część, która dotyczy elektroniki opracował Piotr Zysek (zysiu). Wszelkie pytania odnośnie elektroniki proszę kierować pod adres zysiu@ckomp.net, a pytania odnośnie obsługi RS 232 spod aplikacji na adres xantospl@go2.pl
Autorzy: Piotr Zysek, Dawid Węgrzyn
13