#define ROWS 6
#define COLS 4
//Matrix of output pins
int ledMat[ROWS][COLS] = {
{22, 23, 24, 25},
{26, 27, 28, 29},
{30, 31, 32, 33},
{34, 35, 36, 37},
{38, 39, 40, 41},
{42, 43, 44, 45}
};
//state of pin matrix
bool ledStat[ROWS][COLS];
//position of cursor
int cursorRow = 0;
int cursorCol = 0;
//column that user has choosen
int column;
//pins of pushButtons
const int inputPin = 2;
const int zeroPin = 3;
const int jumpPin = 18;
const int stopPin = 19;
// state flags of pushbutton
volatile bool inputPressed = false;
volatile bool zeroPressed = false;
volatile bool jumpPressed = false;
volatile bool stopPressed = false;
// non-blocking variables
unsigned long previousBlinkMillis = 0;
bool blinkState = LOW;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
column = 0;
for (int row = 0; row < ROWS; row++)
{
for (int col = 0; col < COLS; col++)
{
pinMode(ledMat[row][col], OUTPUT);
ledStat[row][col] = 0;
}
}
pinMode(inputPin, INPUT_PULLUP);
pinMode(zeroPin, INPUT_PULLUP);
pinMode(jumpPin, INPUT_PULLUP);
pinMode(stopPin, INPUT_PULLUP);
// setting outside interrupt
attachInterrupt(digitalPinToInterrupt(inputPin), inputISR, FALLING);
attachInterrupt(digitalPinToInterrupt(zeroPin), zeroISR, FALLING);
attachInterrupt(digitalPinToInterrupt(jumpPin), jumpISR, FALLING);
attachInterrupt(digitalPinToInterrupt(stopPin), stopISR, FALLING);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.print("This system is used to fill in positions in a table!\n");
Serial.print("Please select a colum(1~4):\n");
while(Serial.available() == 0) {}
column = Serial.parseInt();
while (Serial.available()) { Serial.read();}//丢掉换行符
Serial.println(column);
cursorRow = 0; // 光标初始在第一行
cursorCol = 0; // 用户输入的列数转换为索引(0-3)
if (column == 0) { //如果输入的是字符char,也将结束循环,因为默认输入的是数字
Serial.println("No table to be filled in, code ending!");
while (true) {} // 结束程序,进入无限循环
}
if (column < 1 || column > 4)
{
Serial.println("Invalid input! Please enter a number between 1 and 4.");
Serial.println("_____________________________________________________");
delay(1000);
return; // 如果输入无效,直接返回,等待下一次输入
}
while(1)
{
updateLEDs(ledStat, cursorRow, cursorCol);
// 检测按键状态
if (inputPressed) {
inputPressed = false;
inputPB();
}
if (zeroPressed) {
zeroPressed = false;
zeroPB();
}
if (jumpPressed) {
jumpPressed = false;
jumpPB();
}
if (stopPressed) {
stopPressed = false;
stopPB();
}
Serial.println("Waiting for button press...");
delay(100);
}
}
/*========================================================================*/
//update LEDs' matrix state and postion of cursor
//all LED pins set as high or low according to the state matrix, except...
//the the led pin now choosed should blinking
void updateLEDs(bool ledStat[ROWS][COLS], int cursorRow, int cursorCol) {
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
if (row == cursorRow && col == cursorCol) {
// 光标LED闪烁
blink(ledMat[row][col], 300);
} else {
// 根据ledStat状态点亮或熄灭LED
digitalWrite(ledMat[row][col], ledStat[row][col] ? HIGH : LOW);
}
}
}
}
void blink(int led, long interval) {
unsigned long currentMillis = millis();
if (currentMillis - previousBlinkMillis >= interval) {
previousBlinkMillis = currentMillis;
blinkState = !blinkState;
digitalWrite(led, blinkState ? HIGH : LOW);
}
}
void inputPB() {
if (digitalRead(inputPin) == LOW) { // 检测按键是否按下(低电平有效)
delay(50); // 简单去抖动
if (digitalRead(inputPin) == LOW) { // 再次确认按键按下
// 1. 点亮当前光标位置的LED
ledStat[cursorRow][cursorCol] = 1;
// 2. 更新光标位置
if (cursorCol < column - 1) {
// 如果当前列小于用户输入的最大列数,光标移动到下一列
cursorCol++;
} else {
// 如果当前列是用户输入的最大列数,光标移动到下一行的第一列
cursorCol = 0;
cursorRow = (cursorRow + 1) % ROWS; // 如果已经是最后一行,回到第一行
}
Serial.println("Input button pressed: LED turned ON and cursor moved.");
while (digitalRead(inputPin) == LOW) {} // 等待按键释放
}
}
}
void zeroPB() {
if (digitalRead(zeroPin) == LOW) { // 检测按键是否按下(低电平有效)
delay(50); // 简单去抖动
if (digitalRead(zeroPin) == LOW) { // 再次确认按键按下
// 1. 熄灭当前光标位置的LED
ledStat[cursorRow][cursorCol] = 0;
// 2. 更新光标位置
if (cursorCol < column - 1) {
// 如果当前列小于用户输入的最大列数,光标移动到下一列
cursorCol++;
} else {
// 如果当前列是用户输入的最大列数,光标移动到下一行的第一列
cursorCol = 0;
cursorRow = (cursorRow + 1) % ROWS; // 如果已经是最后一行,回到第一行
}
Serial.println("Zero button pressed: LED turned OFF and cursor moved.");
while (digitalRead(zeroPin) == LOW) {} // 等待按键释放
}
}
}
void jumpPB() {
if (digitalRead(jumpPin) == LOW) { // 检测按键是否按下(低电平有效)
delay(50); // 简单去抖动
if (digitalRead(jumpPin) == LOW) { // 再次确认按键按下
// 更新光标位置到下一列的第一行
cursorCol = 0; // 移动到下一列,如果已经是最后一列,回到第一列
cursorRow = (cursorRow + 1) % ROWS; // 回到第一行
Serial.println("Jump button pressed: Cursor moved to next column.");
while (digitalRead(jumpPin) == LOW) {} // 等待按键释放
}
}
}
void stopPB() {
if (digitalRead(stopPin) == LOW) {
delay(50); // 简单去抖动
if (digitalRead(stopPin) == LOW) { // 确保按键真的被按下
Serial.println("Program stopped!");
delay(100); // 让消息有足够时间发送
cli(); // 关闭所有中断(彻底停住 Arduino)
while (true) {} // 进入死循环,程序完全停止
}
}
}
// 中断服务程序
void inputISR() {
inputPressed = true;
}
void zeroISR() {
zeroPressed = true;
}
void jumpISR() {
jumpPressed = true;
}
void stopISR() {
stopPressed = true;
}