Advertisement
milanmetal

[AVR/C] Blinkanje LED diode uporedo sa svim ostalim

Dec 27th, 2017
356
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.08 KB | None | 0 0
  1. /*
  2.  *
  3.  * Ne moze da radi najbolje, u sustini njeno stanje mijenjam, ali posto ostale periferije
  4.  * komuniciraju preko njenog pina, cak i kada je ugasen, dodje sledeca periferija
  5.  * i aktivira ju nezeljeno, tako da ona nema kada da se vizuelno iskljuci, iako joj je napon
  6.  * nuliran. Nezeljeni PWM
  7.  *
  8.  * Autor: Milan Nedic
  9.  * 27.12.2017
  10.  *
  11.  * Ovde mozete pogledati demo ovog koda:
  12.  * https://www.youtube.com/watch?v=RTINMCzFO0U&feature=youtu.be
  13.  * https://www.youtube.com/watch?v=RTINMCzFO0U&feature=youtu.be
  14.  * https://www.youtube.com/watch?v=RTINMCzFO0U&feature=youtu.be
  15.  * https://www.youtube.com/watch?v=RTINMCzFO0U&feature=youtu.be
  16.  *
  17.  * Video je UNLISTED, vide ga samo ljudi koji dobiju link.
  18.  *
  19.  * */
  20.  
  21. #include <avr/io.h>
  22. #include <util/delay.h>
  23.  
  24. ///////////////////////////////////////////////////////////////////////////////////////
  25.  
  26. #define KEY_L       0
  27. #define KEY_D       1                                   // ovo su tezine koju ovaj tasteri zauzimaju na portu.
  28. #define KEY_R       2
  29. #define KEY_U       3
  30.  
  31. #define KEY_PINS    PINC                                // port na koji su nakaceni
  32.  
  33. // Ovo su makroi sa uslovima definisam preko bit-maski.
  34. // Onaj nacin sa vezbi mi nesto nije sljakao kako treba pa sam iskopao
  35. // i dopunio na ovaj nacin.
  36. #define KEY_L_PRESS     (~(KEY_PINS) & (1 << KEY_L))
  37. #define KEY_D_PRESS     (~(KEY_PINS) & (1 << KEY_D))
  38. #define KEY_R_PRESS     (~(KEY_PINS) & (1 << KEY_R))
  39. #define KEY_U_PRESS     (~(KEY_PINS) & (1 << KEY_U))
  40.  
  41. // Povecava citljivost koda. Vrednosti su random, moze sta god hoces
  42. // sem ovog NONE, to treba biti nula.
  43. enum BUTTONS {NONE = 0, LEFT = 10, DOWN = 11, RIGHT = 12, UP = 13};
  44.  
  45. // Sluzi za implementaciju debouncera.
  46. unsigned char enable = 0;
  47.  
  48. // Vrednost koju vrati funkcija koja ocitava pritisnuti taster.
  49. unsigned char taster = 0;
  50.  
  51. ///////////////////////////////////////////////////////////////////////////////////////
  52.  
  53. //makroi za kontrolu pinova preko kojih je kontroler povezan sa 74HC165:
  54. #define SCL_HI (PORTC |= (1<<5))
  55. #define SCL_LO (PORTC &= ~(1<<5))
  56. #define SDA (PINC & (1 << 4))
  57. #define SHLD_HI (PORTB |= (1<<5))
  58. #define SHLD_LO (PORTB &= ~(1<<5))
  59. ///////////////////////////////////////////////////////////////////////////////////////
  60.  
  61.  
  62.                               //  0     1     2     3     4     5     6     7     8     9
  63. const unsigned char   cifre[] = { 0x05, 0xdd, 0x46, 0x54, 0x9c, 0x34, 0x24, 0x5d, 0x04, 0x14 };
  64. const unsigned char iskljucen = 0xff;
  65.                               // _3.14 kao pocetna vrednost :)
  66. unsigned char trenutniIspis[] = {0x00, 0x50, 0xdd, 0x9c};
  67.  
  68.  
  69. // da ne bih prosledjivao nekakve nizove karaktera i fakticki pravio stringove,
  70. // zatim pljuvao krv da uporedim ono sto imam sa onim sta sam proslijedio,
  71. // ovo ce funkcionalno odglumiti taj proslijedjeni string tj dace kodu smisao na prvi pogled
  72. // a sustinski je to zapravo najobicniji unsigned char iliti osmobitni int.
  73. // Kompajler ce sve ove kljucne rijeci da zamjeni sa njihovim vrijednostima i prakticno
  74. // ce vrijednosti koje se kriju iza rijeci biti i proslijedjene i ocitane (kod funkcija)
  75.  
  76. enum LABELE {init = 1, update = 2, LED = 11, displej7SEG = 12, TASTERI = 13, PREKIDACI = 14, BROJAC = 15};
  77.  
  78.  
  79. // Ovo ispod su look-up tabele koje sadrze pocetna stanja registara kao i
  80. // nacine inicijalizacije portova pojedinih periferija...
  81.                                 // PORTB      PORTC PORTD DDRB  DDRC  DDRD
  82. unsigned char STATE_7SEG[]      = {0x00,      0x00, 0x00, 0x0f, 0x00, 0xff};
  83. unsigned char STATE_LED[]       = {~(1 << 4), 0x00, 0x00, 0x00, 0x00, 0xff};    // ovaj prvi pokazuje da i ovo moze i zbunjuje citaoce.
  84. unsigned char STATE_SWITCHES[]  = {0x00,      0x00, 0xfe, 0x20, 0x20, 0xff};    // DDRB ako je 0x30 onda ce biti PB5 --> Q0 aktivan
  85. unsigned char STATE_BUTTONS[]   = {0x00,      0x00, 0x00, 0x00, 0x00, 0x00};
  86.  
  87. unsigned char STATE_INTERRUPT[] = {0x00,      0x00, 0x00, 0x00, 0x00, 0x00};
  88.  
  89.  
  90. ///////////////////////////////////////////////////////////////////////////////////
  91. ///////////////////////////////////////////////////////////////////////////////////
  92. ///////////////////////////////////////////////////////////////////////////////////
  93. ///////////////////////////////////////////////////////////////////////////////////
  94.  
  95. // 16MHz Clock
  96. #define F_CPU 16000000UL
  97.  
  98. // Calculate the value needed for
  99. // the CTC match value in OCR1A.
  100. #define CTC_MATCH_OVERFLOW ((F_CPU / 1000) / 8)
  101.  
  102. #include <avr/interrupt.h>
  103. #include <util/atomic.h>
  104.  
  105. volatile unsigned long timer1_millis;
  106. long milliseconds_since;
  107.  
  108. ISR (TIMER1_COMPA_vect)
  109. {
  110.     timer1_millis++;
  111.  
  112.     /////////////////// ja dodao
  113.     if(timer1_millis > 1000) {
  114.         timer1_millis = 0;
  115.     }
  116.     ///////////////////
  117. }
  118.  
  119. unsigned long millis ()
  120. {
  121.     unsigned long millis_return;
  122.  
  123.     // Ensure this cannot be disrupted
  124.     ATOMIC_BLOCK(ATOMIC_FORCEON) {
  125.         millis_return = timer1_millis;
  126.     }
  127.  
  128.     return millis_return;
  129. }
  130.  
  131. void flash_led ()
  132. {
  133.     unsigned long milliseconds_current = millis();
  134.  
  135.     //if (milliseconds_current - milliseconds_since > 1000 ) {
  136.     if (milliseconds_current > 500 && milliseconds_current < 900 ){
  137.         // LED connected to PC0/Analog 0
  138.         PORTD ^= (1 << PD4);
  139.         milliseconds_since = milliseconds_current;
  140.     } else {
  141.         PORTD = 0xef;
  142.     }
  143. }
  144.  
  145. void initCounterStuff() {
  146.     // CTC mode, Clock/8
  147.     TCCR1B |= (1 << WGM12) | (1 << CS11);
  148.  
  149.     // Load the high byte, then the low byte
  150.     // into the output compare
  151.     OCR1AH = (CTC_MATCH_OVERFLOW >> 8);
  152.     OCR1AL = CTC_MATCH_OVERFLOW;
  153.  
  154.     // Enable the compare match interrupt
  155.     TIMSK1 |= (1 << OCIE1A);
  156.  
  157.     // PC0/Analog 0 to Output
  158.     DDRD |= (1 << PD4);
  159.  
  160.     // Now enable global interrupts
  161.     sei();
  162.  
  163.     DDRB = ~0xef;
  164.     PORTB = 0xef;
  165.     //PORTD = 0xf7;
  166. }
  167.  
  168. ///////////////////////////////////////////////////////////////////////////////////
  169. ///////////////////////////////////////////////////////////////////////////////////
  170. ///////////////////////////////////////////////////////////////////////////////////
  171. ///////////////////////////////////////////////////////////////////////////////////
  172.  
  173.  
  174. void ispis_7SEG (unsigned char karakter, unsigned char pozicija)
  175. {
  176.     PORTB = ~(0x01 << (4-pozicija));    // ukljucenje displeja na zeljenoj
  177.                                         // poziciji
  178.     PORTD = karakter;                   // prikaz karaktera
  179.     _delay_ms(2);                       // pauza 2ms
  180. }
  181.  
  182.  
  183. // Switch-o-ception...
  184. // Trenutno mi ne pada elegantniji nacin da se obavi ovoliko dodjeljivanje. Polu brute-force pristup.
  185. void execute(unsigned char operacija, unsigned char periferija){
  186.     switch(operacija) {
  187.         case init:
  188.             switch(periferija) {
  189.                 case LED:
  190.                     DDRB = STATE_LED[3];
  191.                     DDRC = STATE_LED[4];
  192.                     DDRD = STATE_LED[5];
  193.                     PORTB = STATE_LED[0];
  194.                     PORTC = STATE_LED[1];
  195.                     PORTD = STATE_LED[2];
  196.                 break;
  197.                 case displej7SEG:
  198.                     DDRB = STATE_7SEG[3];
  199.                     DDRC = STATE_7SEG[4];
  200.                     DDRD = STATE_7SEG[5];
  201.                     PORTB = STATE_7SEG[0];
  202.                     PORTC = STATE_7SEG[1];
  203.                     PORTD = STATE_7SEG[2];
  204.                 break;
  205.                 case TASTERI:
  206.                     DDRB = STATE_BUTTONS[3];
  207.                     DDRC = STATE_BUTTONS[4];
  208.                     DDRD = STATE_BUTTONS[5];
  209.                     PORTB = STATE_BUTTONS[0];
  210.                     PORTC = STATE_BUTTONS[1];
  211.                     PORTD = STATE_BUTTONS[2];
  212.  
  213.                 break;
  214.                 case PREKIDACI:
  215.                     DDRB = STATE_SWITCHES[3];
  216.                     DDRC = STATE_SWITCHES[4];
  217.                     DDRD = STATE_SWITCHES[5];
  218.                     PORTB = STATE_SWITCHES[0];
  219.                     PORTC = STATE_SWITCHES[1];
  220.                     PORTD = STATE_SWITCHES[2];
  221.                 break;
  222.  
  223.                 case BROJAC:
  224.                     DDRB = STATE_INTERRUPT[3];
  225.                     DDRC = STATE_INTERRUPT[4];
  226.                     DDRD = STATE_INTERRUPT[5];
  227.                     PORTB = STATE_INTERRUPT[0];
  228.                     PORTC = STATE_INTERRUPT[1];
  229.                     PORTD = STATE_INTERRUPT[2];
  230.                 break;
  231.             }
  232.         break;
  233.  
  234.         // sada ponovo sve u slucaju UPDATE operacije.
  235.         case update:
  236.             switch(periferija) {
  237.                 case LED:
  238.                     STATE_LED[0] = PORTB;
  239.                     STATE_LED[1] = PORTC;
  240.                     STATE_LED[2] = PORTD;
  241.                 break;
  242.                 case displej7SEG:
  243.                     STATE_7SEG[0] = PORTB;
  244.                     STATE_7SEG[1] = PORTC;
  245.                     STATE_7SEG[2] = PORTD;
  246.                 break;
  247.                 case TASTERI:
  248.                     STATE_BUTTONS[0] = PORTB;
  249.                     STATE_BUTTONS[1] = PORTC;
  250.                     STATE_BUTTONS[2] = PORTD;
  251.                 break;
  252.                 case PREKIDACI:
  253.                     STATE_SWITCHES[0] = PORTB;
  254.                     STATE_SWITCHES[1] = PORTC;
  255.                     STATE_SWITCHES[2] = PORTD;
  256.                 break;
  257.  
  258.                 case BROJAC:
  259.                     STATE_INTERRUPT[0] = PORTB;
  260.                     STATE_INTERRUPT[1] = PORTC;
  261.                     STATE_INTERRUPT[2] = PORTD;
  262.                 break;
  263.             }
  264.         break;
  265.     }
  266. }
  267.  
  268.  
  269.  
  270. unsigned char ocitaj_prekidace()
  271. {
  272.     unsigned char i, tmp = 0, mask = 0x80;
  273.     //impuls za upis stanja prekidaca u registar
  274.     SHLD_HI;
  275.     SHLD_LO;
  276.     SHLD_HI;
  277.  
  278.     for (i=0; i<8; i++)
  279.     {
  280.         SCL_LO;
  281.         SCL_HI; //generisanje aktivne ivice takta
  282.  
  283.         if (SDA) //provera stanja ulaznog pina
  284.             tmp |= mask;
  285.  
  286.             mask >>= 1;
  287.     }
  288.     return tmp;
  289. }
  290.  
  291. // Proverava uslove definisane kao MACRO i vraca odgovarajucu enumerisanu vrijednost.
  292. unsigned char ocitajTaster(){
  293.     enum BUTTONS btn;
  294.  
  295.     if(KEY_L_PRESS) {
  296.         btn = LEFT;
  297.     } else if (KEY_D_PRESS){
  298.         btn = DOWN;
  299.     } else if (KEY_R_PRESS){
  300.         btn = RIGHT;
  301.     } else if (KEY_U_PRESS){
  302.         btn = UP;
  303.     } else {
  304.         btn = NONE;
  305.     }
  306.  
  307.     return btn;
  308. }
  309.  
  310. int main(void)
  311. {
  312.     unsigned char prekidaci = 0;
  313.  
  314.     /*
  315.      * Rad sa periferijom je ogradjen izmedju dva poziva funkcije execute
  316.      *
  317.      * execute(init, PERIFERIJA);       // inicijalizujem registre
  318.      *
  319.      * // ovde ide kod koji radi sa tom periferijom
  320.      *
  321.      * execute(update, PERIFERIJA);     // cuvam njihovo stanje za sledeci prolaz petlje.
  322.      *
  323.      * Ovo je zapravo implementacija slozenijeg VREMENSKOG MULTIPLEKSA
  324.      * gdje se ne vrsi multipleks nad jednim portom u jednoj ulozi,
  325.      * nego nad svim portovima koji obavljaju visestruke funkcije...
  326.      * Kontam za neke brze operacije i bez delaya, moze maaali milion razlicitih stvari
  327.      * da se radi na ovaj nacin :D :D :D
  328.      *
  329.      * */
  330.     while(1) {
  331.  
  332.         ///////////////////////////////////////////////////////////////////////////////////
  333.  
  334.         execute(init, BROJAC);
  335.  
  336.             initCounterStuff();
  337.             flash_led();
  338.  
  339.         execute(update, BROJAC);
  340.  
  341.         // Inicijalizujem registre za koriscenje prekidaca
  342.         // prije je ovde bila: initSwitches(); sada 6 starih funkcija zamjenila ova jedna
  343.         execute(init, PREKIDACI);
  344.         // Ovdje budzis svoj kod koji zelis da se vozi nad registrima
  345.         // postavljenim za rad sa prekidacima.
  346.         //------------------------
  347.             prekidaci = ocitaj_prekidace();
  348.  
  349.             trenutniIspis[0] = prekidaci;
  350.         //------------------------
  351.         // Na kraju upotrebe, vratim trenutno stanje registara u LUT
  352.         execute(update, PREKIDACI);
  353.  
  354.         ///////////////////////////////////////////////////////////////////////////////////
  355.  
  356.  
  357.  
  358.  
  359.         execute(init, BROJAC);
  360.  
  361.                     initCounterStuff();
  362.                     flash_led();
  363.  
  364.                 execute(update, BROJAC);
  365.  
  366.  
  367.  
  368.         // Dio koji obavlja sve poslove vezane za tastere.
  369.         execute(init, TASTERI);
  370.  
  371.             taster = ocitajTaster();
  372.             if(!taster) enable = 1;
  373.  
  374.             if(enable == 1) {
  375.                 switch(taster) {
  376.                     case LEFT:
  377.                         // Prvi karakter se brise vracanjem svih prekidaca na NULU.
  378.                         // Radi nesto...
  379.                         enable = 0;
  380.                     break;
  381.  
  382.                     case DOWN:
  383.                         // Drugi brises pomocu tastera.
  384.                         trenutniIspis[1] = iskljucen;
  385.                         enable = 0;
  386.                     break;
  387.  
  388.                     case RIGHT:
  389.                         // Treci...
  390.                         trenutniIspis[2] = iskljucen;
  391.                         enable = 0;
  392.                     break;
  393.                     case UP:
  394.                         // Cetvrti...
  395.                         trenutniIspis[3] = iskljucen;
  396.                         enable = 0;
  397.                     break;
  398.                 }
  399.             }
  400.  
  401.         execute(update, TASTERI);
  402.  
  403.  
  404.  
  405.  
  406.         execute(init, BROJAC);
  407.  
  408.                     initCounterStuff();
  409.                     flash_led();
  410.  
  411.                 execute(update, BROJAC);
  412.  
  413.         ///////////////////////////////////////////////////////////////////////////////////
  414.  
  415.         // Isto radim sa 7SEG displejima kao i sa prekidacima
  416.         // Ucitam u registre njihova poslednja stanja i radim nad njima nesto
  417.         // Na kraju to samo vratim u LUT i ovaj proces se ponavlja stotinama
  418.         // i hiljadama puta u sekundi recimo... brzinom while(1)
  419.         execute(init, displej7SEG);
  420.             ispis_7SEG (trenutniIspis[0], 1);
  421.             ispis_7SEG (trenutniIspis[1], 2);
  422.             ispis_7SEG (trenutniIspis[2], 3);
  423.             ispis_7SEG (trenutniIspis[3], 4);
  424.         execute(update, displej7SEG);
  425.  
  426.  
  427.         execute(init, BROJAC);
  428.  
  429.                     initCounterStuff();
  430.                     flash_led();
  431.  
  432.                 execute(update, BROJAC);
  433.  
  434.         ///////////////////////////////////////////////////////////////////////////////////
  435.  
  436.     }
  437.     return 0;
  438. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement