Циклически бегущие огни без ассемблера. Код (C++): inline uint8_t ROL(uint8_t x) { return((x&0x80)>>7)|(x<<1); } static const uint8_t bit_pin [] = {3, 4, 5, 6, 7, 8, 9, 10 }; void setup() { // Serial.begin(250000); // while(!Serial){}; // Serial.println("Staring..."); // DDRD = 0b11111111; for( int8_t i = sizeof(bit_pin); i--; ) { pinMode(bit_pin[i], OUTPUT); } } void loop() { static uint8_t MyVar = 0b00001011; // PORTD = MyVar; uint8_t v(MyVar); for( int8_t i = sizeof(bit_pin); i--; ) { digitalWrite(bit_pin[i], v & 0b1 ? HIGH : LOW ); v >>= 1; } MyVar = ROL(MyVar); delay(200); }
Код (C++): // Arduino UNO pins 0 - 7 inline uint8_t ROL(uint8_t x) { return((x&0x80)>>7)|(x<<1); } обзову каждый бит буквой (буква может принимать значение 0 или 1), чтобы видно было куда какой бит попадает: пусть x = abcdefgh; x&0x80 = a0000000; побитовое и. оставили старший бит, который нужно закольцевать (x&0x80)>>7 = 0000000a; сдвиг вправо на 7 бит, закольцевали старший бит (x<<1) = bcdefgh0; собственно сдвиг влево. младший бит замещен 0, старший потерян ((x&0x80)>>7)|(x<<1) = bcdefgha; побитовое или воссоединяет закольцованный бит a со сдвинутой цепочкой bcdefgh
Я так понял в конечном счете двигать нужно будет символы а не битики. Следовательно это код вообще не подойдет. Вам нужен "кольцевой буфер".
Ну да, есть двумерный массив с данными температуры и времени его то мне и хочется сдвигать. Примерно вот так сделать планирую, если получится...) https://goo.gl/photos/uh8BhSByTi6hGJ4x8
Циклический сдвиг битов реализован аппаратно в процессоре, но этот блок процессора не умеет двигать элементы массива. Поэтому это совсем другая задача. Сдвигать элементы массива то же не целесообразно так как это вызывает большую нагрузку на процессор. Например если у Вас в строке 20 символов - нужно будет 20 перемещений. Гораздо эффективнее хранить номер элемента массива которой будет выводится в самой левой позиции дисплея. Аналогичная технология переменятся в кольцевых буферах: - буфер клавиатура - буфер данных RS232
Обычно не массив двигают, а точку входа в него. Каждый раз отправляя данные на экран вы начинаете чтение массива с индекса j = i+1. Только нужно позаботится о том, чтобы после чтения последнего элемента, итератор переходил на элемент 0.
Можно даже и не запоминать, просто сдвинуть по очереди все 4 символа, а потом по такому же принципу отобразить температуру, только теперь символы должны появляться.
Примерно так: Код (C++): class Iterator { public: Iterator( uint8_t i_start): pos(i_start) { if ( size <= pos ) pos = 0; } Iterator& operator++() { if ( size <= ++pos ) pos = 0; return *this; } // Iterator operator++(uint8_t) { Iterator res(*this); operator++(); return res; } operator uint8_t() const { return pos; } private: static const uint8_t size; uint8_t pos; }; const uint8_t Iterator::size = ASZ; .... arr[ASZ]; // Строка для вывода в окно. loop { static Iterator pos(0); // Позиция окна вывода в строке arr. SetPos(0); // позиция печати for ( Iterator i(pos), uint8_t n(5); --n; ++i ) { // Выводим в окно из (5-1)=4х символов PrintCell(arr[i]); // печать символа и сдвиг в следующую позицию } ++pos; // Продвигаем окно delay(500); }
Проверить не начем Код (C++): #define LEN 10 char st[] = {'LCD 123456789'}; int pos; void setup() { pos = 0; Serial.begin(9600); } void loop() { for(int i = pos; i++ ; i < LEN) Serial.print(st[i]); Serial.println(' '); pos++; if (pos >= LEN) pos = 0; delay(500); }
Так проще, но это не циклический сдвиг. И логика циклического счётчика размазана по коду, а не собрана в классе. В цикл for(int i = pos; i++ ; i < LEN) нужно добавить размер "окна". На реальном экране "лишние" символы могут печататься и засорять изображение. Имитацию цикла можно получить повторением начала строки в конце. К стати еще вопрос, нужно чтобы строка выползала на пустой экран? Между циклами должен быть пустой экран?
Ну да, срорее всего нужен. Там ещё такой нюанс есть... В момент чтения температуры с датчика индикатор заметно мерцал, Решил, я эту проблему считыванием показаний раз в минуту Код (C++): if (sec==0)dps.getTemperature(&Temperature); И отключением всех разрядов на момент чтения Код (C++): if (switchTime==0) PORTB |= B00001111 Вот и получается, когда последний символ скроется нужно будет отключить разряды, а потом начинать выводить температуру... Я вот уже думаю, может зря я это затеял.....?
Согласен, всё таки основной скетч хоть переписывал несколько раз подряд, всё таки добился нужного функционала)) Конечно, надо пытаться задумку реализовать - может чего и получится...
Теперь вы умеете возводить двойку в степень Этот код только для бегущих огней подходит. Код (C++): DDRD = 0xFF; PORTD = MyVar;