Skip to content

Zenitheee/keyboard-piano

Repository files navigation

键盘钢琴项目 (Keyboard Piano)

基于STM32F4的ZLG7290键盘钢琴实现,支持热启动状态恢复功能。

功能特性

  • 9个音阶支持: 键盘1-9对应C4到D5音阶
  • ZLG7290键盘控制器: 通过I2C接口通信,支持中断触发
  • 热启动恢复: 设备重启时自动恢复到重启前的状态,用户无感知
  • 实时音频播放: 按键按下即时播放对应音符
  • 状态持久化: 使用备份SRAM保存状态,断电不丢失
  • 软件序列监控: 智能看门狗机制,确保关键任务按正确顺序执行后才喂狗

硬件连接

蜂鸣器连接

  • PG6: 蜂鸣器控制引脚

ZLG7290键盘控制器连接

I2C接口

  • PB6: I2C1_SCL (时钟线)
  • PB7: I2C1_SDA (数据线)

中断接口

  • PD13: ZLG7290中断输出引脚 (下降沿触发)

ZLG7290键盘布局

[1] [2] [3]
[4] [5] [6]
[7] [8] [9]

音阶对应关系

键盘按键 音符 频率(Hz) ZLG7290键值 说明
1 C4 262 0x1C 中央C
2 D4 294 0x1B D音
3 E4 330 0x1A E音
4 F4 349 0x14 F音
5 G4 392 0x13 G音
6 A4 440 0x12 A音
7 B4 494 0x0C B音
8 C5 523 0x0B 高音C
9 D5 587 0x0A 高音D

工作原理

键盘检测流程

  1. 中断触发: 按键按下时,ZLG7290拉低PD13引脚
  2. 中断处理: GPIO中断设置key_flag标志
  3. I2C验证读取: 主循环检测到标志后,使用三次验证机制读取按键值
    • 读取两次键盘值,如果一致则使用
    • 如果不一致则读取第三次
    • 第三次读取的值如果与前两次的任意一次相同则使用第三次的数据
    • 如果仍然不一致则算作读取失败
  4. 键值映射: 将ZLG7290键值映射为1-9按键编号
  5. 音符播放: 根据按键编号播放对应音符

热启动功能

工作原理

  • 使用STM32F4的备份SRAM存储状态信息
  • 每100ms自动保存当前状态
  • 按键状态变化时立即保存
  • 设备重启时自动检测并恢复状态

状态信息包含

  • 当前按下的按键
  • 播放状态
  • 播放持续时间
  • 数据完整性校验

热启动特点

  • 用户无感知: 重启后自动恢复,用户体验连续
  • 数据安全: 使用魔数和校验和验证数据完整性
  • 断电保护: 备份SRAM在主电源断开时由备用电池供电

编译和使用

开发环境

  • STM32CubeMX
  • Keil MDK-ARM
  • STM32F4xx HAL库

编译步骤

  1. 使用STM32CubeMX打开 Beep.ioc 文件
  2. 生成代码到MDK-ARM项目
  3. 在Keil中打开项目文件
  4. 编译并下载到STM32F4开发板

使用方法

  1. 连接ZLG7290键盘控制器按照上述引脚定义
  2. 下载程序到开发板
  3. 按下ZLG7290键盘上的1-9按键
  4. 蜂鸣器会播放对应的音符
  5. 测试热启动:在播放过程中重启设备,观察是否自动恢复

代码结构

2_Beep/
├── Src/
│   ├── main.c          # 主程序,包含钢琴逻辑和热启动功能
│   ├── zlg7290.c       # ZLG7290键盘控制器驱动
│   ├── i2c.c           # I2C接口配置
│   └── gpio.c          # GPIO配置
├── Inc/
│   ├── zlg7290.h       # ZLG7290驱动头文件
│   └── i2c.h           # I2C接口头文件
└── README.md           # 本文件

技术细节

音频生成

  • 使用GPIO输出方波信号驱动蜂鸣器
  • 通过控制高低电平持续时间产生不同频率
  • 实时计算延时参数确保音频准确性

ZLG7290通信

  • I2C地址: 0x71 (读取), 0x70 (写入)
  • 键值寄存器: 0x01
  • 中断方式: 下降沿触发
  • 通信速度: 100kHz
  • 验证机制: 三次读取验证,确保数据可靠性
    • 前两次一致:直接使用
    • 前两次不一致:第三次与任意一次匹配即可使用
    • 三次都不一致:读取失败

热启动实现

  • 备份SRAM地址: 0x40024000
  • 魔数验证: 0xDEADBEEF
  • 校验和算法确保数据完整性
  • 自动状态恢复机制

软件序列监控

  • 监控原理: 只有在确认所有关键任务都按正确顺序执行完毕后,才允许喂狗
  • 任务检查点:
    • 检查点A (0x01): 按键检测完成
    • 检查点B (0x02): 按键处理完成
    • 检查点C (0x04): 音频播放完成
    • 检查点D (0x08): 显示更新完成
    • 检查点E (0x10): 系统维护完成
  • 关键任务序列: A + B + E (0x13) - 必须完成的最小任务集
  • 完整任务序列: A + B + C + D + E (0x1F) - 理想的完整执行序列
  • 超时保护: 5秒超时机制,防止系统死锁
  • 统计监控: 详细的序列完成、超时、失败统计

注意事项

  1. 硬件连接: 确保ZLG7290正确连接到I2C和中断引脚
  2. 电源管理: 热启动功能需要备用电池支持备份SRAM
  3. I2C地址: ZLG7290的I2C地址可能需要根据硬件配置调整
  4. 中断优先级: 确保中断优先级配置正确

故障排除

按键无响应

  1. 检查I2C连接是否正确
  2. 检查中断引脚PD13连接
  3. 使用示波器检查I2C通信
  4. 验证ZLG7290电源供电

音频问题

  1. 检查蜂鸣器连接到PG6
  2. 验证音频频率计算
  3. 检查GPIO输出配置

扩展功能

可以在此基础上扩展以下功能:

  • 和弦播放支持
  • 音量控制
  • 节拍器功能
  • MIDI输出
  • 录音回放功能

调试功能

启用调试信息

在相应头文件中取消注释以下宏定义:

// 启用I2C验证调试信息
#define DEBUG_I2C_VALIDATION

// 启用序列监控调试信息  
#define DEBUG_SEQUENCE_MONITOR

// 启用乱序执行调试信息
#define DEBUG_SCRAMBLED_EXECUTION

调试输出内容

  • I2C验证: 三次读取的详细数据对比
  • 序列监控: 检查点设置、序列完成状态、统计信息
  • 看门狗状态: 喂狗成功/失败、序列监控状态
  • 乱序执行: 操作类型统计、执行次数、随机种子状态

乱序执行功能 (侧信道攻击防护)

功能概述

乱序执行功能通过在关键状态执行时插入随机代码,混淆程序的执行模式,从而抵抗基于功耗分析和时序分析的侧信道攻击。

工作原理

  • 随机操作生成: 在关键代码段前后插入5-40个随机操作
  • 多种操作类型: 包括虚拟计算、内存访问、循环延时、位运算、算术运算、条件分支
  • 动态种子更新: 使用按键值、时间戳等动态更新随机种子
  • 统计监控: 详细记录各类操作的执行统计

操作类型详解

1. 虚拟计算 (SCRAMBLE_OP_DUMMY_CALC)

  • 执行无意义的数学运算
  • 包含循环、位移、异或等操作
  • 结果存储在volatile变量中防止编译器优化

2. 内存访问 (SCRAMBLE_OP_MEMORY_ACCESS)

  • 对虚拟缓冲区进行读写操作
  • 随机访问不同内存位置
  • 操作后恢复原始值,不影响系统状态

3. 循环延时 (SCRAMBLE_OP_LOOP_DELAY)

  • 执行随机长度的空循环
  • 包含NOP指令防止编译器优化
  • 模拟不同的处理时间

4. 位运算 (SCRAMBLE_OP_BITWISE)

  • 执行XOR、移位、取反等位运算
  • 创建复杂的位操作模式
  • 增加功耗分析的难度

5. 算术运算 (SCRAMBLE_OP_ARITHMETIC)

  • 执行加减乘除等算术操作
  • 使用随机数作为操作数
  • 模拟不同的计算负载

6. 条件分支 (SCRAMBLE_OP_CONDITIONAL)

  • 执行随机的if/else分支
  • 创建不可预测的执行路径
  • 增加时序分析的复杂度

执行模式

普通模式 (SCRAMBLED_EXECUTE)

  • 执行5-20个随机操作
  • 用于一般的代码段保护
  • 较低的性能开销

关键模式 (SCRAMBLED_EXECUTE_CRITICAL)

  • 执行5-40个随机操作
  • 用于关键代码段的增强保护
  • 分三个阶段执行,提供更强的混淆效果

集成位置

乱序执行已集成到以下关键状态:

  1. 按键检测状态 (State_KeyDetect_Handler)

    • I2C通信前后执行乱序代码
    • 使用按键值更新随机种子
  2. 按键处理状态 (State_KeyProcess_Handler)

    • 按键处理前后执行乱序代码
    • 保护按键映射逻辑
  3. 音频播放状态 (State_AudioPlay_Handler)

    • 音符播放前后执行乱序代码
    • 使用音符信息更新随机种子
  4. 系统维护状态 (State_SystemMaintain_Handler)

    • 状态保存前后执行乱序代码
    • 使用时间戳更新随机种子

配置选项

// 启用/禁用乱序执行功能
#define ENABLE_SCRAMBLED_EXECUTION

// 启用乱序执行调试信息
#define DEBUG_SCRAMBLED_EXECUTION

// 配置参数
#define SCRAMBLE_MIN_OPERATIONS     5       // 最小随机操作数
#define SCRAMBLE_MAX_OPERATIONS     20      // 最大随机操作数
#define SCRAMBLE_DUMMY_BUFFER_SIZE  32      // 虚拟缓冲区大小

API接口

// 初始化乱序执行模块
void ScrambledExecution_Init(void);

// 执行普通乱序操作
void ScrambledExecution_Execute(void);

// 执行关键乱序操作
void ScrambledExecution_ExecuteInCriticalSection(void);

// 更新随机种子
void ScrambledExecution_UpdateSeed(uint32_t new_seed);

// 获取统计信息
ScrambleStats_t* ScrambledExecution_GetStats(void);

// 打印统计信息
void ScrambledExecution_PrintStats(void);

// 启用/禁用功能
void ScrambledExecution_Enable(uint8_t enable);

统计信息

系统会记录以下统计信息:

  • 总乱序执行次数
  • 执行的操作总数
  • 平均每次执行的操作数
  • 各类操作的执行次数
  • 当前随机种子状态
  • 最后执行时间

性能影响

  • CPU开销: 每次乱序执行增加约0.1-2ms的处理时间
  • 内存开销: 约100字节的RAM用于统计和缓冲区
  • 可配置性: 可通过宏定义调整操作数量平衡安全性和性能

安全效果

  • 功耗分析抵抗: 随机操作掩盖真实操作的功耗特征
  • 时序分析抵抗: 不可预测的执行时间增加分析难度
  • 模式识别抵抗: 每次执行的操作序列都不相同
  • 动态防护: 随机种子持续更新,防护效果不断变化

注意事项

  1. 性能权衡: 根据实际需求调整操作数量
  2. 随机性质量: 定期更新随机种子确保随机性
  3. 编译器优化: 使用volatile关键字防止编译器优化掉虚拟操作
  4. 调试模式: 生产环境中应禁用调试输出以避免信息泄露

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages