Redfern_89

led_clock.c

Dec 29th, 2018
215
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.08 KB | None | 0 0
  1. /*
  2.  * led_clock.c
  3.  *
  4.  * Created: 24.12.2018 19:24:51
  5.  * Author : Redfern.89
  6.  */
  7.  
  8. // Частота проца в герцах
  9. #ifndef F_CPU
  10. #define F_CPU   16000000UL
  11. #endif
  12.  
  13. #include <avr/io.h>
  14. #include <util/delay.h>
  15. #include <avr/interrupt.h>
  16. #include <math.h>
  17.  
  18. // Настройки портов ввода-вывода
  19. #define RCLK_DDR    DDRD        //         
  20. #define SCLK_DDR    DDRD        //           SSSSSSSSSS      PPPPPPPPP    III
  21. #define DATA_DDR    DDRD        //          S               P         P    I
  22. #define RCLK_PORT   PORTD       //          S               P         P    I
  23. #define SCLK_PORT   PORTD       //           SSSSSSSSSS     P PPPPPPPP     I
  24. #define DATA_PORT   PORTD       //                     S    P              I
  25. #define RCLK        PD5         //                     S    P              I
  26. #define SCLK        PD6         //           SSSSSSSSSS     P             III
  27. #define DATA        PD7         //
  28. //  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  29. #define I2C_DDR     DDRC        //
  30. #define I2C_PORT    PORTC       //               2222
  31. #define I2C_PIN     PINC        //          I        2   ccc
  32. #define I2C_SCL     PC0         //          I    2222   c
  33. #define I2C_SDA     PC1         //          I   2       c
  34. #define I2C_ACK     0           //          I    2222    ccc
  35. #define I2C_NACK    1           //
  36.  
  37. /*  ~~~~~~~~~~~~~~~~~~~~ МАКРОСЫ ~~~~~~~~~~~~~~~~~~~~ */
  38.  
  39. // Упарвление защелкой и сдвигом регистров
  40. #define _74hc595_RegisterLatch(code)    {   RCLK_PORT &= (1 << RCLK); code; RCLK_PORT |= (1 << RCLK);   }
  41. #define _74hc595_RegisterShift()        {   SCLK_PORT &= ~(1 << SCLK); SCLK_PORT |= (1 << SCLK);        }
  42.  
  43. // Управление i2c-портами
  44. #define ONE_SCL                         {   I2C_DDR &= ~(1 << I2C_SCL); I2C_PORT |= (1 << I2C_SCL);     }
  45. #define NULL_SCL                        {   I2C_DDR |= (1 << I2C_SCL);  I2C_PORT &= ~(1 << I2C_SCL);    }
  46. #define ONE_SDA                         {   I2C_DDR &= ~(1 << I2C_SDA); I2C_PORT |= (1 << I2C_SDA);     }
  47. #define NULL_SDA                        {   I2C_DDR |= (1 << I2C_SDA);  I2C_PORT &= ~(1 << I2C_SDA);    }
  48. #define I2C_DELAY                       {   _delay_ms(1);   }
  49.    
  50. // Управление таймером 0 для IRDA
  51. #define TIMER0_START                    {   TCCR0B = (1 << CS01) | (1 << CS00);                         }
  52. #define TIMER0_STOP                     {   TCCR0B = 0x00;                                              }
  53.  
  54.  
  55. // Данные о сегментах индикатора (LSBFIRST)
  56. uint8_t digits[11] = {//               A   
  57.   0b11000000,         //1          #########
  58.   0b11111001,         //2         #         #
  59.   0b10100100,         //3       F #         # B
  60.   0b10110000,         //4         #    G    #
  61.   0b10011001,         //5          #########
  62.   0b10010010,         //6         #         #
  63.   0b10000010,         //7       E #         # C
  64.   0b11111000,         //8         #         #
  65.   0b10000000,         //9          #########
  66.   0b10010000,         //0              D       ##
  67.   0b11111111          //8.                     dp
  68. };
  69.  
  70. // Данные о группах светодиодов
  71. const uint8_t groups[4] = {
  72.     0b11111011,
  73.     0b11111101,
  74.     0b11110111,
  75.     0b11101111
  76. };
  77.  
  78. /* Кое-какие глобальные переменные */
  79. unsigned char NC                        = 0b11111111;
  80. unsigned char display_data[4]           = {0b11111111, 0b11111111, 0b11111111, 0b11111111};
  81. const static int max_groups             = 4;
  82. static int display_pos                  = 0;
  83. volatile int NEC_REPEAT_FLAG            = 0;
  84. volatile int NEC_START_FLAG             = 0;
  85. volatile int NEC_IR_DONE                = 0;
  86. /* Протокол NEC */
  87. volatile unsigned long int NEC_SCLK     = 0;        // Тактовые синхроимпульсы (64 мкс)
  88. volatile unsigned long int NEC_RECV_CNT = 0;        // Кол-во принятых битов
  89. const static int NEC_MIN_PREAMBLE       = 212;      // Преамбула+пауза (минимальное время)
  90. const static int NEC_MAX_PREAMBLE       = 216;      // Преамбула+пауза (максимальное время)
  91. const static int NEC_MIN_REPEAT         = 178;
  92. const static int NEC_MAX_REPEAT         = 180;
  93. const static int NEC_MIN_ONE_BIT        = 34;
  94. const static int NEC_MAX_ONE_BIT        = 46;
  95. const static int NEC_MIN_NULL_BIT       = 17;
  96. const static int NEC_MAX_NULL_BIT       = 19;
  97. const static int NEC_MAX_RESET_OVF      = 1200;
  98. const static int NEC_PACKET_LENGTH      = 32;
  99. unsigned char NEC_RESPONSE_DATA[4]      = {0b00000000, 0b00000000, 0b00000000, 0b00000000};
  100.  
  101.  
  102. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  103.                         Shift registers functions
  104.  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  105.  
  106. // Отправка данных в регистр
  107. void _74hc595_SPI_send(char data) {
  108.     int i;
  109.     unsigned char val;
  110.    
  111.     for (i = 0; i < 8; i++) {
  112.         val = !!(data & (1 << (7 - i)));
  113.         if (val) DATA_PORT |= (1 << DATA); else DATA_PORT &= (1 << DATA);
  114.         _74hc595_RegisterShift();  
  115.     }
  116. }
  117.  
  118. // Отправка данных в регистры и защелкивание
  119. void _74hc595_RegisterWrite(unsigned char data1, unsigned char data2) {
  120.     _74hc595_RegisterLatch({
  121.         _74hc595_SPI_send(data1);
  122.         _74hc595_SPI_send(data2);
  123.     });
  124. }
  125.  
  126. // Отправка данных в регистры с защелкиванием (2.0)
  127. void _74hc595_RegisterWrite2(unsigned char* data, int registrs_count) {
  128.     unsigned int i = 0;
  129.     _74hc595_RegisterLatch({
  130.        
  131.         for (i = 0; i < registrs_count; i++) {
  132.             _74hc595_SPI_send(data[i]);
  133.         }
  134.            
  135.     });
  136. }
  137. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  138.                             i2c Functions
  139.  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  140. // Условие STOP
  141. unsigned char i2c_stop(void) {
  142.     unsigned char error = 0;
  143.    
  144.     NULL_SCL;
  145.     I2C_DELAY;
  146.     NULL_SDA;
  147.     I2C_DELAY;
  148.    
  149.     ONE_SCL;
  150.     I2C_DELAY;
  151.     ONE_SDA;
  152.     I2C_DELAY;
  153.    
  154.     if (( I2C_PIN & (1 << I2C_SDA)) == 0) error = 2;
  155.     if (( I2C_PIN & (1 << I2C_SCL)) == 0) error |= 1;
  156.    
  157.     I2C_DELAY;
  158.     I2C_DELAY;
  159.     I2C_DELAY;
  160.     I2C_DELAY;
  161.    
  162.     return error;
  163. }
  164.  
  165. // Условие START
  166. void i2c_start(void) {
  167.     NULL_SDA;
  168.     I2C_DELAY;
  169.     NULL_SCL;
  170.     I2C_DELAY;
  171. }
  172.  
  173. // Условие RESTART
  174. void i2c_restart(void) {
  175.     ONE_SDA;
  176.     I2C_DELAY;
  177.     ONE_SCL;
  178.     I2C_DELAY;
  179.    
  180.     NULL_SDA;
  181.     I2C_DELAY;
  182.     NULL_SCL;
  183.     I2C_DELAY;
  184. }
  185.  
  186. // Инициализация шины i2c
  187. void i2c_init(void) {
  188.     ONE_SDA;
  189.     ONE_SCL;
  190.    
  191.     i2c_stop();
  192. }
  193.  
  194. // Отправка байта по шине i2c
  195. unsigned char i2c_write(unsigned char data) {
  196.     unsigned char i;
  197.     unsigned char ask = I2C_ACK;
  198.    
  199.     for (i = 0; i < 8; i++) {
  200.        
  201.         if ((data & 0x80) == 0) {       // Пиздец
  202.             NULL_SDA;
  203.         } else {
  204.             ONE_SDA;
  205.         }
  206.         I2C_DELAY;
  207.         ONE_SCL;
  208.         I2C_DELAY;
  209.         NULL_SCL;
  210.        
  211.         data = (data << 1);
  212.     }
  213.    
  214.     ONE_SDA;
  215.     I2C_DELAY;
  216.     ONE_SCL;
  217.     I2C_DELAY;
  218.    
  219.     if ((I2C_PIN & (1 << I2C_SDA)) == (1 << I2C_SDA)) {
  220.         ask = I2C_NACK;
  221.     } else {
  222.         ask = I2C_ACK;
  223.     }
  224.    
  225.     NULL_SCL;
  226.    
  227.     return ask;
  228. }
  229.  
  230. // Чтение байта по шине i2c
  231. unsigned char i2c_read(unsigned char ask) {
  232.     unsigned char byte = 0;
  233.     unsigned char i;
  234.    
  235.     for (i = 0; i < 8; i++) {
  236.         byte = (byte << 1);
  237.         ONE_SCL;
  238.         I2C_DELAY;
  239.         if ((I2C_PIN & (1 << I2C_SDA)) == (1 << I2C_SDA)) byte |= 0x01;
  240.         NULL_SCL;
  241.         I2C_DELAY;
  242.     }
  243.    
  244.     if (ask == I2C_ACK) {
  245.         NULL_SDA;
  246.     } else {
  247.         ONE_SDA;
  248.     }
  249.    
  250.     I2C_DELAY;
  251.     ONE_SCL;
  252.     I2C_DELAY;
  253.     NULL_SCL;
  254.     ONE_SDA;
  255.    
  256.     return byte;
  257. }
  258. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  259.                             DS1307 Functions
  260.  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  261.  
  262. // Чтение данных из DS1307
  263. unsigned char DS1307_Read(unsigned char address, unsigned char data) {
  264.     unsigned char res;
  265.     i2c_start();
  266.    
  267.     res = i2c_write(0b11010000);
  268.     if (!res) return 0;
  269.     res = i2c_write(address);
  270.     if (!res) return 0;
  271.     i2c_start();
  272.     res = i2c_write(0b11010001);
  273.     if (!res) return 0;
  274.     res = i2c_read(data);
  275.     if (!res) return 0;
  276.     i2c_stop();
  277.     return 1;
  278. }
  279.  
  280.  
  281. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  282.                             NEC 2.0 functions
  283.  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  284.  
  285. // Сброс данных по IRDA
  286. void NEC_Reset_IRDA() {
  287.     TIMER0_STOP;
  288.     NEC_START_FLAG = 0;
  289.     NEC_REPEAT_FLAG = 0;
  290.     NEC_RECV_CNT = 0;
  291.     NEC_SCLK = 0;
  292. }
  293.  
  294. // Таймер обработки длительности импульсов
  295. ISR (TIMER0_OVF_vect) {
  296.     TCNT0 = 0xF0;
  297.     if (++NEC_SCLK >= NEC_MAX_RESET_OVF) {
  298.         NEC_SCLK = 0;
  299.         NEC_REPEAT_FLAG = 0;
  300.         NEC_START_FLAG = 0;
  301.         TIMER0_START;
  302.     }
  303. }
  304.  
  305. // Обработчик внешнего прерывания
  306. ISR (INT0_vect) {
  307.     TIMER0_START;
  308.    
  309.     if (NEC_SCLK >= NEC_MIN_PREAMBLE && NEC_SCLK < NEC_MAX_PREAMBLE) {
  310.         NEC_START_FLAG = 1;
  311.         NEC_REPEAT_FLAG = 0;
  312.     }
  313.    
  314.     if ((NEC_SCLK >= NEC_MIN_REPEAT && NEC_SCLK < NEC_MAX_REPEAT) && NEC_START_FLAG) {
  315.         NEC_START_FLAG = 0;
  316.         NEC_REPEAT_FLAG = 1;
  317.     }
  318.    
  319.     // Пожалуй, это самые уебансике места в программе...
  320.     if ((NEC_SCLK >= NEC_MIN_ONE_BIT && NEC_SCLK < NEC_MAX_ONE_BIT) && NEC_START_FLAG) {
  321.         NEC_RECV_CNT++;
  322.        
  323.         // Знаю, по-идиотски, умнее лень было придумывать
  324.         if (NEC_RECV_CNT < 9) {                                     // Биты 1-8
  325.             NEC_RESPONSE_DATA[0] |= (1 << NEC_RECV_CNT);
  326.         } else if (NEC_RECV_CNT >= 9 && NEC_RECV_CNT < 17) {        // Биты 9-16
  327.             NEC_RESPONSE_DATA[1] |= (1 << (NEC_RECV_CNT -9));
  328.         } else if (NEC_RECV_CNT >= 17 && NEC_RECV_CNT < 25 ) {      // Биты 17-24
  329.             NEC_RESPONSE_DATA[2] |= (1 << (NEC_RECV_CNT - 17));
  330.         } else if (NEC_RECV_CNT >= 25) {                            // Биты 25-32
  331.             NEC_RESPONSE_DATA[3] |= (1 << (NEC_RECV_CNT - 25));
  332.         }
  333.     }
  334.    
  335.     NEC_SCLK = 0;
  336.    
  337.     if (NEC_RECV_CNT == NEC_PACKET_LENGTH) {
  338.         NEC_Reset_IRDA();
  339.         if ((NEC_RESPONSE_DATA[0] + NEC_RESPONSE_DATA[1] == 0xFF) && (NEC_RESPONSE_DATA[2] + NEC_RESPONSE_DATA[3] == 0xFF)) {
  340.             NEC_IR_DONE = 1;
  341.         }
  342.     }
  343. }
  344.  
  345. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  346.                             Main Functions
  347.  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  348.  
  349. // Динамическая индикация
  350. ISR (TIMER2_OVF_vect) {
  351.     TCNT2 = 0xFA;
  352.     display_pos = (display_pos + 1) % max_groups;
  353.     unsigned char display[2] = {display_data[display_pos], groups[display_pos]};
  354.        
  355.     _74hc595_RegisterWrite2(display, 2);
  356. }
  357.  
  358. // Подсчет времени
  359. ISR (TIMER1_OVF_vect) {
  360.    
  361. }
  362.  
  363. // Отрисовка цифр на дисплее
  364. void print_display(int hours, int minutes, int colon_blink) {
  365.     if (hours == 0) {
  366.         display_data[0] = digits[0];
  367.         display_data[1] = colon_blink ? digits[0] | (1 << 0) : digits[0];
  368.         } else if (hours >= 1 && hours <= 9) {
  369.         display_data[0] = digits[0];
  370.         display_data[1] = colon_blink ? digits[hours] | (1 << 0) : digits[hours];
  371.         } else if (hours >= 10 && hours <= 99) {
  372.         display_data[0] = digits[(unsigned int)round(hours % 100) / 10];
  373.         display_data[1] = colon_blink ? digits[(unsigned int)round(hours % 10)] | (1 << 0) : digits[(hours % 10)];
  374.     }
  375.  
  376.     if (minutes == 0) {
  377.         display_data[2] = digits[0];
  378.         display_data[3] = digits[0];
  379.         } else if (minutes >= 1 && minutes <= 9) {
  380.         display_data[2] = digits[0];
  381.         display_data[3] = digits[minutes];
  382.         } else if (minutes >= 10 && minutes <= 99) {
  383.         display_data[2] = digits[(unsigned int)round(minutes % 100) / 10];
  384.         display_data[3] = digits[(unsigned int)round(minutes % 10)];
  385.     }
  386. }
  387.  
  388. // Инициализация микроконтроллера
  389. void MCU_init() {
  390.     // Инициализация портов ввода-вывода
  391.     RCLK_DDR |= (1 << RCLK);
  392.     SCLK_DDR |= (1 << SCLK);
  393.     DATA_DDR |= (1 << DATA);
  394.    
  395.     // Инициализация внешнего прерывания (на спад)
  396.     EICRA = (1 << ISC01);
  397.     EIMSK = (1 << INT0);
  398.     EIFR = (1 << INTF0);
  399.     PCICR = 0x00;
  400.    
  401.     // Инициализация таймера/счестчика 0 для подсчета временного интервала между импульсами
  402.     TCCR0B = (1 << CS01) | (1 << CS00);
  403.     TIMSK0 = (1 << TOIE0);
  404.     TCNT0 = 0xF0;
  405.    
  406.     // Иницмализация таймера/счетчика 1 для работы интерфейса
  407.     TCCR1B = (1 << CS10) | (1 << CS11);
  408.     TIMSK1 = (1 << TOIE1);
  409.     TCNT1 = 0xFFFE;
  410.    
  411.     // Инициализация таймера/счестчика 2 для динамической индикации
  412.     TCCR2B = (1 << CS20);
  413.     TIMSK2 = (1 << TOIE2);
  414.     TCNT2 = 0xFA;
  415.    
  416.     // Инициализация i2c
  417.     i2c_init();
  418. }
  419.  
  420.  
  421. int main(void) {
  422.    
  423.     asm("CLI");
  424.     MCU_init();
  425.     asm("SEI");
  426.    
  427.     return 0;
  428. }
Advertisement
Add Comment
Please, Sign In to add comment