i.MX RT1010之FlexIO模拟I2S外设
恩智浦的i.MX RT1010是跨界处理器产品,作为i.MX RT跨界MCU系列的一个新的切入点,i.MX RT1010是成本最低的LQFP封装方式与i.MX RT系列产品一贯的高性能和易用性的结合产物。
i.MX RT1010处理器基于ARM Cortex-M7平台,它具有较高的CPU性能和最佳的实时响应,并具有丰富的外设资源。其中FlexIO是一个高度可配置的模块,能够模拟多种不同的通信协议,包括UART, I2C, SPI, I2S等。本文介绍如何利用i.MX RT1010的FlexIO外设来模拟I2S总线。
一、硬件平台
本应用笔记主要介绍如何使用FlexIO模块模拟I2S接口,实现音频数据的采集,传输并播放。使用FlexIO模块模拟I2S总线信号,可以代替传统的I2S或者SAI外设来传输音频数据,非常节省MCU的片上资源。整个demo基于i.MX RT1010 EVK板子进行开发,如下所示。

i.MX RT1010利用板载麦克风采集音频数据到sram缓冲区中进行处理,然后使用模拟的I2S接口将音频数据发送到音频播放设备,所有音频数据的处理都围绕板上的编解码芯片WM8960实现。另外,为了能够成功演示该demo,需要对i.MX RT1010 EVK板子进行如下操作和改动,整体实物图也如下所示。
音频扬声器的数字接口插入RT1010 EVK板的J11端口。
将ISP拨码开关SW8更改为0b0010模式。
将J1-3和J1-4引脚用短路帽连接,将USB线插到板上的J9口进行供电。
去掉iMX RT1010 EVK板上的R85,R87,R88,R20这几个电阻。
FLEXIO需要用到的具体引脚和U10的对应连接关系如下:
引脚名称 位置 位置 FlexIO引脚号 SDA_RX J54-2 U10-16 FlexIO03 SDA_TX J26-8 U10-14 FlexIO26 SYNC J26-6 U10-13 FlexIO22 BCLK J26-4 U10-12 FlexIO21

二、 应用
2.1 系统架构
在此应用中,demo整个架构和I2S接口的连接关系如图所示。i.MX RT1010作为I2S的从设备,利用FlexIO模拟了四根引脚,它们分别是I2S接口的SDA_RX、SDA_TX、FSYNC(WS)以及BLCK。WM8960编解码器作为I2S的主设备,从MIC接收音频信号,然后通过SDA_RX引脚将音频数据传输到RT1010。RT1010将接收的音频数据处理后,再通过SDA_TX引脚发送给WM8960,WM8960将PCM数据转成模拟信号交由扬声器播放。此外,RT1010通过I2C接口对WM8960进行初始化配置操作。

2.2 时钟及采样频率配置
与MCU做为I2S主机不同的是,当MCU作为I2S从机时,FSYNC和BLCK信号是由WM8960产生的,因此第一步要把WM8960配置成master模式。WM8960的MCLK时钟可以由RT1010提供,也可以由WM8960提供。本应用中,我们利用RT1010产生MCLK信号比较方便,并把MCLK配置为6.144MHz。
常见的I2S采样频率通常有两组,如下所示。 本应用中,I2S采样频率配置为16kHz,同样WM8960的采样频率也需要被配置为16kHz。一旦I2S的采样频率确定了,那FSYNC信号的频率也就确定了,也为16kHz。
| Typical Sample Frequency (Hz) | Typical Sample Frequency (Hz) |
|---|---|
| 11025 | 8000 |
| 22050 | 16000 |
| 44100 | 24000 |
| -------- | 32000 |
| -------- | 48000 |
为了能够模拟I2S接口作为slave模式,FlexIO的时钟配置是有一定要求的,它必须是采样频率的某个倍数,这样FlexIO的定时器才能匹配这个频率。在本应用中,FlexIO时钟被配置为6.144MHz,FlexIO模拟的I2S接口基于这个时钟来实现。
下一步,需要对WM8960进行一系列配置,使其从板载MIC采集的音频信号在传输给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
此外,在本应用中还需要将I2S模式配置为经典I2S模式。有读者如果对I2S协议不清楚,可以参考笔者的另一篇博客i.MX RT600之I2S外设介绍及应用。
下面给出了WM8960编解码器的部分配置代码:
wm8960_config_t wm8960Config = {
.i2cConfig = {.codecI2CInstance
= BOARD_CODEC_I2C_INSTANCE,.codecI2CSourceClock = BOARD_CODEC_I2C_CLOCK_FREQ},
.route = kWM8960_RoutePlaybackandRecord,
.rightInputSource = kWM8960_InputDifferentialMicInput2,
.playSource = kWM8960_PlaySourceDAC,
.slaveAddress = WM8960_I2C_ADDR,
.bus = kWM8960_BusI2S,
.format = {.mclk_HZ = 6144000U,
.sampleRate = kWM8960_AudioSampleRate16KHz,
.bitWidth = kWM8960_AudioBitWidth32bit},
.master_slave = true,
};
codec_config_t boardCodecConfig = {
.codecDevType = kCODEC_WM8960,
.codecDevConfig = &wm8960Config
};
/* Init codec */
CODEC_Init(&codecHandle, &boardCodecConfig);
2.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接口的内部连接。 Timer0和定时Timer2连接的FlexIO引脚分别用于产生BCLK信号和FSYNC信号,而SHIFTER0和SHIFTER2的FlexIO引脚分别用于产生SDA_TX信号和SDA_RX信号。下面分别介绍SHIFTER和Timer使用方法和配置。

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

下面需要对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
到这里,FlexIO用于模拟I2S接口的基本配置就介绍完毕,接下来还需要介绍音频数据的处理机制。
2.4 音频流处理
MCU在同时接收和发送PCM数据并进行播放的应用场景中,容易出现播放音乐卡顿的情况,为了避免出现这种卡顿,一个好的传输机制是必不可少的,下图就给出了一种处理PCM数据的思路。
每当FlexIO中的SHIFTER有DMA请求产生时,应立即从SHIFTBUF读取或写入音频数据。下图中两个缓冲区用于PCM数据的发送和接收,这两个缓冲区构成了ping-pang buffer。PCM数据帧的位宽为64位(左通道和右通道),每个缓冲区被设置为256bit,即存放4帧PCM数据, 每当一个缓冲区中的PCM数据接收满或发送时,下一个缓冲区将立即开始接收或发送。

2.5 注意事项
在利用FlexIO模拟I2S时,需要注意两点:
由于FlexIO同步延迟,当FlexIO用来模拟I2S从设备时,串行数据的输出有效时间是FlexIO时钟周期的2.5倍。 因此,I2S的BCLK最大时钟频率应当是FlexIO时钟频率的六分之一。
FlexIO是一个功能强大,非常灵活的模块,除了本文给出的Timer和SHIFTER的配置外,读者也可以利用其它配置模拟出I2S接口。
至此,i.MX RT1010之FlexIO模拟I2S外设介绍完毕。
i.MX RT1010之FlexIO模拟I2S外设的更多相关文章
- i.MX RT1010之FlexIO模拟SSI外设
恩智浦的i.MX RT1010是跨界处理器产品,作为i.MX RT跨界MCU系列的一个新的切入点,i.MX RT1010是成本最低的LQFP封装方式与i.MX RT系列产品一贯的高性能和易用性的结合产 ...
- i.MX RT600之I2S外设介绍及应用
恩智浦的i.MX RT600是跨界处理器产品,同样也是i.MX RTxxx系列的开山之作.不同于i.MX RT1xxx系列单片机,i.MX RT600 采用了双核架构,将新一代Cortex-M33内核 ...
- RT600 I2S外设介绍及应用
恩智浦的i.MX RT600是跨界处理器产品,同样也是i.MX RTxxx系列的开山之作.不同于i.MX RT1xxx系列单片机,i.MX RT600 采用了双核架构,将新一代Cortex-M33内核 ...
- i.MX RT600之DMIC外设介绍及应用
恩智浦的i.MX RT600是跨界处理器产品,同样也是i.MX RTxxx系列的开山之作.不同于i.MX RT1xxx系列单片机,i.MX RT600 采用了双核架构,将新一代Cortex-M33内核 ...
- 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU外设那些事(2)- 善变的FlexRAM
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列MCU的FlexRAM外设. 本文是外设系列第二篇,上一篇讲的是离内核最近的高速缓存L1 Cache, ...
- 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU启动那些事(11.3)- FlexSPI NOR连接方式大全(RT1010)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RT1010的FlexSPI NOR启动的连接方式. 在写完 <FlexSPI NOR启动连接方式(RT1015/ ...
- 第38章 I2S—音频播放与录音输入—零死角玩转STM32-F429系列
第38章 I2S—音频播放与录音输入 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/ ...
- ios设备app作为蓝牙外设端
苹果手机可以作为蓝牙外设端,被蓝牙中央端来扫描连接交互数据,实现模拟蓝牙外设硬件.通过阅读CoreBluetooth库,可以找到一个CBPeripheralManager的类,该类主要的作用就是允许你 ...
- ESP32音频输入-MAX4466,MAX9814,SPH0645LM4H,INMP441(翻译)
有几种方法可以将模拟音频数据输入到ESP32中. 直接从内置的模数转换器(ADC)读取 这对于一次性读取很有用,但不适用于高采样率. 使用I2S通过DMA读取内置ADC 适用于模拟麦克风,例如MAX4 ...
随机推荐
- 大数据-SparkStreaming
SparkStreaming SparkStreaming是一种微批处理,准实时的流式框架.数据来源包括:Kafka, Flume,TCP sockets,Twitter,ZeroMQ等 SparkS ...
- JavaScript——BOM和DOM
什么是BOM bom:浏览器对象模型 什么是DOM dom:文档对象模型 BOM操作: 调用windows浏览器窗口 windows对象可以通过点调用子对象 windows.navigator对象,可 ...
- python之路之io多路复用
1.实现io多路复用利用select s1同时接受三个客户端(开启了三个服务器端口) #!/usr/bin/env python # -*- coding: utf-8 -*- import sock ...
- MVC5+EF6 入门完整教程5 :UI的一些改造
https://www.cnblogs.com/miro/p/4095165.html 上篇文章介绍了EF实现CRUD及一些基本的Html Helpers. 这次我们将会对之前的内容进行一些修改和重构 ...
- MySQL学习(八)删除表数据
表空洞的产生 删除某个行数据 或删除某个页 如下图所示,这个删除过程只是标记了某行的位置为删除,假如此时在300与600之间插入了一行数据,那么 同理,当删除某个页时,该页就会被复用.所以当删 ...
- Linux中通配符
通配符是由shell处理的, 它只会出现在 命令的“参数”里.当shell在“参数”中遇到了通配符时,shell会将其当作路径或文件名去在磁盘上搜寻可能的匹配:若符合要求的匹配存在,则进行代换(路径扩 ...
- spring注解注入:<context:component-scan>以及其中的context:include-filter>和 <context:exclude-filter>的是干什么的?
转自:https://www.cnblogs.com/vanl/p/5733655.html spring注解注入:<context:component-scan>使用说明 sprin ...
- codeforces 1189C Candies! / 前缀和
http://codeforces.com/problemset/problem/1189/C 求一下前缀和,给定区间的数字和除以10就是答案 AC代码: #include<iostream&g ...
- Dataset数据的XML持久化处理
主要方法是用ADO.NET的DataTale 填充到Dataset Dataset 内置了XML持久化的方法,WriteXML和ReadXML:简单的WinFrom实例:从数据库的表 private ...
- oracle 数据库创建表
好好好好久没更新了,最近真是堕落了,做的都是小菜鸟做的东西,都没得写,但是最近数据库突然从mysql换到oracle,哈哈哈哈哈,还真是挺复杂的 1.首先建表 fund 是表名称 其他的是字段名称 c ...