1.这是控制灯的流程图
2.首先在proteus 8软件绘制电路图
配置好51的最小系统,复位电路,晶振电路,按键电路,彩灯电路,数码管电路等
这里的数码管采用共阴极接法,a=p02、b=p03、c=p04、d=p05、e=p06、f=p01、g=p00、dp无、com接地。因为我的实物是这种接法,不是标准的共阴数码管。
3.在keil软件进行编程
代码:
cpp
#include <reg52.h> // AT89C52头文件
typedef unsigned char u8;
typedef unsigned int u16;
sbit RED = P2^1; // Q1: 红灯
sbit YELLOW = P2^2; // Q2: 黄灯
sbit GREEN = P2^3; // Q3: 绿灯
sbit START_BUTTON = P3^4; // 启动按键
sbit RESET_BUTTON = P3^5; // 复位按键
sbit a = P0^2; // a段 -> P0.2
sbit b = P0^3; // b段 -> P0.3
sbit c = P0^4; // c段 -> P0.4
sbit d = P0^5; // d段 -> P0.5
sbit e = P0^6; // e段 -> P0.6
sbit f = P0^1; // f段 -> P0.1
sbit g = P0^0; // g段 -> P0.0
// 共阴极数码管0~9的段码
u8 seg_table[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
// 状态枚举(Q3Q2Q1顺序)
typedef enum
{
STATE_000 = 0, // 000(全灭)
STATE_001, // 001(红灯亮)
STATE_011, // 011(红灯+黄灯亮)
STATE_010, // 010(黄灯亮)
STATE_110, // 110(黄灯+绿灯亮)
STATE_100, // 100(绿灯亮)
STATE_101, // 101(红灯+绿灯亮)
STATE_111 // 111(全亮)
} State;
State current_state = STATE_000; // 初始状态
bit is_started = 0; // 启动标志
void delay(u16 n)//12.000MHz
{
u8 i, j;
while(n--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
// 更新彩灯状态(严格按Q3Q2Q1顺序)
void update_leds()
{
switch (current_state)
{
case STATE_000: // 000(全灭)
GREEN = 1; YELLOW = 1; RED = 1;
break;
case STATE_001: // 001(红灯亮)
GREEN = 1; YELLOW = 1; RED = 0;
break;
case STATE_011: // 011(红灯+黄灯亮)
GREEN = 1; YELLOW = 0; RED = 0;
break;
case STATE_010: // 010(黄灯亮)
GREEN = 1; YELLOW = 0; RED = 1;
break;
case STATE_110: // 110(黄灯+绿灯亮)
GREEN = 0; YELLOW = 0; RED = 1;
break;
case STATE_100: // 100(绿灯亮)
GREEN = 0; YELLOW = 1; RED = 1;
break;
case STATE_101: // 101(红灯+绿灯亮)
GREEN = 0; YELLOW = 1; RED = 0;
break;
case STATE_111: // 111(全亮)
GREEN = 0; YELLOW = 0; RED = 0;
break;
}
}
// 状态切换
void next_state()
{
switch (current_state)
{
case STATE_000: current_state = STATE_001; break;
case STATE_001: current_state = STATE_011; break;
case STATE_011: current_state = STATE_010; break;
case STATE_010: current_state = STATE_110; break;
case STATE_110: current_state = STATE_100; break;
case STATE_100: current_state = STATE_101; break;
case STATE_101: current_state = STATE_111; break;
case STATE_111: current_state = STATE_000; break;
}
}
// 数码管显示函数
void display_digit(u8 num)
{
u8 seg = seg_table[num];
// 将标准段码映射到实际引脚
a = (seg >> 0) & 0x01; // a对应段码的最低位
b = (seg >> 1) & 0x01; // b
c = (seg >> 2) & 0x01; // c
d = (seg >> 3) & 0x01; // d
e = (seg >> 4) & 0x01; // e
f = (seg >> 5) & 0x01; // f
g = (seg >> 6) & 0x01; // g
}
// 更新数码管显示
void update_seg_display()
{
u8 display_num;
switch (current_state)
{
case STATE_000: display_num = 1; break;
case STATE_001: display_num = 2; break;
case STATE_011: display_num = 3; break;
case STATE_010: display_num = 4; break;
case STATE_110: display_num = 5; break;
case STATE_100: display_num = 6; break;
case STATE_101: display_num = 7; break;
case STATE_111: display_num = 8; break;
}
display_digit(display_num);
}
void main()
{
while (1)
{
if (START_BUTTON == 0)
{
delay(20);
if (START_BUTTON == 0) is_started = 1;
}
if (RESET_BUTTON == 0)
{
delay(20);
if (RESET_BUTTON == 0)
{
current_state = STATE_000;
is_started = 0;
update_leds();
display_digit(0); // 复位时数码管显示 0
}
}
if (is_started)
{
update_leds(); // 更新LED状态
update_seg_display(); // 更新数码管显示
delay(1000); // 每个状态持续1s
next_state(); // 切换到下一状态
}
}
}
4.仿真效果
按下SB1:1-8循环显示,彩灯也一样循环显示
最后按下SB2:彩灯停止,数码管显示0