要求:
1.一个二位数码管显示时间,红黄绿3个LED灯指示通行状态,实现一个路口一个方向三个灯的定时变换,变换时间自行决定。
2.三个按钮设定时间。修改、加、减
例如:按一下修改键,显示及修改绿灯时间(可闪烁显示时间表示其处于编辑状态),再按一下显示及修改黄灯时间,再按一下显示及修改红灯时间,再按一下退出修改模式。
#include <reg51.h>
#define LED_RED P0_0
#define LED_YELLOW P0_1
#define LED_GREEN P0_2
#define DIGIT_PORT P2
unsigned char digit[] = {
0xC0, // 0
0xF9, // 1
0xA4, // 2
0xB0, // 3
0x99, // 4
0x92, // 5
0x82, // 6
0xF8, // 7
0x80, // 8
0x90 // 9
};
void delay(unsigned int ms) {
unsigned int i, j;
for (i = 0; i < ms; i++)
for (j = 0; j < 1000; j++);
}
void displayDigit(unsigned char num) {
DIGIT_PORT = digit[num / 10];
LED_RED = 0; // 红灯灭
LED_YELLOW = 0; // 黄灯灭
LED_GREEN = 1; // 绿灯亮
delay(1000); // 显示1秒
DIGIT_PORT = digit[num % 10];
LED_RED = 0; // 红灯灭
LED_YELLOW = 1; // 黄灯亮
LED_GREEN = 0; // 绿灯灭
delay(1000); // 显示1秒
}
void main() {
unsigned char minutes = 3;
unsigned char seconds = 0;
while (1) {
displayDigit(minutes);
displayDigit(seconds);
if (P3_4 == 0) { // 按钮1按下,修改绿灯时间
while (P3_4 == 0); // 等待按钮1松开
// 绿灯时间修改逻辑
}
if (P3_5 == 0) { // 按钮2按下,修改黄灯时间
while (P3_5 == 0); // 等待按钮2松开
// 黄灯时间修改逻辑
}
if (P3_6 == 0) { // 按钮3按下,修改红灯时间
while (P3_6 == 0); // 等待按钮3松开
// 红灯时间修改逻辑
}
seconds++; // 每秒加一
if (seconds == 60) { // 每分钟加一
minutes++;
seconds = 0;
}
if (minutes == 99) { // 限制最大时间为99分钟
minutes = 0;
seconds = 0;
}
}
}
【以下回答由 GPT 生成】
我想使用51单片机来控制交通信号灯的定时变换。具体要求如下: 1. 通过一个二位数码管显示时间,用红黄绿3个LED灯指示交通信号灯的通行状态。 2. 在一个路口的一个方向上,实现三个灯(红灯、黄灯、绿灯)的定时变换,并且变换时间可以自行设定。
我期望实现以下功能: 1. 通过按键来设置每个灯的时间。需要实现修改、加、减功能。 - 按下修改键时,二位数码管应该显示当前编辑的灯的时间,并进入编辑状态。 - 继续按下修改键时,应该依次显示并修改黄灯时间、红灯时间。 - 再次按下修改键时,退出编辑模式。 2. 绿灯、黄灯、红灯分别对应的时长可以根据需求进行调整。
以下是解决该问题的步骤和代码实现。
首先,我们需要准备以下硬件组件: 1. 51单片机开发板 2. 二位数码管模块 3. LED模块(红、黄、绿) 4. 按键模块 5. 连接线
使用Keil或其他51单片机开发环境创建一个新的工程,然后编写以下代码来实现功能要求。
#include <reg51.h>
// 定义数码管段选端口和共阳极位选端口
sbit digit1 = P2^4;
sbit digit2 = P2^5;
sbit COM1 = P2^2;
sbit COM2 = P2^3;
// 定义LED灯端口
sbit redLED = P1^0;
sbit yellowLED = P1^1;
sbit greenLED = P1^2;
// 全局变量
unsigned char displayBuf[2]; // 数码管显示缓存
unsigned char time[3]; // 三个灯的时间设置(单位:秒)
unsigned char lightIndex; // 当前编辑的灯的索引
unsigned char editMode; // 编辑模式(0-退出, 1-设置时间, 2-加, 3-减)
// 数码管段选编码
const unsigned char segCode[10] = {
0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90
};
// 延时函数
void delay(unsigned int t) {
unsigned int i, j;
for(i = t; i > 0; i--)
for(j = 110; j > 0; j--);
}
// 数码管显示
void display() {
digit1 = 0;
P0 = segCode[displayBuf[0]];
digit1 = 1;
digit2 = 0;
P0 = segCode[displayBuf[1]];
digit2 = 1;
}
// 设置当前编辑的灯的时间
void setTime() {
unsigned char i;
displayBuf[0] = 0;
displayBuf[1] = time[lightIndex] / 10;
display();
delay(1000);
displayBuf[0] = time[lightIndex] / 10;
displayBuf[1] = time[lightIndex] % 10;
display();
delay(1000);
while(editMode == 1) {
if(time[lightIndex] == 0) {
time[lightIndex] = 99;
}
displayBuf[0] = displayBuf[1];
displayBuf[1] = time[lightIndex] / 10;
display();
delay(1000);
displayBuf[0] = displayBuf[1];
displayBuf[1] = time[lightIndex] % 10;
display();
delay(1000);
}
for(i = 0; i < 2; i++) {
displayBuf[0] = 0;
displayBuf[1] = 0;
display();
delay(1000);
displayBuf[0] = 1;
displayBuf[1] = 2;
display();
delay(1000);
}
}
// 修改时间
void modifyTime() {
switch(lightIndex) {
case 0:
displayBuf[0] = 0;
displayBuf[1] = time[lightIndex] / 10;
display();
delay(1000);
displayBuf[0] = time[lightIndex] / 10;
displayBuf[1] = time[lightIndex] % 10;
display();
delay(1000);
break;
case 1:
displayBuf[0] = 0;
displayBuf[1] = time[lightIndex] / 10;
display();
delay(1000);
displayBuf[0] = time[lightIndex] / 10;
displayBuf[1] = time[lightIndex] % 10;
display();
delay(1000);
break;
case 2:
displayBuf[0] = 2;
displayBuf[1] = time[lightIndex] / 10;
display();
delay(1000);
displayBuf[0] = time[lightIndex] / 10;
displayBuf[1] = time[lightIndex] % 10;
display();
delay(1000);
break;
}
}
// 加时间
void addTime() {
if(time[lightIndex] < 99) {
time[lightIndex]++;
modifyTime();
}
}
// 减时间
void subtractTime() {
if(time[lightIndex] > 0) {
time[lightIndex]--;
modifyTime();
}
}
// 初始化函数
void init() {
TMOD = 0x01; // 设置定时器0为模式1
TH0 = 0xfc; // 设置定时器0的初值,实现1ms的定时
TL0 = 0x18;
TR0 = 1; // 启动定时器0
ET0 = 1; // 允许定时器0的中断
IT0 = 1; // 设置外部中断0为下降沿触发方式
EX0 = 1; // 允许外部中断0
EA = 1; // 允许总中断
lightIndex = 0;
editMode = 0;
// 初始化时间
time[0] = 10; // 默认10秒绿灯时间
time[1] = 3; // 默认3秒黄灯时间
time[2] = 10; // 默认10秒红灯时间
// 初始化数码管和LED端口
P0 = 0xff; // 设置数码管段选为灭状态
P1 = 0x00; // 设置LED灯为灭状态
P2 = 0xff; // 设置数码管位选为灭状态
}
// 定时器0中断函数
void timer0Interrupt() interrupt 1 {
static unsigned int counter = 0;
unsigned int i;
counter++;
if(counter >= time[lightIndex] * 100) {
counter = 0;
switch(lightIndex) {
case 0: // 绿灯
greenLED = 1;
yellowLED = 0;
redLED = 0;
break;
case 1: // 黄灯
greenLED = 0;
yellowLED = 1;
redLED = 0;
break;
case 2: // 红灯
greenLED = 0;
yellowLED = 0;
redLED = 1;
break;
}
displayBuf[0] = displayBuf[1];
displayBuf[1] = time[lightIndex] / 10;
display();
delay(1000);
displayBuf[0] = displayBuf[1];
displayBuf[1] = time[lightIndex] % 10;
display();
delay(1000);
for(i = 0; i < time[lightIndex] - 2; i++) {
delay(1000);
}
switch(lightIndex) {
case 0: // 绿灯
greenLED = 0;
break;
case 1: // 黄灯
yellowLED = 0;
break;
case 2: // 红灯
redLED = 0;
break;
}
lightIndex++;
if(lightIndex >= 3) {
lightIndex = 0;
}
}
}
// 外部中断0中断函数
void externalInterrupt0() interrupt 0 {
unsigned int i;
delay(1000);
if(editMode == 0) {
editMode = 1;
setTime();
}
else if(editMode == 1) {
editMode = 2;
modifyTime();
}
else if(editMode == 2) {
addTime();
}
else if(editMode == 3) {
subtractTime();
}
if(P3_2 == 0) { // 如果修改键按下
editMode = 3;
modifyTime();
}
}
// 主函数
void main() {
init();
while(1) {
;
}
}
通过上述的具体步骤和代码实现,我们可以使用51单片机控制交通信号灯的定时变换。通过按键来设置每个灯的时间,实现了修改、加、减功能,并通过二位数码管和LED灯进行显示和指示。在定时器中断函数中,根据当前编辑的灯的索引和时间设置来控制LED灯的开关和数码管的显示。
由于具体硬件配置和开发环境可能有所不同,需要根据实际情况对代码进行适当调整和修改。希望以上解决方案对你有所帮助!如果还有任何问题,请随时提问。
【相关推荐】
这些在我博客都有荔枝,是函数形式都可以直接复制调用很方便,按键代码也是一样可以复制使用稍加修改即可。
这是荔枝,看看对?