Redfern_89

barno_ebanoe.c

Dec 26th, 2017
192
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.91 KB | None | 0 0
  1. #include <avr/io.h>
  2. #include <util/delay.h>
  3.  
  4. // Сигналы управления сдвиговыми регистрами
  5. #define RCLK 6    // Защелка
  6. #define SCLK 7    // Тактирование
  7. #define DATA 5    // Данные
  8.  
  9. // Тактовая частота процессора 16MHz
  10. #define F_CPU 16000000UL
  11.  
  12. // Макрос управления защелкой
  13. #define _74hc595_registerLatch(code) { PORTD &= ~(1 << RCLK); code; PORTD |= 1 << RCLK; }
  14. // Макрос управления сдвигом регистров
  15. #define _74hc595_registerShift() { PORTD &= ~(1 << SCLK); PORTD |= (1 << SCLK); }
  16.  
  17. // Данные о сегментах индикаторов
  18. const uint8_t digits[11] = {//        A
  19.   0b11000000,         //          #########
  20.   0b11111001,         //         #         #
  21.   0b10100100,         //       F #         # B
  22.   0b10110000,         //         #    G    #
  23.   0b10011001,         //          #########
  24.   0b10010010,         //         #         #
  25.   0b10000010,         //       E #         # C
  26.   0b11111000,         //         #         #
  27.   0b10000000,         //          #########
  28.   0b10010000,         //              D       ##
  29.   0b11111111          //                      dp
  30. };
  31.  
  32. // Данные о группах светодиодов (16 бит)
  33. const uint16_t groups[15] = {
  34. /* -------- 3 DIGIT DISPLAY -------- */
  35.   0b0000010000000000, // DIGIT 1      (0)
  36.   0b0000001000000000, // DIGIT 2      (1)
  37.   0b0000000100000000, // DIGIT 3      (2)
  38. /* -------- 6 DIGIT DISPLAY -------- */  
  39.   0b0000000010000000, // DIGIT 1      (3)
  40.   0b0000000001000000, // DIGIT 2      (4)
  41.   0b0000000000100000, // DIGIT 3      (5)
  42.   0b0000000000010000, // DIGIT 4      (6)
  43.   0b0000000000001000, // DIGIT 5      (7)
  44.   0b0000000000000100, // DIGIT 6      (8)
  45. /* --------  40 Leds Scale  -------- */
  46.   0b0010000000000000, // SCALE 1      (9)
  47.   0b0001000000000000, // SCALE 2      (10)
  48.   0b0000100000000000, // SCALE 3      (11)
  49.   0b0000000000000010, // SCALE 4      (12)
  50.   0b0000000000000001  // SCALE 5      (13)
  51. };
  52.  
  53. // Данные о светодиодах в шкале
  54. const uint8_t scale_leds[9] = {
  55.   0b11111111, // 0 LED's  
  56.   0b11111110, // 1 LED's
  57.   0b11111100, // 2 LED's
  58.   0b11111000, // 3 LED's
  59.   0b11110000, // 4 LED's
  60.   0b11100000, // 5 LED's
  61.   0b11000000, // 6 LED's
  62.   0b10000000, // 7 LED's
  63.   0b00000000  // 8 LED's
  64. };
  65.  
  66. uint8_t NC              = 0b11111111;   // Пустое значение
  67. unsigned int display_position       = 0;        // Текущее значение на экране / группа
  68. unsigned int CNT_Impulse        = 0;        // Колличество импульсов с датчика
  69. unsigned int CountImpulse       = 10;       // Точность точность измерений
  70. unsigned int CNT_OVF            = 0;        // Переполнения
  71. unsigned int TMP_CNT_OVF        = 0;        // Для сравнения с предыдущими переполнениями
  72. unsigned int TMP_TCNT           = 0;        // Запоминаем, сколько осталось до переполнения
  73. unsigned int ImpulsePerRotate       = 6;        // Колличество импульсов на 1 оборот колеса
  74. unsigned int CNT_Mileage_Impulse    = 0;        // Для подсчета импульсов пробега
  75. unsigned int total_scale_leds       = 40;       // Колличество светодиодов в шкале
  76. unsigned int leds_per_group     = 8;        // Колличество светодиодов на группу
  77. unsigned int MaximumSpeedCalc       = 200;      // Максимальная расчетная скорость
  78. unsigned int factorial          = 0;        // Факториал (сопоставление скорость/шкала)
  79. unsigned int speed_scale        = 0;        // Скорость на шкале светодиодов
  80.  
  81. float LengthCircle          = 180.6128F;    // Размер колеса. R13 175/70
  82. float mileage               = 0.0F;     // Текущий пробег
  83. float Speed                 = 0.0F;     // Текущая скорость
  84. bool speed_flag             = false;    // Флаг измерения скорости
  85.  
  86. uint8_t display_data[14] = {NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC};
  87.  
  88. // Отправка данных по SPI
  89. void _74hc595_SPI_send(uint8_t data) {
  90.   for (uint8_t i = 0; i < 8; i++) {
  91.     byte value = !!(data & (1 << (7 - i)));
  92.     if (value) PORTD |= 1 << DATA; else PORTD &= ~(1 << DATA);
  93.     _74hc595_registerShift();
  94.   }  
  95. }
  96.  
  97. // Запись в регистры
  98. void _74hc595_registerWrite(uint16_t groups, uint8_t segments) {
  99.   // "Защелкиваем" данные в регистры
  100.   _74hc595_registerLatch({
  101.    _74hc595_SPI_send(groups >> 8);        // Сначала старший байт
  102.     _74hc595_SPI_send((groups) & 0xFF);   // Затем младший байт
  103.     _74hc595_SPI_send(segments);          // Теперь Один байт, отвечающий за сегменты
  104.   });
  105. }
  106.  
  107. // Описание таймера индикации
  108. ISR (TIMER1_OVF_vect) {
  109.   TCNT1 = 64456;                                    // Начинаем отсчет с 64456
  110.   display_position = (display_position + 1) % 14;                   // Счиатем до 14 и сбрасываемся
  111.   _74hc595_registerWrite(groups[display_position], display_data[display_position]); // Отправляем в регистры текущие данные (Группа, сегменты)
  112. }
  113.  
  114. // Описание таймера подсчета импульсов
  115. ISR (TIMER0_OVF_vect) {
  116.    CNT_OVF++;
  117. }
  118.  
  119. // Описание внешнего прерывания
  120. ISR (INT0_vect) {
  121.    // Считаем пробег
  122.    // Как только кол-во импульсов стало равно одному обороту колеса
  123.    // Прибавляем ктекущему пробегу длину колеса и преводим в километры
  124.    if (++CNT_Mileage_Impulse >= ImpulsePerRotate) {
  125.       mileage = mileage + (LengthCircle * 0.00001);
  126.       CNT_Mileage_Impulse = 0;
  127.    }
  128.    
  129.    // Счиатаем данные для расчета скорости
  130.    if (++CNT_Impulse >= CountImpulse) {
  131.       TMP_TCNT = TCNT0;     // Запоминаем, сколько осталось до переполнения
  132.       TMP_CNT_OVF = CNT_OVF;    // Запоминаем кол-во переполнений
  133.      
  134.       /* Обнуляем текущие счетчики */
  135.       CNT_OVF = 0;
  136.       TCNT0 = 0;
  137.       CNT_Impulse = 0;
  138.       speed_flag = true;
  139.    }
  140. }
  141.  
  142. // Заполнение участка массива индикации нулями
  143. void fill_display(int offset, int count) {
  144.    for (int i = offset; i < count; i++) {
  145.       display_data[i] = NC;
  146.    }
  147. }
  148.  
  149. // Как я с этим заебался. Вывод данных на шкалу светодиодов
  150. void printLedScale(float leds) {
  151.    int led      = 0;
  152.    int unusedGroups = 0;
  153.    int groups       = 0;
  154.    int current      = 0;
  155.    
  156.    if (leds > total_scale_leds) leds = total_scale_leds;
  157.    groups = ceil(leds / leds_per_group);
  158.    if (leds > 0) {
  159.       for (int i = 0; i < groups; i++) {
  160.      current = i +1;
  161.      if (current |= groups) {
  162.         display_data[i +9] = scale_leds[7];
  163.      } else {
  164.         led = leds - (leds_per_group * (groups - 1) ) -1;
  165.         display_data[i +9] = scale_leds[led];
  166.      }
  167.      unusedGroups = leds_per_group - groups;
  168.      
  169.      if (unusedGroups > 0) {
  170.         fill_display(groups +9, unusedGroups);
  171.      }
  172.       }
  173.    }
  174.    
  175. }
  176.  
  177. // Муторная процедура отображения данных на 3х цифровом индикаторе
  178. void print3digitDisplay(int number) {
  179.   if (number == 0) {
  180.     display_data[0] = (digits[0] & ~(1 << 7));
  181.     display_data[1] = digits[0];
  182.     display_data[2] = digits[0];
  183.   } else  if (number >= 1 && number <= 9) {
  184.     display_data[0] = digits[number];
  185.     fill_display(1, 2);
  186.   } else if (number >= 10 && number <= 99) {
  187.     display_data[0] = digits[round(number % 100) / 10];
  188.     display_data[1] = digits[round(number % 10)];
  189.     fill_display(2, 1);
  190.   } else if (number >= 100 && number <= 999) {
  191.     display_data[0] = digits[round(number / 100) % 10];
  192.     display_data[1] = digits[round(number % 100) / 10];
  193.     display_data[2] = digits[round(number % 10)];
  194.   }
  195. }
  196.  
  197. // Еще более мторная тема для 6ти цифр
  198. void print6digitDisplay(unsigned long int number) {
  199.   if (number <= 9) {
  200.     display_data[3] = digits[number];
  201.     fill_display(4, 5);
  202.   } else if (number >= 10 && number <= 99) {
  203.     display_data[3] = digits[round(number % 100) / 10];
  204.     display_data[4] = digits[round(number % 10)];
  205.     fill_display(5, 4);
  206.   } else if (number >= 100 && number <= 999) {
  207.     display_data[3] = digits[round(number % 100) / 10];
  208.     display_data[4] = digits[round(number % 100) / 10];
  209.     display_data[5] = digits[round(number % 10)];
  210.     fill_display(6, 3);
  211.   } else if (number >= 10000 && number <= 99999) {
  212.     display_data[3] = digits[round(number / 10000)];
  213.     display_data[4] = (digits[round(number / 1000 % 10)] & ~(1 << 7)); // Ставим точку после 2го разяряда (ex. 32.768)
  214.     display_data[5] = digits[round(number % 1000 / 100)];
  215.     display_data[6] = digits[round(number % 100 / 10)];
  216.     display_data[7] = digits[round(number % 10)];
  217.     fill_display(7, 1);
  218.   } else if (number >= 100000 && number <= 999999) {
  219.     display_data[3] = digits[round(number / 100000)];
  220.     display_data[4] = digits[round(number / 10000 % 10)];
  221.     display_data[5] = (digits[round(number / 1000 % 10)] & ~(1 << 7)); // Ставим точку после 3го разряда (ex. 327.680)
  222.     display_data[6] = digits[round(number % 1000 / 100)];
  223.     display_data[7] = digits[round(number % 100 / 10)];
  224.     display_data[8] = digits[round(number % 10)];
  225.   }
  226. }
  227.  
  228. // Тетст всего экрана (все группы и сегменты)
  229. void test_display() {
  230.   int i;
  231.  
  232.   for (i = 0; i < 14; i++) {
  233.     display_data[i] = ~NC;
  234.   }
  235. }
  236.  
  237. // Основная программа
  238. int main () {
  239.   // SPI - выводы для регистров
  240.   DDRD = 0b11100000;
  241.  
  242.   // Инициализация таймера 0 (Подсчет импульсов) 8bit
  243.   TIMSK0 = (1 << TOIE0);                             // Разрешаем таймер по переполнению
  244.   TCCR0B = (1 << CS12) | (0 << CS11) | (1 << CS10);  // Предделитель /1024
  245.   // 16000000 / 1024 = 15625
  246.  
  247.   // Таймер 1 (динамической индикации) 16 bit
  248.   TIMSK1 = (1 << TOIE1);
  249.   TCCR1B = (0 << CS12) | (1 << CS11) | (0 << CS10);  // Предделитель /8
  250.   TCNT1 = 64456;
  251.  
  252.   // Инициализация внешнего прерывания (на спад) на INT0
  253.   EICRA |= (1 << ISC01);
  254.   EIMSK |= (1 << INT0);
  255.  
  256.   // Разрешание прерываний
  257.   asm("SEI");    
  258.  
  259.   // Вечный цикл
  260.   while (1) {
  261.       _delay_ms(500);
  262.       /*
  263.      Расчет скорости. пройденное расстояние делим Дельту времени и переводим в часы. Вот, как это сделалнно
  264.      
  265.         Таймер TIMER0 настроен на предделитель /1024, значит он будет рабоать на частоте 15.625KHz
  266.         Счиатем так: Колличество переполнений умножаем на разрядность таймера, прибавляем остатки от незаконченного
  267.         переполнения, делим на частоту таймера и переводим в часы. Это расчет дельты времени
  268.        
  269.       */
  270.       Speed = ((( CountImpulse / ImpulsePerRotate ) * LengthCircle) / (( TMP_CNT_OVF * 256 + TMP_TCNT) / 15625.0F)) * 0.036F;
  271.       factorial = (MaximumSpeedCalc / total_scale_leds);
  272.       speed_scale = floor(Speed / factorial);
  273.      
  274.       // Выводим текущие значения
  275.       print6digitDisplay((unsigned int) mileage);
  276.       print3digitDisplay(Speed);
  277.       printLedScale(speed_scale);
  278.   }
  279.  
  280.   return 0;
  281. }
Advertisement
Add Comment
Please, Sign In to add comment