Facebook
From ja, 7 Years ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 323
  1. /********************************************************************
  2. * Autor: Artur Cichowski                                                                                *
  3. * Program demonstujący wykorzystanie przerwania od Timera, w którym *
  4. * obslugiwane są cztery przyciski. Program realizuje także obsługę  *
  5. * w sposób cykliczny czterech wyświetlaczy siedmisegmentowych.      *
  6. ********************************************************************/
  7.    
  8. #include <avr/interrupt.h>        // funkcje sei(), cli()
  9. #include <util/delay.h>
  10. #include "main.h"
  11.  
  12. #define HAPSIM 0
  13.  
  14. volatile unsigned char kl_ENTER = 0;    //przycisk ENTER (KEY0)
  15. volatile unsigned char kl_UP = 0;               //przycisk UP (KEY1)
  16. volatile unsigned char kl_DOWN = 0;             //przycisk DOWN (KEY2)
  17. volatile unsigned char kl_CANCEL = 0;   //przycisk CANCELv(KEY3)
  18.  
  19.  volatile signed char cyfry[4];   //wartości tablicy modyfikowane są przyciskami
  20.  
  21.  
  22. signed char cyfry_kopia[4];
  23. char dzielnik_f;
  24. char miganie;
  25. char menu=0x00;
  26.  
  27.  
  28.  
  29. //deklaracje funkcji
  30. void init_TIMER0 (void);
  31. void init_pins (void);
  32. char BCD_to_7_seg(char cyfra);
  33. void display_7seg(void);
  34. int main(void);
  35.  
  36.  
  37.  
  38. // Timer 1
  39. void init_TIMER1 (void){
  40.  
  41. #if HAPSIM
  42. TCCR1B = _BV(CS10)|_BV(WGM13)|_BV(WGM12);
  43. #else
  44.         TCCR1B = _BV(CS12)|_BV(WGM13)|_BV(WGM12);    
  45. #endif 
  46.         ICR1=62499;
  47.         TCNT1=0x0000;
  48.        
  49.         TIMSK |= _BV(TICIE1);
  50. };
  51.  
  52.  
  53. //Timer0 jest zainicjalizowany w celu generowania przerwań od jego przepełnienia.
  54. void init_TIMER0 (void) {
  55. #if HAPSIM
  56.         TCCR0 = _BV(CS00); //fclk/1,
  57. #else
  58.         TCCR0 = _BV(CS02)|_BV(CS01)|_BV(CS00);      //fclk/1024,
  59. #endif 
  60.         TCNT0 = 0x00; //wartość zliczona przez licznik
  61.         TIMSK = _BV(TOIE0); //selektywne zezwolenie na przerwania od przepełnienia licznika0 TOIE0=1, przepełnienie co 256*64us=16,38ms, dla HAPSIM co 0,128ms
  62. };
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73. union {         //do obsługi przycisków -> w przerwaniu ISR
  74.  struct {
  75.   unsigned char ENTER:1;        //LSB
  76.   unsigned char UP:1;
  77.   unsigned char DOWN:1;
  78.   unsigned char CANCEL:1;
  79.   unsigned char ENTER_PREV:1;
  80.   unsigned char UP_PREV:1;
  81.   unsigned char DOWN_PREV:1;
  82.   unsigned char CANCEL_PREV:1; //MSB
  83.  } flags;
  84.   char byte;
  85. } key;
  86.  
  87. union {         //do obsługi przycisków -> w przerwaniu ISR
  88.  struct {
  89.   unsigned char ENTER:1;           //LSB
  90.   unsigned char UP:1;
  91.   unsigned char DOWN:1;
  92.   unsigned char CANCEL:1;
  93.   unsigned char ENTER_PREV:1;
  94.   unsigned char UP_PREV:1;
  95.   unsigned char DOWN_PREV:1;
  96.   unsigned char CANCEL_PREV:1;
  97.   unsigned char ENTER_PREV1:1;
  98.   unsigned char UP_PREV1:1;
  99.   unsigned char DOWN_PREV1:1;
  100.   unsigned char CANCEL_PREV1:1;
  101.   unsigned char ENTER_PREV2:1;
  102.   unsigned char UP_PREV2:1;
  103.   unsigned char DOWN_PREV2:1;
  104.   unsigned char CANCEL_PREV2:1; //MSB
  105.   } flags;
  106.   int word;
  107. } falling_slope;  
  108.  
  109.  
  110.  
  111.  
  112. ISR (TIMER0_OVF_vect) { //przerwanie wywoływane co ok. 16,4 ms
  113.  
  114. sei();
  115.  
  116.         key.byte=(key.byte<<4);// przesuwając w lewą stronę bity z dołu uzupełniane są zerami
  117. //ustawienie jedynek na pozycjach od 0 do 3 w przypadku odczytania zer z odpowiednich wejść KEYx
  118.         key.byte|=((bit_is_clear(PINKEY,KEY0))|(bit_is_clear(PINKEY,KEY1) << 1)|(bit_is_clear(PINKEY,KEY2) << 2)|(bit_is_clear(PINKEY,KEY3) << 3));
  119.         falling_slope.word=(falling_slope.word<<4);
  120.        
  121.         if(key.flags.ENTER){  //czy wciśnięty jest przycisk ENTER?
  122.                 if(!key.flags.ENTER_PREV) falling_slope.flags.ENTER=1; //Czy wykryto zbocze opadające
  123.                 if(falling_slope.flags.ENTER_PREV2) kl_ENTER = 1; //Czy od chwili wykrycia zbocza opadającego upłynęły 3 przerwania z wciśniętym przyciskiem
  124.         }
  125.         else{
  126.                 falling_slope.word&=0xEEEE;  //wyzerowanie flag dla przycisku ENTER potwierdzających wykrycie zbocza opadającego
  127.         };     
  128.        
  129.                
  130.         if(key.flags.UP){  //czy wciśnięty jest przycisk UP?
  131.                 if(!key.flags.UP_PREV) falling_slope.flags.UP=1; //Czy wykryto zbocze opadające
  132.                 if(falling_slope.flags.UP_PREV2) kl_UP = 1; //Czy od chwili wykrycia zbocza opadającego upłynęły 3 przerwania z wciśniętym przyciskiem
  133.         }
  134.         else{
  135.                 falling_slope.word&=0xDDDD;  //wyzerowanie flag dla przycisku UP potwierdzających wykrycie zbocza opadającego
  136.         };             
  137.                
  138.         if(key.flags.DOWN){  //czy wciśnięty jest przycisk DOWN?
  139.                 if(!key.flags.DOWN_PREV) falling_slope.flags.DOWN=1; //Czy wykryto zbocze opadające
  140.                 if(falling_slope.flags.DOWN_PREV2) kl_DOWN = 1; //Czy od chwili wykrycia zbocza opadającego upłynęły 3 przerwania z wciśniętym przyciskiem
  141.         }
  142.         else{
  143.                 falling_slope.word&=0xBBBB;  //wyzerowanie flag dla przycisku DOWN potwierdzających wykrycie zbocza opadającego
  144.         };     
  145.                
  146.         if(key.flags.CANCEL){  //czy wciśnięty jest przycisk CANCEL?
  147.                 if(!key.flags.CANCEL_PREV) falling_slope.flags.CANCEL=1;  //Czy wykryto zbocze opadające
  148.                 if(falling_slope.flags.CANCEL_PREV2) kl_CANCEL = 1;  //Czy od chwili wykrycia zbocza opadającego upłynęły 3 przerwania z wciśniętym przyciskiem
  149.         }
  150.         else{
  151.                 falling_slope.word&=0x7777;  //wyzerowanie flag dla przycisku CANCEL potwierdzających wykrycie zbocza opadającego
  152.         };
  153.                
  154.         dzielnik_f++;
  155.         if(dzielnik_f==15){                              //częstotliwość migania modyfikowanej cyfry //16e6/(1024*256*(2*XXXX)) ok. 2Hz
  156.         dzielnik_f=0;
  157.         miganie=!miganie;};
  158. };
  159.  
  160. ISR(TIMER1_CAPT_vect)
  161. {
  162.         cyfry[3]--;
  163.         if (cyfry[3]<0) {
  164.                 cyfry[3]=9;
  165.                 cyfry[2]--;
  166.  
  167.                 if(cyfry[2]<0) {
  168.                         cyfry[2]=5;
  169.                         cyfry[1]--;
  170.        
  171.                         if(cyfry[1]<0) {
  172.                                 cyfry[1]=9;
  173.                                 cyfry[0]--;
  174.        
  175.                                 if(cyfry[0]<0) {
  176.                                        
  177.                                         cyfry[0]=5;
  178.                                         }
  179.                                 };
  180.                         };
  181.                 };
  182.         };
  183.  
  184. void init_pins (void) {
  185.         /*ustawienie odpowiednich pinów mikrokontrolera jako
  186.         wyjść dla portu, do którego podłączono diody LED*/
  187.         DIRLED |= (_BV(LED0)|_BV(LED1)|_BV(LED2)|_BV(LED3));
  188.         /*ustawienie odpowiednich pinów mikrokontrolera jako
  189.         wejść dla portu, do którego podłączono przyciski KEY*/
  190.         DIRKEY &= ~(_BV(KEY0)|_BV(KEY1)|_BV(KEY2)|_BV(KEY3));
  191.         /*ustawienie odpowiednich pinów mikrokontrolera jako
  192.         wejść dla portu, do którego podłączono przełączniki SW*/
  193.         DIRSWITCH &= ~(_BV(SW0)|_BV(SW1)|_BV(SW2)|_BV(SW3));
  194.         /*ustawienie wyjść dla portu, do którego podłączono katody wyświetlacza*/
  195.         DIRHEX = 0xFF;
  196.         /*ustawienie odpowiednich pinów mikrokontrolera jako
  197.         wyjść dla portu, do którego podłączono anody wyświetlacza*/
  198.         DIRHEXA |= (_BV(HEXA0)|_BV(HEXA1)|_BV(HEXA2)|_BV(HEXA3));
  199.         /*ustawienie pinu PB0 (dot. BUZ) w stamn wysoki - aktywowany stanem niskim */
  200.         PORTBUZ |= (_BV(BUZ));
  201.        
  202. };
  203.        
  204. //funkcja transkodera kodu BCD na kod wyswietlacza siedmiosegmentowego
  205. char BCD_to_7_seg(char cyfra){
  206. char katody = 0xFF; //domyślnie wszystkie segmenty wyłączone
  207.         switch(cyfra){
  208.                 case 0 : katody=0xC0; //0b11000000
  209.                                  break;
  210.                 case 1 : katody=0xF9;  
  211.                      break;
  212.                 case 2 : katody=0xA4;  
  213.                      break;
  214.                 case 3 : katody=0xB0;  
  215.                      break;
  216.                 case 4 : katody=0x99;  
  217.                      break;
  218.                 case 5 : katody=0x92;  
  219.                      break;
  220.                 case 6 : katody=0x82;  
  221.                      break;
  222.                 case 7 : katody=0xF8;  
  223.                      break;
  224.                 case 8 : katody=0x80;  
  225.                      break;
  226.                 case 9 : katody=0x90;  
  227.                      break;
  228.     };
  229.         return katody;
  230. };     
  231.  
  232.  
  233. //funkcja obsługi wyswietlacza siedmiosegmentowego
  234. //funkcja uaktywnia cyklicznie poszczególne wyświetlacze
  235. void display_7seg(void)
  236. {
  237. static char select = 1; //zmienna o zakresie od 1 do 4
  238.         PORTHEXA |= (_BV(HEXA0)|_BV(HEXA1)|_BV(HEXA2)|_BV(HEXA3)); //wyłączenie wszystkich wyświetlaczy
  239.         select++;                         //wskazanie na kolejną cyfrę
  240.         if(select>4) select=1;
  241.         //cykliczne aktywowanie wyświetlaczy 7-seg
  242.         switch(select)
  243.      {
  244.         case 1 :PORTHEX  = BCD_to_7_seg(cyfry[0]); //wizualizacja cyfry[0]
  245.                                 PORTHEXA &= ~_BV(HEXA0);                    //aktywacja 1 wyświetlacza
  246.                                 break;
  247.         case 2 :PORTHEX  = BCD_to_7_seg(cyfry[1]); //wizualizacja cyfry[1]
  248.                                 PORTHEXA &= ~_BV(HEXA1);                    //aktywacja 2 wyświetlacza
  249.                                 break;
  250.         case 3 :PORTHEX  = BCD_to_7_seg(cyfry[2]); //wizualizacja cyfry[2]
  251.                                 PORTHEXA &= ~_BV(HEXA2);                    //aktywacja 3 wyświetlacza
  252.                                 break;
  253.         case 4 :PORTHEX  = BCD_to_7_seg(cyfry[3]); //wizualizacja cyfry[3]
  254.                                 PORTHEXA &= ~_BV(HEXA3);                    //aktywacja 4 wyświetlacza
  255.                                 break;
  256.          };
  257. };
  258.  
  259. void display_7seg_kopia(void)
  260. {
  261. static char select = 1; //zmienna o zakresie od 1 do 4
  262.         PORTHEXA |= (_BV(HEXA0)|_BV(HEXA1)|_BV(HEXA2)|_BV(HEXA3)); //wyłączenie wszystkich wyświetlaczy
  263.         select++;                         //wskazanie na kolejną cyfrę
  264.         if(select>4) select=1;
  265.         //cykliczne aktywowanie wyświetlaczy 7-seg
  266.         switch(select)
  267.      {
  268.         case 1 :PORTHEX  = BCD_to_7_seg(cyfry_kopia[0]); //wizualizacja cyfry[0]
  269.                                 if((miganie) || (menu!=0x10))
  270.                                 PORTHEXA &= ~_BV(HEXA0);                    //aktywacja 1 wyświetlacza
  271.                                 break;
  272.         case 2 :PORTHEX  = BCD_to_7_seg(cyfry_kopia[1]); //wizualizacja cyfry[1]
  273.                                 if((miganie) || (menu!=0x20))
  274.                                 PORTHEXA &= ~_BV(HEXA1);                    //aktywacja 2 wyświetlacza
  275.                                 break;
  276.         case 3 :PORTHEX  = BCD_to_7_seg(cyfry_kopia[2]); //wizualizacja cyfry[2]
  277.                                 if((miganie) || (menu!=0x30))
  278.                                 PORTHEXA &= ~_BV(HEXA2);                    //aktywacja 3 wyświetlacza
  279.                                 break;
  280.         case 4 :PORTHEX  = BCD_to_7_seg(cyfry_kopia[3]); //wizualizacja cyfry[3]
  281.                                 if((miganie) || (menu!=0x40))
  282.                                 PORTHEXA &= ~_BV(HEXA3);                    //aktywacja 4 wyświetlacza
  283.                                 break;
  284.          };
  285. };
  286. void display_7seg_kopia1(void)
  287. {
  288.         PORTHEXA |= (_BV(HEXA0)|_BV(HEXA1)|_BV(HEXA2)|_BV(HEXA3)); //wyłączenie wszystkich wyświetlaczy
  289.         // pętla
  290.         while(1){
  291.                 PORTBUZ &= ~(_BV(BUZ));
  292.                 PORTHEXA &= ~(_BV(HEXA0)|_BV(HEXA1)|_BV(HEXA2)|_BV(HEXA3)); //włączenie??
  293.         };
  294. };
  295.  
  296.        
  297. int main(void)
  298. {
  299.         key.byte=0xFF;   //inicjalizacja flag stanami nieaktywnymi
  300.         falling_slope.word=0x0000; //inicjalizacja flag stanami nieaktywnymi
  301.         PORTHEX = 0xFF;                          //wyłączenie wszystkich segmentów
  302.         PORTHEXA |= (_BV(HEXA0)|_BV(HEXA1)|_BV(HEXA2)|_BV(HEXA3)); //wyłączenie wszystkich wyświetlaczy
  303.         init_pins();                            //inicjalizacja kierunkowości wyprowadzeń
  304.         init_TIMER0();                          //inicjalizacja Timera0
  305.         init_TIMER1();                         
  306.         sei();                                          //globalne zezwolenie na przerwania
  307.  
  308.  
  309.  
  310.        
  311.         while(1)                                        //nieskończona pętla
  312.         {
  313. //modyfikacje poszczególnych cyfr pod wpływem wciśnięcia danego przycisku  
  314.           switch(menu){
  315.                         case 0x00 : if(kl_ENTER == 1){
  316.                                                         cyfry_kopia[0]=cyfry[0];
  317.                                                         cyfry_kopia[1]=cyfry[1];
  318.                                                         cyfry_kopia[2]=cyfry[2];
  319.                                                         cyfry_kopia[3]=cyfry[3];
  320.                                                         menu=0x10;
  321.                                                         kl_ENTER=0;
  322.                                                 };
  323.                                                 break;
  324.  
  325.                         case 0x10 : if(kl_ENTER == 1){
  326.                                                         menu=0x20;
  327.                                                         kl_ENTER=0;
  328.                                                 };
  329.  
  330.                                                 if(kl_UP == 1){
  331.                                                         cyfry_kopia[0]++;
  332.                                                         if (cyfry_kopia[0] > 5) cyfry_kopia[0] = 0;
  333.                                                         kl_UP = 0;
  334.                                                 };
  335.  
  336.                                                 if(kl_DOWN == 1){
  337.                                                         cyfry_kopia[0]--;
  338.                                                         if (cyfry_kopia[0] < 0) cyfry_kopia[0] = 5;
  339.                                                         kl_DOWN = 0;
  340.                                                 };
  341.  
  342.  
  343.                                                 if(kl_CANCEL == 1){
  344.                                                         menu=0x00;
  345.                                                         kl_CANCEL = 0;
  346.                                                 };
  347.                                                 break;
  348.                         case 0x20 : if(kl_ENTER == 1){
  349.                                                         menu=0x30;
  350.                                                         kl_ENTER=0;
  351.                                                 };
  352.  
  353.                                                 if(kl_UP == 1){
  354.                                                         cyfry_kopia[1]++;
  355.                                                         if (cyfry_kopia[1] > 9) cyfry_kopia[1] = 0;
  356.                                                         kl_UP = 0;
  357.                                                 };
  358.  
  359.                                                 if(kl_DOWN == 1){
  360.                                                         cyfry_kopia[1]--;
  361.                                                         if (cyfry_kopia[1] < 0) cyfry_kopia[1] = 9;
  362.                                                         kl_DOWN = 0;
  363.                                                 };
  364.  
  365.  
  366.                                                 if(kl_CANCEL == 1){
  367.                                                         menu=0x00;
  368.                                                         kl_CANCEL = 0;
  369.                                                 };
  370.                                                 break;
  371.                         case 0x30 : if(kl_ENTER == 1){
  372.                                                         menu=0x40;
  373.                                                         kl_ENTER=0;
  374.                                                 };
  375.  
  376.                                                 if(kl_UP == 1){
  377.                                                         cyfry_kopia[2]++;
  378.                                                         if (cyfry_kopia[2] > 5) cyfry_kopia[2] = 0;
  379.                                                         kl_UP = 0;
  380.                                                 };
  381.  
  382.                                                 if(kl_DOWN == 1){
  383.                                                         cyfry_kopia[2]--;
  384.                                                         if (cyfry_kopia[2] < 0) cyfry_kopia[2] = 5;
  385.                                                         kl_DOWN = 0;
  386.                                                 };
  387.  
  388.  
  389.                                                 if(kl_CANCEL == 1){
  390.                                                         menu=0x00;
  391.                                                         kl_CANCEL = 0;
  392.                                                 };
  393.                                                 break;
  394.                         case 0x40 : if(kl_ENTER == 1){
  395.                                                         cyfry[0]=cyfry_kopia[0];
  396.                                                         cyfry[1]=cyfry_kopia[1];
  397.                                                         cyfry[2]=cyfry_kopia[2];
  398.                                                         cyfry[3]=cyfry_kopia[3];
  399.                                                         menu=0x00;
  400.                                                         kl_ENTER=0;
  401.                                                 };
  402.  
  403.                                                 if(kl_UP == 1){
  404.                                                         cyfry_kopia[3]++;
  405.                                                         if (cyfry_kopia[3] > 9) cyfry_kopia[3] = 0;
  406.                                                         kl_UP = 0;
  407.                                                 };
  408.  
  409.                                                 if(kl_DOWN == 1){
  410.                                                         cyfry_kopia[3]--;
  411.                                                         if (cyfry_kopia[3] < 0) cyfry_kopia[3] = 9;
  412.                                                         kl_DOWN = 0;
  413.                                                 };
  414.  
  415.  
  416.                                                 if(kl_CANCEL == 1){
  417.                                                         menu=0x00;
  418.                                                         kl_CANCEL = 0;
  419.                                                 };
  420.                                                 break;
  421.  
  422.  
  423. };
  424.         if(menu==0)
  425.                 display_7seg(); //wizualizacja cyfr
  426.         else
  427.                 display_7seg_kopia(); //wizualizacja cyfr
  428.                
  429.         if (cyfry[0]==0 && cyfry[1]==0 && cyfry[2]==0 && cyfry[3]==0)
  430.                 display_7seg_kopia1(); //brzęczenie i miganie
  431.         };
  432. return 0;
  433. }
  434.