Individální projekty MPOA

Mikroprocesory s architekturou ARM

Uživatelské nástroje

Nástroje pro tento web


2014:spi-oled-msp

Rozdíly

Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.

Odkaz na výstup diff

Obě strany předchozí revize Předchozí verze
Následující verze
Předchozí verze
2014:spi-oled-msp [2015/01/10 17:52]
Milan Abrman
2014:spi-oled-msp [2015/01/10 19:48] (aktuální)
Milan Abrman
Řádek 48: Řádek 48:
 Pokud je v menu zobrazen požadovaný parametr který má být změněn je možné třetím tlačítkem s názvem submenu prohlížet všechny podnabídky,​ které daný parametr umožňuje. Neustálým stiskáváním tohoto tlačítka je projížděno dokola kruhové menu, které toto tlačítko u každé nabídky vyvolává. Pokud je nalezen požadovaný parametr, který má být změněn stiskne se jednoduše poslední nastavovací tlačítko, které má název SET. Tímto stiskem dojde okamžitě k odeslání dat po SPI lince do koncového SPI zařízení a jsou nastaveny příslušné bity jeho řídícího registru, které odpovídají nastavenému parametru. Zároveň s tímto odesláním dat dojde také k zapamatování této volby. Na OLED displeji při zpětném prochází v hlavním menu, již bude na druhém řádku displeje u této volby indikován i zvolený parametr. Tím je zřetelně indikováno,​ jak bylo koncové zařízení nastaveno. Pokud je v menu zobrazen požadovaný parametr který má být změněn je možné třetím tlačítkem s názvem submenu prohlížet všechny podnabídky,​ které daný parametr umožňuje. Neustálým stiskáváním tohoto tlačítka je projížděno dokola kruhové menu, které toto tlačítko u každé nabídky vyvolává. Pokud je nalezen požadovaný parametr, který má být změněn stiskne se jednoduše poslední nastavovací tlačítko, které má název SET. Tímto stiskem dojde okamžitě k odeslání dat po SPI lince do koncového SPI zařízení a jsou nastaveny příslušné bity jeho řídícího registru, které odpovídají nastavenému parametru. Zároveň s tímto odesláním dat dojde také k zapamatování této volby. Na OLED displeji při zpětném prochází v hlavním menu, již bude na druhém řádku displeje u této volby indikován i zvolený parametr. Tím je zřetelně indikováno,​ jak bylo koncové zařízení nastaveno.
  
-==== Program pro řízení ​====+==== Vybrané statě ​řídícího algoritmu ​====
  
-== Odeslání 16b proměnné ​==+== Inicializace SPI komunikace ​==
  
 <code cpp> <code cpp>
-void send_SPI(unsigned int c)+void SPI_ini(void)
 { {
-//funkce odešle po SPI lince 16bitovou proměnnou+ // začátek inicializace ​SPI 
 + UCA0CTL1 |= UCSWRST; //​nastavím 
 + UCA0CTL0 ​ = UCMST + UCSYNC + UCCKPL + UCMSB; // master mode, synchronní mód, polarita hodin,MSB 
 + UCA0CTL1 ​ = UCSSEL_2; 
 + UCA0BR0 ​  = 0x00;       ​  ​       //předdělička nižší bity 
 + UCA0BR1 ​  = 0x00;       ​ //​předdělička vyšší bity 
 + UCA0MCTL ​ = 0x00;       ​ //​modulace,​ vždy zapsat 0 (bez modulace) 
 + UCA0CTL1 &=~ UCSWRST; //​vynuluji 
 + //konec inicializace SPI
  
- unsigned int a; +
- a=c>>​8; ​       //do a je uložena horní ​část 16bitové ​proměnné+</​code>​ 
 + 
 +== Odeslání dat po SPI lince do koncového SPI zařízení == 
 +<code cpp> 
 +void DAC_send(unsigned int c) 
 +
 +     unsigned int a; 
 +     ​a=c>>​8; ​                   // shiftování doprava o 8 → uložena horní ​polovina 16 bit proměnné
  
- while(!(UCA0IFG&​UCTXIFG)); ​  ​//čekej dokud je buffer ​prázdný +     while(!(UCA0IFG & UCTXIFG)); // čekej dokud není prázdný ​zásobník 
- UCA0TXBUF=(unsigned char)a; ​ //pošli horní část ​proměnné +     ​UCA0TXBUF=(unsigned char)a; ​ // vloží ​proměnnou a do zásobníku 
- while(!(UCA0IFG&​UCTXIFG)); ​  ​//čekej dokud je buffer ​prázdný +     ​while(!(UCA0IFG & UCTXIFG)); // čekej dokud není prázdný ​zásobník 
- UCA0TXBUF=(unsigned char)c; ​ //pošli spodní část ​proměnné +     ​UCA0TXBUF=(unsigned char)c; ​ // vloží ​proměnnou c do zásobníku (horních 8 bitů) 
- while(!(UCA0IFG&​UCTXIFG)); ​  ​//čekej dokud je buffer ​prázdný+     ​while(!(UCA0IFG & UCTXIFG)); // čekej dokud není prázdný ​zásobník
  
- P1OUT ​|= BIT6+     ​P8OUT ​|= BIT1; // vytvořen krátký pulz (obě jsou součástí enable pro DAC) 
- P1OUT &=~BIT6+     P8OUT &=~BIT1
- return;+     ​return;
 } }
 </​code>​ </​code>​
  
-== Funkce pro odeslání příkazu do LCD==+== Funkce pro inicializaci OLED displeje==
 <code cpp> <code cpp>
-void LCD_CMD(unsigned char command)+// funkce SPI_send je vytvořena naprosto stejně jako DAC_send,​pouze má na jiném pinu MCU vyveden chip select 
 +void LCD_ini(void)
 { {
- P8OUT &=~ BIT1+ cekej                          // čekací smyčka, zpomalení komunikace pro řadič 
- SPIDAT |A0; //A0 do 1 + INIDATA ​DB5 | DB4 | DB3      ​// nastavení příslušných inicializačních bitů 
- SPIDAT=SPIDAT+command+ SPI_send (INIDATA)             // pošle data po SPI 
- SPIDAT &=~ WR; //WR vynuluji + cekej; 
- send_SPI(SPIDAT);+ INIDATA ​EN | DB5 | DB4 | DB3 // inicializační bity se signálem enable pro displej 
 + SPI_send ​(INIDATA)
 + cekej; 
 + INIDATA = DB5 | DB4 | DB3; 
 + SPI_send (INIDATA);​ 
 + cekej;
  
- SPIDAT ​|= WR; //WR, A0 přepnu do 1 + INIDATA = DB1; 
- send_SPI(SPIDAT);+ SPI_send (INIDATA);​ 
 + cekej; 
 + INIDATA = EN DB1; 
 + SPI_send (INIDATA);​ 
 + cekej; 
 + INIDATA ​DB1
 + SPI_send ​(INIDATA)
 + cekej;
  
 + INIDATA = DB3 | DB2;
 + SPI_send(INIDATA);​
 + cekej;
 + INIDATA = EN | DB3 | DB2;
 + SPI_send (INIDATA);
 + cekej;
 + INIDATA = DB3 | DB2;
 + SPI_send(INIDATA);​
 + cekej;
  
- SPIDAT=SPIDAT&​0xFF00+ INIDATA ​DB0
- return;+ SPI_send(INIDATA);​ 
 + cekej; 
 + INIDATA = EN | DB0; 
 + SPI_send (INIDATA);​ 
 + cekej; 
 + INIDATA = DB0; 
 + SPI_send(INIDATA);​ 
 + cekej; 
 + 
 + INIDATA = DB2 | DB1; 
 + SPI_send(INIDATA);​ 
 + cekej; 
 + INIDATA = EN | DB2 | DB1; 
 + SPI_send (INIDATA);​ 
 + cekej; 
 + INIDATA = DB2 | DB1; 
 + SPI_send(INIDATA);​ 
 + cekej;
 } }
 </​code>​ </​code>​
  
-== Funkce pro odeslání dat do LCD==+== Funkce pro instrukcí ​do LCD==
 <code cpp> <code cpp>
-void LCD_DATA(unsigned ​char data)+void LCD_instr ​(unsigned ​int instrukce)
 { {
- + LCDINSTR ​instrukce
- SPIDAT=SPIDAT+data+ SPI_send (LCDINSTR)
- SPIDAT &=~ A0; //A0 vynuluji + cekej; 
- SPIDAT &=~ WR; //WR vynuluji + LCDINSTR ​EN | instrukce
- send_SPI(SPIDAT); + SPI_send ​(LCDINSTR); 
- SPIDAT |WR; //WR, A0 přepnu do 1 + cekej; 
- send_SPI(SPIDAT); + LCDINSTR ​instrukce
- + SPI_send ​(LCDINSTR); 
- SPIDAT=SPIDAT&​0xFF00;​ + cekej;
- return;+
 } }
 </​code>​ </​code>​
-== Umístění kurzoru ​na pozici ​==+== Výpis znaku na displej ​==
 <code cpp> <code cpp>
-void cursor(unsigned int pozice)+void LCD_znak ​(unsigned int znak)
 { {
-LCD_CMD(0x46);  // cursor command + LCDZNAK = RS | znak; 
-LCD_DATA((unsigned char)pozice); // lower + SPI_send ​(LCDZNAK); 
-pozice=pozice>>​8+ cekej; 
-LCD_DATA((unsigned char)pozice); // higher+ LCDZNAK = EN | RS | znak; 
 + SPI_send ​(LCDZNAK); 
 + cekej; 
 + LCDZNAK ​RS | znak
 + SPI_send ​(LCDZNAK); 
 + cekej;
 } }
 </​code>​ </​code>​
-== Vynulování RAM displeje ​==+== Funkce pro výpis řetězce na displeji ​==
 <code cpp> <code cpp>
-void graphics_clear(void)+void LCD_text(char radek, char pozice,char prepis, char text [20])
 { {
 + if (radek==1)
 + {
 + LCD_instr(DB7 |0x00+pozice-1);​ //​nastavení výpisu od požadovaného segmentu 1.řádku
 + }
  
-//funkce vyčistí grafickou a textovou část + else if (radek==2) 
-//všechny pozice RAM jsou vyplněny nulami +
-//bez vynulování zobrazuje LCD nahodilé symboly a grafiku+ LCD_instr(DB7 |0x40+pozice-1); ​//nastavení výpisu od požadovaného segmentu 2.řádku 
 + }
  
-unsigned int m=0//​proměnné pro cykly + char buffer[20]
-unsigned ​int n=0; //​proměnné pro cykly + int i=0; 
-LCD_CMD(0x4F); + sprintf(buffer,text); // výpis řetězce na OLED
-for(m=0;​m<​27;​m++) +
-{+
  
 + while (buffer[i]!=0)
 + {
 + LCD_znak(buffer[i]);​
 + i++;
 + }
 + if(prepis==true) ​      // povolení přepisu zbývajících segmentů
 + {
 + for (i;​i>​0;​i--)
 + {
 + LCD_znak('​ ');
 + }
 + }
 + else if (prepis==false)
 + {
  
- for(n=0;n<40;n+++
-+
- cursor(9600+m*360+n); //výběr jednotlivých sektorů paměti LCD+</​code>​ 
 +== Nastavení a povolení tlačítek == 
 +<code cpp> 
 +void tlacitka_ini (void
 +
 + // inicializace tlačítek 
 + P1REN |= BIT2; // povolím pullup rezistor na portu 1 a pinu 2 
 + P1OUT |= BIT2; // připojím pullup rezistor na 2
  
- LCD_CMD(0x42); ​       //nastav zápis + P1REN |= BIT3
-                                      //sektor LCD vyplněn nulami + P1OUT |= BIT3;
- 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);+
  
- } + P1REN |= BIT4; 
-}+ P1OUT |= BIT4; 
 + 
 + P1REN |= BIT5; 
 + P1OUT |= BIT5; 
 + // konec inicializace tlačítek
 } }
 </​code>​ </​code>​
-== Zápis pixelu na pozici ​==+== Přerušení od časovače, ošetření zákmitů tlačítek a přiřazení funkce tlačítům==
 <code cpp> <code cpp>
-void write_pixel(unsigned int x,unsigned int y)+// Timer A0 interrupt service routine → odstranění zákmitů tlačitek 
 +#pragma vector = TIMER0_A0_VECTOR 
 +__interrupt ​void Timer_A0 ​(void)
 { {
- static int pozicnik=0;​ + if(menu<9     // nastavení pro tlačítko menu UP
- 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 + static int old_state;​ 
- LCD_CMD(0x42); + int new_state= P1IN & BIT2
- LCD_DATA(0x00);+ if(new_state < old_state) 
 +
 + btn1_pressed = true
 + menu++; 
 +
 + old_state = new_state;
  }  }
- else+ if(menu>​1) ​   // nastavevní pro tlačítko menu DOWN
  {  {
- cursor(pole[0]);//​předchozí pozici vyčistit + static int old_state2;​ 
- LCD_CMD(0x42); + int new_state2= P1IN & BIT3
- LCD_DATA(0x00);+ if(new_state2 < old_state2) 
 +
 + btn2_pressed = true
 + menu--; 
 +
 + old_state2 = new_state2;
  }  }
  
- mem=9600+y*40+sektor+ static int old_state3 // nastavení pro tlačítko submenu 
- pole[pozicnik]=mem+ int new_state3P1IN & BIT4
- pozicnik++;​ + if(new_state3 < old_state3)
- +
- if(pozicnik==20)+
  {  {
- pozicnik=0;+ btn3_pressed ​true; 
 + submenu++;
  }  }
 + old_state3 = new_state3;
  
 + if(submenu-1 == pocet_submenu)
 + {
 + submenu=1;​
 + }
  
- cursor(mem); + if (send_param!=false // nastavení pro tlačítko SET 
- LCD_CMD(0x42)+
- LCD_DATA(0b10000000>>​subbit);+ static int old_state4
 + int new_state4= P1IN & BIT5
 + if(new_state4 < old_state4) 
 +
 + btn4_pressed = true; 
 +
 + old_state4 = new_state4;​ 
 + }
 } }
 </​code>​ </​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== ==Test grafické části řízení - jezdící had==
 <code cpp> <code cpp>
-unsigned int px=0+// 1. menu 
-unsigned int py=0; + if((btn1_pressed || btn2_pressed) && menu==1) 
-//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 ​íznak + LCD_instr(DB0); ​            // kompletní vymazání displeje 
-//a proměnná se dekrementujepoloha aktuálního bodu je zapsána pomocí write_pixel(px,py);+ LCD_text(1,​1,​true,"​Input"​)
 + btn1_pressed=false;​ 
 + btn2_pressed=false;​ 
 + send_param=false; ​          // deaktivace SET tlačítka 
 + pocet_submenu=2;​ 
 + submenu=0; 
 + if(nastaveni1==1) ​         ​// zapamatování nastavení (pokud vybrán Optical) 
 +
 + LCD_text(2,​1,​true,​"Optical"); 
 + submenu=1;​ 
 +
 + else if (nastaveni1==2) ​  // zapamatování nastavení (pokud vybrán Coaxial) 
 +
 + LCD_text(2,​1,​true,"​Coaxial"​);​ 
 + submenu=2;​ 
 +
 +
 + else ​if(menu==1 && submenu==1   // výběíslušného submenu 3. tlačítkem 
 +
 + send_param=true; ​         ​// umožnění potvrzení tlačítkem SET 
 + LCD_text(2,1,​true,"​Optical"​);​ 
 + if(btn4_pressed == true)  // jestliže ​je stisknuto 4. tlačítko ​(SET) 
 +
 + SPDIFDAT |= BIT0// nastavení nultého bitu na SPI zařízení do 1 
 + SPDIF_send(SPDIFDAT);​ 
 + btn4_pressed=false;​ 
 + nastaveni1=1;​ 
 +
 + }
  
-while(1) + else if(menu==&& submenu==2
-+
-if(xpriznak==0) + send_param=true;           // umožnění potvrzení tlačítkem SET        
-px+++ LCD_text(2,​1,​true,"​Coaxial"​)
-if(ypriznak==0) + if(btn4_pressed ​== true)   // jestliže je stisknuto 4. tlačítko (SET) 
-py++;+
 + SPDIFDAT &=~ BIT0; // nastavení nultého bitu na SPI zařízení do 0 
 + SPDIF_send(SPDIFDAT); 
 + btn4_pressed=false; 
 + nastaveni1=2;​ 
 + }
  
-if(xpriznak!=0) + } 
-px--; +// konec 1.menu
-if(ypriznak!=0) +
-py--;+
  
-if(px==319) +// pro ostatní nabídky menu je algoritmus totožný pouze se změnami příslušných proměnných ​ 
-xpriznak=1;​ +</​code>​
-if(py==239) +
-ypriznak=1;+
  
-if(px==0) +Výsledné zařízení je zobrazeno na následujícím obrázku. V horní části obrázku se nachází vývojový kit a z něj jsou vedeny vodiče pro tlačítka a také vodiče do dvou převodníků. Prvním převodníkem je převodník sloužící jako logická sonda (zelené LED), která indikuje nastavené bity řídícího registru koncového SPI zařízení. Druhým převodníkem ​(červené LEDje převodník sloužící pro převod sériové linky pro paralelní 8 bitovou komunikaci OLED displeje.
-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>​+
  
 +{{ :​2014:​spi-oled-msp:​img_20141111_214344.jpg?​nolink |}}
 ==== Závěr ==== ==== 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 ​vypsáno písmeno C pro zjištění správně textové mřížky LCD. Grafická ​část zobrazuje jezdícího hadaBě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 ) ípadně využít procesor s rychlejším SPI modulemPoužitý LCD výrobce Raystar nedosahuje ​í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+Cílem práce bylo oživit komunikaci s periferií po SPI lince. Touto periferií může být chápán například D/A převodník, ​či přijímač S/PDIF a mnoho dalších obvodů, které umožňují své řízení po SPI a umožňují tak SW řízení své činnosti. Cílem práce bylo také oživit komunikaci s OLED displejem a na tomto displeji vytvořit intuitivní ovládací menu přípravkuMenu mělo být přehledné ​jasně informující o právě nastavených parametrech koncového obvodu. posledním důležitým blokem návrhu bylo vytvoření vhodného algoritmu pro snímání stavu tlačítekAlgoritmus musel efektivně potlačit zákmitykteré se na tlačítkách vyskytují a stabilizovat tak jejich činnost a tím stabilizovat činnost celého zařízení při jeho ovládání za pomocí těchto tlačítekihlédnutím na tyto požadavky a na dosažené výsledky ​je možné konstatovat,​ že zadání bylo splněno. Ovládací menu funguje spolehlivě. Spolehlivě fungují také tlačítka. Bezchybně funguje také zasílání dat po SPI lince do koncového zařízení,​což bylo hlavním úkolem této práce.
2014/spi-oled-msp.1420908757.txt.gz · Poslední úprava: 2015/01/10 17:52 autor: Milan Abrman