Пятое упражнение по Arduino: Shift-Out, click button, digital{Read,Write}Fast
- Войдите на сайт для отправки комментариев
Втр, 31/12/2013 - 23:01
Мой пятый урок по изучению Arduino. Совершенствую навыки. Программа гоняет 8 светодиодов через сдвиговый регистр (демультиплексор) по 8 разным программам, две кнопки переключения программ. Самостоятельная (очередная) реализация способво записи и чтения цифровых пинов. Начал реализовывать обобщённый класс реагирующий на операции с кнопками. Комментарии приветствуются.
#include <Arduino.h> #define portWrite(set,mask,port) do {\ byte state = port;\ state &= ~mask;\ state |= set;\ port = state;\ } while(0) #define _digitalWriteFast(P, V) \ do {\ if((P) < 8)\ portWrite((V) << (P),_BV(P), PORTD);\ else if((P) < 14)\ portWrite((V) << ((P)-8),_BV((P)-8), PORTB);\ else\ portWrite((V) << ((P)-14),_BV((P)-14), PORTC);\ } while(0) #define portRead(bit,pin,ret) do {\ ret = pin;\ ret >>= bit;\ ret &= 1;\ } while(0) #define _digitalReadFast(P, ret) do {\ if((P) < 8)\ portRead((P), PIND, ret);\ else if((P) < 14)\ portRead((P)-8, PINB, ret);\ else\ portRead((P)-14, PINC, ret);\ } while(0) static inline byte digitalReadFast(byte pin) { byte ret; _digitalReadFast(pin, ret); return ret; } static inline void digitalWriteFast(byte pin, byte value) { _digitalWriteFast(pin, value); } #define datapin 2 #define clockpin 3 #define latchpin 4 #define next_button 13 #define prev_button 12 // We'll also declare a global variable for the data we're // sending to the shift register: void setup() { pinMode(datapin, OUTPUT); pinMode(clockpin, OUTPUT); pinMode(latchpin, OUTPUT); pinMode(next_button, INPUT); pinMode(prev_button, INPUT); } static byte shift_out_register = 0; void shift_out(byte latch, byte clock, byte data, byte value) { shift_out_register = value; digitalWriteFast(latch, 0); for (byte i = 0; i < 8; ++i) { digitalWriteFast(clock, 0); digitalWriteFast(data, value & 1); value >>= 1; digitalWriteFast(clock, 1); } digitalWriteFast(latch, 1); } void xset(byte latch, byte clock, byte data, byte num, byte value) { bitWrite(shift_out_register, num, value); shift_out(latch, clock, data, shift_out_register); } void binary_count() { static unsigned long next_turn = 0; static byte data = 0; unsigned long time = millis(); if (time > next_turn) { shift_out(latchpin, clockpin, datapin, data); data++; next_turn = time + 1000; } } void ping_pong(bool bounce = false) { static unsigned long next_turn = 0; static byte index = 0; unsigned long time = millis(); if (time > next_turn) { index &= 31; byte num = index >> 1; if (num > 7) num = (15 - num); if (index & 1) { shift_out(latchpin, clockpin, datapin, 0); next_turn = time - 1; } else { xset(latchpin, clockpin, datapin, num, 1); if (bounce) xset(latchpin, clockpin, datapin, 7 - num, 1); next_turn = time + 100; } ++index; } } void random_led() { static unsigned long next_turn = 0; static byte index = 0; unsigned long time = millis(); if (time > next_turn) { index &= 1; byte num = random(8); if (index & 1) { shift_out(latchpin, clockpin, datapin, 0); next_turn = time - 1; } else { xset(latchpin, clockpin, datapin, num, 1); next_turn = time + 100; } ++index; } } void one_after_another(bool original = false) { static unsigned long next_turn = 0; static byte index = 0; unsigned long time = millis(); if (time > next_turn) { index &= 15; byte num = index; byte show; if (num > 7) { if (original) { num = 15 - num; show = _BV(num+1) - 1; } else { num &= 7; show = ~(_BV(num+1) - 1); } } else { show = _BV(num+1) - 1; } shift_out(latchpin, clockpin, datapin, show); next_turn = time + 100; ++index; } } void one_on_at_a_time() { static unsigned long next_turn = 0; static byte index = 0; unsigned long time = millis(); if (time > next_turn) { index &= 7; shift_out(latchpin, clockpin, datapin, _BV(index)); next_turn = time + 100; ++index; } } void marquee_nd() { static unsigned long next_turn = 0; static byte index = 0; unsigned long time = millis(); if (time > next_turn) { index &= 3; shift_out(latchpin, clockpin, datapin, _BV(index) | _BV(index+4)); next_turn = time + 200; ++index; } } class Button { byte pin, prev_state; bool _clicked; void process_button() { byte val = digitalReadFast(pin); _clicked = false; if(val == 0 && prev_state == 1) { _clicked = true; } prev_state = val; } public: Button(byte _pin) : pin(_pin) { prev_state = 1; _clicked = false; } bool is_clicked() { process_button(); return _clicked; } }; Button b_next(next_button); Button b_prev(prev_button); byte current_alg = 2; void loop() { if (b_next.is_clicked()) { ++current_alg; shift_out(latchpin, clockpin, datapin, 0); } if (b_prev.is_clicked()) { --current_alg; shift_out(latchpin, clockpin, datapin, 0); } current_alg &= 7; switch (current_alg) { case 0: binary_count(); break; case 1: ping_pong(true); break; case 2: ping_pong(false); break; case 3: random_led(); break; case 4: one_after_another(false); break; case 5: one_after_another(true); break; case 6: one_on_at_a_time(); break; case 7: marquee_nd(); break; } } int main(void) { init(); setup(); //endless loop for (;;) { loop(); } return 0; }
Забыл добавить, что результат очень похож на программу для управления гирляндой :)