Cortex-M3 (NXP LPC1788)之IIS应用--UDA1380进行音频数据播放

发布者:cyzcee最新更新时间:2016-05-26 来源: eefocus关键字:Cortex-M3  LPC1788  UDA1380  音频数据 手机看文章 扫描二维码
随时随地手机看文章
        LPC1788发送到I2S总线上的音频数据要通过音频解码芯片才能输出模拟音频信号。开发板上使用的是UDA1380,对它的寄存器的配置可以通过L3总线或者I2C总线进行,这里使用I2C总线进行控制,对于I2C总线的操作可以参考之前I2C的介绍。UDA1380的寄存器主要分成3类,系统控制、插值滤波(interpolation filter)、抽取滤波(decimator filter)。插值滤波和DAC转换有关,用于控制控制声音的输出参数。抽取滤波和ADC有关,用于控制对音频的采样。寄存器的地址和功能如图1所示。

图1:UDA1380寄存器地址和功能

        根据图1的红色标记中的内容,可以知道两个滤波器的正常使用需要一个128fs的clock,这个时钟可以通过SYSCLK引脚或者WSI的信号获得。在硬件连接上,通过将LPC1788的MCLK输出的时钟,连接到UDA1380的SYSCLK引脚。因此,我们需要配置I2S的发送模式控制寄存器I2STXMODE,使能TX_REF在MCLK输出,使UDA1380内部产生一个滤波器需要的时钟。

        程序中我们通过I2S发送一段音频数据,该数据是我从WAV格式的文件中去掉WAV头格式后得到的一个纯音频数据数组。该WAV音频为16位双通道 采样频率为44.1KHZ。LPC1788将该数组发送到I2S总线,UDA1380读取该数据进行声音的输出。程序如下

 

  1. #include "i2c.h"  
  2. #include "audio.h"  
  3.   
  4. #define rI2SDAO         (*(volatile unsigned *)(0x400A8000))  
  5. #define rI2STXFIFO      (*(volatile unsigned *)(0x400A8008))  
  6. #define rI2STXRATE      (*(volatile unsigned *)(0x400A8020))  
  7. #define rI2STXBITRATE   (*(volatile unsigned *)(0x400A8028))  
  8. #define rI2STXMODE      (*(volatile unsigned *)(0x400A8030))  
  9.   
  10. #define rI2SDMA1        (*(volatile unsigned *)(0x400A8014))  
  11. #define rI2SDMA2        (*(volatile unsigned *)(0x400A8018))  
  12. #define rI2SSTATE       (*(volatile unsigned *)(0x400A8010))  
  13. #define rI2SIRQ         (*(volatile unsigned *)(0x400A801C))  
  14.   
  15. #define rI2SDAI         (*(volatile unsigned *)(0x400A8004))  
  16. #define rI2SRXFIFO      (*(volatile unsigned *)(0x400A800C))  
  17. #define rI2SRXRATE      (*(volatile unsigned *)(0x400A8024))  
  18. #define rI2SRXBITRATE   (*(volatile unsigned *)(0x400A802C))  
  19. #define rI2SRXMODE      (*(volatile unsigned *)(0x400A8034))  
  20.   
  21. #define rIOCON_P0_07    (*(volatile unsigned *)(0x4002C01C))  
  22. #define rIOCON_P0_08    (*(volatile unsigned *)(0x4002C020))  
  23. #define rIOCON_P0_09    (*(volatile unsigned *)(0x4002C024))  
  24. #define rIOCON_P1_16    (*(volatile unsigned *)(0x4002C0C0))  
  25.   
  26. #define UDA1380_ADDRESS 0x1A  
  27.   
  28. void Uda1380_WriteData(unsigned char reg, unsigned short int data)  
  29. {  
  30.     unsigned char config[3];  
  31.       
  32.     config[0] = reg;  
  33.     config[1] = (data >> 8) & 0xFF;    //MS  
  34.     config[2] = data&0xFF;             //LS  
  35.       
  36.       
  37.     I2C0_MasterTransfer(UDA1380_ADDRESS, config, sizeof(config), 0, 0);  
  38.       
  39.     I2C0_MasterTransfer(UDA1380_ADDRESS, config, 1, &config[1], 2);     //校验写入的数据是否正确  
  40.     if((config[1]<<8|config[2]) != data)  
  41.     {  
  42.         while(1);   //写入和读出的数据不一致  
  43.     }  
  44. }  
  45.   
  46. void Uda1380_config()  
  47. {  
  48.     I2C0_Init();  
  49.       
  50.     Uda1380_WriteData(0x7F, 0x0);         //restore L3-default values  
  51.     Uda1380_WriteData(0x01, 0x0);         //数据格式为标准的I2S格式  
  52.       
  53.     Uda1380_WriteData(0x13, 0x0);         //配置音频的输出  
  54.     Uda1380_WriteData(0x14, 0x0);             
  55.   
  56.     Uda1380_WriteData(0x00, 0x2|0x1<<8|0x1<<9);     //使能DAC的时钟,选择使用SYSCLK产生128fs的时钟  
  57.     Uda1380_WriteData(0x02,0x1<<15|0x1<<13|0x1<<10|0x1<<8); //使能DAC 电源  
  58.       
  59. }  
  60.   
  61. int main(void)  
  62. {     
  63.     unsigned int count=0, i;  
  64.     unsigned char flag=1;  
  65.       
  66.     rIOCON_P0_07 = (rIOCON_P0_07&(~0x3))|0x1;   //I2S_TX_SCK  
  67.     rIOCON_P0_08 = (rIOCON_P0_08&(~0x3))|0x1;   //I2S_TX_WS  
  68.     rIOCON_P0_09 = (rIOCON_P0_09&(~0x3))|0x1;   //I2S_TX_SDA  
  69.     rIOCON_P1_16 = (rIOCON_P1_16&(~0x3))|0x2;   //I2SMCLK  
  70.     rPCONP |= 0x1<<27;  
  71.       
  72.     rI2SDAO = (16 - 1)<<6 | 0x1<<4 | 0x1<<3  |0x1;  //16位, 立体音, 禁止发送  
  73.   
  74.     rI2STXMODE |= 0x1<<3;       //使能MCLK输出,使TX_REF输出到UDA1380的SYSCLK引脚  
  75.       
  76.     rI2STXRATE = 0x1<<8|0x1;    //配置分数速率寄存器 得到TX_REF=CCLK/(1/1)/2  
  77.     rI2STXBITRATE = CCLK/2/(44100*2*16) - 1;  //44.1KHZ采样16位  
  78.       
  79.     for(i = 0; i <0x1000000; i++);  //延时 等待UDA1380内部通过SYSCLK产生稳定的128fs提供插值滤波和抽取滤波使用  
  80.       
  81.     Uda1380_config();  
  82.       
  83.     rI2SDAO &= ~ (1<<4);  
  84.     rI2SDAO &= ~ (1<<3);  
  85.     rI2SDAO &= ~ (1<<15);   //启动I2S数据传输  
  86.       
  87.     while(flag)  
  88.     {  
  89.         if(((rI2SSTATE>>16)&0xFF)<=4)       //如果发送FIFO中的数据小于或等于4个字  
  90.         {  
  91.             for(i=0; i<8-(((rI2SSTATE>>16)&0xFF)); i++)     //将FIFO填充到8个字  
  92.             {  
  93.                 rI2STXFIFO = *(unsigned int *)(audio + count);  //转换成int类型的指针,从指针指向的位置读取32位数据  
  94.                   
  95.                 count+=4;               //读取一个字,相当于读取char类型数组中的4个元素  
  96.                  
  97.                 if(count>=sizeof(audio)) //数组中的数据发送完  
  98.                 {  
  99.                     flag = 0;  
  100.                     break;  
  101.                 }  
  102.             }  
  103.         }  
  104.     }  
  105.       
  106.     rI2SDAO |= 0x1<<3|0x1<<4;   //停止I2S传输  
  107.       
  108.     return 0;  
  109. }  
下面对程序需要注意的做下说明:

 

1,i2c.h中是上一篇介绍I2C总线中所用的函数,aduio.h中存放的是音频数据的数组,const unsigned char audio[]={0,0,0,0,0,......................

2,I2C总线每次发送的数据为1个字节,而UDA1380的寄存器为16为,因此我们先发送高字节然后再发送低字节,具体的时序可以参考UDA1380的数据手册。

3,程序中配置发送控制寄存器I2STXMODE使能了MCLK输出TX_REF的时钟到UDA1380的SYSCLK引脚,而UDA1380中配置成使用该时钟产生内部滤波器需要的128fs的时钟。在图1中标志中说明run at ....因此在程序中配置UDA1380之前,使用了一个for延时,用于等待UDA1380内部产生稳定的128fs时钟。只有这样才能正确的配置0x10之后的滤波器相关寄存器。否则对0x10之后的滤波器相关寄存器操作会失败。这点没有验证,但是在debug调试的时候可以正常的有声音输出,但是下载到板子上运行,则没有效果。如果去掉for循环延时效果也不正常发音。如果不使能MCLK输出,则写0x13寄存器的值不会成功,读取该寄存器的值永远都是其默认值。因此推测和UDA1380的SYSCLK产生内部滤波器使用的128fs时钟有关。 

      参考了linux内核里面的uda1380的驱动,其中也提到了配置0x10以后的滤波器相关寄存器要满足条件


 

  1. 107         /* the interpolator & decimator regs must only be written when the  
  2. 108          * codec DAI is active.  
  3. 109          */  

 

 

谁有这方面的经验,希望多指教!

 

关键字:Cortex-M3  LPC1788  UDA1380  音频数据 引用地址:Cortex-M3 (NXP LPC1788)之IIS应用--UDA1380进行音频数据播放

上一篇:STM32 IAP 设计实例 (二)
下一篇:Cortex-M3 (NXP LPC1788)之IIS控制器

推荐阅读最新更新时间:2024-03-16 14:55

Cortex-M3基础学习
  因为项目所需,所以不得不开始研究M3,我用的是NXP公司的 LPC1768 这个芯片,它是具有三级流水线的哈佛结构,带独立的本地指令和数据总线以及用于外设的稍微低性能的第三条总线,还包含一个支持随机跳转的内部预取指单元。好了,今天只是初步测试一下它的GPIO功能,所谓的GPIO也就是通用输入/输出口(General Purpose Input Output),万丈高楼平地起,慢慢来吧。实验的原理图很简单,就是几个LED灯,关于灯的电流及电压参数,这里不作详细介绍,有兴趣的可以到网上或供应商那里要一份数据手册看一下,做技术的不能懒,有些东西该看的还是要看的。      图1 硬件原理图   硬件原理图很简单了,74
[单片机]
<font color='red'>Cortex-M3</font>基础学习
Flash download failed-Cortex-M3的原因及解决办法
首先,此类错误基本是被STM32芯片遇到,并且基本都是使用JLINK仿真器,其实我们以下的方法不一定可以帮你解决问题,问题真正的原因我们也没有在这个帖子公开、如果需要解决,请联系armjishu的JLINK仿真器工程师,他会帮助你解决的;生产的JLINK可以解决这个问题。 MDK中出现 Error: Flash download failed- Cortex-M3 的原因及解决办法: 1.Jtag模式下,主要是芯片大小选错 出现这处问题通常是MDK中的Flash的编程算法没有配置或没有配置正确, 神舟系列用的是STM32芯片。 在主菜单中打开Flash- Configure Falsh Tools配置窗口,切换到 U
[单片机]
Flash download failed-Cortex-M3的原因及解决办法
μCOS-II在ARM Cortex-M3处理器上的移植
0 引言 嵌入式系统已经广泛渗透到了人们工作、生活中的各个领域,嵌入式处理器已占分散处理器市场份额的94%,其中ARM的应用最为广泛。基于ARM内核的处理器以其诸多优异性能而成为各类产品中选用较多的处理器之一。 当系统越来越大,应用越来越多时,就出现了如何管理众多的硬件资源,以及如何满足系统的实时控制要求和如何提高系统软件开发效率等不可回避的问题。这时,使用嵌入式操作系统很有必要。操作系统的主要作用有:统一管理系统资源;为用户提供访问硬件的接口;调度多个应用程序和管理文件系统等。 1 概述 μC/OS-II是著名的、源码公开的实时内核,是专为嵌入式应用设计的,可用于各类8位、16位和32位处理器。μC/OS-II已经
[单片机]
μCOS-II在ARM <font color='red'>Cortex-M3</font>处理器上的移植
你不得不知的Cortex-M3和M4微控制器使用秘诀
  许多嵌入式开发人员对ARM Cortex处理器架构颇为熟悉,但很少有人能够对这种流行架构了如指掌,从而可以充分发挥它独特的特性和性能。ARM Cortex-M4处理器尤为如此,它拥有引以为豪的增强架构、天生的数字信号处理(DSP)能力和可选的浮点加速器,使精于此道的程序设计人员或硬件工程师可以充分发挥它的优势。本文接下来将就Cortex-M3/M4微控制器(MCU)的一些更有趣的(但经常遭到忽视的)特性展开详细的论述。   大部分采用Cortex-M3/M4 MCU的目标应用是便携式的,并且供电电源来自电池或能源收集系统,因此我们所探讨的大部分概念涉及如何减少系统整体能耗的技术。然而,在许多情况下,这些节能技术也是处理器应用
[单片机]
你不得不知的<font color='red'>Cortex-M3</font>和M4微控制器使用秘诀
Cortex-M3中断优先级
STM32(Cortex-M3)中有两个优先级的概念——抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级(有关这个概念在下面附加内容有)',每个中断源都需要被指定这两种优先级。 具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。 当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在
[单片机]
爱特梅尔SAM3U评测工具套件加速应用开发
爱特梅尔公司(Atmel® Corporation)宣布推出SAM3U-EK评测工具套件,可为业界首款带有高速480 Mbps USB + Phy之基于ARM® Cortex® -M3闪存微控制器实现快速应用开发。该工具套件除了备有用于高速USB设备的即插即用接口外,还配有一个高速SDIO/SDCard/MMC插槽、两个UART连接器、一个ZigBee®无线报头、两个模拟输入、音频输入和输出,以及一个JTAG-ICE调试端口。针对应用开发,SAM3U-EK电路板配置了一个带电阻性触控板和背光照明的240 x 320 TFT彩色LCD显示器、3D加速器和温度传感器、电位计、板上512K x 16-bit PSRAM和2G-bi
[单片机]
“节能之星”EFM32应用方案-手持式激光测距仪
概述 随着现代科技的发展以及人们生活水平的提高,便携式 激光测距 仪在各行各业中都有广泛的应用,如建筑业,高尔夫,行车速度与车距测量。激光是一种电磁波,具有方向性强、单色性好、相干性好、亮度高等特性,使其成为测距的首选电磁波。 目前常用的激光测距方法主要有: 1、 脉冲测距法:利用 脉冲激光器 发射单次激光脉冲或激光脉冲串,测量激光脉冲到达目标并由目标返回到接收器的往返时间,由此运算目标距离。此方法误差较大,适用于远距离测量。 2、 干涉测距法:利用光的干涉原理,通过测量激光发射与接收这间的干涉条纹来测量距离。此方法精度非常高,但只能测量相对距离,不能测量绝对距离。 3、 相位式测距法:采用连续调制的激光光束照射实测目标
[测试测量]
“节能之星”EFM32应用方案-手持式激光测距仪
浅谈μCOSII在Cortex-M3核的ARM处理器上的移植
随着科学技术的发展,嵌入式技术已被广泛应用到汽车电子、无线通信、数码产品等各个领域。嵌入式操作系统及嵌入式处理器技术发展迅猛,嵌入式操作系统典型代表有μCOS—II、μClinux、Winclow CE、VxWorks等;嵌入式处理器包括ARM、MIPS、PowerPC等。 1 软硬件开发环境及处理器介绍 1.1 软件硬开发环境 本移植过程使用的软件环境是RealView MDK开发套件,此产品是ARM公司最新推出的针对各种嵌入式处理器的软件开发工具,该开发套件功能强大,包括了μVisiON3集成开发环境和RealView编译器。使用的硬件平台是深圳英蓓特公司推出的全功能评估板STMl03V100,其上所采用的处理器是ST意
[单片机]
浅谈μCOSII在<font color='red'>Cortex-M3</font>核的ARM处理器上的移植
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved