找回密码
 立即注册
查看: 111|回复: 4

用【STCAI-万能实验板】做实验 用I2S音频播放方式实现电子琴

[复制链接]
  • 打卡等级:以坛为家I
  • 打卡总天数:235
  • 最近打卡:2026-03-05 11:40:53
已绑定手机

11

主题

68

回帖

581

积分

高级会员

积分
581
发表于 4 天前 | 显示全部楼层 |阅读模式
一直想做一个可以自定义音色,并且可以发出和弦声音的简易电子琴,看到STC32G144K246特别加大了程序存储空间,
正好赶上论坛鼓励大家学习新的芯片,组织了使用万能实验板做实验的活动,我用论坛签到积分兑换了三块实验板,申请了2个芯片,开始行动。

一开始不是很顺利,因为我用的是64脚的芯片,实验板设计时为了兼容64脚和100脚芯片,由于脚位奇偶排列原因,出现了一点疏漏
造成64脚的脚位丝印与实际脚位有偏差,官方更新了正确的脚位图,大家注意一下。

截图202603012329372975.jpg 截图202603012333276130.jpg
为了方便试验,我做了简易的标签贴纸,放在附件了,需要的朋友可以自行打印


脚位贴纸.pdf

221.18 KB, 下载次数: 3

1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:235
  • 最近打卡:2026-03-05 11:40:53
已绑定手机

11

主题

68

回帖

581

积分

高级会员

积分
581
发表于 4 天前 | 显示全部楼层
今天完成了单一的音乐播放,烧录完即可循环播放,借鉴了之前AI8051上例程,但是有一点不一样的地方就是STC32G144K246必须使用PLL时钟,我是个菜鸟,弄明白这些花费了一点时间。但终于出声音了。
文件见附件 电子琴.hex (450.42 KB, 下载次数: 0) ,程序如下:
  1. //=================== 头文件包含 ============================================
  2. #include "STC32G144K246.H"
  3. #include "intrins.h"
  4. #include "yinyue.h"
  5. //=================== 主时钟和采样率定义宏 =================================
  6. #define FOSC 56000000UL      // 系统主时钟 96MHz (由PLL产生)
  7. #define PLL_CLK 480000000UL  // PLL输出时钟 480MHz
  8. #define SampleRate 8000     // 定义采样率
  9. //=================== I2S配置 ============================================
  10. #define MCKOE 0 // I2S主时钟输出使能, 0:禁止I2S主时钟输出, 1:允许I2S主时钟输出
  11. #define I2SEN 0x04 // I2S使能位, 0x00:关闭, 0x04:使能
  12. #define I2S_MODE 2 // I2S模式, 0:从发送, 1:从接收, 2:主发送, 3:主接收,
  13. #define PCMSYNC 0  // PCM同步模式, 0: 长同步, 1: 短同步
  14. #define STD_MODE 0 // I2S标准模式, 0: I2S标准格式, 1: MSB对齐格式, 2:LSB对齐格式, 3:PCM模式, CS4334或CS4344选择0:I2S标准格式,PT8211选择1: MSB对齐格式
  15. #define CKPOL 0           // I2S时钟极性, 0:SCLK空闲时为低电平, 1:SCLK空闲时为高电平
  16. #define DATLEN 0   // 数据长度, 0:16位, 1:24位, 2:32位, 3:保留
  17. #define CHLEN 0           // 声道长度(在PCM模式下), 0:16位, 1: 32位
  18. // 分频系数计算
  19. #define I2S_MCLKDIV (FOSC / (8 * 16 * 2 * SampleRate))  // MCLK分频系数
  20. #define I2S_BCLKDIV (FOSC / (16 * 2 * SampleRate))      // BCLK分频系数
  21. //=================== 类型定义 ============================================
  22. typedef unsigned char u8;
  23. typedef unsigned int u16;
  24. typedef unsigned long u32;
  25. typedef signed int s16;
  26. // 扩展音频索引变量
  27. u32 yinyue_index;
  28. // 扩展音频播放状态
  29. bit yinyue;
  30. u16 buffer[2];
  31. bit flip;
  32. bit flip_local;
  33. //=================== 延时函数 ==============================================
  34. void delay_ms(u16 ms)
  35. {
  36.     u16 i;
  37.     while(ms--)
  38.     {
  39.         i = 4000;
  40.         while(i--);
  41.     }
  42. }
  43. //=================== PLL时钟初始化 ==========================================
  44. void pll_init(void)
  45. {
  46.     // STC32G的PLL初始化
  47.     HPLLCR = 0x10;           // 选择HIRC作为PLL输入
  48.     HPLLPDIV = 8;            // 预分频8, HIRC 48MHz/8 = 6MHz
  49.     HPLLCR |= 0x0e;          // 倍频80, 6MHz*80 = 480MHz
  50.     HPLLCR |= 0x80;          // 使能HPLL
  51.    
  52.     delay_ms(10);             // 等待PLL稳定
  53.    
  54.     CLKDIV = 5;              // 系统时钟分频: 480MHz/5 = 96MHz
  55.     CLKSEL = 0x04;           // 选择HPLL/2作为主时钟源
  56.    
  57.     delay_ms(10);             // 等待时钟切换完成
  58. }
  59. //=================== 系统初始化 ============================================
  60. void system_init(void)
  61. {
  62.     WTST = 0x00;
  63.     CKCON = 0x00;
  64.     EAXFR = 1;
  65.     // 初始化IO口
  66.     P0M0 = 0x00;
  67.     P0M1 = 0x00;
  68.     P1M0 = 0x00;
  69.     P1M1 = 0x00;
  70.    
  71.     P2M0 = 0x00;
  72.     P2M1 = 0x00;
  73.     P2PU = 0xff;     
  74.    
  75.     P3M0 = 0x00;
  76.     P3M1 = 0x00;
  77.     P3PU = 0xff;     
  78.     P4M0 = 0x00;
  79.     P4M1 = 0x00;
  80.     P5M0 = 0x00;
  81.     P5M1 = 0x00;
  82. }
  83. //=================== I2S初始化 ============================================
  84. void i2s_init(void)
  85. {
  86.     I2SMD = 0xff;                               // 模块使能寄存器,初始化为FFH
  87.     I2SSR = 0x00;                               // 状态寄存器清零
  88.     I2SCR = 0x80 + 0x00;                        // 使能I2S模块(0x80), +0x00:Motorola格式, +0x10:TI格式
  89.     HSCLKDIV = 1;                               // 高速时钟分频 1~255 (默认为2)
  90.     I2S_CLKDIV = 1;                             // I2S时钟分频
  91.     I2SMCKDIV = I2S_MCLKDIV;                    // I2S主时钟分频,I2SMCLK = 系统时钟/2/I2S_CLKDIV/HSCLKDIV/I2SMCKDIV, 或I2SMCLK = PLLCLK/2/I2S_CLKDIV/HSCLKDIV/I2SMCKDIV
  92.     I2SPRH = (MCKOE << 1) + (I2S_BCLKDIV & 1);  // 高字节:bit1控制I2S_BMCLK输出使能, bit0为BCLK分频系数的bit0, 同时控制是否输出MCLK
  93.     I2SPRL = I2S_BCLKDIV / 2;                    // 低字节:BCLK分频系数的bit8~bit1
  94.     I2SCFGH = I2S_MODE;                          // 配置I2S工作模式
  95.     I2SCFGL = (PCMSYNC << 7) + (STD_MODE << 4) + (CKPOL << 3) + (DATLEN << 1) + CHLEN;
  96.     P_SW3 = (P_SW3 & 0x3f) | (2 << 6);           // I2S引脚切换,
  97.                                        // 00: P3.2(BCLK) P3.3(MCLK) P3.4(SD) P3.5(LRCK),
  98.                                        // 01: P1.7(BCLK) P1.6(MCLK) P1.5(SD) P1.4(LRCK),
  99.                                        // 10: P2.3(BCLK) P2.2(MCLK) P2.1(SD) P2.0(LRCK),
  100.                                        // 11: P4.3(BCLK) P1.6(MCLK) P4.1(SD) P4.0(LRCK)
  101. }
  102. //=================== 音频初始化 ==============================================
  103. void audio_init(void)
  104. {
  105.     yinyue_index = 0;
  106.     buffer[0] = 128;
  107.     buffer[1] = 128;
  108.     flip = 0;
  109.     flip_local = 0;
  110. }
  111. //=================== I2S中断服务程序 ================================
  112. void I2S_ISR(void) interrupt 62
  113. {
  114.     if (I2SSR & 0x02)  // 发送缓冲区空
  115.     {
  116.         s16 audio_data;
  117.         
  118.         // 正确的8位转16位转换
  119.         // 减去128去除直流偏置,左移7位得到16位有符号值
  120.         audio_data = ((s16)buffer[flip] - 128) << 7;
  121.         
  122.         // 音量调节选项(取消注释其中一个):
  123.         // audio_data = ((s16)buffer[flip] - 128) << 6;  // 最小音量
  124.         // audio_data = ((s16)buffer[flip] - 128) << 7;  // 中等音量
  125.         // audio_data = ((s16)buffer[flip] - 128) << 8;  // 最大音量
  126.         
  127.         // 发送16位数据
  128.         I2SDRH = (u8)(audio_data >> 8);   // 高8位
  129.         I2SDRL = (u8)audio_data;           // 低8位
  130.         
  131.         // 左声道切换缓冲区
  132.         if (!(I2SSR & 0x04))
  133.         {
  134.             flip = !flip;
  135.         }
  136.     }
  137. }
  138. //=================== 主函数 ==============================================
  139. void main(void)
  140. {
  141.     system_init();   // 系统初始化
  142.     pll_init();      // PLL时钟初始化
  143.     i2s_init();      // I2S初始化
  144.     audio_init();    // 音频初始化
  145.    
  146.     I2SCFGH |= I2SEN;  // 使能I2S
  147.     EA = 1;              // 使能全局中断
  148.    
  149.     while (1)
  150.     {
  151.         if (flip_local != flip)
  152.         {
  153.             buffer[flip_local] = yinyue_pcm[yinyue_index];
  154.             
  155.             yinyue_index++;
  156.             if (yinyue_index >= yinyue_pcm_len)
  157.             {
  158.                 yinyue_index = 0;
  159.             }
  160.             
  161.             flip_local = flip;
  162.         }
  163.         _nop_();
  164.     }
  165. }
复制代码


截图202603012345005203.jpg



但是可能是因为之前没注意丝印错误,一直把VCC接到IO口上测试的原因,现在这个单片机在3.3V下能够正常工作,5V下就不正常了。不知道还有没有其他问题,反正现在用3.3V能播放了。下一步添加7个按键实现7个音节。

回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:179
  • 最近打卡:2026-03-05 00:02:24
已绑定手机

8

主题

184

回帖

1111

积分

金牌会员

DIY玩家

积分
1111
发表于 3 天前 | 显示全部楼层
灰太*** 发表于 2026-3-1 23:51
今天完成了单一的音乐播放,烧录完即可循环播放,借鉴了之前AI8051上例程,但是有一点不一样的地方就是STC3 ...

5V电源有无稳压滤波
真正的学徒往往怀着大师的心
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:235
  • 最近打卡:2026-03-05 11:40:53
已绑定手机

11

主题

68

回帖

581

积分

高级会员

积分
581
发表于 前天 09:40 来自手机 | 显示全部楼层
狂热主宰 发表于 2026-3-2 14:56
5V电源有无稳压滤波

我回来加个滤波电容试一下
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:345
  • 最近打卡:2026-03-05 08:34:25

842

主题

1万

回帖

2万

积分

管理员

积分
22582
发表于 昨天 10:18 | 显示全部楼层

已更新设计

截图202603041018049482.jpg



截图202603041023314281.jpg
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-3-5 22:40 , Processed in 0.110737 second(s), 70 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表