Advertisement
Guest User

binäruhr1-korrigiert-1

a guest
Jul 17th, 2019
270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.12 KB | None | 0 0
  1. //  Binäruhr 1.0
  2. //
  3. //  Copyright (C) 2009 Paul Wilhelm <paul@mosfetkiller.de>
  4. //  http://mosfetkiller.de/?s=binaeruhr
  5.  
  6. //  Includes
  7. #define F_CPU   1000000UL   //  8 MHz / 8 (CKDIV enabled)
  8. #include <util/delay.h>
  9. #include <avr/interrupt.h>
  10. #include <avr/io.h>
  11.  
  12. #define FALSE 0
  13. #define TRUE 1
  14.  
  15. //  DS1307 address
  16. #define DS1307_ADDRESS      0b11010000  //  Bit 0 = R/W bit
  17.  
  18. //  Pinbelegungen
  19. #define I2C_SCL_w_port      PORTA
  20. #define I2C_SCL_r_port      PINA
  21. #define I2C_SCL_dir         DDRA
  22. #define I2C_SCL_bit         0
  23.  
  24. #define I2C_SDA_w_port      PORTA
  25. #define I2C_SDA_r_port      PINA
  26. #define I2C_SDA_dir         DDRA
  27. #define I2C_SDA_bit         1
  28.  
  29. //  Pinbelegungen Schalter nach GND (Hoch und Runter hängen am I2C-Bus...unschön, funktioniert aber)
  30. #define BUTTON_UP_PORT_OUT  PORTA   //  Hoch
  31. #define BUTTON_UP_PORT_IN   PINA
  32. #define BUTTON_UP_PIN       0
  33.  
  34. #define BUTTON_DOWN_PORT_OUT    PORTA   //  Runter
  35. #define BUTTON_DOWN_PORT_IN     PINA
  36. #define BUTTON_DOWN_PIN     1
  37.  
  38. #define BUTTON_ENTER_PORT_OUT   PORTD   //  Enter
  39. #define BUTTON_ENTER_PORT_IN    PIND
  40. #define BUTTON_ENTER_PIN        6
  41.  
  42. //  Makros
  43. #define set_bit(var, bit)   ((var) |= (1 << (bit)))
  44. #define clear_bit(var, bit) ((var) &= (unsigned)~(1 << (bit)))
  45.  
  46. #define set_I2C_SCL_dir     set_bit     (I2C_SCL_dir,       I2C_SCL_bit)
  47. #define clear_I2C_SCL_dir   clear_bit   (I2C_SCL_dir,       I2C_SCL_bit)
  48. #define set_I2C_SCL         set_bit     (I2C_SCL_w_port,    I2C_SCL_bit)
  49. #define clear_I2C_SCL       clear_bit   (I2C_SCL_w_port,    I2C_SCL_bit)
  50.  
  51. #define set_I2C_SDA_dir     set_bit     (I2C_SDA_dir,       I2C_SDA_bit)
  52. #define clear_I2C_SDA_dir   clear_bit   (I2C_SDA_dir,       I2C_SDA_bit)
  53. #define set_I2C_SDA         set_bit     (I2C_SDA_w_port,    I2C_SDA_bit)
  54. #define clear_I2C_SDA       clear_bit   (I2C_SDA_w_port,    I2C_SDA_bit)
  55.  
  56. #define I2C_Delay_us        100 //  Immer schön langsam...wir haben ja Zeit :-)
  57.  
  58. //  Bei Fehlern in der I2C-Übertragung leuchtet die LED unten links auf
  59. //  und das Programm wird gestoppt.
  60.  
  61. //  Prototypen
  62. void init();
  63. void draw_matrix();
  64. void i2c_start();
  65. void i2c_stop();
  66. void i2c_put_byte(unsigned char byte);
  67. unsigned char i2c_get_byte(unsigned char ack);
  68.  
  69. //  LED-Matrix
  70. volatile unsigned char matrix[8][6];
  71.  
  72. //  Zeit
  73. volatile unsigned char time[7];
  74.  
  75. //  Display
  76. volatile unsigned char display_dim = 9;
  77.  
  78. //  Tastenzähler
  79. volatile unsigned char button_up = 0, button_down = 0, button_enter = 0;
  80.  
  81.  
  82. //  Main
  83. int main(void)
  84. {
  85.     //  Initialisieren
  86.     init();
  87.  
  88.  
  89.     //  Benutzereingaben entgegennehmen (Uhr stellen)
  90.     set_bit(TIMSK, OCIE0A); //  Tastenzähler einschalten
  91.  
  92.     unsigned char parameter = 0, value = 0, value_old = 0, max = 0;
  93.  
  94.     unsigned char input = TRUE;
  95.     while (input)
  96.     {
  97.         //  Maximalwert festlegen (ja ja, ist unschön :-D)
  98.         switch (parameter)
  99.         {
  100.             case 0:
  101.             case 1: max = 59; break;
  102.             case 2: max = 24; break;
  103.             case 3: max = 7; break;
  104.             case 4: max = 31; break;
  105.             case 5: max = 12; break;
  106.             case 6: max = 100; break;
  107.         }
  108.  
  109.         //  Wert hoch
  110.         if ((button_up >= 10) && (button_down == 0))
  111.         {
  112.             button_up = 0;
  113.             if (value < max) value++; else value = 0;
  114.         }
  115.  
  116.         //  Wert runter
  117.         if ((button_down >= 10) && (button_up == 0))
  118.         {
  119.             button_down = 0;
  120.             if (value > 0) value--; else value = max;
  121.         }
  122.  
  123.         //  Enter (nächster Parameter)
  124.         if (button_enter >= 10)
  125.         {
  126.             button_enter = 0;
  127.             if (parameter < 6) parameter++; else parameter = 0;
  128.  
  129.             //  value auf Parameterwert setzen
  130.             value = time[parameter];
  131.  
  132.             //  Gewählten Parameter blinken lassen
  133.             if (parameter == 0)
  134.             {
  135.                 //  Die Sekunden brauchen eine Extrawurst
  136.                 for (unsigned char k = 1; k < 5; k++)
  137.                 {
  138.                     for (unsigned char i = 0; i < 6; i++)
  139.                     {
  140.                         matrix[0][i] = k % 2;
  141.                     }
  142.                     _delay_ms(50);
  143.                 }
  144.             }
  145.             else
  146.             {
  147.                 //  Alle anderen Parameter
  148.                 for (unsigned char k = 1; k < 5; k++)
  149.                 {
  150.                     for (unsigned char i = 1; i < 8; i++)
  151.                     {
  152.                         matrix[i][parameter - 1] = k % 2;
  153.                     }
  154.                     _delay_ms(50);
  155.                 }
  156.             }
  157.  
  158.             //  Neu zeichnen
  159.             draw_matrix();
  160.         }
  161.  
  162.         //  Hoch + Runter gleichzeitig gedrückt: Eingabe beendet
  163.         if ((button_down >= 10) && (button_up >= 10))
  164.         {
  165.             //  Ganz wichtig! Warten, bis die Taster wieder losgelassen wurden, ansonsten gibt es I2C-Brei...
  166.             while ((button_down > 0) || (button_up > 0));
  167.  
  168.             //  Sicher ist sicher!
  169.             _delay_ms(25);
  170.  
  171.             input = FALSE;
  172.         }
  173.  
  174.         if (value != value_old)
  175.         {
  176.             time[parameter] = value;
  177.             value_old = value;
  178.  
  179.             draw_matrix();
  180.         }
  181.     }
  182.  
  183.     clear_bit(TIMSK, OCIE0A);   //  Tastenzähler ausschalten
  184.  
  185.  
  186.     //  Jetzt gehts los!
  187.     i2c_start();    //  Sicherheitshalber :-)
  188.     i2c_stop();
  189.  
  190.     //  Register Address auf 0x07 setzen (Control Register)
  191.     i2c_start();
  192.     i2c_put_byte(DS1307_ADDRESS | 0);   //  Schreiben
  193.     i2c_put_byte(0x07);
  194.  
  195.     //  Control Register setzen (Output Control = 0; Square Wave Enable = 0; Rate Select = 0)
  196.     i2c_put_byte(0);
  197.     i2c_stop();
  198.  
  199.     //  Register Address auf 0x00 setzen (Register 0)
  200.     i2c_start();
  201.     i2c_put_byte(DS1307_ADDRESS | 0);   //  Schreiben
  202.     i2c_put_byte(0x00);
  203.  
  204.     //  Zeit setzen
  205.     i2c_put_byte(((time[0] / 10) << 4) | (time[0] - (time[0] / 10) * 10));  //  Clock Halt (Bit 7 = 0)
  206.     i2c_put_byte(((time[1] / 10) << 4) | (time[1] - (time[1] / 10) * 10));
  207.     i2c_put_byte(((time[2] / 10) << 4) | (time[2] - (time[2] / 10) * 10));  //  24 Hour Format (Bit 6 = 0)
  208.     i2c_put_byte(time[3]);
  209.     i2c_put_byte(((time[4] / 10) << 4) | (time[4] - (time[4] / 10) * 10));
  210.     i2c_put_byte(((time[5] / 10) << 4) | (time[5] - (time[5] / 10) * 10));
  211.     i2c_put_byte(((time[6] / 10) << 4) | (time[6] - (time[6] / 10) * 10));
  212.     i2c_stop();
  213.  
  214.     //  Hauptschleife
  215.     while (1)
  216.     {
  217.         //  Register address auf 0 setzen
  218.         i2c_start();
  219.         i2c_put_byte(DS1307_ADDRESS | 0);   //  Schreiben
  220.         i2c_put_byte(0x00);
  221.         i2c_stop();
  222.  
  223.         //  Zeit lesen
  224.         i2c_start();
  225.         i2c_put_byte(DS1307_ADDRESS | 1);   //  Lesen
  226.  
  227.         for (unsigned char i = 0; i < 7; i++)
  228.         {
  229.             unsigned char temp = i2c_get_byte(!(i == 6));   //  0..5 = TRUE; 6 = FALSE
  230.  
  231.             if (i == 0)
  232.             {
  233.                 time[i] = (temp & 0b00001111) + ((temp & 0b01110000) >> 4) * 10;    //  Bit 7 (Clock Halt) im Register 0 nicht verwenden!
  234.             }
  235.             else
  236.             {
  237.                 //  Die Maske darf auch auf die Stunden (Register 2) angewendet werden, da Bit 6 = 0 ist (24h-Format)
  238.                 time[i] = (temp & 0b00001111) + ((temp & 0b11110000) >> 4) * 10;
  239.             }
  240.         }
  241.         i2c_stop();
  242.  
  243.  
  244.         //  --- Schnickschnack ---
  245.  
  246.         //  Das Display von 22:00 Uhr bis 5:59 Uhr dimmen
  247.         if ((time[2] >= 22) || (time[2] < 6)) display_dim = 1; else display_dim = 9;
  248.  
  249.  
  250.         //  Matrix füllen
  251.         draw_matrix();
  252.     }
  253. }
  254.  
  255.  
  256. //  Initialisieren
  257. void init()
  258. {
  259.     //  Ports vorbereiten
  260.     DDRA = 0b00;    //  PA1 = SDA; PA0 = SCAL - beziehungsweise PA1 = Taster "Runter"; PA0 = Taster "Hoch"
  261.     PORTA = 0b11;   //  PullUp
  262.  
  263.     DDRB =  0b11111111; //  PB0-PB7: Spalten (Anoden)
  264.     PORTB = 0b00000000; //  LOW
  265.  
  266.     DDRD =  0b0111111;  //  PD6: Taster "Enter"; PD5-PD0: Zeilen (Kathoden)
  267.     PORTD = 0b1111111;  //  HIGH
  268.  
  269.     cli();
  270.  
  271.     // Timer-Interrupt TIMER0 vorbereiten (Tastenzähler)
  272.     set_bit(TCCR0A, WGM01); //  CTC
  273.     set_bit(TCCR0B, CS02);  //  Prescaler 1024
  274.     clear_bit(TCCR0B, CS01);
  275.     set_bit(TCCR0B, CS00);
  276.  
  277.     //  Tastenzähler-Geschwindigkeit
  278.     OCR0A = 10; //  Ca. 100 Hz
  279.  
  280.     //  Timer-Interrupt TIMER1 vorbereiten (Display-Multiplexing)
  281.     set_bit(TIMSK, OCIE1A);
  282.  
  283.     //  Multiplexing-Geschwindigkeit (blockweise)
  284.     OCR1AH = 0x00;
  285.     OCR1AL = 0xf0;
  286.  
  287.     set_bit(TCCR1B, WGM12); //  CTC
  288.     clear_bit(TCCR1B, CS12);    //  Prescaler 64
  289.     set_bit(TCCR1B, CS11);
  290.     set_bit(TCCR1B, CS10);
  291.  
  292.     sei();
  293. }
  294.  
  295. //  LED-Matrix füllen
  296. void draw_matrix()
  297. {
  298.     //  Sekunden vertikal
  299.     for (unsigned char temp_y = 0; temp_y < 6; temp_y++)
  300.     {
  301.         matrix[0][temp_y] = time[0] & (1 << (5 - temp_y));
  302.     }
  303.  
  304.     //  Restliche Werte horizontal
  305.     for (unsigned char i = 0; i < 6; i++)
  306.     {
  307.         for (unsigned char temp_x = 1; temp_x < 8; temp_x++)
  308.         {
  309.             matrix[temp_x][i] = time[i + 1] & (1 << (temp_x - 1));
  310.         }
  311.     }
  312. }
  313.  
  314. //  Interruptvektor von TIMER0 - Tastenzähler
  315. ISR(TIMER0_COMPA_vect)
  316. {
  317.     //  Hoch
  318.     if (bit_is_clear(BUTTON_UP_PORT_IN, BUTTON_UP_PIN))
  319.     {
  320.         if (button_up < 255) button_up++;
  321.     }
  322.     else
  323.     {
  324.         if (button_up > 0) button_up--;
  325.     }
  326.  
  327.     //  Runter
  328.     if (bit_is_clear(BUTTON_DOWN_PORT_IN, BUTTON_DOWN_PIN))
  329.     {
  330.         if (button_down < 255) button_down++;
  331.     }
  332.     else
  333.     {
  334.         if (button_down > 0) button_down--;
  335.     }
  336.  
  337.     //  Enter
  338.     if (bit_is_clear(BUTTON_ENTER_PORT_IN, BUTTON_ENTER_PIN))
  339.     {
  340.         if (button_enter < 255) button_enter++;
  341.     }
  342.     else
  343.     {
  344.         if (button_enter > 0) button_enter--;
  345.     }
  346. }
  347.  
  348. //  Interruptvektor von TIMER1 - LED-Multiplexing
  349. ISR(TIMER1_COMPA_vect)
  350. {
  351.     for (unsigned char y = 0; y < 6; y++)
  352.     {
  353.         for (unsigned char x = 0; x < 8; x++)
  354.         {
  355.             if (matrix[x][y] > 0)   //  LED an
  356.             {
  357.                 PORTB = (1 << x);   //  X (0..7)
  358.                 PORTD = 0b1000000 | (~(1 << y));    //  Y (0..5)
  359.             }
  360.             for (unsigned long i = 0; i < display_dim; i++) { asm volatile("nop"::); }  //  Verzögerung
  361.             PORTB = 0b00000000; //  LED aus
  362.             PORTD = 0b1111111;
  363.         }
  364.     }
  365. }
  366.  
  367.  
  368. //  Startbedingung
  369. //  SCL HIGH, SDA wechselt auf LOW
  370. void i2c_start()
  371. {
  372.     //  SCL ist immer noch HIGH
  373.     clear_I2C_SDA;      //  SDA: LOW
  374.     set_I2C_SDA_dir;    //  SDA: Schreiben
  375.     _delay_us(I2C_Delay_us);
  376.  
  377.     clear_I2C_SCL;      //  SCL: LOW
  378.     set_I2C_SCL_dir;    //  SCL: Schreiben
  379.     _delay_us(I2C_Delay_us);
  380. }
  381.  
  382. //  Stopbedingung
  383. void i2c_stop()
  384. {
  385.     //  SCL ist immer noch LOW
  386.     clear_I2C_SDA;      //  SDA: LOW
  387.     set_I2C_SDA_dir;    //  SDA: Schreiben
  388.     _delay_us(I2C_Delay_us);
  389.  
  390.     clear_I2C_SCL_dir;  //  SCL: Lesen
  391.     set_I2C_SCL;        //  SCL: HIGH (PullUp)
  392.     _delay_us(I2C_Delay_us);
  393.  
  394.     clear_I2C_SDA_dir;  //  SDA: Lesen
  395.     set_I2C_SDA;        //  SDA: HIGH (PullUp)
  396. }
  397.  
  398. void i2c_put_byte(unsigned char byte)
  399. {
  400.     unsigned char bit;
  401.  
  402.     for(bit = 0; bit < 8; bit++)
  403.     {
  404.  
  405.         if (byte & 0b10000000)
  406.         {
  407.             //  Bit = 1
  408.             clear_I2C_SDA_dir;  //  SDA: Lesen
  409.             set_I2C_SDA;        //  SDA: HIGH (PullUp)
  410.         } else {
  411.             //  Bit = 0
  412.             clear_I2C_SDA;      //  SDA: LOW
  413.             set_I2C_SDA_dir;    //  SDA: Schreiben
  414.         }
  415.  
  416.         clear_I2C_SCL_dir;  //  SCL: Lesen
  417.         set_I2C_SCL;        //  SCL: HIGH (PullUp)
  418.         _delay_us(I2C_Delay_us);
  419.  
  420.         clear_I2C_SCL;          //  SCL: LOW
  421.         set_I2C_SCL_dir;        //  SCL: Schreiben
  422.         _delay_us(I2C_Delay_us);
  423.  
  424.         byte <<= 1;
  425.     }
  426.  
  427.     //  SDA Release
  428.     clear_I2C_SDA_dir;      //  SDA: Lesen
  429.     set_I2C_SDA;            //  SDA: HIGH (PullUp)
  430.     _delay_us(I2C_Delay_us);
  431.  
  432.     //  SCL wieder auf HIGH setzen
  433.     clear_I2C_SCL_dir;  //  SCL: Lesen
  434.     set_I2C_SCL;        //  SCL: HIGH (PullUp)
  435.     _delay_us(I2C_Delay_us);
  436.  
  437.     //  ACK empfangen
  438.     if (bit_is_set(I2C_SDA_r_port, I2C_SDA_bit))
  439.     {
  440.         //  Fehler!
  441.         matrix[7][5] = 1;   //  LED unten links setzen
  442.         while (1);  //  Endlosschleife
  443.     }
  444.  
  445.     _delay_us(I2C_Delay_us);
  446.  
  447.     clear_I2C_SCL;          //  SCL: LOW
  448.     set_I2C_SCL_dir;        //  SCL: Schreiben
  449.     _delay_us(I2C_Delay_us);
  450. }
  451.  
  452. unsigned char i2c_get_byte(unsigned char ack)
  453. {
  454.     unsigned char bit, byte = 0;
  455.  
  456.     clear_I2C_SDA_dir;
  457.     set_I2C_SDA;
  458.  
  459.     for(bit = 0; bit < 8; bit++)
  460.     {
  461.         clear_I2C_SCL_dir;
  462.         set_I2C_SCL;
  463.         _delay_us(I2C_Delay_us);
  464.         if (bit_is_set(I2C_SDA_r_port, I2C_SDA_bit))
  465.         {
  466.             byte = (byte << 1) | 0b00000001;
  467.         } else {
  468.             byte = (byte << 1);
  469.         }
  470.  
  471.         clear_I2C_SCL;
  472.         set_I2C_SCL_dir;
  473.         _delay_us(I2C_Delay_us);
  474.     }
  475.  
  476.     //  ACK ausgeben?
  477.     if (ack == TRUE)
  478.         clear_I2C_SDA;      //  SDA: LOW
  479.  
  480.     set_I2C_SDA_dir;        //  SDA: Schreiben
  481.     _delay_us(I2C_Delay_us);
  482.  
  483.     clear_I2C_SCL_dir;
  484.     set_I2C_SCL;
  485.     _delay_us(I2C_Delay_us);
  486.  
  487.     clear_I2C_SCL;
  488.     set_I2C_SCL_dir;
  489.     _delay_us(I2C_Delay_us);
  490.  
  491.     clear_I2C_SDA_dir;
  492.     set_I2C_SDA;
  493.  
  494.     return byte;
  495. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement