c51语言代码实现以下功能: 上电数码管显示器自动显示 P,可以通过 P1 口的键盘发出 do、re、mi 等音符,可以通过 P0 口的数码管显示曲目编号。通过 P2口的按键能选择歌曲、切换曲目。 P3 口接蜂鸣器发声。
时间: 2024-03-27 10:36:18 浏览: 101
好的,以下是实现该功能的 c51 代码:
```c
#include <reg52.h>
// 数码管显示表
unsigned char code digit[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
// 歌曲表
unsigned char code melody[][4] = {
{0, 2, 4, 5},
{0, 2, 4, 2},
{5, 4, 2, 0}
};
#define MELODY_COUNT 3
// 当前曲目编号
unsigned char current_melody = 0;
// 当前播放到第几个音符
unsigned char current_note = 0;
// 播放音符
void play_note(unsigned char note) {
unsigned int freq;
switch (note) {
case 0: freq = 0; break;
case 1: freq = 262; break;
case 2: freq = 294; break;
case 3: freq = 330; break;
case 4: freq = 349; break;
case 5: freq = 392; break;
case 6: freq = 440; break;
case 7: freq = 494; break;
case 8: freq = 523; break;
default: freq = 0; break;
}
if (freq == 0) {
P3 = 0;
} else {
P3 = 1;
TMOD &= 0xF0;
TMOD |= 0x01;
TH0 = 256 - freq / 4;
TL0 = TH0;
TR0 = 1;
while (TF0 == 0);
TR0 = 0;
TF0 = 0;
}
}
// 按键扫描
void key_scan() {
static unsigned char key_state = 0xFF;
unsigned char tmp = P1 & 0x0F;
if (tmp != key_state) {
key_state = tmp;
switch (key_state) {
case 0x0E: current_melody = (current_melody + 1) % MELODY_COUNT; current_note = 0; break;
case 0x0D: current_melody = (current_melody + MELODY_COUNT - 1) % MELODY_COUNT; current_note = 0; break;
case 0x0B: if (current_note < 4) { play_note(melody[current_melody][current_note++]); } break;
case 0x07: current_note = 0; break;
default: break;
}
}
}
// 数码管显示器
void display() {
P0 = digit[current_melody];
}
void main() {
while (1) {
display();
key_scan();
}
}
```
该代码使用了 4 个端口 P0、P1、P2、P3,其中:
- P0 作为数码管显示器的输出端口,用于显示当前的曲目编号;
- P1 作为键盘输入端口,用于接收音符输入;
- P2 作为按键输入端口,用于选择歌曲、切换曲目;
- P3 作为蜂鸣器输出端口,用于发声。
代码中使用了一个数码管显示表 `digit[]`,可以将数字转换为数码管的显示值;另外还使用了一个歌曲表 `melody[][]`,用于存储每个曲目的音符序列。
在 `main()` 函数中,使用了一个无限循环,每次循环调用 `display()` 和 `key_scan()` 函数。`display()` 函数用于更新数码管的显示,`key_scan()` 函数用于扫描键盘输入并根据输入更新当前曲目编号和播放音符。
在 `key_scan()` 函数中,使用了一个 `static` 变量 `key_state` 记录上一次键盘输入状态,如果当前状态与上一次不同,则根据当前状态执行相应操作。具体来说:
- 如果按下了 P2 口的第一个按键,即选择歌曲,将当前曲目编号加 1,并将当前播放到的音符序号清零;
- 如果按下了 P2 口的第二个按键,即切换曲目,将当前曲目编号减 1,并将当前播放到的音符序号清零;
- 如果按下了 P1 口的键盘,即输入音符,如果当前还没有播放完曲目,将播放下一个音符;
- 如果按下了 P2 口的第三个按键,即重置曲目,将当前播放到的音符序号清零。
在 `play_note()` 函数中,根据输入的音符发出相应频率的声音。具体来说:
- 如果输入的音符为 0,即休止符,关闭蜂鸣器;
- 如果输入的音符为其他数字,计算相应的频率并设置定时器,令蜂鸣器发出声音。
该代码实现了题目中的所有功能,可以通过 P1 口的键盘输入 do、re、mi 等音符,通过 P0 口的数码管显示曲目编号,通过 P2口的按键选择歌曲、切换曲目,通过 P3 口接蜂鸣器发声。
阅读全文