当前位置: 首页 > news >正文

RP2040下的I2S Slave Out,PIO状态机(四)

        晚上回家后,进行硬件的实际调试,测试的时候我发现一个问题,输出有点不对劲,BCK和LRCK都是正确的,我用192k的fs,16bit的位深,按道理,发送数据的pin上的信号频率应该是介于BCK和LRCK之间的,但是DOUT的频率示波器测试大概是2K多一点,BCK是6.144Mhz,LRCK是192K,这个数据明显不对。我检查了线路,没有明显的缺陷,我想大概率问题还是在代码上。我又仔细检查了代码。我发现一个问题,DMA的双缓冲区是INT32类型的,而我需要发送的是16位数据。在初始化状态机的代码里面我发现这样的信息:

static inline void i2s_out_slave_init( PIO pio, uint sm, uint offset, uint dout_pin, uint bit_depth) 
{// 自动推导连续时钟引脚(硬件设计常见布局)uint bck_pin  = dout_pin + 1;   // BCK 紧邻 DOUTuint lrck_pin = dout_pin + 2;  // LRCK 紧邻 BCK// 初始化所有引脚功能pio_gpio_init(pio, dout_pin);  // DOUTpio_gpio_init(pio, bck_pin);    // BCK(输入)pio_gpio_init(pio, lrck_pin);   // LRCK(输入)// 核心配置(与标准实现一致)pio_sm_config c = i2s_slave_out_program_get_default_config(offset);sm_config_set_out_pins(&c, dout_pin, 1);          // DOUT 绑定sm_config_set_in_pins(&c, bck_pin);               // BCK 为时钟源sm_config_set_jmp_pin(&c, lrck_pin);              // LRCK 用于声道同步sm_config_set_out_shift(&c, false, false, bit_depth); // 左移(MSB先出),禁用 autopullsm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);    // 合并 FIFO// 应用配置状态机pio_sm_init(pio, sm, offset, &c);// 统一设置初始电平和引脚方向pio_sm_set_pins_with_mask( pio, sm, 0, (7u << dout_pin) );  // zero outputpio_sm_set_pindirs_with_mask( pio, sm, (1u << dout_pin), (7u << dout_pin) );
}

        其中一行代码如下:

sm_config_set_out_shift(&c, false, false, bit_depth); // 左移(MSB先出),禁用 autopull

        这里面有注释,MSB先出,发送16位就终止,这个是I2S标准的格式,意思就是先从高位发送,如果我给的16位有效值都在低位,那岂不是根本发不出去?我想了一下,这个环节我的确还没处理,我想了一下,我应该可以在创建正弦表的时候处理这个问题。我改了一下代码,在生成正弦值之后,把数据左移16位,把有效位放在高16位上,代码如下:

// 生成正弦波表(预计算优化)
bool CSineWave::GenerateSineTable() 
{if( bit_depth == 0 ) {return false;}uint shift = 32 - bit_depth;const double amplitude = static_cast<double>( ( uint32_t(1) << (bit_depth - 1) ) - 1 );for( uint32_t i = 0; i < SINE_TABLE_LENGTH; ++ i ) {int32_t value = static_cast<int32_t>( std::round(amplitude * sin( 2.0 * M_PI * static_cast<double>(i) / SINE_TABLE_LENGTH ) ) );sine_table[i] = value << shift;    }return true;
}

        编译之后,再次测试,OUTPIN输出在示波器上显示出正确的频率。

http://www.lryc.cn/news/613389.html

相关文章:

  • HMC1119LP4METR ADI亚德诺 高频功率放大器 MMIC集成电路IC
  • 自动化测试篇--BUG篇
  • Android-Kotlin基础(Jetpack④-Room)
  • RepoCoder:仓库级代码补全的迭代检索生成框架解析与应用前沿
  • 前缀和
  • 网卡名eth1、em1 、eno1、ens1 的区别
  • C++ vector 扩容时到底发生了什么?
  • 纯本地AI知识库搭建:DeepSeek-R1+AnythingLLM全流程
  • priority_queue的使用和模拟
  • Kotlin中String的==相等比较符
  • C语言sprintf、strcmp、strcpy、strcat函数详解:字符串操作的核心工具
  • 「日拱一码」045 机器学习-因果发现算法
  • 力扣238:除自身之外数组的乘积
  • LeetCode算法日记 - Day 4: 三数之和、四数之和
  • 力扣300:最长递增子序列
  • 优选算法 力扣 LCR 179. 查找总价格为目标值的两个商品 双指针降低时间复杂度 C++题解 每日一题
  • Cesium粒子系统模拟风场动态效果
  • 【Zephyr】02_从零教你开发芯片级ADC驱动(HAL层篇)
  • 第三章:【springboot】框架介绍MyBatis
  • 恒虚警检测(CFAR)仿真:杂波边缘与多目标场景分析
  • 在新建word中使用以前文件中的列表样式
  • java中override和overload的区别
  • Java 大视界 -- Java 大数据在智能安防门禁系统中的人员行为分析与异常事件预警(385)
  • AR技术:制造业质量控制的“智能革新”
  • Redis最新安装教程(WindowsLinux)
  • Kubernetes(k8s)之Service服务
  • SpringBoot的优缺点
  • 【更新被拒绝,因为推送的一个分支的最新提交落后于其对应的远程分支。】
  • VLMEvalKit使用记录
  • 公开致歉声明