马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
随便写写,汇总一下,就一个单片机,没有模仿软件,什么都没有~
点阵、数码管、led同时点亮
- #include <reg52.h>
- sbit ADDR0 = P1^0;
- sbit ADDR1 = P1^1;
- sbit ADDR2 = P1^2;
- sbit ADDR3 = P1^3;
- sbit ENLED = P1^4;
- // 交通灯控制引脚定义
- sbit A_Red = P0^0;
- sbit A_Yellow = P0^1;
- sbit A_Green = P0^2;
- sbit B_Red = P0^3;
- sbit B_Yellow = P0^4;
- sbit B_Green = P0^5;
- unsigned char code LedChar[] = { // 数码管显示字符转换表
- 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
- 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
- };
- unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- unsigned char flag1s = 0; // 1秒定时标志
- // 交通灯状态变量
- unsigned char current_state = 0; // 0:A绿灯 1:A黄灯 2:B绿灯 3:B黄灯
- unsigned char count_down = 27; // 当前倒计时
- bit yellow_blink = 0; // 黄灯闪烁标志
- unsigned int timer_count = 0; // 定时器计数
- // LED流水灯变量
- static unsigned char j = 0;
- static unsigned int shift1 = 0x01;
- static unsigned int shift2 = 0x80;
- static unsigned char dir1 = 0;
- void main()
- {
- EA = 1; // 开启总中断
- TMOD = 0x11; // 使用定时器0和定时器1
- // 定时器0初始化(2ms,用于1秒定时)
- TH0 = 0xFC;
- TL0 = 0x67;
- ET0 = 1;
- TR0 = 1;
- // 定时器1初始化(1ms,用于数码管扫描)
- TH1 = 0xFC;
- TL1 = 0x67;
- ET1 = 1;
- TR1 = 1;
- // 初始状态:A绿灯,B红灯
- A_Green = 0;
- B_Red = 0;
- A_Red = B_Green = B_Yellow = A_Yellow = 1;
- while (1)
- {
- if (flag1s == 1) // 每秒触发一次
- {
- flag1s = 0;
-
- // 交通灯状态机处理
- if(count_down > 0) count_down--;
-
- if(count_down == 0) {
- switch(current_state) {
- case 0: // A绿灯结束
- current_state = 1;
- count_down = 3;
- A_Green = 1;
- A_Yellow = 0;
- break;
-
- case 1: // A黄灯结束
- current_state = 2;
- count_down = 17;
- A_Yellow = 1;
- B_Red = 1;
- B_Green = 0;
- break;
-
- case 2: // B绿灯结束
- current_state = 3;
- count_down = 3;
- B_Green = 1;
- B_Yellow = 0;
- break;
-
- case 3: // B黄灯结束
- current_state = 0;
- count_down = 27;
- B_Yellow = 1;
- A_Red = 1;
- A_Green = 0;
- break;
- }
- }
- // 更新数码管显示(显示倒计时)
- LedBuff[0] = LedChar[count_down % 10]; // 个位
- LedBuff[1] = LedChar[count_down / 10]; // 十位
- // 其余位保持熄灭
- LedBuff[2] = LedBuff[3] = LedBuff[4] = LedBuff[5] = 0xFF;
- }
- }
- }
- // 定时器1中断服务函数(1ms,用于数码管扫描和LED流水灯)
- void Timer1_ISR() interrupt 3
- {
- static unsigned char index = 0;
-
- TH1 = 0xFC;
- TL1 = 0x67;
-
- // 黄灯闪烁处理(500ms间隔)
- if(++timer_count % 250 == 0 &&
- (current_state == 1 || current_state == 3)) {
- yellow_blink = ~yellow_blink;
- if(current_state == 1) A_Yellow = yellow_blink;
- else B_Yellow = yellow_blink;
- }
- // 数码管动态扫描
- P0 = 0xFF; // 消隐
- ENLED = 0;
- ADDR3 = 1; // 选择数码管
-
- switch(index) {
- case 0: ADDR2=0; ADDR1=0; ADDR0=0; P0=LedBuff[0]; break;
- case 1: ADDR2=0; ADDR1=0; ADDR0=1; P0=LedBuff[1]; break;
- default: P0 = 0xFF; // 其余位不显示
- }
-
- index = (index >= 1) ? 0 : index+1;
- // LED流水灯控制(复用case 6)
- if(index == 0) { // 每轮扫描结束后处理LED
- ADDR3 = 1; // 选择LED控制地址
- ADDR2 = 1;
- ADDR1 = 1;
- ADDR0 = 0;
-
- j++;
- if (j >= 200) { // 每200ms改变一次LED位置
- j = 0;
- if (dir1 == 0) { // 从左向右移动
- shift1 <<= 1;
- shift2 >>= 1;
- if (shift1 == 0x80 && shift2 == 0x01)
- dir1 = 1; // 改变方向
- } else { // 从右向左移动
- shift1 >>= 1;
- shift2 <<= 1;
- if (shift1 == 0x01 && shift2 == 0x80)
- dir1 = 0; // 改变方向
- }
- }
- P0 = ~(shift1 | shift2); // 输出LED状态
- }
- }
- // 定时器0中断服务函数(2ms,用于1秒定时)
- void Timer0_ISR() interrupt 1
- {
- static unsigned int sec_count = 0;
-
- TH0 = 0xFC;
- TL0 = 0x67;
-
- if(++sec_count >= 500) { // 500 * 2ms = 1秒
- sec_count = 0;
- flag1s = 1;
- }
- }
复制代码 红绿灯熄灭
实现30秒绿灯倒计时熄灭,20秒倒计时红灯熄灭
- #include <reg52.h>
- sbit ADDR0 = P1^0;
- sbit ADDR1 = P1^1;
- sbit ADDR2 = P1^2;
- sbit ADDR3 = P1^3;
- sbit ENLED = P1^4;
- // 交通灯控制引脚定义
- sbit A_Red = P0^0;
- sbit A_Yellow = P0^1;
- sbit A_Green = P0^2;
- sbit B_Red = P0^3;
- sbit B_Yellow = P0^4;
- sbit B_Green = P0^5;
- unsigned char code LedChar[] = {
- 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
- 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
- };
- unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- volatile unsigned char flag1s = 0;
- volatile unsigned int timer_count = 0;
- unsigned char current_state = 0; // 0:A绿灯 1:A黄灯 2:B绿灯 3:B黄灯
- unsigned char count_down = 27; // 当前倒计时
- bit yellow_blink = 0; // 黄灯闪烁标志
- void main() {
- EA = 1;
- TMOD = 0x11;
-
- // 定时器0初始化(2ms)
- TH0 = 0xFC;
- TL0 = 0x67;
- ET0 = 1;
- TR0 = 1;
- // 定时器1初始化(1ms)
- TH1 = 0xFC;
- TL1 = 0x67;
- ET1 = 1;
- TR1 = 1;
- // 初始状态:A绿灯,B红灯
- A_Green = 0;
- B_Red = 0;
- A_Red = B_Green = B_Yellow = A_Yellow = 1;
- while(1) {
- if(flag1s) {
- flag1s = 0;
-
- // 状态机处理
- if(count_down > 0) count_down--;
-
- if(count_down == 0) {
- switch(current_state) {
- case 0: // A绿灯结束
- current_state = 1;
- count_down = 3;
- A_Green = 1;
- A_Yellow = 0;
- break;
-
- case 1: // A黄灯结束
- current_state = 2;
- count_down = 17;
- A_Yellow = 1;
- B_Red = 1;
- B_Green = 0;
- break;
-
- case 2: // B绿灯结束
- current_state = 3;
- count_down = 3;
- B_Green = 1;
- B_Yellow = 0;
- break;
-
- case 3: // B黄灯结束
- current_state = 0;
- count_down = 27;
- B_Yellow = 1;
- A_Red = 1;
- A_Green = 0;
- break;
- }
- }
- // 更新数码管显示
- LedBuff[0] = LedChar[count_down % 10]; // 个位
- LedBuff[1] = LedChar[count_down / 10]; // 十位
- }
- }
- }
- // 定时器1中断(数码管扫描)
- void Timer1_ISR() interrupt 3 {
- static unsigned char index = 0;
-
- TH1 = 0xFC;
- TL1 = 0x67;
-
- // 黄灯闪烁处理(500ms间隔)
- if(++timer_count % 250 == 0 &&
- (current_state == 1 || current_state == 3)) {
- yellow_blink = ~yellow_blink;
- if(current_state == 1) A_Yellow = yellow_blink;
- else B_Yellow = yellow_blink;
- }
- // 数码管动态扫描
- P0 = 0xFF;
- ENLED = 0;
- ADDR3 = 1;
-
- switch(index) {
- case 0: ADDR2=0; ADDR1=0; ADDR0=0; P0=LedBuff[0]; break;
- case 1: ADDR2=0; ADDR1=0; ADDR0=1; P0=LedBuff[1]; break;
- default: P0 = 0xFF;
- }
-
- index = (index >= 1) ? 0 : index+1;
- }
- // 定时器0中断(1秒定时)
- void Timer0_ISR() interrupt 1 {
- static unsigned int sec_count = 0;
-
- TH0 = 0xFC;
- TL0 = 0x67;
-
- if(++sec_count >= 500) { // 500 * 2ms=1秒
- sec_count = 0;
- flag1s = 1;
- }
- }
复制代码 红绿灯跳转
当绿灯30秒剩余三秒时跳转至黄灯,当黄灯3秒后 跳转红灯,红灯20秒后继承跳转
- #include <reg52.h>
- sbit ADDR0 = P1^0;
- sbit ADDR1 = P1^1;
- sbit ADDR2 = P1^2;
- sbit ADDR3 = P1^3;
- sbit ENLED = P1^4;
- unsigned char code LedChar[] = { // 数码管显示字符转换表
- 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
- 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
- };
- unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- unsigned char flag1s = 0;
- unsigned char countDownPhase = 0; // 倒计时阶段:0=30->0, 1=20->0
- unsigned long sec = 30; // 初始值设为30
- bit countDownFinished = 0; // 倒计时结束标志
- void main()
- {
- char j;
- unsigned char buf[6];
- EA = 1; // 开启总中断
- TMOD = 0x01; // 只使用定时器0
- // 定时器0初始化(T0)
- TH0 = 0xFC; // 定时1ms
- TL0 = 0x67;
- ET0 = 1; // 使能定时器0中断
- TR0 = 1; // 启动定时器0
- // 初始化显示30
- buf[0] = sec%10; // 个位
- buf[1] = sec/10%10; // 十位
- buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0; // 高位补0
-
- // 高位消零处理
- for (j=5; j>=1; j--)
- {
- if (buf[j] == 0)
- LedBuff[j] = 0xFF; // 不显示前导零
- else
- break;
- }
- // 显示有效数字
- for (; j>=0; j--)
- {
- LedBuff[j] = LedChar[buf[j]];
- }
- while (1)
- {
- if (flag1s == 1) // 每秒触发一次
- {
- flag1s = 0;
-
- if (!countDownFinished) // 如果倒计时未结束
- {
- if (sec > 0)
- {
- sec--; // 秒计数器减1
-
- // 分解秒数为单个数字
- buf[0] = sec%10; // 个位
- buf[1] = sec/10%10; // 十位
- buf[2] = sec/100%10;
- buf[3] = sec/1000%10;
- buf[4] = sec/10000%10;
- buf[5] = sec/100000%10;
- // 高位消零处理
- for (j=5; j>=1; j--)
- {
- if (buf[j] == 0)
- LedBuff[j] = 0xFF; // 不显示前导零
- else
- break;
- }
- // 显示有效数字
- for (; j>=0; j--)
- {
- LedBuff[j] = LedChar[buf[j]];
- }
- }
- else
- {
- countDownFinished = 1; // 倒计时结束
-
- // 切换到下一阶段
- countDownPhase++;
- if (countDownPhase == 1) {
- // 进入20->0阶段
- sec = 20;
- countDownFinished = 0; // 重置结束标志
-
- // 更新显示
- buf[0] = sec%10;
- buf[1] = sec/10%10;
- buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
-
- for (j=5; j>=1; j--)
- {
- if (buf[j] == 0)
- LedBuff[j] = 0xFF;
- else
- break;
- }
- for (; j>=0; j--)
- {
- LedBuff[j] = LedChar[buf[j]];
- }
- }
- else if (countDownPhase >= 2) {
- // 所有阶段完成,重置到第一阶段
- countDownPhase = 0;
- sec = 30;
- countDownFinished = 0;
-
- // 更新显示
- buf[0] = sec%10;
- buf[1] = sec/10%10;
- buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
-
- for (j=5; j>=1; j--)
- {
- if (buf[j] == 0)
- LedBuff[j] = 0xFF;
- else
- break;
- }
- for (; j>=0; j--)
- {
- LedBuff[j] = LedChar[buf[j]];
- }
- }
- }
- }
- }
- }
- }
- // 定时器0中断服务函数(修改LED控制部分)
- void Timer0_ISR() interrupt 1
- {
- static unsigned char j = 0;
- static unsigned char i = 0;
- static unsigned int cnt = 0;
- static unsigned int shift1 = 0x01;
- static unsigned int shift2 = 0x80;
- static unsigned char dir1 = 0;
- TH0 = 0xFC; // 重新加载初值
- TL0 = 0x67;
-
- P0 = 0xFF; // 显示消隐
- ENLED = 0; // 使能显示
- ADDR3 = 1; // 选择数码管和LED
- // 数码管动态扫描(保持不变)
- switch (i)
- {
- case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;
- case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;
- case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;
- case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;
- case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;
- case 5: ADDR2=1; ADDR1=0; ADDR0=1; i++; P0=LedBuff[5]; break;
- case 6: // LED控制(修改部分)
- ADDR2=1; ADDR1=1; ADDR0=0;
-
- // 根据倒计时阶段控制LED
- if (countDownPhase == 0) {
- // 30秒倒计时阶段,点亮第一个LED(P0.0)
- P0 = 0xFE; // 二进制 1111 1110,仅P0.0为低电平
- } else {
- // 20秒倒计时阶段,熄灭所有LED
- P0 = 0xFF; // 二进制 1111 1111,所有LED熄灭
- }
-
- i = 0;
- break;
- default: break;
- }
- // 1秒定时处理(保持不变)
- cnt++;
- if (cnt >= 1000) // 1000ms = 1s
- {
- cnt = 0;
- flag1s = 1; // 设置1秒标志
- }
- }
复制代码 增加B车道
30秒阶段LED 逻辑:
30 秒→4 秒:点亮 LED2和 LED7
3 秒→0 秒:点亮 LED3和 LED
20 秒阶段 LED 逻辑:
20 秒→4 秒:点亮 LED4和 LED5
3 秒→0 秒:点亮 LED4和 LED6
- #include <reg52.h>
- sbit ADDR0 = P1^0;
- sbit ADDR1 = P1^1;
- sbit ADDR2 = P1^2;
- sbit ADDR3 = P1^3;
- sbit ENLED = P1^4;
- unsigned char code LedChar[] = { // 数码管显示字符转换表
- 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
- 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
- };
- unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- unsigned char flag1s = 0;
- unsigned char countDownPhase = 0; // 倒计时阶段:0=30秒阶段, 1=20秒阶段
- unsigned long sec = 30; // 初始值设为30
- bit countDownFinished = 0; // 倒计时结束标志
- void main()
- {
- char j;
- unsigned char buf[6];
- EA = 1; // 开启总中断
- TMOD = 0x01; // 只使用定时器0
- // 定时器0初始化(T0)
- TH0 = 0xFC; // 定时1ms
- TL0 = 0x67;
- ET0 = 1; // 使能定时器0中断
- TR0 = 1; // 启动定时器0
- // 初始化显示30
- buf[0] = sec%10; // 个位
- buf[1] = sec/10%10; // 十位
- buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0; // 高位补0
-
- // 高位消零处理
- for (j=5; j>=1; j--)
- {
- if (buf[j] == 0)
- LedBuff[j] = 0xFF; // 不显示前导零
- else
- break;
- }
- // 显示有效数字
- for (; j>=0; j--)
- {
- LedBuff[j] = LedChar[buf[j]];
- }
- while (1)
- {
- if (flag1s == 1) // 每秒触发一次
- {
- flag1s = 0;
-
- if (!countDownFinished) // 如果倒计时未结束
- {
- if (sec > 0)
- {
- sec--; // 秒计数器减1
-
- // 分解秒数为单个数字
- buf[0] = sec%10; // 个位
- buf[1] = sec/10%10; // 十位
- buf[2] = sec/100%10;
- buf[3] = sec/1000%10;
- buf[4] = sec/10000%10;
- buf[5] = sec/100000%10;
- // 高位消零处理
- for (j=5; j>=1; j--)
- {
- if (buf[j] == 0)
- LedBuff[j] = 0xFF; // 不显示前导零
- else
- break;
- }
- // 显示有效数字
- for (; j>=0; j--)
- {
- LedBuff[j] = LedChar[buf[j]];
- }
- }
- else
- {
- countDownFinished = 1; // 倒计时结束
-
- // 切换到下一阶段
- countDownPhase++;
- if (countDownPhase == 1) {
- // 进入20->0阶段
- sec = 20;
- countDownFinished = 0; // 重置结束标志
-
- // 更新显示
- buf[0] = sec%10;
- buf[1] = sec/10%10;
- buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
-
- for (j=5; j>=1; j--)
- {
- if (buf[j] == 0)
- LedBuff[j] = 0xFF;
- else
- break;
- }
- for (; j>=0; j--)
- {
- LedBuff[j] = LedChar[buf[j]];
- }
- }
- else if (countDownPhase >= 2) {
- // 所有阶段完成,重置到第一阶段
- countDownPhase = 0;
- sec = 30;
- countDownFinished = 0;
-
- // 更新显示
- buf[0] = sec%10;
- buf[1] = sec/10%10;
- buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
-
- for (j=5; j>=1; j--)
- {
- if (buf[j] == 0)
- LedBuff[j] = 0xFF;
- else
- break;
- }
- for (; j>=0; j--)
- {
- LedBuff[j] = LedChar[buf[j]];
- }
- }
- }
- }
- }
- }
- }
- // 定时器0中断服务函数(修改LED控制部分)
- void Timer0_ISR() interrupt 1
- {
- static unsigned char j = 0;
- static unsigned char i = 0;
- static unsigned int cnt = 0;
- TH0 = 0xFC; // 重新加载初值
- TL0 = 0x67;
-
- P0 = 0xFF; // 显示消隐
- ENLED = 0; // 使能显示
- ADDR3 = 1; // 选择数码管和LED
- // 数码管动态扫描
- switch (i)
- {
- case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;
- case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;
- case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;
- case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;
- case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;
- case 5: ADDR2=1; ADDR1=0; ADDR0=1; i++; P0=LedBuff[5]; break;
- case 6: // LED控制部分
- ADDR2=1; ADDR1=1; ADDR0=0;
-
- // 根据倒计时阶段和剩余秒数控制LED
- if (countDownPhase == 0) {
- // 30秒倒计时阶段
- if (sec > 3) {
- // 前27秒:LED1(P0.0)和LED6(P0.5)亮
- P0 = 0xDE; // 二进制 1101 1110 (P0.0和P0.5低电平)
- } else if (sec > 0) {
- // 后3秒:LED2(P0.1)和LED6(P0.5)亮
- P0 = 0xDD; // 二进制 1101 1101 (P0.1和P0.5低电平)
- } else {
- // 倒计时结束:熄灭所有LED
- P0 = 0xFF;
- }
- } else if (countDownPhase == 1) {
- // 20秒倒计时阶段
- if (sec > 3) {
- // 前17秒:LED3(P0.2)和LED4(P0.3)亮
- P0 = 0xF3; // 二进制 1111 0011 (P0.2和P0.3低电平)
- } else if (sec > 0) {
- // 后3秒:LED3(P0.2)和LED5(P0.4)亮
- P0 = 0xEB; // 二进制 1110 1011 (P0.2和P0.4低电平)
- } else {
- // 倒计时结束:熄灭所有LED
- P0 = 0xFF;
- }
- } else {
- // 其他阶段:熄灭所有LED
- P0 = 0xFF;
- }
-
- i = 0;
- break;
- default: break;
- }
- // 1秒定时处理
- cnt++;
- if (cnt >= 1000) // 1000ms = 1s
- {
- cnt = 0;
- flag1s = 1; // 设置1秒标志
- }
- }
复制代码 按键控制led灯的10秒定时亮灭
- #include <reg52.h>
- // 引脚定义(补充完整矩阵按键输出和输入引脚)
- sbit ADDR0 = P1^0;
- sbit ADDR1 = P1^1;
- sbit ADDR2 = P1^2;
- sbit ADDR3 = P1^3;
- sbit ENLED = P1^4;
- sbit KEY_OUT_1 = P2^3; // 矩阵按键输出引脚(完整定义)
- sbit KEY_OUT_2 = P2^2;
- sbit KEY_OUT_3 = P1^2; // 假设KEY_OUT_3连接到P1^2(避免与ADDR2冲突)
- sbit KEY_OUT_4 = P1^3; // 假设KEY_OUT_4连接到P1^3(避免与ADDR3冲突)
- sbit KEY_IN_1 = P2^4; // 矩阵按键输入引脚(完整定义)
- sbit KEY_IN_2 = P2^5;
- sbit KEY_IN_3 = P2^6;
- sbit KEY_IN_4 = P2^7;
- sbit LED1 = P0^0; // K2控制的LED(原LED)
- sbit LED4 = P0^3; // K1控制的LED4(假设连接到P0^3)
- // 状态变量
- unsigned char KeySta[4][4] = { // 按键状态数组(使用[0][0]对应K1,[0][1]对应K2)
- {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}
- };
- unsigned int Timer10s_LED1 = 0; // LED1的10秒计时计数器
- unsigned int Timer10s_LED4 = 0; // LED4的10秒计时计数器
- bit Led1Active = 0; // LED1激活标志
- bit Led4Active = 0; // LED4激活标志
- // 定时器0参数(1ms定时)
- #define TIMER0_RELOAD_H 0xFC // 1ms初值高位
- #define TIMER0_RELOAD_L 0x67 // 1ms初值低位
- void main()
- {
- // 硬件初始化
- ENLED = 0; // 使能LED控制
- ADDR3 = 1; // 选择LED所在电路(共阳连接)
- ADDR2 = 1;
- ADDR1 = 1;
- ADDR0 = 0;
- LED1 = 1; // 初始熄灭LED1
- LED4 = 1; // 初始熄灭LED4
- // 定时器0初始化
- TMOD = 0x01; // 模式1(16位定时器)
- TH0 = TIMER0_RELOAD_H;
- TL0 = TIMER0_RELOAD_L;
- ET0 = 1; // 使能定时器中断
- EA = 1; // 使能总中断
- TR0 = 1; // 启动定时器
- // 矩阵按键初始化
- KEY_OUT_1 = 1; // 初始拉高所有行
- KEY_OUT_2 = 1;
- KEY_OUT_3 = 1;
- KEY_OUT_4 = 1;
- while (1)
- {
- // 检测K1按键状态(矩阵坐标[0][0],第1行第1列)
- if (KeySta[0][0] == 0 && !Led4Active) // K1按下且LED4未激活
- {
- LED4 = 0; // 点亮LED4
- Led4Active = 1; // 标记LED4激活
- Timer10s_LED4 = 0; // 重置LED4计时器
- while (KeySta[0][0] == 0); // 等待K1释放
- }
- // 检测K2按键状态(矩阵坐标[0][1],第1行第2列)
- if (KeySta[0][1] == 0 && !Led1Active) // K2按下且LED1未激活
- {
- LED1 = 0; // 点亮LED1
- Led1Active = 1; // 标记LED1激活
- Timer10s_LED1 = 0; // 重置LED1计时器
- while (KeySta[0][1] == 0); // 等待K2释放
- }
- }
- }
- /* 定时器0中断服务函数(1ms执行一次) */
- void InterruptTimer0() interrupt 1
- {
- static unsigned char keyout = 0; // 矩阵行扫描索引
- static unsigned char keybuf[4][4] = { // 按键消抖缓冲区
- {0xFF, 0xFF, 0xFF, 0xFF},
- {0xFF, 0xFF, 0xFF, 0xFF},
- {0xFF, 0xFF, 0xFF, 0xFF},
- {0xFF, 0xFF, 0xFF, 0xFF}
- };
- // 重新加载定时器初值
- TH0 = TIMER0_RELOAD_H;
- TL0 = TIMER0_RELOAD_L;
- // 扫描第1行(KEY_OUT_1)
- KEY_OUT_1 = 0; // 拉低第1行
- KEY_OUT_2 = 1; // 拉高其他行
- KEY_OUT_3 = 1;
- KEY_OUT_4 = 1;
- // 读取K1和K2的按键值(第1行第1、2列)
- keybuf[0][0] = (keybuf[0][0] << 1) | KEY_IN_1; // K1(第1列)
- keybuf[0][1] = (keybuf[0][1] << 1) | KEY_IN_2; // K2(第2列)
- // K1消抖逻辑
- if ((keybuf[0][0] & 0x0F) == 0x00)
- {
- KeySta[0][0] = 0; // 标记K1按下
- }
- else if ((keybuf[0][0] & 0x0F) == 0x0F)
- {
- KeySta[0][0] = 1; // 标记K1释放
- }
- // K2消抖逻辑
- if ((keybuf[0][1] & 0x0F) == 0x00)
- {
- KeySta[0][1] = 0; // 标记K2按下
- }
- else if ((keybuf[0][1] & 0x0F) == 0x0F)
- {
- KeySta[0][1] = 1; // 标记K2释放
- }
- // LED1计时逻辑
- if (Led1Active)
- {
- Timer10s_LED1++;
- if (Timer10s_LED1 >= 10000)
- {
- LED1 = 1;
- Led1Active = 0;
- }
- }
- // LED4计时逻辑
- if (Led4Active)
- {
- Timer10s_LED4++;
- if (Timer10s_LED4 >= 10000)
- {
- LED4 = 1;
- Led4Active = 0;
- }
- }
- }
复制代码 按下按键暂停红绿灯时间
- #include <reg52.h>
- // 引脚定义
- sbit ADDR0 = P1^0;
- sbit ADDR1 = P1^1;
- sbit ADDR2 = P1^2;
- sbit ADDR3 = P1^3;
- sbit ENLED = P1^4;
- sbit KEY_OUT_1 = P2^3;
- sbit KEY_OUT_2 = P2^2;
- sbit KEY_OUT_3 = P1^2;
- sbit KEY_OUT_4 = P1^3;
- sbit KEY_IN_1 = P2^4; // K1按键输入
- sbit KEY_IN_2 = P2^5; // K2按键输入
- // 数码管显示
- unsigned char code LedChar[] = {
- 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
- 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
- };
- unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- // 状态变量
- unsigned char flag1s = 0;
- unsigned char flag10ms = 0;
- unsigned char countDownPhase = 0; // 0=30秒阶段, 1=20秒阶段
- unsigned long sec = 30;
- bit countDownFinished = 0;
- // 按键状态和LED控制
- unsigned char KeySta[4][4] = {
- {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}
- };
- bit K1_Pressed = 0; // K1按键按下标志
- bit K2_Pressed = 0; // K2按键按下标志
- bit LED_SpecialMode = 0; // 特殊LED模式标志
- unsigned int SpecialModeTimer = 0; // 特殊模式计时器(10秒)
- unsigned int secCnt = 0; // 秒计数器
- bit SpecialModeType = 0; // 0=K1模式, 1=K2模式
- void main()
- {
- char j;
- unsigned char buf[6];
- // 初始化
- EA = 1;
- TMOD = 0x01;
- TH0 = 0xFC;
- TL0 = 0x67;
- ET0 = 1;
- TR0 = 1;
-
- // 初始化显示30
- buf[0] = sec%10;
- buf[1] = sec/10%10;
- buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
-
- for (j=5; j>=1; j--)
- {
- if (buf[j] == 0)
- LedBuff[j] = 0xFF;
- else
- break;
- }
- for (; j>=0; j--)
- {
- LedBuff[j] = LedChar[buf[j]];
- }
- while (1)
- {
- // 检测K1按键状态(30秒阶段)
- if (countDownPhase == 0 && KeySta[0][0] == 0 && !K1_Pressed && sec > 3)
- {
- K1_Pressed = 1;
- LED_SpecialMode = 1;
- SpecialModeTimer = 0;
- SpecialModeType = 0; // K1模式
- while (KeySta[0][0] == 0); // 等待释放
- }
- else if (KeySta[0][0] == 1)
- {
- K1_Pressed = 0;
- }
- // 检测K2按键状态(20秒阶段)
- if (countDownPhase == 1 && KeySta[0][1] == 0 && !K2_Pressed && sec > 3)
- {
- K2_Pressed = 1;
- LED_SpecialMode = 1;
- SpecialModeTimer = 0;
- SpecialModeType = 1; // K2模式
- while (KeySta[0][1] == 0); // 等待释放
- }
- else if (KeySta[0][1] == 1)
- {
- K2_Pressed = 0;
- }
- // 特殊模式计时
- if (flag10ms && LED_SpecialMode) {
- SpecialModeTimer++;
- if (SpecialModeTimer >= 1000) { // 1000*10ms = 10秒
- LED_SpecialMode = 0;
- }
- }
- // 倒计时处理
- if (flag1s == 1)
- {
- flag1s = 0;
-
- if (!countDownFinished)
- {
- if (sec > 0)
- {
- sec--;
-
- buf[0] = sec%10;
- buf[1] = sec/10%10;
- buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
- for (j=5; j>=1; j--)
- {
- if (buf[j] == 0)
- LedBuff[j] = 0xFF;
- else
- break;
- }
- for (; j>=0; j--)
- {
- LedBuff[j] = LedChar[buf[j]];
- }
- }
- else
- {
- countDownFinished = 1;
- countDownPhase++;
- LED_SpecialMode = 0; // 阶段切换时重置特殊模式
-
- if (countDownPhase == 1) {
- sec = 20;
- countDownFinished = 0;
-
- buf[0] = sec%10;
- buf[1] = sec/10%10;
- buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
-
- for (j=5; j>=1; j--)
- {
- if (buf[j] == 0)
- LedBuff[j] = 0xFF;
- else
- break;
- }
- for (; j>=0; j--)
- {
- LedBuff[j] = LedChar[buf[j]];
- }
- }
- else if (countDownPhase >= 2) {
- countDownPhase = 0;
- sec = 30;
- countDownFinished = 0;
-
- buf[0] = sec%10;
- buf[1] = sec/10%10;
- buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
-
- for (j=5; j>=1; j--)
- {
- if (buf[j] == 0)
- LedBuff[j] = 0xFF;
- else
- break;
- }
- for (; j>=0; j--)
- {
- LedBuff[j] = LedChar[buf[j]];
- }
- }
- }
- }
- }
- }
- }
- // 定时器0中断服务函数
- void Timer0_ISR() interrupt 1
- {
- static unsigned char i = 0;
- static unsigned int cnt = 0;
- static unsigned char keyout = 0;
- static unsigned char keybuf[4][4] = {
- {0xFF, 0xFF, 0xFF, 0xFF},
- {0xFF, 0xFF, 0xFF, 0xFF},
- {0xFF, 0xFF, 0xFF, 0xFF},
- {0xFF, 0xFF, 0xFF, 0xFF}
- };
- TH0 = 0xFC;
- TL0 = 0x67;
-
- // 按键扫描(仅扫描第1行)
- KEY_OUT_1 = 0;
- KEY_OUT_2 = 1;
- KEY_OUT_3 = 1;
- KEY_OUT_4 = 1;
- keybuf[0][0] = (keybuf[0][0] << 1) | KEY_IN_1; // K1
- keybuf[0][1] = (keybuf[0][1] << 1) | KEY_IN_2; // K2
- // K1消抖
- if ((keybuf[0][0] & 0x0F) == 0x00)
- KeySta[0][0] = 0;
- else if ((keybuf[0][0] & 0x0F) == 0x0F)
- KeySta[0][0] = 1;
- // K2消抖
- if ((keybuf[0][1] & 0x0F) == 0x00)
- KeySta[0][1] = 0;
- else if ((keybuf[0][1] & 0x0F) == 0x0F)
- KeySta[0][1] = 1;
- // 数码管显示和LED控制
- P0 = 0xFF;
- ENLED = 0;
- ADDR3 = 1;
- switch (i)
- {
- case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;
- case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;
- case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;
- case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;
- case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;
- case 5: ADDR2=1; ADDR1=0; ADDR0=1; i++; P0=LedBuff[5]; break;
- case 6:
- ADDR2=1; ADDR1=1; ADDR0=0;
-
- if (countDownPhase == 0) {
- // 30秒阶段
- if (sec > 3) {
- // 前27秒
- if (LED_SpecialMode && !SpecialModeType) {
- P0 = 0xD7; // LED1(P0.0)和LED4(P0.3)亮 (11010111)
- } else {
- P0 = 0xDE; // 默认:LED1(P0.0)和LED6(P0.5)亮 (11011110)
- }
- } else if (sec > 0) {
- // 后3秒
- P0 = 0xDD; // LED2(P0.1)和LED6(P0.5)亮 (11011101)
- } else {
- P0 = 0xFF; // 熄灭所有
- }
- } else if (countDownPhase == 1) {
- // 20秒阶段
- if (sec > 3) {
- // 前17秒
- if (LED_SpecialMode && SpecialModeType) {
- P0 = 0xF6; // LED1(P0.0)和LED4(P0.3)亮 (11110110)
- } else {
- P0 = 0xF3; // 默认:LED3(P0.2)和LED4(P0.3)亮 (11110011)
- }
- } else if (sec > 0) {
- // 后3秒
- P0 = 0xEB; // LED3(P0.2)和LED5(P0.4)亮 (11101011)
- } else {
- P0 = 0xFF; // 熄灭所有
- }
- } else {
- P0 = 0xFF;
- }
-
- i = 0;
- break;
- default: break;
- }
- // 定时处理
- cnt++;
- if (cnt >= 10) { // 10ms
- cnt = 0;
- flag10ms = 1;
-
- secCnt++;
- if (secCnt >= 100) { // 100*10ms = 1s
- secCnt = 0;
- flag1s = 1;
- }
- } else {
- flag10ms = 0;
- }
- }
复制代码 基于STC89C52单片机的交通灯控制系统设计
用单片机控制一个交通信号灯系统,设 A 车道与 B 车道交织构成十字路口, A 是主车道, B 是支车道。具体要求如下:(1)用发光二极管模仿交通信号灯, A 、 B 车道各三盏灯,分别代表红、黄、绿;用
按键开关模仿车辆检测信号。(2)
正常情况下, A 、 B 辆车道轮替放行, A 车道放行30s,此中3s用于警告; B 车道放行20s,此中3s用于警告。
(3)
在交通繁忙时,交通信号灯控制系统应有手控开关,可人为地改变信号灯的状态,以缓解交通拥挤状况。在 B 车道放行期间,若 A 车道有车而 B 车道无车,按下开关K1使 A 车道放行10s;在 A 车道放行期间,若 B 车道有车而 A 车道无车,按下开关K2使 B 车道放行10s。(4)有紧急车辆通过时,按下K3开关使 A 、 B 车道均为红灯,禁行15s。
- #include <reg52.h>
- sbit ADDR0 = P1^0;
- sbit ADDR1 = P1^1;
- sbit ADDR2 = P1^2;
- sbit ADDR3 = P1^3;
- sbit ENLED = P1^4;
- // 矩阵按键引脚定义
- sbit KEY_IN_1 = P2^4; // 第1列
- sbit KEY_IN_2 = P2^5; // 第2列
- sbit KEY_IN_3 = P2^6; // 第3列
- sbit KEY_IN_4 = P2^7; // 第4列
- sbit KEY_OUT_1 = P2^3; // 第1行
- sbit KEY_OUT_2 = P2^2; // 第2行
- sbit KEY_OUT_3 = P2^1; // 第3行
- sbit KEY_OUT_4 = P2^0; // 第4行
- unsigned char code LedChar[] = {
- 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
- 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
- };
- unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- unsigned char flag1s = 0;
- unsigned char countDownPhase = 0; // 0=30秒阶段, 1=20秒阶段
- unsigned long sec = 30;
- bit countDownFinished = 0;
- // 按键和LED控制变量
- bit K1_pressed = 0; // K1按下标志(第1行第1列)
- bit K2_pressed = 0; // K2按下标志(第1行第2列)
- unsigned char K1_holdTime = 0; // K1按下保持时间
- unsigned char K2_holdTime = 0; // K2按下保持时间
- bit LED_override = 0; // LED覆盖标志
- unsigned char overrideLEDState = 0xFF; // 覆盖的LED状态
- unsigned char normalLEDState = 0xFF; // 正常LED状态
- void KeyScan();
- void UpdateLEDs();
- void main()
- {
- char j;
- unsigned char buf[6];
- EA = 1;
- TMOD = 0x01;
- TH0 = 0xFC;
- TL0 = 0x67;
- ET0 = 1;
- TR0 = 1;
- // 初始化显示30
- buf[0] = sec%10;
- buf[1] = sec/10%10;
- buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 0;
-
- for (j=5; j>=1; j--) {
- if (buf[j] == 0) LedBuff[j] = 0xFF;
- else break;
- }
- for (; j>=0; j--) {
- LedBuff[j] = LedChar[buf[j]];
- }
- while(1) {
- KeyScan();
-
- if (flag1s == 1) {
- flag1s = 0;
-
- // 处理K1按下后的10秒计时
- if (K1_pressed) {
- K1_holdTime++;
- if (K1_holdTime >= 10) {
- K1_pressed = 0;
- K1_holdTime = 0;
- LED_override = 0; // 恢复正常LED状态
- }
- }
-
- // 处理K2按下后的10秒计时
- if (K2_pressed) {
- K2_holdTime++;
- if (K2_holdTime >= 10) {
- K2_pressed = 0;
- K2_holdTime = 0;
- LED_override = 0; // 恢复正常LED状态
- }
- }
-
- // 正常倒计时处理
- if (!countDownFinished) {
- if (sec > 0) {
- sec--;
-
- // 更新数码管显示
- buf[0] = sec%10;
- buf[1] = sec/10%10;
- for (j=5; j>=1; j--) {
- if (buf[j] == 0) LedBuff[j] = 0xFF;
- else break;
- }
- for (; j>=0; j--) {
- LedBuff[j] = LedChar[buf[j]];
- }
-
- // 更新正常LED状态
- if (countDownPhase == 0) { // 30秒阶段
- if (sec > 3) normalLEDState = 0xDE; // LED1&6
- else if (sec > 0) normalLEDState = 0xDD; // LED2&6
- else normalLEDState = 0xFF;
- }
- else if (countDownPhase == 1) { // 20秒阶段
- if (sec > 3) normalLEDState = 0xF3; // LED3&4
- else if (sec > 0) normalLEDState = 0xEB; // LED3&5
- else normalLEDState = 0xFF;
- }
- } else {
- // 倒计时结束,切换到下一阶段
- countDownFinished = 1;
- }
- } else {
- // 阶段切换处理
- countDownPhase++;
- if (countDownPhase == 1) { // 切换到20秒阶段
- sec = 20;
- countDownFinished = 0;
- normalLEDState = 0xF3; // LED3&4
- }
- else if (countDownPhase >= 2) { // 循环回到30秒阶段
- countDownPhase = 0;
- sec = 30;
- countDownFinished = 0;
- normalLEDState = 0xDE; // LED1&6
- }
-
- // 更新数码管显示
- buf[0] = sec%10;
- buf[1] = sec/10%10;
- for (j=5; j>=1; j--) {
- if (buf[j] == 0) LedBuff[j] = 0xFF;
- else break;
- }
- for (; j>=0; j--) {
- LedBuff[j] = LedChar[buf[j]];
- }
- }
- }
- }
- }
- void KeyScan()
- {
- static unsigned char keyDebounceK1 = 0;
- static unsigned char keyDebounceK2 = 0;
-
- // 扫描第1行
- KEY_OUT_1 = 0; // 选通第1行
- KEY_OUT_2 = 1;
- KEY_OUT_3 = 1;
- KEY_OUT_4 = 1;
-
- // 检测K1 (第1行第1列)
- if (KEY_IN_1 == 0) {
- keyDebounceK1++;
- if (keyDebounceK1 >= 5 && !K1_pressed && countDownPhase == 0 && sec >= 10) {
- K1_pressed = 1;
- K1_holdTime = 0;
- LED_override = 1;
- overrideLEDState = 0xF3; // LED3和LED4亮
- }
- } else {
- keyDebounceK1 = 0;
- }
-
- // 检测K2 (第1行第2列)
- if (KEY_IN_2 == 0) {
- keyDebounceK2++;
- if (keyDebounceK2 >= 5 && !K2_pressed && countDownPhase == 1 && sec >= 10) {
- K2_pressed = 1;
- K2_holdTime = 0;
- LED_override = 1;
- overrideLEDState = 0xDE; // LED1和LED6亮
- }
- } else {
- keyDebounceK2 = 0;
- }
- }
- void Timer0_ISR() interrupt 1
- {
- static unsigned char i = 0;
- static unsigned int cnt = 0;
- TH0 = 0xFC;
- TL0 = 0x67;
-
- P0 = 0xFF;
- ENLED = 0;
- ADDR3 = 1;
- // 数码管动态扫描
- switch(i) {
- case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;
- case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;
- case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;
- case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;
- case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;
- case 5: ADDR2=1; ADDR1=0; ADDR0=1; i++; P0=LedBuff[5]; break;
- case 6:
- ADDR2=1; ADDR1=1; ADDR0=0;
-
- // LED控制
- if (LED_override) {
- P0 = overrideLEDState; // 使用覆盖的LED状态
- } else {
- P0 = normalLEDState; // 正常LED状态
- }
- i = 0;
- break;
- default: break;
- }
- // 1秒定时
- cnt++;
- if (cnt >= 1000) {
- cnt = 0;
- flag1s = 1;
- }
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
|