STC32G144K246PLL时钟I2S音频播放方式电子琴

/

复制代码
  • /=================== 头文件包含 ============================================
  • #include "STC32G144K246.H"
  • #include "intrins.h"
  • #include "yinyue.h"
  • //=================== 主时钟和采样率定义宏 =================================
  • #define FOSC 56000000UL // 系统主时钟 96MHz (由PLL产生)
  • #define PLL_CLK 480000000UL // PLL输出时钟 480MHz
  • #define SampleRate 8000 // 定义采样率
  • //=================== I2S配置 ============================================
  • #define MCKOE 0 // I2S主时钟输出使能, 0:禁止I2S主时钟输出, 1:允许I2S主时钟输出
  • #define I2SEN 0x04 // I2S使能位, 0x00:关闭, 0x04:使能
  • #define I2S_MODE 2 // I2S模式, 0:从发送, 1:从接收, 2:主发送, 3:主接收,
  • #define PCMSYNC 0 // PCM同步模式, 0: 长同步, 1: 短同步
  • #define STD_MODE 0 // I2S标准模式, 0: I2S标准格式, 1: MSB对齐格式, 2:LSB对齐格式, 3:PCM模式, CS4334或CS4344选择0:I2S标准格式,PT8211选择1: MSB对齐格式
  • #define CKPOL 0 // I2S时钟极性, 0:SCLK空闲时为低电平, 1:SCLK空闲时为高电平
  • #define DATLEN 0 // 数据长度, 0:16位, 1:24位, 2:32位, 3:保留
  • #define CHLEN 0 // 声道长度(在PCM模式下), 0:16位, 1: 32位
  • // 分频系数计算
  • #define I2S_MCLKDIV (FOSC / (8 * 16 * 2 * SampleRate)) // MCLK分频系数
  • #define I2S_BCLKDIV (FOSC / (16 * 2 * SampleRate)) // BCLK分频系数
  • //=================== 类型定义 ============================================
  • typedef unsigned char u8;
  • typedef unsigned int u16;
  • typedef unsigned long u32;
  • typedef signed int s16;
  • // 扩展音频索引变量
  • u32 yinyue_index;
  • // 扩展音频播放状态
  • bit yinyue;
  • u16 buffer[2];
  • bit flip;
  • bit flip_local;
  • //=================== 延时函数 ==============================================
  • void delay_ms(u16 ms)
  • {
  • u16 i;
  • while(ms--)
  • {
  • i = 4000;
  • while(i--);
  • }
  • }
  • //=================== PLL时钟初始化 ==========================================
  • void pll_init(void)
  • {
  • // STC32G的PLL初始化
  • HPLLCR = 0x10; // 选择HIRC作为PLL输入
  • HPLLPDIV = 8; // 预分频8, HIRC 48MHz/8 = 6MHz
  • HPLLCR |= 0x0e; // 倍频80, 6MHz*80 = 480MHz
  • HPLLCR |= 0x80; // 使能HPLL
  • delay_ms(10); // 等待PLL稳定
  • CLKDIV = 5; // 系统时钟分频: 480MHz/5 = 96MHz
  • CLKSEL = 0x04; // 选择HPLL/2作为主时钟源
  • delay_ms(10); // 等待时钟切换完成
  • }
  • //=================== 系统初始化 ============================================
  • void system_init(void)
  • {
  • WTST = 0x00;
  • CKCON = 0x00;
  • EAXFR = 1;
  • // 初始化IO口
  • P0M0 = 0x00;
  • P0M1 = 0x00;
  • P1M0 = 0x00;
  • P1M1 = 0x00;
  • P2M0 = 0x00;
  • P2M1 = 0x00;
  • P2PU = 0xff;
  • P3M0 = 0x00;
  • P3M1 = 0x00;
  • P3PU = 0xff;
  • P4M0 = 0x00;
  • P4M1 = 0x00;
  • P5M0 = 0x00;
  • P5M1 = 0x00;
  • }
  • //=================== I2S初始化 ============================================
  • void i2s_init(void)
  • {
  • I2SMD = 0xff; // 模块使能寄存器,初始化为FFH
  • I2SSR = 0x00; // 状态寄存器清零
  • I2SCR = 0x80 + 0x00; // 使能I2S模块(0x80), +0x00:Motorola格式, +0x10:TI格式
  • HSCLKDIV = 1; // 高速时钟分频 1~255 (默认为2)
  • I2S_CLKDIV = 1; // I2S时钟分频
  • I2SMCKDIV = I2S_MCLKDIV; // I2S主时钟分频,I2SMCLK = 系统时钟/2/I2S_CLKDIV/HSCLKDIV/I2SMCKDIV, 或I2SMCLK = PLLCLK/2/I2S_CLKDIV/HSCLKDIV/I2SMCKDIV
  • I2SPRH = (MCKOE << 1) + (I2S_BCLKDIV & 1); // 高字节:bit1控制I2S_BMCLK输出使能, bit0为BCLK分频系数的bit0, 同时控制是否输出MCLK
  • I2SPRL = I2S_BCLKDIV / 2; // 低字节:BCLK分频系数的bit8~bit1
  • I2SCFGH = I2S_MODE; // 配置I2S工作模式
  • I2SCFGL = (PCMSYNC << 7) + (STD_MODE << 4) + (CKPOL << 3) + (DATLEN << 1) + CHLEN;
  • P_SW3 = (P_SW3 & 0x3f) | (2 << 6); // I2S引脚切换,
  • // 00: P3.2(BCLK) P3.3(MCLK) P3.4(SD) P3.5(LRCK),
  • // 01: P1.7(BCLK) P1.6(MCLK) P1.5(SD) P1.4(LRCK),
  • // 10: P2.3(BCLK) P2.2(MCLK) P2.1(SD) P2.0(LRCK),
  • // 11: P4.3(BCLK) P1.6(MCLK) P4.1(SD) P4.0(LRCK)
  • }
  • //=================== 音频初始化 ==============================================
  • void audio_init(void)
  • {
  • yinyue_index = 0;
  • buffer[0] = 128;
  • buffer[1] = 128;
  • flip = 0;
  • flip_local = 0;
  • }
  • //=================== I2S中断服务程序 ================================
  • void I2S_ISR(void) interrupt 62
  • {
  • if (I2SSR & 0x02) // 发送缓冲区空
  • {
  • s16 audio_data;
  • // 正确的8位转16位转换
  • // 减去128去除直流偏置,左移7位得到16位有符号值
  • audio_data = ((s16)buffer[flip] - 128) << 7;
  • // 音量调节选项(取消注释其中一个):
  • // audio_data = ((s16)buffer[flip] - 128) << 6; // 最小音量
  • // audio_data = ((s16)buffer[flip] - 128) << 7; // 中等音量
  • // audio_data = ((s16)buffer[flip] - 128) << 8; // 最大音量
  • // 发送16位数据
  • I2SDRH = (u8)(audio_data >> 8); // 高8位
  • I2SDRL = (u8)audio_data; // 低8位
  • // 左声道切换缓冲区
  • if (!(I2SSR & 0x04))
  • {
  • flip = !flip;
  • }
  • }
  • }
  • //=================== 主函数 ==============================================
  • void main(void)
  • {
  • system_init(); // 系统初始化
  • pll_init(); // PLL时钟初始化
  • i2s_init(); // I2S初始化
  • audio_init(); // 音频初始化
  • I2SCFGH |= I2SEN; // 使能I2S
  • EA = 1; // 使能全局中断
  • while (1)
  • {
  • if (flip_local != flip)
  • {
  • buffer[flip_local] = yinyue_pcm[yinyue_index];
  • yinyue_index++;
  • if (yinyue_index >= yinyue_pcm_len)
  • {
  • yinyue_index = 0;
  • }
  • flip_local = flip;
  • }
  • _nop_();
  • }
  • }

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

https://www.stcaimcu.com/thread-22809-1-1.html

(出处: 国芯人工智能技术交流网站)

相关推荐
LCG米5 小时前
STM32硬件CRC外设实测:多项式固定陷阱、CRC-32校验不匹配根因与软件查表法耗时对比落地
stm32·单片机·嵌入式硬件
La Pulga9 小时前
【FreeRTOS源码学习笔记】任务切换
单片机·mcu·学习·嵌入式·freertos·实时操作系统
女神下凡12 小时前
芯参谋(85):Linux_PPI_NAND_驱动开发指南
linux·运维·arm开发·驱动开发·单片机·嵌入式硬件·设计规范
Zw-awa13 小时前
从 CH340 到 HC-05 和 HC-06:让小车脱离电脑
stm32
硅基手札14 小时前
【Linux 内核专栏 19】20 · 嵌入式子系统 — GPIO·pinctrl·clock·regulator
linux·运维·单片机·linux内核·嵌入式开发·调试定位
何粥学16 小时前
Vivado 2024.2 开发记录(AC820 Zynq-7020)——软件使用,点亮led灯
单片机·嵌入式硬件·zynq
Sakura_j_h_17 小时前
51 单片机驱动四位数码管:动态扫描、限流电阻与消影的取舍
单片机·嵌入式硬件·51单片机·嵌入式·数码管·动态扫描·限流电阻
HANDY0920018 小时前
从“不照人”到“剂量达标”:扇叶遮挡式UV-C空气消毒的工程边界与可验证评估框架
开发语言·人工智能·嵌入式硬件·智能家居
飞凌嵌入式20 小时前
千次静电放电试炼,守住飞凌嵌入式硬件可靠底线
嵌入式硬件
蹊黎1 天前
Linux 下用 C 语言实现进度条
linux·c语言·单片机