Dołączenie drukarki do mikrokontrolera z rodziny 8051

Port równoległy jest do dziś jednym z najpowszechniej stosowanych interfejsów drukarkowych. Celem artykułu jest przedstawienie przykładu sposobu, w jaki można podłączyć drukarkę do systemu wyposażonego w mikrokontroler z rdzeniem 8051/8052. Obecnie port równoległy wypierany jest z zastosowań przez dużo wygodniejszy w użyciu interfejs USB. Stale jednak stanowi podstawowe wyposażenie komputerów PC, a w sklepach czy na rynku podzespołów wtórnych, bez większych kłopotów można kupić drukarkę wyposażoną w złącze równoległe. Jej przeznaczenie w systemie z mikrokontrolerem może być różne i zależy od potrzeb i inwencji konstruktora czy programisty. Ciekawy dla elektroników amatorów wydaje się być zwłaszcza rynek wtórny, gdzie za niewielką cenę można nabyć drukarkę igłową czy atramentową, wyposażoną w ten rodzaj interfejsu i dołączyć ją do własnego urządzenia.

Typowo złącze portu równoległego komputera PC to tzw. złącze DSUB żeńskie o 25 doprowadzeniach. Złącze zawiera: 8 linii danych, 5 linii do raportowania statusu drukarki, 4 linie kontrolne. Wyszczególnienie numerów wyprowadzeń wraz z krótkim opisem ich funkcji zawiera tabela 1. Port równoległy nowoczesnego komputera PC może pracować w jednym z 5 trybów: Compatibility Mode, Nibble Mode, Byte Mode, EPP (Enhanced Parallel Port), ECP (Enhanced Capability Port). Oczywiście nic nie stoi na przeszkodzie, aby opracować własny interfejs dla systemu z mikrokontrolerem pracujący w trybach rozszerzonych, jednak dla większości zastosowań służących dołączeniu drukarki wystarczającym jest tryb standardowy, to jest Compatibility. Na jego opisie skupi się ten artykuł, dla niego również opracowany został przykładowy interfejs łączący mikrokontroler AT89S8252 z drukarką igłową marki EPSON LX400.
Tryb standardowy, często nazywany również trybem Centronics, umożliwia wyłącznie przesyłanie danych do drukarki czy innego dołączonego urządzenia. Transmisja przebiega więc jednokierunkowo, z prędkością typowo około 50 kB/s, a maksymalnie około 150 kB/s. Przesyłanie danych z prędkością do około 2 MB na sekundę jest możliwe w trybach EPP i ECP dzięki dodatkowym układom takim, jak bufor FIFO oraz kontroler DMA. Wróćmy jednak do trybu standardowego i drukarki.
Dane są przesyłane w formie słów 8-bitowych i zapisywane do drukarki przez opadające zbocze sygnału STROBE. Minimalny czas trwania impulsu STROBE to 1 μs. Wymagane jest, aby słowo danych pojawiło się jako pierwsze oraz aby upłynął krótki czas (około 500 ns) pomiędzy wysłaniem słowa danych a opadającym zboczem sygnału STROBE. Po odbiorze danych, drukarka ustawia stan wysoki sygnału BUSY zgłaszając w ten sposób stan zajętości (np. wydruk linii czy też przepełnienie bufora danych). Po zakończeniu np. wydruku linii, ustawiany jest stan niski linii BUSY oraz pojawia się krótki, trwający kilka μs (typowo 5..12 μs. Uwaga: czas trwania może być różny dla różnych drukarek) ujemny impuls na linii ACK. Potwierdza on odbiór danych oraz sygnalizuje gotowość drukarki do przyjęcia następnych. Na rysunku 1 przedstawiono typowe sekwencje sygnałów właściwe dla transmisji danych pomiędzy drukarką oraz komputerem PC.

przebiegi sterujące

 

Rysunek 1. Sygnały podczas transmisji danych do drukarki.

Przesyłając dane do drukarki można zignorować stan linii ACK badając tylko stan linii BUSY. Nieznacznie przyspiesza to transmisję. Poziomy napięć sygnałów na doprowadzeniach portu równoległego zgodne są z wymaganiami dla układów TTL. Z racji tego, że port wyjściowy komputera PC wyposażony jest w układy buforów, obciążalność prądowa takiego portu jest znacznie wyższa, niż 1 s.o.l.[1] i w praktyce może sięgać nawet kilkudziesięciu mA dla pojedynczego wyprowadzenia. Uwaga ta dotyczy linii wyjściowych. Obciążenie wnoszone przez wejście portu jest równe 1 s.o.l.
Na koniec tego krótkiego opisu jedna ważna uwaga. Drukarka oprócz komponentów elektronicznych, zawiera również mnóstwo różnego rodzaju elektromagnesów. Mogą to być na przykład to silniki prądu stałego oraz silniki krokowe, głowica drukująca i inne układy wykonawcze. Są one źródłem licznych zakłóceń, z którymi w skrajnych przypadkach musi poradzić sobie układ interfejsu. Z tego powodu zalecane jest, aby układy wyjściowe miały możliwie niską impedancję. To oznacza, co najmniej użycie układów buforów wyjściowych, a nawet w skrajnych przypadkach optoizolacji, mimo, iż mikrokontroler może bezpośrednio sterować drukarką. Odrębnym zagadnieniem jest poprawne wykonanie kabla łączącego drukarkę z portem równoległym. Ten jednak najczęściej kupowany jest jako gotowy, wykonany fabrycznie a więc z zachowaniem odpowiednich norm dla połączenia.

 

 

Tryby pracy interfejsu równoległego

Compatibility mode(tryb standardowy) to oryginalny interfejs równoległy Centronics. Opracowany został i przeznaczony do użytku z drukarkami igłowymi oraz starszymi modelami drukarek laserowych. Tryb Compatibility może być łączony z trybem Nibble dla uzyskania transmisji dwukierunkowej.

Nibble mode(tryb podziału bajtu) pozwala na przesłanie danych z powrotem do komputera PC. Tryb Nibble używa linii statusu (kontrolnych) do przesłania dwóch „porcji” o długości 4 bitów w dwóch cyklach transmisji. Tryb ten używany był np. przez popularny w latach 90-tych program Norton Commander do transmisji danych przez interfejs równoległy umożliwiając połączenie w ten sposób dwóch komputerów.

Byte modewymaga dwukierunkowego portu wyjściowego komputera. Umożliwia transmisję danych do i z komputera poprzez port równoległy w postaci liczb jednobajtowych. Niektóre starsze modele drukarek laserowych wymagały tego trybu do poprawnej komunikacji z komputerem. Dane przesyłane są do / z komputera z tą samą prędkością.

ECP mode (Enhanced Capability Port mode)to zaawansowany tryb pracy portu równoległego umożliwiający podłączenie drukarki i skanera. Wymaga użycia specjalnego oprzyrządowania, to jest kontrolera DMA oraz układów buforów FIFO do kolejkowania danych oraz dla szybkiej ich wymiany. Ten tryb pracy portu równoległego pozwala na przykład na sprzętową kompresję danych (np. obrazów ze starszych modeli skanerów) oraz ich przesyłanie z prędkością do 2MB na sekundę. Jedną z ciekawych funkcji jest adresowanie kanałów transmisji. Używane jest ona do obsługi dołączonych urządzeń wielofunkcyjnych. Na przykład, jeśli urządzenie wielofunkcyjne drukuje i w tym samym czasie wysyła dane przez modem, oprogramowanie przydziela modemowi nowy kanał transmisji tak, że obie te funkcje mogą być realizowane jednocześnie.

EPP mode (Enhanced Parallel Port mode)to zaawansowany tryb transmisji opracowany przez firmy Intel, Xircom i Zenith Data Systems. Umożliwia on pracę portu równoległego zarówno w trybie zbliżonym do ECP jak i w trybie standardowym. W trybie EPP używane są tzw. cykle danych, które przesyłają dane pomiędzy komputerem i urządzeniem peryferyjnym oraz cykle adresowe, które mogą przyporządkowywać adres, kanał lub zawierać komendę sterującą. Dane przesyłane są z prędkością od 500kB na sekundę do 2MB na sekundę. Tryb EPP jest w pełni dwukierunkowy. Umożliwia to dołączenie do komputera urządzeń do akwizycji danych, przenośnych napędów dysków i innych urządzeń.

 

 

Tabela 1. Opis sygnałów złącza Centronics w odniesieniu do drukarki EPSON LX400.

Nr wyprowadzenia portu równoległego komputera PC Nr wyprowadzenia portu równoległego drukarki EPSON LX400 Nazwa sygnału Kierunek sygnału w odniesieniu do komputera PC Opis funkcji
1 19 /STROBE Dwukierunkowy Sygnał zapisu danych do bufora drukarki. Szerokość impulsu musi być większa niż 0,5 μs na urządzeniu odbierającym!
2 2 Dane, bit 0 Wyjście Bit danych numer 0
3 3 Dane, bit 1 Wyjście Bit danych numer 1
4 4 Dane, bit 2 Wyjście Bit danych numer 2
5 5 Dane, bit 3 Wyjście Bit danych numer 3
6 6 Dane, bit 4 Wyjście Bit danych numer 4
7 7 Dane, bit 5 Wyjście Bit danych numer 5
8 8 Dane, bit 6 Wyjście Bit danych numer 6
9 9 Dane, bit 7 Wyjście Bit danych numer 7
10 10 /ACK Wejście Krótki ujemny impuls, o czasie trwania około 12μs oznacza, że drukarka odebrała słowo danych i jej kontroler gotowy jest na przyjęcie następnego.
11 11 BUSY Wejście Stan wysoki oznacza, że kontroler jest zajęty i drukarka nie może odbierać danych. Pojawia się on w następujących sytuacjach:
- Podczas przesyłania czy odbioru danych,
- Podczas drukowania,
- Gdy drukarka jest odłączona,
- Gdy kontroler drukarki zgłasza błąd wydruku.
12 12 PE Wejście (Paper Empty) Stan wysoki sygnału informuje o braku papieru w drukarce.
13 13 SELECTED Wejście Stan wysoki oznacza, że drukarka jest wybrana i załączona. W drukarce EPSON LX400 wyprowadzenie dołączone na stałe do +5V przez rezystor 3,3 kΩ
14 14 /LF Wyjście (Line Feed) Stan niski powoduje, że papier wysuwany jest automatycznie o 1 linię po zakończeniu wydruku.
15 32 /ERROR Wejście Stan niski oznacza, że nastąpił błąd wydruku. Może to być spowodowane jedną z następujących sytuacji:
- Skończył się papier,
- Drukarka jest odłączona (w stanie off-line),
- Wystąpił błąd kontrolera drukarki (np. zablokowana głowica drukująca).
16 31 /INIT Wyjście Stan niski powoduje wyzerowanie bufora drukarki oraz ustawienie głowicy drukującej w pozycji spoczynkowej. Minimalny czas trwania stanu niskiego sygnału INIT dla drukarki EPSON LX400 wynosi 50 μs.
17 36 /SELECT PRINTER Wyjście Stan wysoki tej linii umożliwia zmianę statusu drukarki przy pomocy rozkazów DC1 i DC3 (Select i Deselect Printer). Stan niski powoduje, że drukarka jest zawsze w stanie „on-line” a rozkazy te są ignorowane.
18...25 19...30 GND   Masy sygnałów interfejsu.

 

Przykłady aplikacji.
Dla potrzeb demonstracji sposobów dołączenia drukarki do systemu z mikrokontrolerem AT89S8252, w oparciu o płytki testowe, wykonałem dwie aplikacje. Pierwsza z nich, której schemat umieszczono na rysunku 2, steruje drukarką z wykorzystaniem dwóch portów mikrokontrolera. Rzadko można sobie pozwolić na taki luksus, toteż aplikacja z rysunku 3 steruje drukarką tak, jak zapisem czy odczytem komórki pamięci leżącej w obszarze adresowania 8 bitowego.

Rysunek 2. Sterowanie pracą drukarki za pomocą wyprowadzeń portów

 

Rysunek 3. Drukarka pracująca jak komórka pamięci w obszarze adresowania 8-bitowego.

Programy sterujące napisane są w języku C i są pewnym fragmentem całości. Aplikacje skupiają się na sposobie sterowania drukarką w trybie tekstowym, pozostawiając Czytelnikowi szczegółową implementację funkcji związanych z sygnalizacją błędów wydruku czy transmisji danych.
Algorytm działania jest wspólny dla obu aplikacji, aczkolwiek różnią się one pomiędzy sobą szczegółami implementacji. W obu dokonano wymiany standardowej funkcji biblioteki stdio.h o nazwie putchar() tak, że funkcja printf() korzystająca z putchar() podczas przesyłania danych, wysyła dane do drukarki zamiast przez interfejs UART mikrokontrolera. Rysunek 4 ilustruje skrócony algorytm działania funkcji putchar(),po jej wymianie na nową implementację. Oczywiście można napisać własne funkcje obsługi, jednak użycie standardowej funkcji printf() umożliwia dostęp do licznych opcji formatowania danych wyjściowych

algorytm

Rysunek 4. Algorytm działania nowej implementacji funkcji putchar()

Jak można zorientować się na podstawie rysunku 4, jako pierwsze wyprowadzane są dane. Następnie badany jest stan linii BUSY i jeśli ta znajduje się w stanie niskim oznacza to, że kontroler drukarki uwikłany jest w realizację jakiegoś procesu i funkcja oczekuje na zmianę stanu na wysoki, czyli na zakończenie bieżących zadań i zgłoszenie możliwości przyjmowania danych. Następnie mikrokontroler sterujący przesyła krótki, ujemny impuls STROBE, o czasie trwania większym niż 1μs. Impuls ten zapisuje dane do pamięci drukarki. Teraz funkcja oczekuje na stan niski linii ACK sygnalizujący odbiór bajtu danych. Cykl ten powtarzany jest dla każdego, wysyłanego do drukarki, kodu znaku.

Sterowanie za pomocą portów.

Na listingu 1 umieszczono program sterujący drukarką podłączoną jak na schemacie z rysunku 2. Zaletą jest prostota wykonania układu, natomiast wadą ilość wykorzystanych doprowadzeń mikrokontrolera. Praktycznie zajęte są prawie wszystkie linie dwóch portów. Dla uproszczenia pominięto sterowanie sygnałem /LF oraz testowanie stanu linii SELECTED, która to sygnalizacja i tak nie jest wykorzystywana w drukarce EPSON LX400 (wyprowadzenie jest na stałe dołączone do +5V przez rezystor 3,3 kΩ).
Program napisano w języku C dla mikrokontrolera z rodziny 8051/8052. Funkcja main() zawiera inicjalizację drukarki a następnie, w przypadku pomyślnego jej przebiegu, wysyła do drukarki napisy. Funkcja putchar() wysyłająca znaki jest bardzo prosta i praktycznie polega na odpowiednim sterowaniu wyprowadzeniami portów mikrokontrolera (zgodnym z opisanymi wcześniej sekwencjami czasowymi) oraz testowaniu stanów linii statusu. Linia sygnalizacji błędu dołączona jest do wejścia przerwania INT0 tak, że opadające zbocze sygnału powoduje przejście do funkcji obsługi przerwania. Zarówno program główny jak i funkcja obsługi przerwania, nie zawierają procedur obsługi błędów. Jak wspomniano wcześniej, szczegółową implementację pozostawiono Czytelnikowi.

Listing 1. Bezpośrednie sterowanie drukarką.
/***********************************************************
DOŁĄCZENIE DRUKARKI 9-IGŁOWEJ W TRYBIE: EPSON_STANDARD_TEXT
DO MIKROKONTROLERA Z RODZINY INTEL 8051. LINIE DANYCH DRUKARKI
DOŁĄCZONE DO P0 PRZEZ DRIVER, LINIE KONTROLNE DO P2 (WEJŚCIA
I WYJŚCIA), LINIA ZGŁOSZENIA BŁĘDU /ERROR DO /INT0 MIKROKONTROLERA.

KWARC 11,0592 MHZ.
***********************************************************/

#pragma SMALL
#include <reg8252.h>
#include <stdio.h>
//SPOSÓB DOŁĄCZENIA DRUKARKI
//linie danych: P0^0 .. P0^7
sbit ACK = P2^3;
sbit BUSY = P2^4;
sbit ERROR = P3^2; //INT0
sbit STROBE = P2^0;
sbit INIT = P2^1;
sbit PRNSEL = P2^2;

//obsługa przerwania INT0,to jest stanu sygnalizacji błędu
void isr_INT0() interrupt 0 using 1
{
    BYTE status = P2;   //odczyt statusu drukarki
        //<-- tu obsługa sygnalizacji błędu
}

//funkcja realizuje opóźnienie k*1ms dla rezonatora f=11.0592 MHz
void delay(WORD k)
{
    WORD i,j;
    for ( j = 0; j < k; ++j)

    for (i = 0; i <= 451; ++i);
}

//funkcja putchar wysyła dane do drukarki, linia STROBE musi być w
//stanie wysokim!
int putchar (const int c)
{
    while (BUSY);       //testowanie stanu BUSY,oczekiwanie na stan niski
    P0 = c;             //wyprowadzenie danych
    STROBE = 0;         //ujemny impuls na linii STROBE
    delay(1);           //to jest zapis danych do drukarki
    STROBE = 1;
    while (!ACK);       //oczekiwanie na stan niski linii ACK
}

//inicjalizacja drukarki (zerowanie bufora i pozycjonowanie głowicy)
bit initprinter()
{
    BYTE cnt = 30;      //30 sekund oczekiwania na ustąpienie BUSY
                        //po wysłaniu sygnału INIT
    PRNSEL = 0;         //aktywny sygnał wyboru drukarki
    INIT = 0;           //zerowanie bufora drukarki, pozycjonowanie głowicy
    delay(1);           //(impuls o czas trwania ~1ms na linii INIT)
    INIT = 1;
    while (BUSY & cnt--) delay(1000);//dopóki BUSY=1 i cnt>0
    return (ERROR);     //funkcja zwraca stan linii sygnalizacji błędu
                        //jeśli błąd, to stan linii = 0
}

//program główny
void main()
{
    P0 = P2 = 0xFF;
    EA = EX0 IT0 = 1;   //załączenie obsługi przerwań zewnętrznych (opadające zbocze
                        //zbocze sygnału na INT0)
    if (initprinter())
    {
        printf("%s\n\r", "tO jEST tEST dRUKARKI!");
        printf("%s\n\r", "ABCDEFGHIJKLMNOPQRSTUVWXYZ 01234567890");
        printf("%s\n\r", "abcdefghijklmnopqrstuvwxyz 01234567890");
    }
        else
    {
        //tu funkcja sygnalizacji błędu
    }
    while(1);
}

 

Drukarka jako komórka pamięci.

Drugi przykład aplikacji jest znacznie bardziej rozbudowany od strony sprzętowej. Konieczne jest zarówno zbudowanie rejestru adresów jak i dekodera adresów oraz układów buforujących dane, sygnały kontrolne i umożliwiających odczyt linii statusu drukarki.
Mikrokontroler z rodziny 8051/8052 żądając dostępu do zewnętrznej komórki pamięci, przesyła przez port P0 na przemian adres oraz dane. Rodzaj przesyłanego słowa (adresowe czy danych) sygnalizowany jest przez wyprowadzenie o nazwie ALE (Address Latch Enable). Opadające zbocze ALE powoduje zapis młodszego bajtu adresu do rejestru adresowego (nie ma go na schemacie) oraz sygnalizuje pojawienie się bajtu danych. Mikrokontroler posiada na swojej liście rozkazy umożliwiające dostęp zarówno dostęp do danych leżących w obszarze adresowania 8-bitowego, jak i 16-bitowego, wykorzystując jako rejestr adresowy bądź to rejestr 8-bitowy Ri, bądź to rejestr 16-bitowy DPTR. W praktyce używanie adresu 16-bitowego skutkuje zmianą stanu P2 w czasie dostępu do danych. Ze względu na to, że P2 może być używany do innych celów, wybrano obszar adresowania 8-bitowego, który jest wystarczający dla poprawnej aplikacji. Wówczas to stan portu P2 nie zmienia się podczas dostępu do danych.
Układ U1 (74HCT573) to ośmiokrotny przerzutnik „D”, który pełni rolę rejestru danych przesyłanych do drukarki. Układ U2 (74LS75) to również przerzutnik typu „D”, jednak w obudowie znajdują się tylko 4 takie przerzutniki. Trzy linie wyjściowe (Q1, Q2, Q3) pełnią rolę sygnałów kontrolnych interfejsu drukarki. Układ U5 (74LS244), to bufor wejściowy umożliwiający po zaadresowaniu odczyt stanu linii statusu drukarki (BUSY, PE, ACK, SELECTED). Wyjątkiem jest linia ERROR, którą dołączono za pośrednictwem przez cały czas otwartego bufora do wyprowadzenia INT0 mikrokontrolera. Układ U4 (74LS138) pełni rolę dekodera adresów. Jest to układ demultipleksera 3/8 wyposażony dodatkowo w trzy wejścia ENABLE (E1, E2, E3).
Na pojawienie się stanu niskiego na wyjściu demultipleksera U4 zezwala następująca formuła: (!RD x !WR) x !AD6 x AD7. Wyjścia wybierane są poprzez wejścia adresowe A i B, dołączone odpowiednio do AD0 i AD1. Stan tych dwóch linii adresowych będzie wpływał na to, które wyjście będzie załączone. Spróbujmy rozszyfrować adresy poszczególnych układów:
1) Wyjście Y0 dołączone jest do U5. Wymagane jest zatem, aby AD0 = AD1 = 0, AD6 = 0 i AD7 = 1. Pozostałe bity słowa adresu nie mają żadnego znaczenia. Można stąd wywnioskować, że na magistrali adresowej musi się pojawić następująca kombinacja bitów: 10xxxx00. Zastępując „x” 0 otrzymujemy adres, który najwygodniej jest wyrazić szesnastkowo jako 0x80.
2) Wyjście Y1 dołączone jest poprzez inwertor do U2. Użycie inwertora jest konieczne, ponieważ zgodnie z zasadą działania przerzutnika typu „Latch” jest on „przeźroczysty”, gdy na wejście taktujące doprowadzona jest „1”, natomiast zmiana stanu z 0 na 1 na tym wejściu, powoduje zapamiętanie informacji. Układ U2 może być zapisany jako komórka pamięci o adresie o 1 wyższym, niż adres U5. Jest to 0x81 (szesnastkowo).
3) Wyjście Y2 dołączone jest (podobnie jak Y1) przez inwertor do U1 pełniącego rolę rejestru danych drukarki. Adres, pod którym można rejestr danych drukarki zapisać, to 0x82 (szesnastkowo).
4) Wyjście Y3 wypracowuje sygnał STROBE. Zapis lub odczyt bajtu spod adresu 0x83 powoduje krótki impuls na wyjściu Y3 trwający tyle, ile sygnał RD czy WR, więc czas jego trwania będzie zależał od częstotliwości zegara mikrokontrolera. Opisywane układy pracowały z zegarem 11,0592MHz. Aplikacja sterująca zapisuje najpierw rejestr danych a później wysyła bajt o dowolnej wartości pod adres 0x83.
Adresy zadeklarowane zostały jako zmienne leżące w obszarze PDATA mikrokontrolera. W związku z tym, że jest to obszar rozciągający się w pamięci zewnętrznej od adres 0 do 0xFF, mikrokontroler adresuje go pośrednio przy pomocy rejestrów 8-bitowych. W ten sposób stan portu P2 nie zmienia się podczas dostępu do rejestrów związanych ze sterowaniem drukarki.
Zapis rejestru polega na przypisaniu odpowiedniej zmiennej wartości a odczyt, na pobraniu wartości zmiennej przez jej użycie w operacjach logicznych lub przypisania. Kompilator sam „wie” na podstawie deklaracji, że przy odczycie czy zapisie tego rodzaju zmiennych, należy odwołać się do pamięci zewnętrznej. Tak dla przykładu może wyglądać zapis rejestru danych drukarki: PRINTER_DATA = ‘A’. A tak pobranie wartości z rejestru statusu: unsigned char status = CTRL_SIGNALS lub CTRL_SIGNALS && 0x01.

Podobnie jak w poprzednim programie (patrz listing 1) tak i tu wymieniona została funkcja putchar(). Jednak, mimo, iż algorytmy działania funkcji z listingu 1 i 2 są zgodne, to jednak implementacja jest zupełnie inna. Funkcja z listingu 2 nie ustawia bezpośrednio stanów linii portów a jedynie zapisuje do zmiennych wartości. Otoczenie sprzętowe mikrokontrolera samo wypracowuje niezbędne sygnały sterujące. Można powiedzieć, że kosztem dodatkowych układów TTL i miejsca na płytce można znacznie uprościć program sterujący.

Listing 2. Obsługa drukarki pracującej w obszarze adresowania 8-bitowego.

/***********************************************************
DOŁĄCZENIE DRUKARKI 9-IGŁOWEJ W TRYBIE: EPSON_STANDARD_TEXT
DO MIKROKONTROLERA Z RODZINY INTEL 8051. DRUKARKA DOŁĄCZONA
W OBSZARZE ADRESOWANIA 8-BITOWEGO.
***********************************************************/

#pragma SMALL
#include <reg8252.h>
#include <stdio.h>

//sygnały sterujące pracą interfejsu
#define LINEFEED    0x01   //stan niski powoduje, że papier automatycznie jest wysuwany
                           //o 1 linię po zakończeniu wydruku
#define INIT        0x02   //stan niski powoduje wyzerowanie bufora drukarki
                           //oraz ustawienie głowicy w pozycji spoczynkowej
#define PRNSEL      0x04   //stan wysoki powoduje, że można zmieniać status drukarki
                           //wysyłając kody DC1/DC3
//sygnały kontrolne drukarki
#define ACK          0x01   //sygnał potwierdzenia odbioru danych przez drukarkę
                            //aktywny jest stan niski
#define BUSY         0x04   //sygnalizacja zajętości drukarki (bufor nie gotowy,
                            //drukarka off-line, błąd drukarki) aktywny stan wysoki
#define PE           0x02   //sygnalizacja braku papieru w drukarce, aktywny stan
                            //wysoki
#define SELECTED     0x04   //zgłoszenie, że drukarka jest on-line i gotowa do
                            //pracy, aktywny jest stan wysoki

at 0x80 pdata BYTE READ_STATUS;  //rejestr statusu drukarki (tylko odczyt)
at 0x81 pdata BYTE CTRL_SIGNALS; //rejestr sygnałów LF, INIT, PRINTER SELECT (tylko zapis)
at 0x82 pdata BYTE PRINTER_DATA; //rejestr danych drukarki (tylko zapis)
at 0x83 pdata BYTE STROBE;       //wysłanie impulsu na linii STROBE (zapis i odczyt)

sbit ERROR = P3^2;               //linia sygnalizacji błędu - INT0

//obsługa przerwania INT0,to jest stanu sygnalizacji błędu
void isr_INT0() interrupt 0 using 1
{
    BYTE status;
    status = READ_STATUS;             //odczyt statusu drukarki
       //tu obsługa sygnalizacji błędu

}

//funkcja realizuje opóźnienie k*1ms dla rezonatora f=11.0592 MHz
void delay(WORD k)
{
    WORD i,j;
    for ( j = 0; j < k; ++j)
        for (i = 0; i <= 451; ++i);
}

//inicjalizacja drukarki (zerowanie bufora i pozycjonowanie głowicy)
bit initprinter()
{
    BYTE cnt = 30;                 //30 sekund oczekiwania na ustąpienie BUSY
                                   //po wysłaniu sygnału INIT
    while ((READ_STATUS && BUSY) & cnt--) delay(1000);    //dopóki BUSY=1 i cnt>0
    return (ERROR);                //funkcja zwraca stan linii sygnalizacji błędu
                                   //jeśli błąd, to stan linii = 0
}

//funkcja putchar wysyła dane do drukarki
int putchar (const int c)
{
    while (READ_STATUS && BUSY);   //testowanie stanu BUSY,oczekiwanie na stan niski
    PRINTER_DATA = c;              //zapis danych do rejestru danych drukarki
    STROBE = 0;                    //ujemny impuls na linii STROBE
    while (!(READ_STATUS && ACK)); //oczekiwanie na stan wysoki linii ACK
}

//program główny
void main()
{
    EA = EX0 IT0 = 1;   //załączenie obsługi przerwań zewnętrznych (opadające zbocze
                        //zbocze sygnału na INT0)
    if (initprinter())
    {
        printf("%s\n\r", "tO jEST tEST dRUKARKI!");
        printf("%s\n\r", "ABCDEFGHIJKLMNOPQRSTUVWXYZ 01234567890");
        printf("%s\n\r", "abcdefghijklmnopqrstuvwxyz 01234567890");
    }
        else
    {
        //tu funkcja sygnalizacji błędu
    }
    while(1);
}

Mam nadzieję, że przedstawione wyżej przykłady aplikacji będą wystarczającymi wskazówkami do samodzielnego eksperymentowania. Okiełznanie drukarki pracującej w trybie tekstowym nie jest trudne. Znacznie gorzej jest w trybie graficznym. Dodatkowo drukarki mają tę nieprzyjemną cechę, że każdy producent stosuje jakieś własne, charakterystyczne rozwiązania i nie zawsze można drukarką sterować przy pomocy tych samych poleceń. Jest to cecha dobrze znana twórcom starszego oprogramowanie pracującego pod kontrolą systemu DOS. Można powiedzieć, że pewne rozkazy są wspólne dla wszystkich drukarek, ale chcąc zmienić czcionkę czy zagęścić wydruk, można napotkać na duże różnice w formacie poleceń pomiędzy drukarkami. Konstruując interfejs przeznaczony do pracy z konkretną drukarką należy bacznie prześledzić informacje zawarte w instrukcji użytkownika.

Jacek Bogusz
jacek.bogusz@easy-soft.net.pl

 


[1]1 s.o.l. to standardowe obciążenie logiczne; dla TTL wynosi ono 10mA w stanie niskim. Oznacza to możliwość dołączenia do wyjścia układu 10 wejść układów TTL.

http://www.tomaszbogusz.blox.pl/

Dodaj nowy komentarz

Zawartość pola nie będzie udostępniana publicznie.