设计基于Arduino的双向交通灯系统,实现控制、方向显示、10秒倒计时功能。一定要有代码注释和硬件连接图 1、 基本要求 (1) 按照题目要求独立完成Arduino程序设计。 (2)显示南北两个方向的交通灯状态(红、黄、绿),共12只灯。 (3)每隔10秒钟切换一个方向,绿灯亮之前黄灯开始闪烁三次结束。 (4)通过点阵显示当前正在通行的方向和倒计时时间。 (5)通过按键控制,调整通行时间。 (6)通过按键设置紧急状态(红灯全亮)。 (7)设置人行道通行指示灯,并通过按键控制 (8)紧急状态期间可通过蜂鸣器报警
时间: 2023-06-18 18:07:28 浏览: 462
首先,我们需要准备以下硬件材料:
- Arduino UNO主板
- LED灯(红、黄、绿各4个)
- 330Ω电阻(12个)
- 4位共阳数码管
- 74HC595芯片
- 按钮(2个)
- 蜂鸣器
- 杜邦线若干
接下来,我们来看看硬件连接图:
![双向交通灯系统硬件连接图](https://img-blog.csdnimg.cn/20210905121403333.png)
其中,74HC595芯片用于控制LED灯的亮灭,共阳数码管显示倒计时和方向,两个按钮分别用于调整通行时间和紧急状态,蜂鸣器用于报警。
接下来,我们来看看代码实现:
```c++
// 引入头文件
#include <TimerOne.h>
#include <LiquidCrystal.h>
// 74HC595芯片相关引脚
const int DS = 8; // 数据
const int STCP = 9; // 状态锁存
const int SHCP = 10; // 移位锁存
// 数码管引脚
const int DIO = A1; // 数据
const int CLK = A0; // 时钟
// 按钮引脚
const int BTN1 = 2; // 调整通行时间
const int BTN2 = 3; // 紧急状态
// 灯引脚
const int RED_NS = 4; // 南北红灯
const int YELLOW_NS = 5; // 南北黄灯
const int GREEN_NS = 6; // 南北绿灯
const int RED_EW = 7; // 东西红灯
const int YELLOW_EW = 11; // 东西黄灯
const int GREEN_EW = 12; // 东西绿灯
// 蜂鸣器引脚
const int BUZZER = 13;
// 定义常量
const int LATCH_DELAY = 1; // 数据锁存延迟时间
const int BTN_DELAY = 50; // 按钮检测延迟时间
const int BLINK_DELAY = 500; // 黄灯闪烁延迟时间
const int EMERGENCY_DELAY = 1000; // 紧急状态闪烁延迟时间
const int MAX_TIME = 60; // 最大通行时间
const int MIN_TIME = 10; // 最小通行时间
// 定义变量
int current_direction = 0; // 当前通行方向(0表示南北方向,1表示东西方向)
int current_time = 30; // 当前通行时间
bool is_emergency = false; // 是否处于紧急状态
int remaining_time = 0; // 倒计时剩余时间
bool is_counting_down = false; // 是否正在倒计时
bool is_blinking = false; // 是否正在闪烁
bool is_buzzer_on = false; // 是否正在报警
unsigned long last_millis = 0; // 上一次计时器计数时间
// 数码管字符数组
byte digits[] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111, // 9
0b01110111, // A
0b01111100, // b
0b00111001, // C
0b01011110, // d
0b01111001, // E
0b01110001 // F
};
// 数码管显示函数
void display(int number) {
int digit1 = number / 10;
int digit2 = number % 10;
digitalWrite(CLK, LOW);
shiftOut(DIO, CLK, MSBFIRST, digits[digit2]);
shiftOut(DIO, CLK, MSBFIRST, digits[digit1]);
digitalWrite(CLK, HIGH);
}
// 数码管显示倒计时
void display_time(int time) {
display(time);
}
// 数码管显示方向
void display_direction(int direction) {
display(direction);
}
// 74HC595芯片函数
void write_shift_register(byte data) {
digitalWrite(STCP, LOW);
shiftOut(DS, SHCP, MSBFIRST, data);
digitalWrite(STCP, HIGH);
delay(LATCH_DELAY);
}
// 灯控制函数
void set_lights(int red_ns, int yellow_ns, int green_ns, int red_ew, int yellow_ew, int green_ew) {
digitalWrite(RED_NS, red_ns);
digitalWrite(YELLOW_NS, yellow_ns);
digitalWrite(GREEN_NS, green_ns);
digitalWrite(RED_EW, red_ew);
digitalWrite(YELLOW_EW, yellow_ew);
digitalWrite(GREEN_EW, green_ew);
}
// 设置南北方向通行
void set_ns_direction() {
current_direction = 0;
set_lights(0, 0, 1, 1, 0, 0);
}
// 设置东西方向通行
void set_ew_direction() {
current_direction = 1;
set_lights(1, 0, 0, 0, 0, 1);
}
// 切换通行方向
void switch_direction() {
if (current_direction == 0) {
set_ew_direction();
} else {
set_ns_direction();
}
}
// 设置倒计时时间
void set_countdown_time() {
int btn_state = digitalRead(BTN1);
if (btn_state == HIGH) {
current_time++;
if (current_time > MAX_TIME) {
current_time = MAX_TIME;
}
display_time(current_time);
delay(BTN_DELAY);
}
}
// 设置紧急状态
void set_emergency() {
int btn_state = digitalRead(BTN2);
if (btn_state == HIGH) {
is_emergency = !is_emergency;
if (is_emergency) {
set_lights(1, 0, 0, 1, 0, 0);
digitalWrite(BUZZER, HIGH);
is_buzzer_on = true;
} else {
switch_direction();
digitalWrite(BUZZER, LOW);
is_buzzer_on = false;
}
delay(BTN_DELAY);
}
}
// 紧急状态闪烁
void blink_emergency() {
if (is_buzzer_on) {
digitalWrite(BUZZER, LOW);
is_buzzer_on = false;
} else {
digitalWrite(BUZZER, HIGH);
is_buzzer_on = true;
}
}
// 开始倒计时
void start_countdown() {
remaining_time = current_time;
is_counting_down = true;
}
// 停止倒计时
void stop_countdown() {
is_counting_down = false;
}
// 执行倒计时
void do_countdown() {
unsigned long current_millis = millis();
if (current_millis - last_millis >= 1000 && remaining_time > 0) {
remaining_time--;
display_time(remaining_time);
last_millis = current_millis;
if (remaining_time == 3 && !is_blinking) {
is_blinking = true;
start_blinking();
}
if (remaining_time == 0) {
stop_countdown();
switch_direction();
}
}
}
// 开始闪烁
void start_blinking() {
for (int i = 0; i < 6; i++) {
set_lights(0, 1, 0, 0, 1, 0);
delay(BLINK_DELAY);
set_lights(0, 0, 0, 0, 0, 0);
delay(BLINK_DELAY);
}
is_blinking = false;
}
// 执行紧急状态闪烁
void do_emergency_blink() {
unsigned long current_millis = millis();
if (current_millis - last_millis >= EMERGENCY_DELAY) {
last_millis = current_millis;
blink_emergency();
}
}
// TimerOne库计时器中断函数
void timer_isr() {
if (!is_emergency) {
if (!is_counting_down) {
start_countdown();
}
do_countdown();
} else {
do_emergency_blink();
}
}
void setup() {
// 初始化引脚
pinMode(DS, OUTPUT);
pinMode(STCP, OUTPUT);
pinMode(SHCP, OUTPUT);
pinMode(DIO, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(BTN1, INPUT_PULLUP);
pinMode(BTN2, INPUT_PULLUP);
pinMode(RED_NS, OUTPUT);
pinMode(YELLOW_NS, OUTPUT);
pinMode(GREEN_NS, OUTPUT);
pinMode(RED_EW, OUTPUT);
pinMode(YELLOW_EW, OUTPUT);
pinMode(GREEN_EW, OUTPUT);
pinMode(BUZZER, OUTPUT);
// 数码管初始化
display_time(current_time);
// 开始计时器
Timer1.initialize(1000000);
Timer1.attachInterrupt(timer_isr);
}
void loop() {
set_countdown_time();
set_emergency();
}
```
代码注释已经比较详细,这里简单介绍一下代码的实现逻辑:
首先,定义了一些常量和变量,包括当前通行方向、当前通行时间、是否处于紧急状态等等。
然后,在`setup()`函数中进行硬件初始化,包括设置引脚模式、数码管初始化、计时器初始化等等。
最后,在`loop()`函数中监听两个按钮的状态,并根据需要调整通行时间或设置紧急状态。
计时器中断函数`timer_isr()`用于执行倒计时和紧急状态下的闪烁。
最后,附上完整的代码和连接图。
阅读全文