#include <Stepper.h>
//两组红绿灯亮起的模式为G1-R2,Y1-R2,R1-G2,R1-Y2。共存在4个节点,在周期结束时,应将计时器清零,重新开始下一轮周期
#define PIN_G1 5
#define PIN_Y1 4
#define PIN_R1 3
#define PIN_G2 8
#define PIN_Y2 7
#define PIN_R2 6
long G1_period = 20000;
long G2_period = 15000;
const int YELLOW_PERIOD = 3000;
int state = 1;
#define PIN_SHCP 10 //时钟信号(SCK)
#define PIN_STCP 9 //锁存信号(RCK)
#define PIN_DS A5 //串行数据口(SI)
long currentTime;
long previousTime;
const long INTERVAL = 500;//黄灯闪烁的周期。500ms亮起,500ms熄灭
int leftTime;//倒计时的时间。单位为s
#define PIN_DIG1 12
#define PIN_DIG2 11
const int FRESH_FREQUENCY = 25;
bool flag_tens_digit = true;
int counter1;
int counter2;
#define PIN_BUTTON A6
const int stepsPerRevolution = 200;
Stepper myStepper(stepsPerRevolution, A4, A3, A2, A1);
bool stepper_clock = true;
long button_time1 = 0;
long button_time2 = 0;
const long BUTTON_INTERVAL = 3000;
//准备所有针脚
void initPins() {
pinMode(PIN_G1, OUTPUT);
pinMode(PIN_Y1, OUTPUT);
pinMode(PIN_R1, OUTPUT);
pinMode(PIN_G2, OUTPUT);
pinMode(PIN_Y2, OUTPUT);
pinMode(PIN_R2, OUTPUT);
pinMode(PIN_SHCP, OUTPUT);
pinMode(PIN_STCP, OUTPUT);
pinMode(PIN_DS, OUTPUT);
pinMode(PIN_DIG1, OUTPUT);
pinMode(PIN_DIG2, OUTPUT);
pinMode(PIN_BUTTON, INPUT);
}
int8_t getCharByte(int c) {
switch (c) {
case 0:
return 0B01111110;
case 1:
return 0B00110000;
case 2:
return 0B01101101;
case 3:
return 0B01111001;
case 4:
return 0B00110011;
case 5:
return 0B01011011;
case 6:
return 0B01011111;
case 7:
return 0B01110000;
case 8:
return 0B01111111;
case 9:
return 0B01111011;
default:
return 0B10000000;
}
}
//使用74HC595输出数字字符
//char1:横向计时器数码管上的数字
//char2: 纵向计时器数码管上的数字
void displayChar(int char1, int char2) {
digitalWrite(PIN_STCP, LOW); //锁存信号低电平,此时可以写入数据
shiftOut(PIN_DS, PIN_SHCP, LSBFIRST, getCharByte(char1));
shiftOut(PIN_DS, PIN_SHCP, LSBFIRST, getCharByte(char2));
digitalWrite(PIN_STCP, HIGH); //拉高锁存信号,将数据写入锁存器.OE管脚一直接在低电平上,一直输出数据
}
void setup() {
initPins();
currentTime = millis();
previousTime = currentTime;
myStepper.setSpeed(60);
//时钟
cli();
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 16000000 / 1024 / FRESH_FREQUENCY - 1;
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS12) | (1 << CS10); // 1024 prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
sei();
}
ISR(TIMER1_COMPA_vect) {
currentTime = millis();
int running_time;
if (currentTime - previousTime <= G1_period)
state = 1;
else if (currentTime - previousTime <= G1_period + YELLOW_PERIOD)
state = 2;
else if (currentTime - previousTime <= G1_period + YELLOW_PERIOD + G2_period)
state = 3;
else if (currentTime - previousTime <= G1_period + 2 * YELLOW_PERIOD + G2_period)
state = 4;
else {
previousTime = currentTime;
digitalWrite(PIN_Y1, LOW);
digitalWrite(PIN_R1, LOW);
digitalWrite(PIN_Y2, LOW);
digitalWrite(PIN_G2, LOW);
digitalWrite(PIN_G1, LOW);
digitalWrite(PIN_R2, LOW);
}
switch (state) {
case 1:
digitalWrite(PIN_Y1, LOW);
digitalWrite(PIN_R1, LOW);
digitalWrite(PIN_Y2, LOW);
digitalWrite(PIN_G2, LOW);
digitalWrite(PIN_G1, HIGH);
digitalWrite(PIN_R2, HIGH);
leftTime = (G1_period - currentTime + previousTime) / 1000 + 1;
counter1 = leftTime;
counter2 = leftTime + YELLOW_PERIOD / 1000;
break;
case 2:
digitalWrite(PIN_G1, LOW);
digitalWrite(PIN_R1, LOW);
digitalWrite(PIN_Y2, LOW);
digitalWrite(PIN_G2, LOW);
digitalWrite(PIN_R2, HIGH);
//实现Y1的闪烁
running_time = currentTime - previousTime - G1_period;
if ((running_time / INTERVAL) % 2 == 0) //亮灯周期
digitalWrite(PIN_Y1, HIGH);
else
digitalWrite(PIN_Y1, LOW);
leftTime = (G1_period + YELLOW_PERIOD - currentTime + previousTime) / 1000 + 1;
counter1 = leftTime;
counter2 = leftTime;
break;
case 3:
digitalWrite(PIN_Y1, LOW);
digitalWrite(PIN_G1, LOW);
digitalWrite(PIN_Y2, LOW);
digitalWrite(PIN_R2, LOW);
digitalWrite(PIN_R1, HIGH);
digitalWrite(PIN_G2, HIGH);
leftTime = (G1_period + YELLOW_PERIOD + G2_period - currentTime + previousTime) / 1000 + 1;
counter1 = leftTime + YELLOW_PERIOD / 1000;
counter2 = leftTime;
break;
case 4:
digitalWrite(PIN_Y1, LOW);
digitalWrite(PIN_G1, LOW);
digitalWrite(PIN_R2, LOW);
digitalWrite(PIN_G2, LOW);
digitalWrite(PIN_R1, HIGH);
//实现Y2的闪烁
running_time = currentTime - previousTime - G1_period - YELLOW_PERIOD - G2_period;
if ((running_time / INTERVAL) % 2 == 0) //亮灯周期
digitalWrite(PIN_Y2, HIGH);
else
digitalWrite(PIN_Y2, LOW);
leftTime = (G1_period + 2 * YELLOW_PERIOD + G2_period - currentTime + previousTime) / 1000 + 1;
counter1 = leftTime;
counter2 = leftTime;
break;
}
if (flag_tens_digit) {
digitalWrite(PIN_DIG2, HIGH);
displayChar(counter1 / 10, counter2 / 10);
digitalWrite(PIN_DIG1, LOW);
}
else {
digitalWrite(PIN_DIG1, HIGH);
displayChar(counter1 % 10, counter2 % 10);
digitalWrite(PIN_DIG2, LOW);
}
flag_tens_digit = !flag_tens_digit;
// handleBluetoothEvent();
}
void loop() {
if (analogRead(PIN_BUTTON) < 50) {
button_time2 = millis();
if (button_time2 - button_time1 >= BUTTON_INTERVAL) {
if (stepper_clock)
myStepper.step(stepsPerRevolution / 4);
else
myStepper.step(-stepsPerRevolution / 4);
stepper_clock = !stepper_clock;
button_time1 = button_time2;
}
}
}