使用AI8G1K08制作一个播放音符的模块
来一个一闪一闪亮晶晶的歌曲,代码如下:#include <STC8G.H>
#include <intrins.h>
#define FOSC 11059200L// 定义主频11.0592MHz
// 音符频率定义(单位:Hz)
#define L5392// 低音Sol
#define L6440// 低音La
#define M1523// 中音Do
#define M2587// 中音Re
#define M3659// 中音Mi
#define M5784// 中音Sol
#define M6880// 中音La
// 定义音符和持续时间
const unsigned int melody[] = {M1, M1, M5, M5, M6, M6, M5}; // 音符序列
const unsigned int duration[] = {500, 500, 500, 500, 500, 500, 1000}; // 持续时间(ms)
unsigned char currentNote = 0;// 当前播放的音符索引
sbit Buzzer = P5^5;// 修改为P5.5为蜂鸣器控制引脚
// 延时函数(毫秒)
void delay_ms(unsigned int ms) {
unsigned int i, j;
for(i = 0; i < ms; i++)
for(j = 0; j < 1000; j++);
}
// 定时器0初始化
void Timer0_Init() {
AUXR &= 0x7F; // 定时器0时钟12T模式
TMOD &= 0xF0; // 设置定时器0为模式1
TMOD |= 0x01;
ET0 = 1; // 使能定时器0中断
EA = 1; // 开总中断
}
// 设置频率
void Set_Freq(unsigned int freq) {
unsigned long reload;
reload = 65536 - (FOSC/12) / (2*freq); // 计算重装值
TR0 = 0; // 先关闭定时器
TH0 = reload >> 8;
TL0 = reload & 0xFF;
TR0 = 1; // 启动定时器
}
void main() {
unsigned char i;
// 设置P5.5为推挽输出
P5M0 = 0x20; // 设置P5.5为推挽输出(0010 0000)
P5M1 = 0x00;
Buzzer = 0; // 初始输出低电平
Timer0_Init();// 初始化定时器
while(1) {
// 播放"1 1 5 5 | 6 6 5 -"
for(i = 0; i < sizeof(melody)/sizeof(melody); i++) {
currentNote = i;// 更新当前音符索引
Set_Freq(melody);// 设置当前音符频率
delay_ms(duration); // 按指定持续时间播放
}
TR0 = 0; // 关闭定时器(静音)
Buzzer = 0; // 确保蜂鸣器关闭
delay_ms(1000); // 播放间隔1秒
}
}
// 定时器0中断服务函数
void Timer0_ISR() interrupt 1 {
Buzzer = ~Buzzer; // 翻转P5.5状态
// 重新装载定时器值
TH0 = (65536 - (FOSC/12) / (2*melody)) >> 8;
TL0 = (65536 - (FOSC/12) / (2*melody)) & 0xFF;
}
程序文件 以下是对该帖子的回复,内容专业、简洁,字数控制在2000字以内:
您好,感谢您分享使用STC8G1K08制作播放音符模块的代码。以下是对您提供的代码进行分析与优化建议,并针对“一闪一闪亮晶晶”歌曲的实现进行说明。
一、代码结构与功能分析
您提供的代码主要实现了以下功能:
1. 定义主频:#define FOSC 11059200L 设置了系统时钟频率为11.0592MHz。
2. 音符频率定义:通过宏定义了不同音符对应的频率值(如M1=523Hz)。
3. 音符序列与持续时间:melody[] 和 duration[] 数组分别存储了音符和每个音符的持续时间。
4. 蜂鸣器控制引脚:sbit Buzzer = P5^5; 将P5.5设置为蜂鸣器控制引脚。
5. 延时函数:delayms() 实现了毫秒级延时,用于控制音符间隔。
6. 定时器初始化:Timer0Init() 函数用于配置定时器0,但代码未完整,需补充。
二、代码问题与优化建议
1. 定时器配置不完整
当前代码中 Timer0Init() 函数仅设置了 AUXR &= 0x7F;,未对 TMOD 进行完整设置,也未开启定时器。建议补充如下内容:
c
void Timer0Init() {
AUXR &= 0x7F; // 定时器0时钟12T模式
TMOD &= 0xF0; // 清除低4位
TMOD |= 0x01; // 定时器0方式1(16位)
TH0 = 0xFF; // 初值设置
TL0 = 0xE0;
ET0 = 1; // 使能定时器0中断
EA = 1; // 全局中断使能
TR0 = 1; // 启动定时器0
}
2. 音符播放逻辑缺失
当前代码中并未实现基于定时器的音符播放逻辑,仅定义了 melody[] 和 duration[],缺少实际驱动蜂鸣器播放音符的代码。建议添加以下逻辑:
c
void playNote(unsigned int frequency, unsigned int duration) {
if (frequency == 0) return;
unsigned int period = FOSC / (frequency2); // 计算周期
unsigned int count = duration1000 / period; // 计算循环次数
for (unsigned int i = 0; i < count; i++) {
Buzzer = ~Buzzer; // 翻转蜂鸣器状态
delayms(period / 1000); // 延时半个周期
}
}
3. 主循环逻辑缺失
目前代码中未包含主循环,无法触发音符播放。建议在 main() 中添加如下逻辑:
c
void main() {
Timer0Init();
while (1) {
for (currentNote = 0; currentNote < sizeof(melody)/sizeof(melody); currentNote++) {
playNote(melody, duration);
}
}
}
三、“一闪一闪亮晶晶”歌曲实现
“一闪一闪亮晶晶”是一首经典的儿歌,其旋律可表示为:
C C G G A A G
F F E E D D C
对应频率(以中音C=523Hz为例):
C: 523Hz
D: 587Hz
E: 659Hz
F: 698Hz
G: 784Hz
修改 melody[] 和 duration[] 数组如下:
c
const unsigned int melody[] = {M1, M1, M5, M5, M6, M6, M5, M3, M3, M2, M2, M1, M1, M1}; // 旋律
const unsigned int duration[] = {500, 500, 500, 500, 500, 500, 1000, 500, 500, 500, 500, 500, 500, 1000}; // 持续时间
四、注意事项
1. 蜂鸣器类型:若使用有源蜂鸣器,无需PWM控制;若为无源蜂鸣器,需通过定时器或PWM控制频率。
2. 延时精度:当前 delayms() 使用的是简单循环延时,精度较低,适合低频音符播放。高频音符建议使用定时器中断实现更精确的波形控制。
3. 程序稳定性:避免在 playNote() 中使用过多嵌套循环,防止影响系统响应。
五、总结
您提供的代码已具备基本框架,但需补充定时器配置、音符播放逻辑及主循环部分。通过完善这些部分,即可实现“一闪一闪亮晶晶”的播放效果。若您需要进一步优化代码性能或扩展功能(如支持多音轨、音量调节等),欢迎继续交流。
如需完整示例代码,可参考以下结构:
c
include
define FOSC 11059200L
define L5392
define L6440
define M1523
define M2587
define M3659
define M5784
define M6880
sbit Buzzer = P5^5;
const unsigned int melody[] = {M1, M1, M5, M5, M6, M6, M5, M3, M3, M2, M2, M1, M1, M1};
const unsigned int duration[] = {500, 500, 500, 500, 500, 500, 1000, 500, 500, 500, 500, 500, 500, 1000};
void delayms(unsigned int ms);
void Timer0Init();
void playNote(unsigned int frequency, unsigned int duration);
void main() {
Timer0Init();
while(1) {
for (int i = 0; i < sizeof(melody)/sizeof(melody); i++) {
playNote(melody, duration);
}
}
}
void playNote(unsigned int frequency, unsigned int duration) {
if (frequency == 0) return;
unsigned int period = FOSC / (frequency2);
unsigned int count = duration1000 / period;
for (int i = 0; i < count; i++) {
Buzzer = ~Buzzer;
delayms(period / 1000);
}
}
void delayms(unsigned int ms) {
unsigned int i, j;
for(i = 0; i < ms; i++)
for(j = 0; j < 1000; j++);
}
void Timer0Init() {
AUXR &= 0x7F;
TMOD &= 0xF0;
TMOD |= 0x01;
TH0 = 0xFF;
TL0 = 0xE0;
ET0 = 1;
EA = 1;
TR0 = 1;
}
希望以上内容对您有所帮助。如有其他技术问题,欢迎继续提问。
[本文内容由国芯人工智能辅助生成,仅供参考] 制板文件 国芯人工智能 发表于 2025-7-3 13:38
以下是对该帖子的回复,内容专业、简洁,字数控制在2000字以内:
您好,感谢您分享使用STC8G1K08制作播放 ...
非常感谢大佬指导,受教{:4_196:} 试试这个
下载时选择时钟12M
#include <AI8G.H>
#define OUT P32
unsigned int p;
unsigned int code A=
{
0xC447, 0xC7A1, 0xCACB, 0xCDC8, 0xD099, 0xD342, 0xD5C5, 0xD824, 0xDA61, 0xDC7D, 0xDE7B, 0xE05D,
0xE223, 0xE3D1, 0xE566, 0xE6E4, 0xE84D, 0xE9A1, 0xEAE3, 0xEC12, 0xED30, 0xEE3F, 0xEF3E, 0xF02E,
0xF112, 0xF1E8, 0xF2B3, 0xF372, 0xF426, 0xF4D1, 0xF571, 0xF609, 0xF698, 0xF71F, 0xF79F, 0xF817,
0xF889, 0xF8F4, 0xF959, 0xF9B9, 0xFA13, 0xFA68, 0xFAB9, 0xFB04, 0xFB4C, 0xFB90, 0xFBCF, 0xFC0C,
0xFC44, 0xFC7A, 0xFCAD, 0xFCDC, 0xFD0A, 0xFD34, 0xFD5C, 0xFD82, 0xFDA6, 0xFDC8, 0xFDE8, 0xFE06,
0xFE22, 0xFE3D, 0xFE56, 0xFE6E, 0xFE85, 0xFE9A, 0xFEAE, 0xFEC1, 0xFED3, 0xFEE4, 0xFEF4, 0xFF03,
0xFF11, 0xFF1F, 0xFF2B, 0xFF37, 0xFF42, 0xFF4D, 0xFF57, 0xFF61, 0xFF6A, 0xFF72, 0xFF7A, 0xFF81,
};
unsigned char code C[]=
{
3,1,8,3,4,8,3,6,8,7,12,16,3,4,8,3,6,8,7,12,16,3,4,8,3,6,8,3,9,8,3,4,8,3,6,8,3,1,8,7,12,8,
3,1,8,3,4,8,3,6,8,7,12,16,3,4,8,3,6,8,7,12,16,3,4,8,3,6,8,4,0,8,3,9,8,3,11,8,3,6,8,7,12,8,
3,1,8,3,4,8,3,6,8,7,12,16,3,4,8,3,6,8,7,12,16,3,4,8,3,6,8,3,9,8,3,4,8,3,6,8,3,1,8,3,4,8,2,9,8,2,11,8,
3,1,16,3,9,16,3,6,16,4,0,16,3,11,8,4,0,4,3,11,4,3,9,8,3,11,8,3,6,8,7,12,24,
3,6,16,3,6,16,3,6,16,3,6,4,3,9,4,3,11,4,4,0,4,3,6,16,3,6,16,3,6,8,3,4,8,3,4,8,3,6,8,
3,6,16,3,6,16,3,6,16,3,6,4,3,9,4,3,11,4,4,0,4,3,6,16,3,6,16,3,6,8,4,2,16,4,0,8,
3,6,16,3,6,16,3,6,16,3,6,4,3,9,4,3,11,4,4,0,4,3,6,16,3,6,16,3,6,8,3,4,8,3,4,8,3,6,8,
3,6,16,3,6,16,3,6,16,3,6,4,3,9,4,3,11,4,4,0,4,4,6,16,3,6,8,3,4,8,3,4,8,3,6,8,3,6,8,7,12,32,
3,6,8,3,6,8,3,4,4,3,4,8,7,12,4,3,6,8,3,4,8,3,1,8,3,1,8,3,4,4,3,1,28,7,12,32,
3,6,8,3,6,8,3,4,8,3,6,8,3,8,8,3,9,16,3,8,16,3,6,8,3,8,4,3,6,4,3,4,16,7,12,24,
3,6,8,3,6,8,3,4,4,3,4,8,7,12,4,3,6,8,3,4,8,3,1,8,3,1,8,3,4,4,3,1,16,7,12,12,
3,4,8,3,4,8,3,6,8,7,12,8,3,4,8,3,4,8,3,6,8,7,12,8,3,4,4,3,6,4,3,9,16,3,11,16,3,6,8,3,1,8,3,1,8,3,4,8,3,4,8,3,6,16,4,0,8,3,11,24,3,6,8,7,12,8,3,6,8,7,12,8,4,0,8,3,11,24,7,12,16,
3,11,8,3,11,8,3,10,8,3,11,8,3,10,4,3,6,8,7,12,4,3,4,8,7,12,8,3,4,8,3,4,8,3,6,8,3,6,8,3,1,8,3,1,8,3,4,8,3,4,8,3,6,16,4,0,8,3,11,24,3,6,8,7,12,8,3,6,8,7,12,8,4,0,8,3,11,24,7,12,16,
3,11,8,3,11,8,3,10,8,3,11,8,3,10,4,3,6,8,7,12,4,3,4,16,3,6,8,3,6,8,3,4,8,3,6,16,7,12,8,3,1,4,3,4,4,3,6,8,3,6,8,3,6,8,4,0,8,4,0,8,7,12,16,
3,9,4,3,9,4,3,11,8,3,9,4,3,11,12,4,0,8,3,6,8,7,12,16,
3,4,4,3,4,4,3,6,16,4,0,12,4,0,4,3,11,8,3,9,8,3,6,8,3,4,8,3,6,12,3,6,12,3,9,8,3,11,16,7,12,16,
3,6,8,3,6,4,3,6,12,3,4,8,3,6,8,4,0,16,3,9,4,3,9,4,3,11,8,3,9,4,3,11,12,4,0,8,4,0,8,7,12,16,
3,4,8,3,6,8,3,9,8,7,12,8,3,4,8,3,6,8,4,0,8,7,12,8,3,11,8,3,9,8,3,8,8,3,6,8,3,4,8,3,6,24,7,12,8,
3,6,16,3,6,16,3,6,16,3,6,4,3,9,4,3,11,4,4,0,4,3,6,16,3,6,16,3,6,8,3,4,8,3,4,8,3,6,8,
3,6,16,3,6,16,3,6,16,3,6,4,3,9,4,3,11,4,4,0,4,3,6,16,3,6,16,3,6,8,4,2,16,4,0,8,
3,6,16,3,6,16,3,6,16,3,6,4,3,9,4,3,11,4,4,0,4,3,6,16,3,6,16,3,6,8,3,4,8,3,4,8,3,6,8,
3,6,16,3,6,16,3,6,16,3,6,4,3,9,4,3,11,4,4,0,4,4,6,16,3,6,8,3,4,8,3,4,8,3,6,8,3,6,8,7,12,32,
3,6,8,3,6,8,3,4,4,3,4,8,7,12,4,3,6,8,3,4,8,3,1,8,3,1,8,3,4,4,3,1,28,7,12,32,
3,6,8,3,6,8,3,4,8,3,6,8,3,8,8,3,9,16,3,8,16,3,6,8,3,8,4,3,6,4,3,4,16,7,12,24,
3,6,8,3,6,8,3,4,4,3,4,8,7,12,4,3,6,8,3,4,8,3,1,8,3,1,8,3,4,4,3,1,16,7,12,12,
3,4,8,3,4,8,3,6,8,7,12,8,3,4,8,3,4,8,3,6,8,7,12,8,3,4,4,3,6,4,3,9,16,3,11,16,3,6,8,3,1,8,3,1,8,3,4,8,3,4,8,3,6,16,4,0,8,3,11,24,3,6,8,7,12,8,3,6,8,7,12,8,4,0,8,3,11,24,7,12,16,
3,11,8,3,11,8,3,10,8,3,11,8,3,10,4,3,6,8,7,12,4,3,4,8,7,12,8,3,4,8,3,4,8,3,6,8,3,6,8,3,1,8,3,1,8,3,4,8,3,4,8,3,6,16,4,0,8,3,11,24,3,6,8,7,12,8,3,6,8,7,12,8,4,0,8,3,11,24,7,12,16,
3,11,8,3,11,8,3,10,8,3,11,8,3,10,4,3,6,8,7,12,4,3,4,16,3,6,8,3,6,8,3,4,8,3,6,16,7,12,8,3,1,4,3,4,4,3,6,8,3,6,8,3,6,8,4,0,8,4,0,8,7,12,16,
3,9,4,3,9,4,3,11,8,3,9,4,3,11,12,4,0,8,3,6,8,7,12,16,
3,4,4,3,4,4,3,6,16,4,0,12,4,0,4,3,11,8,3,9,8,3,6,8,3,4,8,3,6,12,3,6,12,3,9,8,3,11,16,7,12,16,
3,6,8,3,6,4,3,6,12,3,4,8,3,6,8,4,0,16,3,9,4,3,9,4,3,11,8,3,9,4,3,11,12,4,0,8,4,0,8,7,12,16,
3,4,8,3,6,8,3,9,8,7,12,8,3,4,8,3,6,8,4,0,8,7,12,8,3,11,8,3,9,8,3,8,8,3,6,8,3,4,8,3,6,24,7,12,8,
7,12,64
};
void Init(void)
{
P3M0=0x00;
P3M1=0x00;
P5M0=0x00;
P5M1=0x00;
AUXR&=0x7F;
TMOD&=0xF0;
AUXR&=0xBF;
TMOD&=0x0F;
ET0=1;
ET1=1;
EA=1;
TH1=0x91;
TL1=0x2E;
TR1=1;
}
void main(void)
{
Init();
while(1)
{
}
}
void Timer0_Isr(void) interrupt 1
{
OUT=!OUT;
}
void Timer1_Isr(void) interrupt 3
{
static unsigned char d,t;
if(d==1)
{
d=0;
if((C<7||C<12)&&t!=C-1)
{
TH0=A*12+C]>>8;
TL0=A*12+C]&0xFF;
TR0=1;
}
else
{
TH0=0;
TL0=0;
TR0=0;
OUT=1;
}
t++;
if(t==C)
{
t=0;
p++;
if(P==sizeof(C)/3)
p=0;
}
}
d++;
}
程序文件:
DebugLab 发表于 2025-7-3 15:42
程序文件:
极乐净土? 晓飛飛 发表于 2025-7-3 19:11
极乐净土?
正确 大神有没有FC游戏的背景音乐代码
页:
[1]