请选择 进入手机版 | 继续访问电脑版
查看: 1517|回复: 0

使用i.MX RT1010 FlexIO模拟I2S

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3298

    主题

    6545

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32001
    最后登录
    2024-4-9
    发表于 2020-6-11 11:25:36 | 显示全部楼层 |阅读模式
    使用i.MX RT1010 FlexIO模拟I2S

    本文主要介绍如何使用FlexIO模块,模拟I2S接口进行音频数据的发送和接收。使用FlexIO模块模拟的I2S接口可以代替传统的I2S/SAI外设来传输音频数据,节省CPU资源。


    i.MX RT1010处理器基于Arm Cortex-M7平台,具有很高的CPU性能和最佳的实时响应,且拥有丰富的外设资源。本文通过一个简单的例程,来演示FlexIO模块模拟I2S总线接口的过程,并进行了验证。
    文中的例程使用模拟的I2S接口,将音频数据接收到SRAM缓冲区中进行处理,再将音频数据传输到音频播放设备,实现音频数据的数字回环,音频数据的处理都基于i.MX RT1010 EVK板上的Codec芯片实现。


    硬件平台



    FlexIO模拟I2S接口的例程基于i.MX RT1010 EVK板,实际硬件平台下图所示。

    1.png

    为了例程能够成功演示,需要注意以下几点:


    音频扬声器的数字接口插入RT1010 EVK板的J11端口。


    将ISP拨码开关SW8更改为0b0010。


    将USB插到板上的J9口进行供电。


    将J1-3和J1-4引脚用短路帽连接。


    对i.MX RT1010EVK板需要进行修改:


    去掉板上的R85,R87,R88,R20这几个电阻。


    将FLEXIO用到的引脚按如下关系进行硬件连接:

    2.png

    应用



    本节介绍了使用FlexIO模拟I2S接口的一些设计要点,重点是FlexIO模块配置介绍。


    1. 系统架构
    例程的整个架构和I2S接口的连接关系如下图所示。
    3.png

    i.MX RT1010作为I2S的从机设备,利用FlexIO模拟了四根引脚,它们分别是I2S接口的SDA_RX、SDA_TX、FSYNC(WS)以及BLCK。


    WM8960编解码器作为I2S的主机设备,从麦克风接收音频信号,然后通过SDA_RX引脚将音频数据传输到RT1010。RT1010将接收的音频数据处理后,再通过SDA_TX引脚发送给WM8960,WM8960将PCM数据转成模拟信号交由扬声器播放。
    此外,RT1010通过I2C接口对WM8960进行初始化配置操作。
    2. 时钟及采样频率配置
    与MCU做为I2S主机不同的是,当MCU作为I2S从机时,FSYNC和BLCK信号是由WM8960产生的,因此第一步要把WM8960配置成master模式。


    WM8960的MCLK时钟可以由RT1010提供,也可以由WM8960提供。本应用中,我们利用RT1010产生MCLK信号比较方便,并把MCLK配置为6.144MHz。
    常见的I2S采样频率通常有两组,如下所示。
    4.png

    本应用中,I2S采样频率配置为16kHz,同样WM8960的采样频率也需要被配置为16kHz。一旦I2S的采样频率确定了,那FSYNC信号的频率也就确定了,也为16kHz。


    为了能够模拟I2S接口作为slave模式,FlexIO的时钟配置是有一定要求的,它必须是采样频率的某个倍数,这样FlexIO的定时器才能匹配这个频率。在本应用中,FlexIO时钟被配置为6.144MHz,FlexIO模拟的I2S接口基于这个时钟来实现。
    下一步,需要对WM8960进行一系列配置,使其从板载麦克风采集的音频信号在传输给RT1010时,是16KHz,32bit的立体声(左右声道)音频数据。
    接着,我们需要计算并配置FlexIO的各个引脚时钟,BCLK时钟信号是由WM8960产生的,MCLK作为WM8960的参考时钟,经过分频得到BCLK时钟,过程如下:
    FSYNC = 16KHz


    MCLK = 6.144MHz


    BCLK = FSYNC * 声道数 * 声道位宽 = 16KHz * 2 * 32 = 1.024MHz


    BCLK_DIV (BLCK分频系数) = MCLK / BCLK =6.144MHz / 1.024MHz = 6


    下面示例给出了WM8960编解码芯片的部分配置代码:
    1. <font size="3" face="微软雅黑">wm8960_config_t wm8960Config = {
    2.     .i2cConfig             = {.codecI2CInstance = BOARD_CODEC_I2C_INSTANCE,
    3.                                 .codecI2CSourceClock = BOARD_CODEC_I2C_CLOCK_FREQ },
    4.     .route                = kWM8960_RoutePlaybackandRecord,
    5.     .rightInputSource = kWM8960_InputDifferentialMicInput2,
    6.     .playSource         = kWM8960_PlaySourceDAC,
    7.     .slaveAddress      = WM8960_I2C_ADDR,
    8.     .bus                    = kWM8960_BusI2S,
    9.     .format                = {.mclk_HZ = 6144000U,
    10.         .sampleRate          = kWM8960_AudioSampleRate16KHz,
    11.         .bitWidth            = kWM8960_AudioBitWidth32bit},
    12.     .master_slave       = true,
    13. };
    14. codec_config_t boardCodecConfig = {
    15.     .codecDevType      = kCODEC_WM8960,
    16.     .codecDevConfig    = &wm8960Config
    17. };
    18. /* Init codec */
    19. CODEC_Init(&codecHandle, &boardCodecConfig);</font>
    复制代码
    3. FlexIO 模拟
    FlexIO是一个具有多种功能,高度可配置的模块,具有以下特点:

    支持多种串行/并行通信协议的仿真,例如UART,I2C,SPI,I2S等。
    灵活的16位定时器,支持多种触发,复位,使能和禁止条件。
    可编程逻辑块,允许在片上实现数字逻辑功能以及内部和外部模块的可配置交互。
    可编程状态机,用于不依赖CPU而实现基本的系统控制功能。
    在i.MX RT1010上,FlexIO共有27个引脚。


    本应用一共使用了4个FlexIO引脚(FlexIO03引脚,FlexIO21引脚,FlexIO22引脚,FlexIO26引脚)分别模拟I2S接口的SDA_RX引脚,BCLK引脚,FSYNC引脚和SDA_TX引脚。下图显示了FlexIO模拟I2S接口的内部连接。
    5.png

    Timer0和定时Timer2连接的FlexIO引脚分别用于产生BCLK信号和FSYNC信号,而SHIFTER0和SHIFTER2的FlexIO引脚分别用于产生SDA_TX信号和SDA_RX信号。


    下面分别介绍SHIFTER和Timer使用方法和配置。
    通过配置SHIFTCTL寄存器,可以将SHIFTER配置成6种模式,本应用中只需要关注Transmit模式和Receive模式就行。
    先对SHIFTER0进行配置。将SHIFTER0配置为Transmit模式,SHIFTER0在移位时钟的上降沿将SHIFTBUF0中的数据从TX引脚输出。SHIFTER2被配置为Receive模式,同样SHIFTER2在移位时钟的下降沿从RX引脚上获取数据并放入SHIFTBUF2。当数据从SHIFTER加载到SHIFTBUF寄存器中或数据从SHIFTBUF寄存器加载到SHIFTER中时,如果已经将SHIFTER状态标志位(SHIFTSDEN SSDE)置1,就可以产生一个DMA请求。
    整个 SHIFTER的微体系结构如下图所示,它充分展示了SHIFTER中各个模块之间的关系以及IO引脚输入输出的关系。

    6.png

    下面需要对Timer0和Timer2进行配置。


    当Timer2检测到FSYNC的上升沿时使能,当其检测到trigger事件的下降沿时禁用。Timer0的使能发生在BLCK的上升沿以及Timer2的trigger事件检测为高电平时,Timer0的关闭发生在其自身的比较事件产生时。此外,Timer0和Timer2的时钟状态需要被初始化为逻辑1。Timer2的时钟模式需要被配置为16位计数模式,其比较事件产生的值设置为0,并使用FSYNC引脚的输入作为递减量,使用BCLK引脚的输入作为trigger事件。Timer0的时钟模式需要被配置为16位计数器,并使用BCLK引脚的输入作为递减量。在此应用中,Timer2的比较事件产生的值设置为127(32 * 4-1),这是根据64bit一帧的音频数据位宽长度计算得到的。
    下面给出了详细的寄存器配置:
    FlEXIO01.SHIFTCTL[0] = 0x00031A02


    FlEXIO01.SHIFTCTL[2] = 0x00800301


    FlEXIO01.TIMCTL[0] = 0x0B401583


    FlEXIO01.TIMCTL[2] = 0x2A401683


    FlEXIO01.TIMCFG[0] = 0x00202500


    FlEXIO01.TIMCFG[2] = 0x00206400


    FlEXIO01.TIMCMP[0] = 0x0000007F


    FlEXIO01.TIMCMP[2] = 0x00000000


    4. 音频数据流处理
    MCU在同时接收和发送PCM数据并进行播放的应用场景中,容易出现播放音乐卡顿的情况,为了避免出现这种卡顿,一个好的传输机制是必不可少的,下图给出了一种处理PCM数据的方法。
    7.png

    每当FlexIO中的SHIFTER有DMA请求产生时,应立即从SHIFTBUF读取或写入音频数据。图中两个缓冲区用于PCM数据的发送和接收,这两个缓冲区构成了ping-pong buffer。PCM数据帧的位宽为64位(左通道和右通道),每个缓冲区被设置为256bit,即存放4帧PCM数据,每当一个缓冲区中的PCM数据接收满或发送时,下一个缓冲区将立即开始接收或发送。

    总结


    本文介绍了利用i.MX RT1010的FlexIO模块来模拟I2S接口的方法和例程。当CPU硬件资源不足,FlexIO可以模拟I2S接口以很好地传输音频数据。使用FlexIO模块模拟I2S接口时,有两个注意事项:


    由于FlexIO同步延迟,当FlexIO用来模拟I2S从设备时,串行数据的输出有效时间是FlexIO时钟周期的2.5倍。因此,I2S的BCLK最大时钟频率应当是FlexIO时钟频率的六分之一。


    FlexIO是一个功能强大,非常灵活的模块,除了本文给出的Timer和SHIFTER的配置外,读者也可以利用其它配置模拟出I2S接口。








    签到签到
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-18 22:50 , Processed in 0.113624 second(s), 20 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

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