前言
昨天也就是星期三,倒数第二节实训课。老师给我们布置了一个实训作业。目的是通过Proteus和keil实现继电器控制白炽灯的亮灭,以及用数码管记录次数.
进阶玩法通过变压器,电桥,稳压器将220V转化成5V的元
Proteus
器件
主体
No. | Component | Quantity | Specifications |
---|---|---|---|
1 | AT89C51 | 1 | 8-bit microcontroller |
2 | RES | 3 | 1kΩ (×1), 200Ω (×1), 10kΩ (×1) |
3 | CAP | 2 | 30pF |
4 | DIO | 1 | - |
5 | BUTTON | 3 | - |
6 | LED-GREEN | 1 | - |
7 | NPN | 1 | Transistor |
8 | VSINE | 1 | Sine wave voltage source |
9 | RX8 | 1 | - |
10 | 7SEG-COM-AN-GRN | 1 | Common anode green 7-segment display |
11 | LAMP | 1 | - |
12 | RELAY | 1 | - |
13 | CAP ELEC | 1 | Electrolytic capacitor |
14 | GROUND | 2 | - |
14 | CRYSTAL | 1 | - |
变压器
No. | Component | Quantity | Specifications |
---|---|---|---|
1 | VSINE | 1 | Sine wave voltage source |
2 | TRAN-2P2S | 1 | Transformer with 2 primary and 2 secondary windings |
3 | BRIDGE | 1 | Bridge rectifier |
4 | CAP | 3 | 100μF (×2), 1nF (×1) |
5 | 7805 | 1 | 5V voltage regulator |
6 | GROUND | 1 | Ground connection |
配置
主体
- 主体的RX8设置为100
- VSINE设置为220v50Hz
变压器
- VSINE 220v 50Hz
- TRAN-2P2S 1H 0.015H
示意图
keil
代码
#include <reg51.h>
// 定义 P2 口的位
sbit LED = P1^7;
sbit BUTTON = P3^6;
sbit LAMP = P3^2;
sbit SWITCH1 = P1^2; // 双控开关位置在P1.2
// 数码管段码表(共阳极)
unsigned char code SEG_CODE[] = {
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
// 延时函数,延时 1ms
void delay_ms(unsigned int ms) {
unsigned int i, j;
for (i = 0; i < ms; i++)
for (j = 0; j < 123; j++);
}
// 串口初始化函数
void UART_Init() {
TMOD = 0x20; // 设置定时器 1 为模式 2
TH1 = 0xFD; // 波特率 9600
TL1 = 0xFD;
SCON = 0x50; // 设置串口为模式 1
TR1 = 1; // 启动定时器 1
}
// 串口发送字符函数
void UART_SendChar(unsigned char c) {
SBUF = c;
while (TI == 0);
TI = 0;
}
// 主函数
void main() {
unsigned char count = 0;
bit button_state = 0;
bit switch_state = 0;
bit led_state = 0;
LAMP = 0;
P0 = 0xFF; // 模拟上拉电阻
UART_Init(); // 初始化串口
while (1) {
// 检测双控开关状态变化
if (SWITCH1 == 0) {
delay_ms(20); // 消抖
if (SWITCH1 == 0 && !switch_state) {
switch_state = 1;
// 增加计数值
if (count < 15) {
count++;
} else {
count = 0; // 复位计数
}
// 在数码管上显示计数
P0 = SEG_CODE[count];
// 通过串口发送当前段码值
UART_SendChar(SEG_CODE[count]);
// 切换LED状态
if (!led_state) {
LED = 0;
led_state = 1;
LAMP = 1;
} else {
LED = 1;
LAMP = 0;
led_state = 0;
}
delay_ms(100); // 增加显示延时
}
} else {
switch_state = 0;
}
// 原有按钮检测逻辑
if (BUTTON == 0) {
delay_ms(20); // 消抖
if (BUTTON == 0) {
if (!button_state) {
button_state = 1;
if (count < 15) {
count++;
} else {
count = 0; // 复位计数
}
P0 = SEG_CODE[count]; // 在数码管上显示计数
delay_ms(100); // 增加显示延时
// 通过串口发送当前段码值
UART_SendChar(SEG_CODE[count]);
if (!led_state) {
LED = 0; // 开灯
led_state = 1;
LAMP = 1;
} else {
delay_ms(200); // 延时 200ms
LED = 1; // 关灯
LAMP = 0;
led_state = 0;
}
}
}
} else {
button_state = 0;
}
}
}
链接
gitee:https://gitee.com/blankzsh/proteus
lanzou: https://saem.lanzouq.com/i2FrT2r3rwbi