Advertisement
BurlakovSG

Counter for Attiny4313

Jun 7th, 2017
478
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.38 KB | None | 0 0
  1. #include <avr/io.h>
  2. #include <avr/eeprom.h>
  3. #include <avr/interrupt.h>
  4. #include <avr/sleep.h>
  5. #include <stdbool.h>
  6. #include <string.h>
  7.  
  8. #define F_CPU 4000000L
  9. #define baudrate 9600L
  10. #define bauddivider (F_CPU/(16*baudrate)-1)
  11. #define HI(x) ((x)>>8)
  12. #define LO(x) ((x)& 0xFF)
  13.  
  14. #define PACKET_BEGIN    '#'
  15. #define COMMAND_QUERY   'Q'
  16. #define COMMAND_SET     'S'
  17. #define RESPONSE        'R'
  18. #define IMPULSE         'I'
  19. #define COUNTER_0       '0'
  20. #define COUNTER_1       '1'
  21. #define COUNTER_ALL     'A'
  22.  
  23. #define BUF_SIZE        64 //размер буфера обязательно равен степени двойки!
  24. #define BUF_MASK        (BUF_SIZE-1)
  25.  
  26. #define read_eeprom(address, value_p, length) eeprom_read_block ((void*)&value_p, (const void*)address, length)
  27. #define write_eeprom(address, value_p, length) eeprom_write_block ((const void*)&value_p, (void*)address, length)
  28.  
  29. typedef struct
  30. {
  31.     uint16_t num_write;
  32.     uint32_t counter[2];
  33. } data_t;
  34.  
  35. typedef struct
  36. {
  37.     uint8_t data[14];
  38.     uint8_t num_data;
  39. } rxdata_t;
  40.  
  41. data_t data;
  42. rxdata_t rx_buffer;
  43. bool flag_counter[2] = {0, 0};      // флаг срабатывания прерывания
  44. uint16_t tick[2] = {0, 0};          // счётчик защиты от дребезга
  45. uint8_t plus[2] = {10, 10};         // цена одного имульса
  46. uint16_t delay[2] = {5000, 5000};   // задержка для счётчика защиты от дребезга
  47. bool flag_save = false;             // флаг записи в память
  48. uint16_t address = 0;               // адрес записи в память
  49. uint8_t idxIN = 0;
  50. uint8_t idxOUT = 0;
  51. uint8_t serial_buffer[BUF_SIZE];
  52.  
  53. enum KA_STATE {         // Возможные состояния разборщика
  54.     WAITING_AMPERSAND,  // ожидание начала пакета
  55.     WAITING_COMMAND,    // ожидание команды
  56.     WAITING_NUMBER,     // ожидание номера счётчика
  57.     WAITING_DATA        // ожидание данных
  58. };
  59.  
  60. enum KA_STATE state = WAITING_AMPERSAND;
  61.  
  62. //обработка прерываний INT0
  63. SIGNAL(INT0_vect) {
  64.     cli();
  65.     flag_counter[0] = true;
  66.     sei();
  67. }
  68.  
  69. //обработка прерываний INT1
  70. SIGNAL(INT1_vect) {
  71.     cli();
  72.     flag_counter[1] = true;
  73.     sei();
  74. }
  75.  
  76. uint8_t read_buffer() {
  77.     uint8_t value = 0;
  78.    
  79.     if (idxIN != idxOUT)
  80.     {
  81.         value = serial_buffer[idxOUT++];
  82.         idxOUT &= BUF_MASK;
  83.     }
  84.  
  85.     return value;
  86. }
  87.  
  88. uint8_t buffer_available() {
  89.     return (idxIN - idxOUT) & BUF_MASK;
  90. }
  91.  
  92. // обработка прерываний UART RX
  93. ISR(USART0_RX_vect) {
  94.     idxOUT &= BUF_MASK;
  95.     if (buffer_available() < (BUF_SIZE - 1)) {
  96.         serial_buffer[idxIN++] = UDR;
  97.         idxIN &= BUF_MASK;
  98.     }
  99. }
  100.  
  101. void settings() {
  102.     // Настройка пинов на вход
  103.     DDRD  = (0<<PD2)|(0<<PD3);
  104.     PORTD = (1<<PD2)|(1<<PD3);
  105.    
  106.     // Настройка UART
  107.     UBRRL = LO(bauddivider);
  108.     UBRRH = HI(bauddivider);
  109.     UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
  110.     UCSRC = (3<<UCSZ0);
  111.    
  112.     // Настройка прерывания
  113.     GIMSK = (1<<INT0)|(1<<INT1);
  114.     MCUCR = (1<<ISC01)|(1<<ISC00)|(1<<ISC11)|(1<<ISC10);
  115.    
  116.     // Отключение компаратора
  117.     ACSR = (1<<ACD);
  118.    
  119.     // Отключим ненужную перефирию
  120.     PRR = (1<<PRTIM1)|(1<<PRTIM0)|(1<<PRUSI);
  121.  
  122.     sei();
  123. }
  124.  
  125. // Чтение значений счётчика из EEPROM
  126. void read_data() {
  127.     while(address < 250) {
  128.         read_eeprom(address, data, sizeof(data));
  129.        
  130.         if (data.num_write != 65534)
  131.         break;
  132.         else
  133.         address += sizeof(data);
  134.     }
  135.    
  136.     if (data.num_write == 65535)
  137.     {
  138.         data.num_write = 0;
  139.         data.counter[0]  = 0;
  140.         data.counter[1]  = 0;
  141.     }
  142. }
  143.  
  144. // Запись значений счётчика в EEPROM
  145. void write_data() {
  146.     data.num_write++;
  147.     write_eeprom(address, data, sizeof(data));
  148.    
  149.     if (data.num_write >= 65534)
  150.     {
  151.         address += sizeof(data);
  152.         data.num_write = 1;
  153.         write_eeprom(address, data, sizeof(data));
  154.     }
  155. }
  156.  
  157. void UARTSend(uint8_t data) {
  158.     while(!(UCSRA & (1<<UDRE)));
  159.     UDR = data;
  160. }
  161.  
  162. void UART_Send_str(uint8_t *data) {
  163.     while (*data)
  164.     UARTSend(*data++);
  165.    
  166.     UARTSend(0x0d);
  167.     UARTSend(0x0a);
  168. }
  169.  
  170. void int2ascii(uint8_t *data, uint8_t start, uint32_t counter) {
  171.     uint8_t i, iNumbersCount = 0;
  172.     uint32_t iTmpNum;
  173.    
  174.     iTmpNum = counter;
  175.    
  176.     while(iTmpNum){
  177.         iTmpNum/=10;
  178.         iNumbersCount++;
  179.     }
  180.    
  181.     iTmpNum = counter;
  182.    
  183.     data += start + 10;
  184.    
  185.     for (i = 0; i < 10; i++){
  186.         if (iNumbersCount)
  187.         {
  188.             *data = (char)((iTmpNum%10)|48);
  189.             iTmpNum /= 10;
  190.             iNumbersCount--;
  191.         }
  192.         else
  193.         {
  194.             *data = (char)(0|48);
  195.         }
  196.        
  197.         data--;
  198.     }
  199. }
  200.  
  201. void crc(uint8_t *data, uint8_t start, uint8_t end, uint8_t *hi, uint8_t *lo ) {
  202.     uint8_t c, i, sum = 0;
  203.    
  204.     data += start;
  205.    
  206.     for (i = start; i <= end; i++)
  207.     {
  208.         sum += *data++;
  209.     }
  210.    
  211.     c = (sum & 0xf0) >> 4;
  212.     *hi = c > 9 ? c + 0x37 : c + 0x30;
  213.    
  214.     c = (sum & 0x0f);
  215.     *lo = c > 9 ? c + 0x37 : c + 0x30;
  216. }
  217.  
  218. void UART_send_all() {
  219.     uint8_t pack_all[26];
  220.    
  221.     pack_all[0] = 0x7e;
  222.     pack_all[1] = 0x52;
  223.     pack_all[2] = 0x41;
  224.    
  225.     int2ascii(pack_all, 2, data.counter[0]);
  226.     int2ascii(pack_all, 12, data.counter[1]);
  227.     crc(pack_all, 1, 22, &pack_all[23], &pack_all[24]);
  228.     pack_all[25] = 0x00;
  229.    
  230.     UART_Send_str(pack_all);
  231. }
  232.  
  233. void UART_Send_counter(uint8_t cnt, uint8_t type) {
  234.     uint8_t pack[16];
  235.    
  236.     pack[0] = 0x7e;
  237.     pack[1] = type; //0x49;
  238.     pack[2] = (char)(cnt|48);
  239.    
  240.     int2ascii(pack, 2, data.counter[cnt]);
  241.     crc(pack, 1, 12, &pack[13], &pack[14]);
  242.     pack[15] = 0x00;
  243.    
  244.     UART_Send_str(pack);
  245. }
  246.  
  247. void clear_buffer() {
  248.     rx_buffer.num_data = 2;
  249.     memset(rx_buffer.data, 0, sizeof(rx_buffer.data));
  250. }
  251.  
  252. void prepare_data() {
  253.     uint32_t result = 0;
  254.     uint8_t i, j, hi, lo;
  255.    
  256.     for (i = 2; i < 12; i++)
  257.     {
  258.         result *= 10;
  259.         j = rx_buffer.data[i] - 48;
  260.         if (j > 9)
  261.         {
  262.             return;
  263.         }
  264.         result += j;
  265.     }
  266.    
  267.     crc(rx_buffer.data, 0, 11, &hi, &lo);
  268.    
  269.     if (rx_buffer.data[12] != hi || rx_buffer.data[13] != lo)
  270.     {
  271.         UART_Send_counter(rx_buffer.data[1] - 48, RESPONSE);
  272.     }
  273.     else
  274.     {
  275.         data.counter[rx_buffer.data[1] - 48] = result;
  276.         flag_save = true;
  277.         UART_Send_counter(rx_buffer.data[1] - 48, RESPONSE);
  278.     }
  279. }
  280.  
  281. void prepare_serial(uint8_t rx_data) {
  282.     switch (state)
  283.     {
  284.         case WAITING_AMPERSAND:
  285.         if (rx_data == PACKET_BEGIN)
  286.         {
  287.             clear_buffer();
  288.             state = WAITING_COMMAND;
  289.         }
  290.         break;
  291.        
  292.         case WAITING_COMMAND:
  293.         rx_buffer.data[0] = rx_data;
  294.        
  295.         switch (rx_data)
  296.         {
  297.             case COMMAND_QUERY:
  298.             state = WAITING_NUMBER;
  299.             break;
  300.            
  301.             case COMMAND_SET:
  302.             state = WAITING_NUMBER;
  303.             break;
  304.            
  305.             default:
  306.             state = WAITING_AMPERSAND;
  307.             break;
  308.         }
  309.         break;
  310.        
  311.         case WAITING_NUMBER:
  312.         rx_buffer.data[1] = rx_data;
  313.        
  314.         switch (rx_data)
  315.         {
  316.             case COUNTER_0:
  317.             if (rx_buffer.data[0] == COMMAND_QUERY)
  318.             {
  319.                 UART_Send_counter(0, RESPONSE);
  320.                 state = WAITING_AMPERSAND;
  321.             }
  322.             else
  323.             {
  324.                 state = WAITING_DATA;
  325.             }
  326.             break;
  327.            
  328.             case COUNTER_1:
  329.             if (rx_buffer.data[0] == COMMAND_QUERY)
  330.             {
  331.                 UART_Send_counter(1, RESPONSE);
  332.                 state = WAITING_AMPERSAND;
  333.             }
  334.             else
  335.             {
  336.                 state = WAITING_DATA;
  337.             }
  338.             break;
  339.            
  340.             case COUNTER_ALL:
  341.             if (rx_buffer.data[0] != COMMAND_SET)
  342.             {
  343.                 UART_send_all();
  344.             }
  345.            
  346.             state = WAITING_AMPERSAND;
  347.             break;
  348.            
  349.             default:
  350.             state = WAITING_AMPERSAND;
  351.             break;
  352.         }
  353.         break;
  354.        
  355.         case WAITING_DATA:
  356.         if (rx_buffer.num_data == 14)
  357.         {
  358.             if (rx_data == 0x0d)
  359.             {
  360.                 prepare_data();
  361.             }
  362.            
  363.             state = WAITING_AMPERSAND;
  364.         }
  365.         else
  366.         {
  367.             rx_buffer.data[rx_buffer.num_data] = rx_data;
  368.             rx_buffer.num_data++;
  369.         }
  370.         break;
  371.     }
  372. }
  373.  
  374. void check_int(uint8_t cnt) {
  375.     if (flag_counter[cnt])
  376.     {
  377.         tick[cnt]++;
  378.        
  379.         if (tick[cnt] > delay[cnt])
  380.         {
  381.             if ((cnt == 0 && !(PIND & (1<<PD2))) || (cnt == 1 && !(PIND & (1<<PD3))))
  382.             {
  383.                 flag_counter[cnt] = false;
  384.                 tick[cnt] = 0;
  385.                 return;
  386.             }
  387.            
  388.             data.counter[cnt] += plus[cnt];
  389.             flag_counter[cnt] = false;
  390.             flag_save = true;
  391.             tick[cnt] = 0;
  392.            
  393.             UART_Send_counter(cnt, IMPULSE);
  394.         }
  395.     }
  396. }
  397.  
  398. int main(void)
  399. {
  400.     settings();
  401.     read_data();
  402.    
  403.     while (1)
  404.     {
  405.         check_int(0);
  406.        
  407.         check_int(1);
  408.        
  409.         if (buffer_available())
  410.         {
  411.             prepare_serial(read_buffer());
  412.         }
  413.        
  414.         if (flag_save)
  415.         {
  416.             write_data();
  417.             flag_save = false;
  418.         }
  419.        
  420.         if (!flag_counter[0] && !flag_counter[1] && !buffer_available())
  421.         {
  422.             set_sleep_mode(SLEEP_MODE_IDLE);
  423.             cli();
  424.             sleep_enable(); // разрешаем сон
  425.             sei();
  426.             sleep_cpu(); // спать!
  427.             sleep_disable();
  428.             sei();
  429.         }
  430.     }
  431. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement