2020 年底做的一个货色,纯属个人爱好。始终想开源然而因为它是一个很大工程,过后做的时候工夫很缓和没有录制过程,而且首次试做过程中也发现了很多可改良的中央,始终想着有朝一日能重做一个版本,然而工程量切实太微小了,也不不便在家做,只好有限搁置。明天是一个非凡日子,就先把源码拿进去整顿一下吧。
设计很简略,一个一键无锁开关,每接通一下播放一次固定音频,第一次接通亮一组 LED(两个),第二次接通亮两组 LED,第三次接通亮三组 LED,第四次燃烧全副 LED 回到初始状态。
主控是通过 8051 单片机实现的,选用的是 STC12C2052,音频播放则是应用了 DFPlayer Mini。电路图待补。
参考一本书里提供的流水灯例程,但它是用 Keil μVersion 写的工程,Keil 免费版对编译完的 16 进制文件大小有限度……所以我只好换了收费的 SDCC 编译器 +Code Blocks,它俩的一些定义有差异,比方寄存器和位定义。
流程设计没什么难的,就是循环检测一个全局变量,开关接通做内部中断,一次中断批改一下全局变量的值,循环变动。用了 I / O 接口 P1 做输入,规范双向输出 / 输入工作形式,6 个引脚连了 6 个 LED,原本把音效也放在 8051 里管制了,起初发现接线很麻烦且没必要,都是一键无锁开关,不如间接接开关了。主控程序用 C 语言写的,上面上代码。
/*
Red Queen Exceed and Engine Sound
*/
#include <mcs51/8051.h>
#define DY_PORT P1 //output
#define DY_SPEED 1000 //led on time, ms
__sfr __at 0xE1 WDT_CONTR;
__sbit __at 0xB3 DY_KEY; //input signal
unsigned char MENU = 0;
void delay (unsigned int a){ // 1ms time delay
unsigned int i;
while(--a != 0){for(i = 0; i < 600; i++);
}
}
void INT1Fun(void) __interrupt 2 __using 3 { //external interrupt 1 for register bank 3
EX1 = 0; //disable INT1
if(DY_KEY == 0){ //signal in
delay(20); //delay 20ms //anti shake
if(DY_KEY == 0){ //signal in
//DY_PORT = 0x3F; //sound//move to switch
MENU++;
if(MENU >3){ //three status
MENU = 0;
}
while(DY_KEY == 0); //wait for switch off
}
}
EX1 = 1; //enable INI1
}
void main(void)
{
EA = 1; //enable CPU interrupt
IT1 = 1; //enable INT1 falling edge
EX1 = 1; //enable INT1
WDT_CONTR = 0; //disable watch dog
/*//reset test
DY_PORT = 0x7C;
delay(3000);
DY_PORT = 0x70;
delay(3000);*/
while(1) {if (MENU == 0) {DY_PORT = 0xFF; //OFF}
if (MENU == 1) { //Exceed 1
DY_PORT = 0x7C; //one set of leds
//delay(5000);
}
if (MENU == 2) { //Exceed 2
DY_PORT = 0x70; //two sets of leds
//delay(5000);
}
if (MENU == 3) { //Exceed 3
DY_PORT = 0x40; //three sets of leds
//delay(5000);
}
}
}
SDCC 的位定义和 Keil 不太一样:
__sbit __at 0xB3 DY_KEY; //SDCC
sbit DY_KEY = P3 ^ 3; //Keil
还有寄存器,SDCC 里是:__sfr __at 0xE1 WDT_CONTR;
头文件也不太一样:
#include <mcs51/8051.h> //SDCC
#include <REG51.h> //Keil
前面还有一些调试过程中的这样那样的内容。待补充。