Przykładowy program dla sterowników SU:
Poniżej prezentuję kody źródłowe przykładowego programu dla sterownika SU 1.2 oraz sterownika SU 1.5. Program został napisany w języku C, w środowisku Atmel Studio 6.
Program wyświetla napis na wyświetlaczu oraz za pomocą klawiszy można zmieniać stan wyjść cyfrowych.
Cały program został podzielony na trzy pliki:
- plik "przyklad_C_SU_12.c" zawiera program główny,
- plik "lcd.c" zawiera procedury od obsługi wyświetlacza LCD.
- plik "procedury.c" zawiera pozostałe procedury.
Program główny został podzielony na trzy części:
- odpowiednia konfiguracja TIMER-a 0 i pinów procesora,
- wyświetlenie napisu na wyświetlaczu LCD,
- w pętli głównej sterownik odczytuje wciśniety klawisz i odpowiednio zmienia stan wyjść.
#include <avr/io.h> #include "avr/interrupt.h" #include "procedury.h" #include "global.h" #include "avr/pgmspace.h" #include "lcd.h" #define KL_UP 0x02 #define KL_LEFT 0x03 #define KL_DOWN 0x04 #define KL_RIGHT 0x05 #define KL_OK 0x06 #define KL_ESC 0x07 volatile unsigned short ms, usx10; volatile unsigned char KLAWISZ_P, KLSZ, KLAWISZ; unsigned char const napis1[] PROGMEM= { "Sterownik SU 1.2á"}; unsigned char const napis2[] PROGMEM= { " firmy E-TRONIX á"}; int main(void) { unsigned char wyjscie; //poniżej konfiguracja TIMER-a 0, // TIMER 0 wykorzystany jest do obsługi klawiatury OCR0=91; TIFR=0; TCCR0=(1<<WGM01)|(0<<CS02)|(1<<CS01)|(0<<CS00); TIMSK=(1<<OCIE0);//załączenie przerwań od TIMER-a 0 sei(); //globalne załączenie przerwań DDRB=0xff; //magistrala danych jako wyjscie sbi(DDRD,4); //aktywacja pinu wyswietlacza sbi(DDRC,6); //aktywacja pinu ING1 odczytu wejsc cyfrowych sbi(DDRC,7); //aktywacja pinu do sterowania wyjsc cyfrowych sbi(DDRA,4); //aktywacja pinu /OE wyjsc cyfrowych sbi(PORTC,6); //stan wysoki na ING1 sbi(PORTC,7); //stan wysoki na OUTG1 cbi(PORTA,4); //stan niski na /OE (sterowanie wyjsc cyfrowych mozliwe) sbi(PORTD,4); //stan wysoki na DISPLAY LCD_init(); //inicjalizacja wyświetlacza LCD LCD_clear(); //wyczyszczenie wyświetlacza LCD_TXT(napis1);//wyświetlenie napisu pierwszego w wierszu pierwszym LCD_xy(1,2); LCD_TXT(napis2);//wyświetlenie napisu drugiego w wierszu drugim wyjscie=0; while(1) //pętla główna programu { switch(KLAWISZ) // w zależności od naciśniętego klawisza sterowane // jest wyjscie cyfrowe { case KL_UP: wyjscie=wyjscie^0b10000001; //wyjście przekaźnikowe nr 1 KLAWISZ=0; break; case KL_DOWN: wyjscie=wyjscie^0b01000010; //wyjście przekaźnikowe nr 2 KLAWISZ=0; break; case KL_LEFT: wyjscie=wyjscie^0b00000100; //wyjście przekaźnikowe nr 3 KLAWISZ=0; break; case KL_RIGHT: wyjscie=wyjscie^0b00001000; //wyjście przekaźnikowe nr 4 KLAWISZ=0; break; case KL_ESC: wyjscie=wyjscie^0b00010000; //wyjście tranzystorowe nr 1 KLAWISZ=0; break; case KL_OK: wyjscie=wyjscie^0b00100000; //wyjście tranzystorowe nr 2 KLAWISZ=0; break; } PORTB=wyjscie; //wystawienie danej na magistralę danych cbi(PORTC,7); //zatrzaśnięcie z magistrali danych na wyjścia cyfrowe sbi(PORTC,7); } }
Plik "lcd.c" zawiera procedury do obsługi wyświetlacza:
#include "global.h" #include <avr/io.h> #include "procedury.h" #include "avr/pgmspace.h" /* ************************************************* * Procedura zapisująca dane w wyświetlaczu LCD. * ************************************************* */ void LCD_clock(u08 data, u08 rs) { MAGIST_DATA=((data&0x0f)<<4); if (rs==1) // linia RS wyświetlacza sbi(MAGIST_DATA,LCD_RS); // ustaw linię RS wyświetlacza else cbi(MAGIST_DATA,LCD_RS); cbi(PORTB,1); sbi(DDRD,4); sbi(MAGIST_DATA,LCD_EN); // ustaw linię EN wyświetlacza wait(1); cbi(PORTD,4); // i wysłanie danych na szynę sbi(PORTD,4); wait(1); cbi(MAGIST_DATA,LCD_EN); // skasuj linię EN wyświetlacza wait(1); cbi(PORTD,4); sbi(PORTD,4); wait(1); cbi(MAGIST_DATA,LCD_RS); // skasuj liniŕ RS wyświetlacza } /* ************************************************* * Wysyłanie danych lub komend do wyświetlacza. * ************************************************* */ void LCD_send(u08 data, u08 rs) { LCD_clock(data >> 4 , rs); // bardziej znacząca część LCD_clock(data & 0x0F, rs); // mniej znacząca część } /* ************************************************* * Procedura wysyłająca komendy do wyświetlacza. * ************************************************* */ void LCD_send_0(u08 ch) { LCD_send(ch, 0); } /* ************************************************* * Procedura wysyłająca dane do wyświetlacza LCD.* ************************************************* */ void LCD_send_1(u08 ch) { LCD_send(ch, 1); } /* ************************************************* * Procedura czyszcząca wyświetlacz LCD. * ************************************************* */ void LCD_clear(void) { LCD_send_0(0x01); // wyczyść LCD wait(100); } /* ************************************************* * Procedura inicjująca wyświetlacz LCD. * ************************************************* */ void LCD_init(void) { register unsigned char i; wait(1600); for(i=0;i<3;i++) { LCD_clock(0x03, 0); //reset LCD wait(40); } LCD_clock(0x02,0); //operacje 4-bitowe LCD_send_0(0x2C); LCD_send_0(0x08); //wylacz lcd, wylacz kursor, wlacz mruganie kursora LCD_clear(); //skasuj lcd, kursor do pozycji home LCD_send_0(0x06); //przesuwaj kursor w prawo w trakcie wyswietlania LCD_send_0(0x0C); //wlacz lcd i wyłącz kursor } /* ************************************************* * Procedura wyświetlająca znak na wyświelaczu * * LCD. * ************************************************* */ void LCD_putchar(char ch) { LCD_send_1(ch); } /* ************************************************* * Procedura wyświetlająca napis umieszczony * * w pamięci programu. * ************************************************* */ void LCD_TXT(unsigned char tablica[]) { unsigned char x; x=0; for (x=0; pgm_read_byte(&tablica[x])!='á'; x++) { LCD_putchar(pgm_read_byte(&tablica[x])); } } /* ************************************************* * Procedura umieszczająca kursor wyświetlacza * * na odpowiednich współrzędnych. * ************************************************* */ void LCD_xy(u08 x, u08 y) { switch(y) { case 1: y=0x00; break; // adres 1 znaku 1 wiersza case 2: y=0x40; break; // adres 1 znaku 2 wiersza } LCD_send_0(0x80+y+x-1); // ustaw adres RAM }
Plik "procedury.c" zawiera m.in. obsługę przerwania TIMER-a 0:
#include "avr/interrupt.h" #include "global.h" #include "procedury.h" #include "lcd.h" #include "avr/pgmspace.h" #define KL_UP 0x02 #define KL_LEFT 0x03 #define KL_DOWN 0x04 #define KL_RIGHT 0x05 #define KL_OK 0x06 #define KL_ESC 0x07 volatile extern unsigned char KLAWISZ_P, KLSZ, KLAWISZ; volatile extern unsigned short ms, usx10; /* ***************************************************** * Obsługa przerwania TIMER-a 0, przerwanie to * * odpowiedzialne jest za obsługę klawiatury w * sterowniku. * ***************************************************** */ ISR(TIMER0_COMP_vect) { usx10++; // if (us==8) us=0; ms++; if (ms==400) { ms=0; KLAWISZ_P=0; if (bit_is_clear(PINC,PC2)) KLAWISZ_P=KL_UP; if (bit_is_clear(PINC,PC3)) KLAWISZ_P=KL_LEFT; if (bit_is_clear(PINC,PC4)) KLAWISZ_P=KL_DOWN; if (bit_is_clear(PINC,PC5)) KLAWISZ_P=KL_RIGHT; if (bit_is_clear(PINA,PA6)) KLAWISZ_P=KL_ESC; if (bit_is_clear(PINA,PA7)) KLAWISZ_P=KL_OK; if (KLAWISZ_P!=0) KLSZ=KLAWISZ_P; if ((KLAWISZ_P==0)&&(KLSZ!=0)) { KLAWISZ=KLSZ; KLSZ=0; } } } /* ***************************************************** * Porcedurka odmierzania czasu. * ***************************************************** */ void wait(unsigned short czas) { usx10=0; while (usx10!=czas); }
Foto. 1. Efekt działania programu.
Początek ..