Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define clock 13 // нога 13
- #define data 12 // нога 12
- #define latch_bin 0b11111011 // нога 10 (порт В2) двоичный
- #define latchbin 0b00000100 // нога 10 (порт В2) инвертированный
- #define stb 9 // 0b11111101 // нога 9 (порт В1)
- // знакогенератор
- const unsigned long symbol[28] = {122885, 49152, 106502, 122882, 49155, 90115, 90119, 114688, 122887, 122883, 114695, 24583, 73733, 57350, 73735, 65543, 49159, 5, 57348, 8197, 16390, 98311, 6, 8199, 57349, 24580, 57347};
- const unsigned long pos[11] = {0, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 262144}; //};
- unsigned long video0[11] = {0}; // видеобуфер банк 0
- unsigned long video1[11] = {0}; // видеобуфер банк 1
- volatile byte j = 10; // счётчик разрядов индикатора для вывода
- volatile boolean v_buffer = 0; // текущий банк видеобуфера
- boolean switch_bank = 0; // индикатор окончания преобразования
- //----------------------настройка частоты обновления индикатора---------------------------------------
- #define Prescaler_8b (1<<CS22)|(1<<CS21)|(1<<CS20) // делитель тактовой частоты микроконтроллера на 1024 для таймера 2
- // CS22 CS21 CS20 Описание для Atmega 328P
- // 0 0 0 Нет синхронизации. Таймер-счетчик 0 оставлен. 0 0 1 /1 (без предделения) 0 1 0 /8 , 0 1 1 /32 , 1 0 0 /64 , 1 0 1 /128 , 1 1 0 /256 , 1 1 1 /1024
- #define T2_count 16
- // Верхняя граница счета. Диапазон от 0 до 255. (16 = по расчётам 488 раз в секунду)
- // Частота прерываний будет = Fclk/(2*N*OCR2A)
- // где N - коэф. предделителя (1, 8, 32, 64, 128, 256 или 1024)
- // можно попробовать поставить подстроечный резистор и регулировать частоту обновления индикатора
- //---------------------------------------------------------------------------------------------------
- ISR(TIMER2_COMPA_vect) { // Обработчик прерывания таймера 2. За одно прерывание показываем десять символов
- switch (v_buffer) { // выбираем, какой из банков видеопамяти текущий
- case 0:
- PORTB = PORTB & latch_bin; // "защёлку" вниз
- shiftOut(data, clock, MSBFIRST, video0[j] >> 24); // проталкиваем самые старшие биты из банка "0"
- shiftOut(data, clock, MSBFIRST, video0[j] >> 16); // следующие 8 бит
- shiftOut(data, clock, MSBFIRST, video0[j] >> 8); // следующие 8 бит
- shiftOut(data, clock, MSBFIRST, video0[j]); // теперь пришёл черёд младшеньких 8 бит
- PORTB = PORTB | latchbin; // "защёлку" вверх
- j++; // переходим к следующему разряду в очередном прерывании по таймеру
- if ( j > 10) {
- j = 1; // если все 10 уже отобразили, начинаем сначала
- if ( switch_bank == 1) v_buffer = 1; // если новое число уже готово, то в следующий раз будем отображать его
- }
- break;
- case 1:
- PORTB = PORTB & latch_bin; // "защёлку" вниз
- shiftOut(data, clock, MSBFIRST, video1[j] >> 24); // проталкиваем самые старшие биты из банка "1"
- shiftOut(data, clock, MSBFIRST, video1[j] >> 16); // следующие 8 бит
- shiftOut(data, clock, MSBFIRST, video1[j] >> 8); // следующие 8 бит
- shiftOut(data, clock, MSBFIRST, video1[j]); // теперь пришёл черёд младшеньких 8 бит
- PORTB = PORTB | latchbin; // "защёлку" вверх
- j++; // переходим к следующему разряду в очередном прерывании по таймеру
- if ( j > 10) {
- j = 1; // если все 10 уже отобразили, начинаем сначала
- if ( switch_bank == 0) v_buffer = 0; // если новое число уже готово, то в следующий раз будем отображать его
- }
- break;
- }
- }
- //----------------------функция преобразования числа в значения разрядов------------------------------
- void translate(unsigned long timestat) { //преобразование большого числа для отображения по разрядам
- boolean v_nul = 0; // какие символы "ведущего нуля" не надо отображать
- byte r = 0; // отображаемый символ в каждом разряде
- switch (v_buffer) { // выбираем для работы "свободный" банк видеобуфера
- case 1:
- memset(video0, 0, 11); // обнуление массива видеобуфера video0[11]
- r = (timestat / 1000000000) % 10; // делим на миллиард потом остаток от деления на 10
- if (r) { // если "r" не равен нулю, то
- video0[10] = symbol[r] | pos[10]; // записываем в видеобуфер полученный символ и его позицию на дисплее
- v_nul = 1; // если символ не "0", то установим флаг, чтобы следующие нули не потерялись.
- }
- r = (timestat / 100000000) % 10; // делим на сто миллионов потом остаток от деления на 10
- if (r != 0 || v_nul != 0) { // если "r" не равен нулю или предыдущий символ не равен "0", то
- video0[9] = symbol[r] | pos[9]; // записываем в видеобуфер полученный символ и его позицию на дисплее
- v_nul = 1; // если символ не "0", то установим флаг, чтобы следующие нули не потерялись.
- }
- r = (timestat / 10000000) % 10; // всё тоже самое повторяем ещё много раз
- if (r != 0 || v_nul != 0) {
- video0[8] = symbol[r] | pos[8];
- v_nul = 1;
- }
- r = (timestat / 1000000) % 10;
- if (r != 0 || v_nul != 0) {
- video0[7] = symbol[r] | pos[7];
- v_nul = 1;
- }
- r = (timestat / 100000) % 10;
- if (r != 0 || v_nul != 0) {
- video0[6] = symbol[r] | pos[6];
- v_nul = 1;
- }
- r = (timestat / 10000) % 10;
- if (r != 0 || v_nul != 0) {
- video0[5] = symbol[r] | pos[5];
- v_nul = 1;
- }
- r = (timestat / 1000) % 10;
- if (r != 0 || v_nul != 0) {
- video0[4] = symbol[r] | pos[4];
- v_nul = 1;
- }
- r = (timestat / 100) % 10;
- if (r != 0 || v_nul != 0) {
- video0[3] = symbol[r] | pos[3];
- v_nul = 1;
- }
- r = (timestat / 10) % 10;
- if (r != 0 || v_nul != 0) {
- video0[2] = symbol[r] | pos[2];
- v_nul = 1;
- }
- r = timestat % 10;
- video0[1] = symbol[r] | pos[1];
- switch_bank = 0; // наш видеобуфер готов, делаем его активным для отображения
- break; // на этом закончим
- case 0:
- memset(video1, 0, 11); // обнуление массива видеобуфера video1[11]
- r = (timestat / 1000000000) % 10; // делим на миллиард потом остаток от деления на 10
- if (r) { // если "r" не равен нулю, то
- video1[10] = symbol[r] | pos[10]; // записываем в видеобуфер полученный символ и его позицию на дисплее
- v_nul = 1; // если символ не "0", то установим флаг, чтобы следующие нули не потерялись.
- }
- r = (timestat / 100000000) % 10; // делим на сто миллионов потом остаток от деления на 10
- if (r != 0 || v_nul != 0) { // если "r" не равен нулю или предыдущий символ не равен "0", то
- video1[9] = symbol[r] | pos[9]; // записываем в видеобуфер полученный символ и его позицию на дисплее
- v_nul = 1; // если символ не "0", то установим флаг, чтобы следующие нули не потерялись.
- }
- r = (timestat / 10000000) % 10; // всё тоже самое повторяем ещё много раз
- if (r != 0 || v_nul != 0) {
- video1[8] = symbol[r] | pos[8];
- v_nul = 1;
- }
- r = (timestat / 1000000) % 10;
- if (r != 0 || v_nul != 0) {
- video1[7] = symbol[r] | pos[7];
- v_nul = 1;
- }
- r = (timestat / 100000) % 10;
- if (r != 0 || v_nul != 0) {
- video1[6] = symbol[r] | pos[6];
- v_nul = 1;
- }
- r = (timestat / 10000) % 10;
- if (r != 0 || v_nul != 0) {
- video1[5] = symbol[r] | pos[5];
- v_nul = 1;
- }
- r = (timestat / 1000) % 10;
- if (r != 0 || v_nul != 0) {
- video1[4] = symbol[r] | pos[4];
- v_nul = 1;
- }
- r = (timestat / 100) % 10;
- if (r != 0 || v_nul != 0) {
- video1[3] = symbol[r] | pos[3];
- v_nul = 1;
- }
- r = (timestat / 10) % 10;
- if (r != 0 || v_nul != 0) {
- video1[2] = symbol[r] | pos[2];
- v_nul = 1;
- }
- r = timestat % 10;
- video1[1] = symbol[r] | pos[1];
- switch_bank = 1; // наш видеобуфер готов, делаем его активным для отображения
- break; // на этом закончим
- }
- }
- //----------------------------------------------------------------------------------
- void setup() {
- pinMode(stb, OUTPUT); // режим выхода
- TCCR2B |= (1 << WGM22); // Режим CTC (сброс по совпадению) для таймера_2
- TCCR2B |= Prescaler_8b; // и предделитель таймера_2
- TIMSK2 |= (1 << OCIE2A); // Разрешить прерывание по совпадению в канале "А"
- OCR2A = T2_count; // дополнительный делитель частоты. Частота прерываний будет = Fclk/(2*N*OCR2A)
- sei (); // Глобально разрешить прерывания
- pinMode(clock, OUTPUT); // режим выхода
- pinMode(data, OUTPUT); // режим выхода
- DDRB = DDRB | latchbin; // режим выхода
- //translate(1234567890); // тестовый сигнал
- }
- //-----------------------------------------------------------------------------------
- void loop() {
- translate(millis() / 10);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement