Пятое упражнение по 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;
}
Забыл добавить, что результат очень похож на программу для управления гирляндой :)