Advertisement
milanmetal

[AVR/C] _v2__MULTITASKING! Sve periferije osim LED niza.

Dec 26th, 2017
196
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.86 KB | None | 0 0
  1. /*
  2.  *
  3.  * Mijesam englesku i srpsku nomenklaturu... jebaji ga
  4.  * Mesam ekavicu i ijekavicu... --||--
  5.  *
  6.  * Autor: Milan Nedic
  7.  * 27.12.2017
  8.  *
  9.  * Ovde mozete pogledati demo ovog koda:
  10.  * https://www.youtube.com/watch?v=RTINMCzFO0U&feature=youtu.be
  11.  * https://www.youtube.com/watch?v=RTINMCzFO0U&feature=youtu.be
  12.  * https://www.youtube.com/watch?v=RTINMCzFO0U&feature=youtu.be
  13.  * https://www.youtube.com/watch?v=RTINMCzFO0U&feature=youtu.be
  14.  *
  15.  * Video je UNLISTED, vide ga samo ljudi koji dobiju link.
  16.  *
  17.  * */
  18.  
  19. #include <avr/io.h>
  20. #include <util/delay.h>
  21.  
  22. ///////////////////////////////////////////////////////////////////////////////////////
  23.  
  24. #define KEY_L       0
  25. #define KEY_D       1                                   // ovo su tezine koju ovaj tasteri zauzimaju na portu.
  26. #define KEY_R       2
  27. #define KEY_U       3
  28.  
  29. #define KEY_PINS    PINC                                // port na koji su nakaceni
  30.  
  31. // Ovo su makroi sa uslovima definisam preko bit-maski.
  32. // Onaj nacin sa vezbi mi nesto nije sljakao kako treba pa sam iskopao
  33. // i dopunio na ovaj nacin.
  34. #define KEY_L_PRESS     (~(KEY_PINS) & (1 << KEY_L))
  35. #define KEY_D_PRESS     (~(KEY_PINS) & (1 << KEY_D))
  36. #define KEY_R_PRESS     (~(KEY_PINS) & (1 << KEY_R))
  37. #define KEY_U_PRESS     (~(KEY_PINS) & (1 << KEY_U))
  38.  
  39. // Povecava citljivost koda. Vrednosti su random, moze sta god hoces
  40. // sem ovog NONE, to treba biti nula.
  41. enum BUTTONS {NONE = 0, LEFT = 10, DOWN = 11, RIGHT = 12, UP = 13};
  42.  
  43. // Sluzi za implementaciju debouncera.
  44. unsigned char enable = 0;
  45.  
  46. // Vrednost koju vrati funkcija koja ocitava pritisnuti taster.
  47. unsigned char taster = 0;
  48.  
  49. ///////////////////////////////////////////////////////////////////////////////////////
  50.  
  51. //makroi za kontrolu pinova preko kojih je kontroler povezan sa 74HC165:
  52. #define SCL_HI (PORTC |= (1<<5))
  53. #define SCL_LO (PORTC &= ~(1<<5))
  54. #define SDA (PINC & (1 << 4))
  55. #define SHLD_HI (PORTB |= (1<<5))
  56. #define SHLD_LO (PORTB &= ~(1<<5))
  57. ///////////////////////////////////////////////////////////////////////////////////////
  58.  
  59.  
  60.                               //  0     1     2     3     4     5     6     7     8     9
  61. const unsigned char   cifre[] = { 0x05, 0xdd, 0x46, 0x54, 0x9c, 0x34, 0x24, 0x5d, 0x04, 0x14 };
  62. const unsigned char iskljucen = 0xff;
  63.                               // _3.14 kao pocetna vrednost :)
  64. unsigned char trenutniIspis[] = {0x00, 0x50, 0xdd, 0x9c};
  65.  
  66.  
  67. // da ne bih prosledjivao nekakve nizove karaktera i fakticki pravio stringove,
  68. // zatim pljuvao krv da uporedim ono sto imam sa onim sta sam proslijedio,
  69. // ovo ce funkcionalno odglumiti taj proslijedjeni string tj dace kodu smisao na prvi pogled
  70. // a sustinski je to zapravo najobicniji unsigned char iliti osmobitni int.
  71. // Kompajler ce sve ove kljucne rijeci da zamjeni sa njihovim vrijednostima i prakticno
  72. // ce vrijednosti koje se kriju iza rijeci biti i proslijedjene i ocitane (kod funkcija)
  73.  
  74. enum LABELE {init = 1, update = 2, LED = 11, displej7SEG = 12, TASTERI = 13, PREKIDACI = 14};
  75.  
  76.  
  77. // Ovo ispod su look-up tabele koje sadrze pocetna stanja registara kao i
  78. // nacine inicijalizacije portova pojedinih periferija...
  79.                                 // PORTB      PORTC PORTD DDRB  DDRC  DDRD
  80. unsigned char STATE_7SEG[]      = {0x00,      0x00, 0x00, 0x0f, 0x00, 0xff};
  81. unsigned char STATE_LED[]       = {~(1 << 4), 0x00, 0x00, 0x00, 0x00, 0xff};    // ovaj prvi pokazuje da i ovo moze i zbunjuje citaoce.
  82. unsigned char STATE_SWITCHES[]  = {0x00,      0x00, 0xfe, 0x20, 0x20, 0xff};    // DDRB ako je 0x30 onda ce biti PB5 --> Q0 aktivan
  83. unsigned char STATE_BUTTONS[]   = {0x00,      0x00, 0x00, 0x00, 0x00, 0x00};
  84.  
  85.  
  86. void ispis_7SEG (unsigned char karakter, unsigned char pozicija)
  87. {
  88.     PORTB = ~(0x01 << (4-pozicija));    // ukljucenje displeja na zeljenoj
  89.                                         // poziciji
  90.     PORTD = karakter;                   // prikaz karaktera
  91.     _delay_ms(2);                       // pauza 2ms
  92. }
  93.  
  94.  
  95. // Switch-o-ception...
  96. // Trenutno mi ne pada elegantniji nacin da se obavi ovoliko dodjeljivanje. Polu brute-force pristup.
  97. void execute(unsigned char operacija, unsigned char periferija){
  98.     switch(operacija) {
  99.         case init:
  100.             switch(periferija) {
  101.                 case LED:
  102.                     DDRB = STATE_LED[3];
  103.                     DDRC = STATE_LED[4];
  104.                     DDRD = STATE_LED[5];
  105.                     PORTB = STATE_LED[0];
  106.                     PORTC = STATE_LED[1];
  107.                     PORTD = STATE_LED[2];
  108.                 break;
  109.                 case displej7SEG:
  110.                     DDRB = STATE_7SEG[3];
  111.                     DDRC = STATE_7SEG[4];
  112.                     DDRD = STATE_7SEG[5];
  113.                     PORTB = STATE_7SEG[0];
  114.                     PORTC = STATE_7SEG[1];
  115.                     PORTD = STATE_7SEG[2];
  116.                 break;
  117.                 case TASTERI:
  118.                     DDRB = STATE_BUTTONS[3];
  119.                     DDRC = STATE_BUTTONS[4];
  120.                     DDRD = STATE_BUTTONS[5];
  121.                     PORTB = STATE_BUTTONS[0];
  122.                     PORTC = STATE_BUTTONS[1];
  123.                     PORTD = STATE_BUTTONS[2];
  124.  
  125.                 break;
  126.                 case PREKIDACI:
  127.                     DDRB = STATE_SWITCHES[3];
  128.                     DDRC = STATE_SWITCHES[4];
  129.                     DDRD = STATE_SWITCHES[5];
  130.                     PORTB = STATE_SWITCHES[0];
  131.                     PORTC = STATE_SWITCHES[1];
  132.                     PORTD = STATE_SWITCHES[2];
  133.                 break;
  134.             }
  135.         break;
  136.  
  137.         // sada ponovo sve u slucaju UPDATE operacije.
  138.         case update:
  139.             switch(periferija) {
  140.                 case LED:
  141.                     STATE_LED[0] = PORTB;
  142.                     STATE_LED[1] = PORTC;
  143.                     STATE_LED[2] = PORTD;
  144.                 break;
  145.                 case displej7SEG:
  146.                     STATE_7SEG[0] = PORTB;
  147.                     STATE_7SEG[1] = PORTC;
  148.                     STATE_7SEG[2] = PORTD;
  149.                 break;
  150.                 case TASTERI:
  151.                     STATE_BUTTONS[0] = PORTB;
  152.                     STATE_BUTTONS[1] = PORTC;
  153.                     STATE_BUTTONS[2] = PORTD;
  154.                 break;
  155.                 case PREKIDACI:
  156.                     STATE_SWITCHES[0] = PORTB;
  157.                     STATE_SWITCHES[1] = PORTC;
  158.                     STATE_SWITCHES[2] = PORTD;
  159.                 break;
  160.             }
  161.         break;
  162.     }
  163. }
  164.  
  165.  
  166.  
  167. unsigned char ocitaj_prekidace()
  168. {
  169.     unsigned char i, tmp = 0, mask = 0x80;
  170.     //impuls za upis stanja prekidaca u registar
  171.     SHLD_HI;
  172.     SHLD_LO;
  173.     SHLD_HI;
  174.  
  175.     for (i=0; i<8; i++)
  176.     {
  177.         SCL_LO;
  178.         SCL_HI; //generisanje aktivne ivice takta
  179.  
  180.         if (SDA) //provera stanja ulaznog pina
  181.             tmp |= mask;
  182.  
  183.             mask >>= 1;
  184.     }
  185.     return tmp;
  186. }
  187.  
  188. // Proverava uslove definisane kao MACRO i vraca odgovarajucu enumerisanu vrijednost.
  189. unsigned char ocitajTaster(){
  190.     enum BUTTONS btn;
  191.  
  192.     if(KEY_L_PRESS) {
  193.         btn = LEFT;
  194.     } else if (KEY_D_PRESS){
  195.         btn = DOWN;
  196.     } else if (KEY_R_PRESS){
  197.         btn = RIGHT;
  198.     } else if (KEY_U_PRESS){
  199.         btn = UP;
  200.     } else {
  201.         btn = NONE;
  202.     }
  203.  
  204.     return btn;
  205. }
  206.  
  207. int main(void)
  208. {
  209.     unsigned char prekidaci = 0;
  210.  
  211.     /*
  212.      * Rad sa periferijom je ogradjen izmedju dva poziva funkcije execute
  213.      *
  214.      * execute(init, PERIFERIJA);       // inicijalizujem registre
  215.      *
  216.      * // ovde ide kod koji radi sa tom periferijom
  217.      *
  218.      * execute(update, PERIFERIJA);     // cuvam njihovo stanje za sledeci prolaz petlje.
  219.      *
  220.      * Ovo je zapravo implementacija slozenijeg VREMENSKOG MULTIPLEKSA
  221.      * gdje se ne vrsi multipleks nad jednim portom u jednoj ulozi,
  222.      * nego nad svim portovima koji obavljaju visestruke funkcije...
  223.      * Kontam za neke brze operacije i bez delaya, moze maaali milion razlicitih stvari
  224.      * da se radi na ovaj nacin :D :D :D
  225.      *
  226.      * */
  227.     while(1) {
  228.  
  229.         ///////////////////////////////////////////////////////////////////////////////////
  230.  
  231.         // Inicijalizujem registre za koriscenje prekidaca
  232.         // prije je ovde bila: initSwitches(); sada 6 starih funkcija zamjenila ova jedna
  233.         execute(init, PREKIDACI);
  234.         // Ovdje budzis svoj kod koji zelis da se vozi nad registrima
  235.         // postavljenim za rad sa prekidacima.
  236.         //------------------------
  237.             prekidaci = ocitaj_prekidace();
  238.  
  239.             trenutniIspis[0] = prekidaci;
  240.         //------------------------
  241.         // Na kraju upotrebe, vratim trenutno stanje registara u LUT
  242.         execute(update, PREKIDACI);
  243.  
  244.         ///////////////////////////////////////////////////////////////////////////////////
  245.  
  246.         // Dio koji obavlja sve poslove vezane za tastere.
  247.         execute(init, TASTERI);
  248.  
  249.             taster = ocitajTaster();
  250.             if(!taster) enable = 1;
  251.  
  252.             if(enable == 1) {
  253.                 switch(taster) {
  254.                     case LEFT:
  255.                         // Prvi karakter se brise vracanjem svih prekidaca na NULU.
  256.                         // Radi nesto...
  257.                         enable = 0;
  258.                     break;
  259.  
  260.                     case DOWN:
  261.                         // Drugi brises pomocu tastera.
  262.                         trenutniIspis[1] = iskljucen;
  263.                         enable = 0;
  264.                     break;
  265.  
  266.                     case RIGHT:
  267.                         // Treci...
  268.                         trenutniIspis[2] = iskljucen;
  269.                         enable = 0;
  270.                     break;
  271.                     case UP:
  272.                         // Cetvrti...
  273.                         trenutniIspis[3] = iskljucen;
  274.                         enable = 0;
  275.                     break;
  276.                 }
  277.             }
  278.  
  279.         execute(update, TASTERI);
  280.  
  281.         ///////////////////////////////////////////////////////////////////////////////////
  282.  
  283.         // Isto radim sa 7SEG displejima kao i sa prekidacima
  284.         // Ucitam u registre njihova poslednja stanja i radim nad njima nesto
  285.         // Na kraju to samo vratim u LUT i ovaj proces se ponavlja stotinama
  286.         // i hiljadama puta u sekundi recimo... brzinom while(1)
  287.         execute(init, displej7SEG);
  288.             ispis_7SEG (trenutniIspis[0], 1);
  289.             ispis_7SEG (trenutniIspis[1], 2);
  290.             ispis_7SEG (trenutniIspis[2], 3);
  291.             ispis_7SEG (trenutniIspis[3], 4);
  292.         execute(update, displej7SEG);
  293.  
  294.         ///////////////////////////////////////////////////////////////////////////////////
  295.  
  296.     }
  297.  
  298.     return 0;
  299. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement