Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.
Obě strany předchozí revize Předchozí verze Následující verze | Předchozí verze | ||
2014:spi-glcd-msp [2014/12/31 17:01] David Čada [Návrh zapojení převodníku] |
2014:spi-glcd-msp [2015/01/09 10:14] (aktuální) David Čada [Závěr] |
||
---|---|---|---|
Řádek 27: | Řádek 27: | ||
{{:2014:spi-glcd-msp:prevodnik.png?500}} | {{:2014:spi-glcd-msp:prevodnik.png?500}} | ||
+ | |||
+ | ==== Program pro řízení ==== | ||
+ | |||
+ | == Odeslání 16b proměnné == | ||
+ | |||
+ | <code cpp> | ||
+ | void send_SPI(unsigned int c) | ||
+ | { | ||
+ | //funkce odešle po SPI lince 16bitovou proměnnou | ||
+ | |||
+ | unsigned int a; | ||
+ | a=c>>8; //do a je uložena horní část 16bitové proměnné | ||
+ | |||
+ | while(!(UCA0IFG&UCTXIFG)); //čekej dokud je buffer prázdný | ||
+ | UCA0TXBUF=(unsigned char)a; //pošli horní část proměnné | ||
+ | while(!(UCA0IFG&UCTXIFG)); //čekej dokud je buffer prázdný | ||
+ | UCA0TXBUF=(unsigned char)c; //pošli spodní část proměnné | ||
+ | while(!(UCA0IFG&UCTXIFG)); //čekej dokud je buffer prázdný | ||
+ | |||
+ | P1OUT |= BIT6; | ||
+ | P1OUT &=~BIT6; | ||
+ | return; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | == Funkce pro odeslání příkazu do LCD== | ||
+ | <code cpp> | ||
+ | void LCD_CMD(unsigned char command) | ||
+ | { | ||
+ | P8OUT &=~ BIT1; | ||
+ | SPIDAT |= A0; //A0 do 1 | ||
+ | SPIDAT=SPIDAT+command; | ||
+ | SPIDAT &=~ WR; //WR vynuluji | ||
+ | send_SPI(SPIDAT); | ||
+ | |||
+ | SPIDAT |= WR; //WR, A0 přepnu do 1 | ||
+ | send_SPI(SPIDAT); | ||
+ | |||
+ | |||
+ | SPIDAT=SPIDAT&0xFF00; | ||
+ | return; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | == Funkce pro odeslání dat do LCD== | ||
+ | <code cpp> | ||
+ | void LCD_DATA(unsigned char data) | ||
+ | { | ||
+ | |||
+ | SPIDAT=SPIDAT+data; | ||
+ | SPIDAT &=~ A0; //A0 vynuluji | ||
+ | SPIDAT &=~ WR; //WR vynuluji | ||
+ | send_SPI(SPIDAT); | ||
+ | SPIDAT |= WR; //WR, A0 přepnu do 1 | ||
+ | send_SPI(SPIDAT); | ||
+ | |||
+ | SPIDAT=SPIDAT&0xFF00; | ||
+ | return; | ||
+ | } | ||
+ | </code> | ||
+ | == Umístění kurzoru na pozici == | ||
+ | <code cpp> | ||
+ | void cursor(unsigned int pozice) | ||
+ | { | ||
+ | LCD_CMD(0x46); // cursor command | ||
+ | LCD_DATA((unsigned char)pozice); // lower | ||
+ | pozice=pozice>>8; | ||
+ | LCD_DATA((unsigned char)pozice); // higher | ||
+ | } | ||
+ | </code> | ||
+ | == Vynulování RAM displeje == | ||
+ | <code cpp> | ||
+ | void graphics_clear(void) | ||
+ | { | ||
+ | |||
+ | //funkce vyčistí grafickou a textovou část | ||
+ | //všechny pozice RAM jsou vyplněny nulami | ||
+ | //bez vynulování zobrazuje LCD nahodilé symboly a grafiku | ||
+ | |||
+ | unsigned int m=0; //proměnné pro cykly | ||
+ | unsigned int n=0; //proměnné pro cykly | ||
+ | LCD_CMD(0x4F); | ||
+ | for(m=0;m<27;m++) | ||
+ | { | ||
+ | |||
+ | |||
+ | for(n=0;n<40;n++) | ||
+ | { | ||
+ | cursor(9600+m*360+n); //výběr jednotlivých sektorů paměti LCD | ||
+ | |||
+ | LCD_CMD(0x42); //nastav zápis | ||
+ | //sektor LCD vyplněn nulami | ||
+ | LCD_DATA(0x00); | ||
+ | LCD_DATA(0x00); | ||
+ | LCD_DATA(0x00); | ||
+ | LCD_DATA(0x00); | ||
+ | LCD_DATA(0x00); | ||
+ | LCD_DATA(0x00); | ||
+ | LCD_DATA(0x00); | ||
+ | LCD_DATA(0x00); | ||
+ | LCD_DATA(0x00); | ||
+ | |||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | == Zápis pixelu na pozici == | ||
+ | <code cpp> | ||
+ | void write_pixel(unsigned int x,unsigned int y) | ||
+ | { | ||
+ | static int pozicnik=0; | ||
+ | static int mem; | ||
+ | static int pole[20]={0}; | ||
+ | unsigned char sektor; | ||
+ | unsigned char subbit; | ||
+ | subbit=x%8; | ||
+ | sektor=(x-subbit)/8; | ||
+ | |||
+ | if(pozicnik!=19) | ||
+ | { | ||
+ | cursor(pole[pozicnik+1]);//předchozí pozici vyčistit | ||
+ | LCD_CMD(0x42); | ||
+ | LCD_DATA(0x00); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | cursor(pole[0]);//předchozí pozici vyčistit | ||
+ | LCD_CMD(0x42); | ||
+ | LCD_DATA(0x00); | ||
+ | } | ||
+ | |||
+ | mem=9600+y*40+sektor; | ||
+ | pole[pozicnik]=mem; | ||
+ | pozicnik++; | ||
+ | |||
+ | if(pozicnik==20) | ||
+ | { | ||
+ | pozicnik=0; | ||
+ | } | ||
+ | |||
+ | |||
+ | cursor(mem); | ||
+ | LCD_CMD(0x42); | ||
+ | LCD_DATA(0b10000000>>subbit); | ||
+ | } | ||
+ | </code> | ||
+ | ==Inicializační sekvence== | ||
+ | <code cpp> | ||
+ | SPIDAT|= A0|WR|RD; | ||
+ | send_SPI(SPIDAT); | ||
+ | _delay_cycles(1000); | ||
+ | SPIDAT|= RESET; | ||
+ | send_SPI(SPIDAT); | ||
+ | _delay_cycles(1000); | ||
+ | _delay_cycles(1000); | ||
+ | |||
+ | // inicializační sekvence pro LCD 320x240 | ||
+ | // pro jiný rozměr je nutno přepočítat | ||
+ | |||
+ | LCD_CMD(0x40); //system set | ||
+ | LCD_DATA(0x30); | ||
+ | LCD_DATA(0x07); | ||
+ | LCD_DATA(0x07); | ||
+ | LCD_DATA(0x27); | ||
+ | LCD_DATA(0x2F); | ||
+ | LCD_DATA(0xEF); | ||
+ | LCD_DATA(0x28); | ||
+ | LCD_DATA(0x00); | ||
+ | |||
+ | LCD_CMD(0x44); //scroll | ||
+ | LCD_DATA(0x0); | ||
+ | LCD_DATA(0x0); | ||
+ | LCD_DATA(0xF0); | ||
+ | LCD_DATA(0x80); | ||
+ | LCD_DATA(0x25); | ||
+ | LCD_DATA(0xF0); | ||
+ | LCD_DATA(0x00); | ||
+ | LCD_DATA(0x4B); | ||
+ | LCD_DATA(0x0); | ||
+ | LCD_DATA(0x0); | ||
+ | |||
+ | LCD_CMD(0x5A); //HDOT SCR | ||
+ | LCD_DATA(0x0); | ||
+ | LCD_CMD(0x5B); //ovlay | ||
+ | LCD_DATA(0x01); | ||
+ | LCD_CMD(0x58); //DISP ON OFF | ||
+ | LCD_DATA(0x56); | ||
+ | LCD_CMD(0x46); //CSRW | ||
+ | LCD_DATA(0x00); | ||
+ | LCD_DATA(0x00); | ||
+ | LCD_CMD(0x5D); //CSR FORM | ||
+ | LCD_DATA(0x04); | ||
+ | LCD_DATA(0x86); | ||
+ | LCD_CMD(0x59); //display ON | ||
+ | </code> | ||
+ | |||
+ | ==Test grafické části řízení - jezdící had== | ||
+ | <code cpp> | ||
+ | unsigned int px=0; | ||
+ | unsigned int py=0; | ||
+ | //proměnné se inkrementují tak dlouho dokud "nenarazí na kraj LCD" | ||
+ | //což je zjištěno pomocí podmínek if(py==239), následně se vynuluje příznak | ||
+ | //a proměnná se dekrementuje, poloha aktuálního bodu je zapsána pomocí write_pixel(px,py); | ||
+ | |||
+ | while(1) | ||
+ | { | ||
+ | if(xpriznak==0) | ||
+ | px++; | ||
+ | if(ypriznak==0) | ||
+ | py++; | ||
+ | |||
+ | if(xpriznak!=0) | ||
+ | px--; | ||
+ | if(ypriznak!=0) | ||
+ | py--; | ||
+ | |||
+ | if(px==319) | ||
+ | xpriznak=1; | ||
+ | if(py==239) | ||
+ | ypriznak=1; | ||
+ | |||
+ | if(px==0) | ||
+ | xpriznak=0; | ||
+ | if(py==0) | ||
+ | ypriznak=0; | ||
+ | |||
+ | write_pixel(px,py); //zápis polohy bodu | ||
+ | |||
+ | for(i=0;i<4000;i++) //jednoduchý delay | ||
+ | {} | ||
+ | |||
+ | } | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ==== Závěr ==== | ||
+ | Funkční řízení LCD po lince SPI je možno vidět na tomto odkazu https://www.youtube.com/watch?v=FCzxzdG-qaQ . Na uvedeném testu je možno vidět postupné několikanásobné vypsání textu Hello world, následně změněna adresa zápisu a vypsáno písmeno C pro zjištění správně textové mřížky LCD. Grafická část zobrazuje jezdícího hada. Během testování se ukázalo, že k řízení by bylo vhodné zvýšit takt procesoru ( použitá vývojová SPI deska využívá takt pouze 4MHz ) případně využít procesor s rychlejším SPI modulem. Použitý LCD výrobce Raystar nedosahuje příliš vysokého kontrastu. V katalogovém listu je uvedena barva černobílá avšak černá tohoto displeje připomíná spíše modrou. Celkový kód je možno vidět zde http://pastebin.com/UqdhU00N |