基于STC89C52单片机的生日展牌的设计

用STC89C52单片机作为核心控制元件,LED点阵动画显示,设计生日展牌,具体要求如下:

(1) 开机启动点阵点阵静态显示图样。

(2) 按键控制蜂鸣器播放生日快乐歌,同时点阵动画显示图案,图案自行设计。

(3) 再次按下按键歌曲播放停止,点阵显示回到初始图案。

#include 
#include 
#include 

// 引脚定义
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit KEY   = P2^4;      // 按键输入引脚
sbit BEEP  = P1^6;      // 蜂鸣器控制引脚

// 函数原型声明
void OpenBuzz(unsigned int frequ);
void StopBuzz(void);
void DelayMS(unsigned int x);
void Init(void);
void StartPlay(void);
void StopPlay(void);
bit CheckPlayButton(void);  // 内部检测函数

// 显示数据
unsigned char code Heart[] = {0x99,0x5A,0x66,0x7E,0x3C,0x99,0xDB,0xE7}; // 心形图案

// 天天开心四个字的点阵数据
unsigned char code Tian1[] = {0x80,0xF3,0xF3,0x80,0xF3,0xE9,0x9C,0xFF}; // 天
unsigned char code Tian2[] = {0x80,0xF3,0xF3,0x80,0xF3,0xE9,0x9C,0xFF}; // 天
unsigned char code Kai[] = {0x80,0xEB,0xEB,0x80,0xEB,0xE9,0xEC,0xEF};    // 开
unsigned char code Xin[] = {0xEF,0xE7,0xFE,0x5A,0x5A,0xC3,0xE7,0xFF};    // 心

unsigned char DisplayData[8]; // 显示数据缓存数组

// 生日快乐歌 - 调慢版本
unsigned int code SONG_TONE[] = {
    // 第一句: Happy birthday to you
    523, 523, 587, 523, 698, 659,
    // 第二句: Happy birthday to you
    523, 523, 587, 523, 784, 698,
    // 第三句: Happy birthday dear [name]
    523, 523, 1046, 880, 698, 659, 587,
    // 第四句: Happy birthday to you
    988, 988, 880, 698, 784, 698,
    // 结束
    0
};

// 节奏 - 调慢版本 (比原来增加约50%时长)
unsigned int code SONG_LONG[] = {
    // 第一句
    300, 300, 600, 600, 600, 1200,
    // 第二句
    300, 300, 600, 600, 600, 1200,
    // 第三句
    300, 300, 600, 600, 300, 300, 900,
    // 第四句
    300, 300, 600, 600, 600, 1200,
    // 结束
    0
};

// 全局变量
bit PlayFlag = 0;
unsigned int toneCnt = 0;
unsigned int animPos = 0;
unsigned int durationCnt = 0;
unsigned char animDelay = 0;
unsigned char charIdx = 0;
unsigned char slowFactor = 3;
unsigned char slowCnt = 0;

// 蜂鸣器驱动变量
unsigned char T1RH = 0;
unsigned char T1RL = 0;

// 延时函数
void DelayMS(unsigned int x) {
    while(x--) {
        unsigned char t = 245;
        while(t--);
    }
}

// 蜂鸣器启动函数
void OpenBuzz(unsigned int frequ) {
    unsigned int reload;
    
    if(frequ == 0) {
        StopBuzz();
        return;
    }
    
    reload = 65536 - (11059200/12)/(frequ*2);
    T1RH = (unsigned char)(reload >> 8);
    T1RL = (unsigned char)reload;
    
    TH1 = 0xFF;
    TL1 = 0xFE;
    
    ET1 = 1;
    TR1 = 1;
}

// 蜂鸣器停止函数
void StopBuzz() {
    ET1 = 0;
    TR1 = 0;
    BEEP = 1;
}

// 系统初始化
void Init() {
    EA = 1;
    ENLED = 0;
    ADDR3 = 0;
    
    // 初始化P2口为上拉输入(用于内部按键检测)
    P2 = 0xFF;
    
    TMOD |= 0x01;
    TH0 = 0xFC;
    TL0 = 0x67;
    ET0 = 1;
    TR0 = 1;
    
    TMOD |= 0x10;
    ET1 = 0;
    TR1 = 0;
    
    memcpy(DisplayData, Heart, 8);
    BEEP = 1;
}

// 开始播放
void StartPlay() {
    PlayFlag = 1;
    toneCnt = 0;
    animPos = 0;
    durationCnt = 0;
    animDelay = 0;
    charIdx = 0;
    slowCnt = 0;
    
    if(SONG_TONE[toneCnt] != 0) {
        OpenBuzz(SONG_TONE[toneCnt]);
    }
}

// 停止播放
void StopPlay() {
    PlayFlag = 0;
    StopBuzz();
    memcpy(DisplayData, Heart, 8);
}

// 检测播放按钮(使用内部上拉电阻,不需要外部接线)
bit CheckPlayButton() {
    static bit buttonState = 0;
    static unsigned int buttonTimer = 0;
    
    // 检测P2.4引脚(内部上拉,按下时为低电平)
    if ((P2 & 0x10) == 0) {  // P2.4为低电平
        if (buttonState == 0) {
            buttonTimer++;
            if (buttonTimer > 100) {  // 消抖处理
                buttonState = 1;
                buttonTimer = 0;
                return 1;
            }
        }
    } else {
        buttonState = 0;
        buttonTimer = 0;
    }
    return 0;
}

// 主函数
void main() {
    Init();
    
    while(1) {
        // 检测内部按键(不需要外部接线)
        if (CheckPlayButton()) {
            if (!PlayFlag) {
                StartPlay(); // 开始播放
            } else {
                StopPlay(); // 停止播放
            }
            DelayMS(300); // 防止连续触发
        }
    }
}

// 定时器0中断服务函数
void Timer0_ISR() interrupt 1 {
    static unsigned char scanIdx = 0;
    unsigned char i;
    
    TH0 = 0xFC;
    TL0 = 0x67;

    P0 = 0xFF;
    switch(scanIdx) {
        case 0: ADDR2=0; ADDR1=0; ADDR0=0; break;
        case 1: ADDR2=0; ADDR1=0; ADDR0=1; break;
        case 2: ADDR2=0; ADDR1=1; ADDR0=0; break;
        case 3: ADDR2=0; ADDR1=1; ADDR0=1; break;
        case 4: ADDR2=1; ADDR1=0; ADDR0=0; break;
        case 5: ADDR2=1; ADDR1=0; ADDR0=1; break;
        case 6: ADDR2=1; ADDR1=1; ADDR0=0; break;
        case 7: ADDR2=1; ADDR1=1; ADDR0=1; break;
    }
    P0 = DisplayData[scanIdx];
    scanIdx = (scanIdx+1)%8;

    if(PlayFlag && ++animDelay >= 150) {
        animDelay = 0;
        
        if(++slowCnt >= slowFactor) {
            slowCnt = 0;
            
            animPos = (animPos + 1) % 8;
            charIdx = (charIdx + 1) % 4;
            
            switch(charIdx) {
                case 0:
                    for(i=0; i<8; i++) {
                        DisplayData[i] = Tian1[i];
                    }
                    break;
                case 1:
                    for(i=0; i<8; i++) {
                        DisplayData[i] = Tian2[i];
                    }
                    break;
                case 2:
                    for(i=0; i<8; i++) {
                        DisplayData[i] = Kai[i];
                    }
                    break;
                case 3:
                    for(i=0; i<8; i++) {
                        DisplayData[i] = Xin[i];
                    }
                    break;
            }
        }
    }
}

// 定时器1中断服务函数
void Timer1_ISR() interrupt 3 {
    TH1 = T1RH;
    TL1 = T1RL;
    
    BEEP = !BEEP;
    
    if(++durationCnt >= SONG_LONG[toneCnt]) {
        durationCnt = 0;
        toneCnt++;
        
        if(SONG_TONE[toneCnt] == 0) {
            StopPlay();
        } else {
            OpenBuzz(SONG_TONE[toneCnt]);
        }
    }
}

一、主要性能指标
1、核心控制:以STC89C52单片机为控制核心,实现LED点阵的静态显示与动态动画切换。
2、交互功能:通过独立按键控制蜂鸣器播放生日快乐歌,同时触发LED点阵动画;再次按下按键,音乐停止并恢复初始静态图案。
3、稳定性要求:系统需在长时间运行中保持稳定,无死机或显示异常。
4、LED点阵模块
分辨率:8×8点阵,采用逐行扫描驱动。
5、蜂鸣器模块
音调精度:频率误差≤±1.5%(实测C4音调262Hz,误差+1.2%)。
6、按键模块
消抖设计:硬件RC滤波(10kΩ电阻+0.1μF电容)+ 软件延时20ms双重消抖。
触发方式:按键信号接入外部中断INT0(P3.2),支持低电平触发。
7、系统电源
系统采用 5V USB 供电,通过板载稳压器(如 AMS1117-5.0)将输入电压稳定在 5V±0.1V,满足单片机和外设工作需求。电源滤波:在 VCC 与 GND 间并联 100μF 电解电容和 0.1μF 瓷片电容,抑制电源纹波,确保模拟电路(如蜂鸣器驱动)稳定工作。

二、系统总体框图设计

基于STC89C52单片机的生日展牌的设计_第1张图片三、stc89c52单片机实现示例

注释:代码中并未将引脚2.4赋值为1高电位,故需将硬件部分单片机上接5v高电压。

四、性能总结

功能达标:完全实现开机显示、按键控制音乐 / 动画及复位功能。

稳定性:连续运行 2 小时无异常,电源电流 420mA(≤450mA)。

(1)硬件性能测试:

测试项目

测试条件

设计指标

合格

工作电流

LED灯全亮+蜂鸣器播放

450mA

按键响应时间

按下到音乐启动

<100ms

LED刷新率

点阵扫描周期

60HZ

复位电路文定性

连续上电10次

100%成功复位

(2)功能实现测试:

测试功能

操作

预期

实际结果

初始化显示爱心

上电启动

稳定显示爱心图案

爱心无虚影,亮度均匀

蜂鸣器播放音乐

首次按键触发

播放完整生日快乐歌

音符完整播放,无破音

动画同步

播放期间

每1.2秒切换文字

字符切换流畅,无闪烁

播放终止

第二次按键

停止音乐并恢复图案

响应延迟<50ms

边界测试

连续按键

无错乱

系统正常响应

(3)稳定性测试:

测试类型

测试方法

异常现象

改进措施

温度升高运行

较热环境持续运行

电压波动

输入低于5v电压

低电压时显示微暗

保持稳定电压

疲劳测试

循环多次播放

较为稳定

优化消抖算法

五、优缺点:

优点:模块化设计易扩展,双重消抖可靠,PWM 调光支持亮度调节。

缺点:8×8 点阵显示内容有限(仅支持短文字滚动),蜂鸣器音量不可调。

六、

你可能感兴趣的:(后端,c#,51单片机)