AVR display
From OmegaV-wiki
H-fil:
#if !defined DISPLAY_HEADER #define DISPLAY_HEADER #define asm __asm__ #define DISPLAY_PORT PORTA //Porten som brukes #define DISPLAY_PIN PINA #define DISPLAY_DDR DDRA #define DISP_RS_PIN 7 #define DISP_RW_PIN 6 #define DISP_EN_PIN 5 #define DISP_D4_PIN 4 #define DISP_D5_PIN 3 #define DISP_D6_PIN 2 #define DISP_D7_PIN 1 //#define F_CPU 8000000L #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include <avr/eeprom.h> #include <avr/pgmspace.h> #include <math.h> typedef char BOOL; #define TRUE 1; #define FALSE 0; //char menyHenta[3]; void sendDisplay(uint8_t data, const uint8_t RS); char hentDisplay(void); uint8_t initDisplay(void); uint8_t checkDispStatus(void* ikkeBrukt); void sendDispRamString(char* progAddresse); void sendDispProgString(char* progAddresse); void sendDispInt(int32_t tall); void sendDispFloat(float tall, uint16_t decimalMultiplier); static inline void sendDisplayData(char data){ sendDisplay(data, 1); } static inline void sendDisplayInstruksjon(char instr){ sendDisplay(instr, 0); } static inline char hentDisplayAddresse(void){ asm volatile("clt"::); return hentDisplay(); } static inline char hentDisplayData(void) { asm volatile("set"::); return hentDisplay(); } static inline void CursDispShift(char ShiftCurs, char HoyreVenstre){ char inst = 0x10; if(ShiftCurs) inst |= 0x08; if(HoyreVenstre) inst |= 0x04; sendDisplayInstruksjon(inst); } static inline void dispClear(void){ sendDisplayInstruksjon(0x01); } static inline void dispHome(void){ sendDisplayInstruksjon(0x02); } static inline void dispEntryMode(char IncDec, char shift){ //IncDec = 1 øker for hver bokstav, og IncDec = 0 minsker char inst = 0x04; if(IncDec) inst |= 0x02; if(shift) inst |= 0x01; sendDisplayInstruksjon(inst); } static inline void dispAvPaa(char main, char cursor, char blink){ char inst = 0x08; if(main) inst |= 0x04; if(cursor) inst |= 0x02; if(blink) inst |= 0x01; sendDisplayInstruksjon(inst); } static inline void dispSetCGRAM(char nyAddresse){ nyAddresse &= 0x3f; nyAddresse |= 0x40; sendDisplayInstruksjon(nyAddresse); } static inline void dispSetDDRAM(char nyAddresse){ nyAddresse |= 0x80; sendDisplayInstruksjon(nyAddresse); } #endif </code> C-fil: <code c> #include "disp.h" char PROGMEM egneKaraktera[] = { 0x0F, 0x14, 0x14, 0x1F, 0x14, 0x14, 0x17, 0x00, //Æ pos 1 0x01, 0x0E, 0x13, 0x15, 0x19, 0x0E, 0x10, 0x00, //Ø pos 2 0x04, 0x0A, 0x04, 0x0E, 0x11, 0x1F, 0x11, 0x00, //Å pos 3 0x00, 0x00, 0x1A, 0x05, 0x0F, 0x14, 0x0F, 0x00, //æ pos 4 0x00, 0x02, 0x0E, 0x15, 0x15, 0x0E, 0x08, 0x00, //ø pos 5 0x04, 0x0A, 0x0E, 0x01, 0x0F, 0x11, 0x0F, 0x00, //å pos 6 0x0C, 0x12, 0x12, 0x0C, 0x00, 0x00, 0x00, 0x00 //Grade-tegn }; uint8_t displayStatus; //0->ikke tilkoblet, 1->tilkoblet void sendDispProgString(char* progAddresse){ char tegn = pgm_read_byte(progAddresse++); while(tegn != 0){ sendDisplayData(tegn); tegn = pgm_read_byte(progAddresse++); } } void sendDispRamString(char* progAddresse){ char* tegn = progAddresse; while(*tegn != 0) sendDisplayData(*tegn++); } void sendDispInt(int32_t tall){ if (tall < 0){ tall = - tall; sendDisplayData('-'); } if(tall == 0){ sendDisplayData('0'); } int32_t divisor = 1000000000; uint8_t startet = 0; while(divisor != 0){ uint8_t sendes = ((uint8_t) (tall/divisor)); if((startet != 0) || (sendes != 0)){ sendDisplayData(sendes+'0'); startet = 0xFF; tall = tall%divisor; } divisor = divisor/10; } } void sendDispFloat(const float tall, const uint16_t decimalMultiplier){ int32_t vises = (int32_t) (tall*decimalMultiplier); sendDispInt(vises/decimalMultiplier); sendDisplayData('.'); sendDispInt( (abs(vises%decimalMultiplier))+0.5 ); } //RS=1 sender data, RS=0 sender instruksjon (LSB bestemmer). T-flagget brukes i funkjonen void sendDisplay(uint8_t data, const uint8_t RS){ DISPLAY_PORT = 0; if(displayStatus==0)//drit i alt hvis displayet ikke er tilkoblet return; int teller = 0; asm volatile("clt" "\n\t"::); while( (hentDisplay() & 0x80) && ((++teller) < 1000) ){ } if (!(teller<1000)){ displayStatus = 0; //OSAddTask(initDisplay, (void*)0, 200); } //Skal altså sende... DISPLAY_DDR = (1<<DISP_RS_PIN)|(1<<DISP_RW_PIN)|(1<<DISP_EN_PIN)|(1<<DISP_D4_PIN)|(1<<DISP_D5_PIN)|(1<<DISP_D6_PIN)|(1<<DISP_D7_PIN); for(uint8_t i = 2 ; i != 0; i--){ uint8_t utByte = 0; if(RS){ utByte |= (1<<DISP_RS_PIN); } if(data & (1<<4)){ utByte |= (1<<DISP_D4_PIN); } if(data & (1<<5)){ utByte |= (1<<DISP_D5_PIN); } if(data & (1<<6)){ utByte |= (1<<DISP_D6_PIN); } if(data & (1<<7)){ utByte |= (1<<DISP_D7_PIN); } DISPLAY_PORT = utByte; asm volatile("nop"::); DISPLAY_PORT |= (1<<DISP_EN_PIN); //Setter EN-pinne asm volatile( "swap %0" "\n\t" //Bytter om slik at neste gang blir low-nibble sendt "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" :"=r" (data) :"r" (data) ); DISPLAY_PORT = utByte; //Resetter EN-pinne } } char hentDisplay(void){ //Setter dataporter til innganger, og styresignalene til utganger. DISPLAY_DDR = (1<<DISP_RS_PIN)|(1<<DISP_RW_PIN)|(1<<DISP_EN_PIN); //setter RW høy og skrur på pullup på innganger uint8_t styreByte = (1<<DISP_RW_PIN)|(1<<DISP_D4_PIN)|(1<<DISP_D5_PIN)|(1<<DISP_D6_PIN)|(1<<DISP_D7_PIN); asm volatile( //Setter RS-bit bestemt av T-bit "bld %0, %1" :"=r" (styreByte) :"I" (DISP_RS_PIN), "r" (styreByte) ); uint8_t ret = 0; DISPLAY_PORT = styreByte; asm volatile("nop"::); for(uint8_t i = 2; i!=0; i--){ DISPLAY_PORT |= (1<<DISP_EN_PIN); //Setter EN-pinne asm volatile( "swap %0" "\n\t" //Bytter om slik at neste gang blir low-nibble sendt "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" :"=r" (ret) :"r" (ret) ); uint8_t p = DISPLAY_PIN; DISPLAY_PORT &= ~(1<<DISP_EN_PIN); //Resetter EN-pinne if(p & (1<<DISP_D4_PIN)){ ret |= (1<<0); } if(p & (1<<DISP_D5_PIN)){ ret |= (1<<1); } if(p & (1<<DISP_D6_PIN)){ ret |= (1<<2); } if(p & (1<<DISP_D7_PIN)){ ret |= (1<<3); } } DISPLAY_PORT = 0; return ret; } uint8_t initDisplay(void){ displayStatus = 1; DISPLAY_DDR = (1<<DISP_RS_PIN)|(1<<DISP_RW_PIN)|(1<<DISP_EN_PIN)|(1<<DISP_D4_PIN)|(1<<DISP_D5_PIN)|(1<<DISP_D6_PIN)|(1<<DISP_D7_PIN); for(char i = 0x0f; i; i=i>>1){ _delay_loop_2(0x3FFF); uint8_t pinne = (1<<DISP_D5_PIN); asm volatile( "bst %3, 1" "\n\t" "bld %0, %2" "\n\t" :"=r" (pinne) :"r" (pinne), "I" (DISP_D4_PIN), "r" (i) //Setter data4 hvis den skal settes ); DISPLAY_PORT = pinne; asm volatile("nop" ::); DISPLAY_PORT |= (1<<DISP_EN_PIN); //Setter EN-pinne asm volatile( "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" "nop" "\n\t" : : ); DISPLAY_PORT &= ~(1<<DISP_EN_PIN); //Resetter EN-pinne } sendDisplayInstruksjon(0x28); if(displayStatus == 0){ return 0; } sendDisplayInstruksjon(0x06); sendDisplayInstruksjon(0x02); sendDisplayInstruksjon(0x0c); sendDisplayInstruksjon(0x48); //setter CG-ram-adresse unsigned int adr = egneKaraktera; while(adr < (egneKaraktera + sizeof(egneKaraktera)) ){ sendDisplayData(pgm_read_byte(adr++)); } dispSetDDRAM(0); return 0; } uint8_t checkDispStatus(void* ikkeBrukt){ //Dette kan skje noe uventet, men OS-et skal passe på at det ikke skjer under utførelse av annen prosess. //Men den kan forårsake at addressen er satt til 0 selv om den ikke var det etter forrige prosess. uint8_t adr = hentDisplayAddresse(); dispSetDDRAM(adr); if(displayStatus){ //OSAddTask(checkDispStatus, (void*)0, 300); //gjentaes hvert 3. sekund } else { //OSAddTask(initDisplay, (void*)0, 300); //Skal prøve å koble til displayet } return 0; } /* chat-discussion with author: Pål says: yess Pål says: fekk bilde no erlend says: jee erlend says: alt e perfekt erlend says: ? Pål says: yepp Pål says: men ka gjer egentlig metoden hentDisplay? erlend says: bare å kjør på da erlend says: hent??? erlend says: hmmmm erlend says: hete den hent erlend says: ? Pål says: char hentDisplay(void){ Pål says: men ej brukte den her uint8_t initDisplay(void* ikkeBrukt){ erlend says: ikke sikker erlend says: ja Pål says: ka e egentlig en void* ikkeBrukt? erlend says: du kan fjern inout hvis du vil erlend says: bare for å tepass drivern te "OS-et" Pål says: k erlend says: brukes ikke te nå, men funksjonen må ha en standard form siden den kalles av "OSet" Pål says: k Pål says: ka du meina med å fjerne inout? erlend says: input erlend says: ikkeBrukt Pål says: ok erlend says: hentDisplay les ut data fra displayet erlend says: hentDisplay les ut data fra displayet erlend says: hentDisplay les ut data fra displayet erlend says: brukes også av sende-funksjonen erlend says: så den må vær der Pål says: ok Pål says: korleis ej kjøm til neste linje? erlend says: huske ikke navne på funksjonen erlend says: men den står nesten nederst i h-fila Pål says: CursDispShift erlend says: setDDRAM eller nå sånt Pål says: k erlend says: nei Pål says: e rutinå slik at ej skriv frå starten av displayet og når ej skal entre nokke so jeng ej til starten og skriv alt på nytt? erlend says: den samme erlend says: har du navnet? Pål says: static inline void dispSetDDRAM(char nyAddresse){ erlend says: ja erlend says: dispSetDDRAM starte i rute 1 Pål says: ok erlend says: evt 0 erlend says: dispSetDDRAM(0x40) starte i rute 0 på andre lnje Pål says: so ej kan gå til den rutå ej vil å skrive det ej vil? alt treng ikkje å ver i sekvens nei? erlend says: ja Pål says: cool Pål says: trur ej he det no erlend says: hvis du skrur på cursor bli det enklar å sje Pål says: k Pål says: no sendte ej hello world å no stend det "å" erlend says: da e det i live Pål says: hmm Pål says: skal ikkje det gå an å skrive sendDispProgString("Hello World"); ? erlend says: nei erlend says: den stringen vil lagres i RAMen erlend says: du må deklarer den som en global variabel Pål says: ok Pål says: greit erlend says: char PROGMEM .... Pål says: k Pål says: hmmm Pål says: char* PROGMEM tekst1 = "hallo verden"; Pål says: sendDispProgString(tekst1); erlend says: ikke char* Pål says: ah erlend says: men du må inkluder ei fil Pål says: å? erlend says: pmgspace eller nå sånt Pål says: ok Pål says: fekk ikkje feilmelding Pål says: den e inkludert i disp.h erlend says: oki erlend says: char PROGMEM tekst1 = "hallo verden"; erlend says: nei erlend says: char* PROGMEM tekst1[] = "hallo verden"; erlend says: [] ? [ ] erlend says: [] = [ ] erlend says: nei Pål says: no funka det Pål says: no stend det hallo verden erlend says: bra ting erlend says: skriv du: char PROGMEM tekst1[] = "hallo verden"; erlend says: ? Pål says: ja Pål says: for å slette so bere sende ej en space? erlend says: ja erlend says: eller funksjone clearDisp eller nå sånt Pål says: ok Pål says: cool erlend says: dispClear kanskje Pål says: no trur ej ej skal få til resten erlend says: det e bra Pål says: tjaa... Pål says: vist ej skal skrive pål er tøff då? Pål says: ø'en blir en x med strek over erlend says: det går ikke Pål says: ok erlend says: fysisk umulig erlend says: sjølmotsigels Pål says: hehe erlend says: har en tabell som definere æøå Pål says: må vel sende ett og ett tegn for å sende æøå Pål says: jepp såg tabelln Pål says: ej drit i æøå ej erlend says: trur æ=\001 erlend says: eller nå sånt erlend says: \00x erlend says: der x-en står som kommentar i tabellen Pål says: k erlend says: asm volatile("jmp 0" : ; erlend says: eller erlend says: asm volatile("jmp 0" "\n\t": ; erlend says: eller erlend says: __asm__ volatile("jmp 0" "\n\t": ; */
