16701|22

84

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

lm3s8962模拟SPI驱动VS1003学习心得~~ [复制链接]

倒腾了很久,参考了高手给我的一个程序,终于用VS1003听到声音了。这里也和大家分享一下我的学习心得~~人人助我,我助人人~~
这段时间仔细的研究了一下IO口模拟SPI和驱动VS1003。因为8962只有一个SPI接口,SD卡要用,驱动VS1003也要用。所以,要做一个MP3,就用IO口模拟了SPI接口。主要的心得如下:
这里附上VS1003的一些资料,以及我的整个工程:

首先,了解一下SPI:
SPI总线接口只占用微处理器四个IO接口:
(1)MOSI – 主器件数据输出,从器件数据输入 
(2)MISO – 主器件数据输入,从器件数据输出  
SCLK – 时钟信号,由主器件产生  
(4)/SS – 从器件使能信号,由主器件控制
2.在点对点的通信中,SPI接口不需要进行寻址操作,且为全双工通信,显得简单高效。
   
多个从器件硬件连接示意图
在多个从器件的系统中,每个从器件需要独立的使能信号,硬件上比I2C系统要稍微复杂一些。

SPI接口在内部硬件实际上是两个简单的移位寄存器,传输的数据为8位,在主器件产生的从器件使能信号和移位脉冲下,按位传输,高位在前,低位在后。如下图所示,在SCLK的下降沿上数据改变,同时一位数据被存入移位寄存器。

[ 本帖最后由 xielijuan 于 2010-12-24 14:24 编辑 ]

图片1.jpg (59.18 KB, 下载次数: 6)

图片1.jpg

vs1003mp3_project.rar

408.72 KB, 下载次数: 605

VS1003数据手册及应用笔记.rar

738.25 KB, 下载次数: 731

最新回复

赞  详情 回复 发表于 2014-1-4 12:33

赞赏

1

查看全部赞赏

 
点赞 关注

回复
举报

84

帖子

0

TA的资源

一粒金砂(中级)

推荐
 
SPI总线接口的模拟
模拟SPI发送一个字节的数据
函数如下:
void SPIPutChar(unsigned char ucData)
{

        unsigned i = 0;

        for(i=0; i<8; i++)
        {
                GPIOPinWrite(GPIO_PORTD_BASE, SoftSSICLK, 0);//SCK = 0;
                if(ucData & 0x80)
                {
                        GPIOPinWrite(GPIO_PORTD_BASE, SoftSSITx, SoftSSITx);//SCO = 1;
                }
                else
                {
                        GPIOPinWrite(GPIO_PORTD_BASE, SoftSSITx, 0);//SCO = 0;
    }
                Delay(1);

                GPIOPinWrite(GPIO_PORTD_BASE, SoftSSICLK, SoftSSICLK);//SCK = 1;        /* 产生正跳变发出数据 */
                Delay(1);
                ucData = ucData<<1;        /* 左移一位,准备发送下一位数据 */
        }

        GPIOPinWrite(GPIO_PORTD_BASE, SoftSSICLK, 0);//SCK = 0;        /* 空闲时低电平 */
2)模拟SPI读取一个字节的数据
函数如下:
void SPIGetChar(unsigned char * reg_data)
{

        unsigned char i = 0;

        *reg_data = 0x00;
        for(i=0; i<8; i++)
        {
                GPIOPinWrite(GPIO_PORTD_BASE, SoftSSICLK, 0);//SCK = 0;
                Delay(1);
                GPIOPinWrite(GPIO_PORTD_BASE, SoftSSICLK, SoftSSICLK);//SCK = 1;                        /* 产生正跳变读取数据 */

                *reg_data = *reg_data<<1;
                if(GPIOPinRead(GPIO_PORTD_BASE, SoftSSIRx))
                {
                        *reg_data = *reg_data | 0x01;
                }
        }

        GPIOPinWrite(GPIO_PORTD_BASE, SoftSSICLK, 0);//SCK = 0;        /* 空闲时低电平 */
 
 

回复

84

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
最后,SPI接口的一个缺点:没有指定的流控制,没有应答机制确认是否接收到数据。

[ 本帖最后由 xielijuan 于 2010-12-24 14:18 编辑 ]

图片3.jpg (46.11 KB, 下载次数: 2)

图片3.jpg

图片4.jpg (56.55 KB, 下载次数: 1)

图片4.jpg
 
 
 

回复

84

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
好,现在说一下,整个程序的编写过程:


初始化VS1003
确保vs1003与处理器的正确与可靠连接。下面是vs1003的引脚图:


对于8962来说,总共需要7个IO口。用三个作为SCLK,MISO,MOSI来模拟SPI模式,这里用GPIOD的4,6 ,7引脚来模拟,即将GPIOD的4,6 ,7引脚分别接到vs1003的SCLK,MISO,MOSI。其余的连接如下:

CS接GPIOC的6号引脚
DREQ 接GPIOC的5号引脚
RESET接GPIOC的4号引脚
DCS接GPIOC的7号引脚.定义如下:
#define VS_RSTn       GPIO_PIN_4 //PC4
#define VS_DREQ       GPIO_PIN_5 //PC5 input
#define VS_CSn        GPIO_PIN_6 //PD6
#define VS_DCn       GPIO_PIN_7 //PC7

IO口模拟SPI,用的是GPIOD接口
在这里,引脚的连接如下
SCLK接GPIOD的4号引脚   
MISO接GPIOD的6号引脚
MOSI接GPIOD的7号引脚
定义如下:
#define SoftSSICLK          GPIO_PIN_4                 //PD
#define        SoftSSIRx          GPIO_PIN_6
#define        SoftSSITx          GPIO_PIN_7

微处理器模块的正确初始化。
正确配置IO口:
注意将与DREQ连接的IO口(即GPIOC的5号引脚)配置为输入,其余配置为输出(CS,DCS和RESET);将GPIOD的4,6 ,7引脚配置为SPI总线接口。

初始化函数如下:
void vs1003_io_init(void)
{
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
       
       
        //_gpio_set_input
        GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, VS_DREQ);
        GPIOPadConfigSet(GPIO_PORTC_BASE, VS_DREQ, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
        //_gpio_set_output
        GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, VS_RSTn | VS_CSn | VS_DCn);
        GPIOPadConfigSet(GPIO_PORTC_BASE, VS_RSTn | VS_CSn | VS_DCn, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD);
       
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
        //_gpio_set_input
        GPIOPinTypeGPIOInput(GPIO_PORTD_BASE,SoftSSIRx);//Rx,input
        GPIOPadConfigSet(GPIO_PORTD_BASE, SoftSSIRx, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
        //_gpio_set_output
        GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, SoftSSICLK | SoftSSITx);
        GPIOPadConfigSet(GPIO_PORTD_BASE, SoftSSICLK | SoftSSITx, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD);
               
        //SPIPutChar(0xff);
    //SPIPutChar(0xff);
    //SPIPutChar(0xff);
        //UARTprintf("vs1003_io_init\n");       
}

[ 本帖最后由 xielijuan 于 2010-12-24 14:20 编辑 ]

图片5.jpg (16.08 KB, 下载次数: 1)

图片5.jpg

图片5.jpg (16.08 KB, 下载次数: 0)

图片5.jpg
 
 
 

回复

84

帖子

0

TA的资源

一粒金砂(中级)

5
 
4.vs1003模块的初始化
上述两步完成后就可以通过SPI总线对VS1003进行初始化了。初始化的一般流程如下:
        硬复位。xReset=0;
        延时,xDCS,xCS,xReset置一;
        等待DREQ为高
        软件复位:SPI_MODE=0x0804;
        等待DREQ为高(软件复位结束)
        设置VS1003的时钟:SCI_CLOCKF=0x9800,3倍频;
        设置VS1003的采样率:SPI_AUDATA=0xBB81,采样率48K,立体声;
        设置重音:SPI_BASS-0x0055;
        设置音量:SCI_VOL=0x2020;
        向VS1003发送4个字节无效数据,用以启动SPI发送。
       
        代码如下:
        硬件复位:
        void Mp3Reset(void)
        {       
                Mp3PutInReset();//xReset = 0   复位vs1003      
                wait(100);//延时100ms
        //发送一个字节的无效数据,启动SPI传输
                Mp3DeselectControl();   //xCS = 1
                Mp3DeselectData();     //xDCS = 1
                Mp3ReleaseFromReset(); //xRESET = 1
                wait(100);            //延时100ms
                while(VS_DREQ_READ() == 0);         //等待DREQ为高
            wait(100);            //延时100ms
            Mp3SetVolume(10,10);  
            Mp3SoftReset();//vs1003软复位
        }
       
        软件复位:
        void Mp3SoftReset(void)
        {
                Mp3WriteRegister (SPI_MODE, 0x08, 0x04); //软件复位
       
                wait(1); //延时1ms
                while(VS_DREQ_READ() == 0);         //等待软件复位结束
                Mp3WriteRegister(SPI_CLOCKF, 0x98, 0x00);//设置vs1003的时钟,3倍频
                Mp3WriteRegister(SPI_AUDATA, 0xBB, 0x81); //采样率48k,立体声
                Mp3WriteRegister(SPI_BASS, 0x00, 0x55);//设置重音
                Mp3SetVolume(20,20);//设置音量
            wait(1); //延时1ms
                   
            //向vs1003发送4个字节无效数据,用以启动SPI发送
            Mp3SelectData();
                SPIPutChar(0);
                SPIPutChar(0);
                SPIPutChar(0);
                SPIPutChar(0);
                Mp3DeselectData();
       
        }
 
 
 

回复

84

帖子

0

TA的资源

一粒金砂(中级)

6
 
5.全面测试VS1003
查看芯片供电是否正常;

模拟部分是否正常:VS1003的所有DVDD,AVDD管脚以及xReset,TEST(Pin 32)接+3.0V,然后测量RCAP应在1.3V左右,否则芯片模拟部分未正常工作。

检查SCI命令是否正确。给音量控制寄存器SCI_VOL循环写入最高值和最低值,正常情况下能从耳机听到滴滴的声音,具体步骤如下:
        拉低xCS;
        设置音量最高:SCI_VOL=0x0000;
        拉高xCS;
        等待500ms,这个时间控制在0.5到1s之间,太大或太小可能都无法听到;
        拉低xCS;
        这只音量最低:SCI_VOL=0xffff;
        等待500ms,道理同上;
        拉高xCS;
        循环,否则以上步骤无法识别。
可以对SCI的读写做进一步的测试:
        拉低xCS;
        写音量控制寄存器:SCI_VOL=0xA2F5;
        适当延时,等待DREQ为高
        读音量控制寄存器,看读回的值是否与写入的一致,如果不为0xA2F5的话,说明SCI读写有问题。

6.正弦测试
Vs1003的SPI总线用来传送MP3数据和控制命令。当要传送MP3数据时,xDCS须设置为低电平,而xCS置1.此时SPI总线称作SDI(串行数据接口)。VS1003拥有一下几种测试模式:
存储器测试,SCI总线测试和正弦测试。
所有这些测试都有相同的步骤:
硬件复位,
置位模式寄存器SPI_MODE的bit5:SM_TEST,
发送测试命令到SDI总线上。
测试命令总共包含8个字节的数据,前4个字节为命令代码,后4个字节为0.正弦测试属于芯片内部的测试功能,如果写SDI无误的话,可以从耳机里听到单一频率的正弦音(可以通过命令更改频率),强烈建议大家对此项步骤测试时不要将耳塞直接塞入耳中,因为系统不同可能导致声音大小会不同,有可能及其刺耳。
正弦测试步骤如下:
        1)进入VS1003的测试模式:SPI_MODE=0x0820;
        2)等待DREQ为高
        3)xDCS = 1(xCS置1),选择vs1003的数据接口
        4)向vs1003发送正弦测试命令:0x53 0xef 0x6e n 0x00 0x00 0x00 0x00,其中
        n =   0x24, 设定vs1003所产生的正弦波的频率值,具体计算方法见vs1003
        的datasheet
        wait(500);延时500ms
        退出正弦测试,发送命令:0x45 0x78 0x69 0x74 0x00 0x00 0x00 0x00;
        wait(500);延时500ms
        循环
        如果这一步通过了,说明你的VS1003已经做好了为你播放MP3的准备。下面的工作就很轻松了,把MP3的文件数据有条不紊的发给VS1003,让它为你完成MP3的解码和播放任务。至此,VS1003的驱动任务就完成了。
        代码如下:
        void VsSineTest(void)
        {
                Mp3PutInReset();  //xReset = 0   复位vs1003
                wait(100);        //延时100ms        
                SPIPutChar(0xff);//发送一个字节的无效数据,启动SPI传输
                Mp3DeselectControl();  
                Mp3DeselectData();     
                Mp3ReleaseFromReset();
                wait(100);                      
                 Mp3WriteRegister(SPI_MODE,0x08,0x20);//进入vs1003的测试模式
                while(VS_DREQ_READ() == 0);     //等待DREQ为高
                 Mp3SelectData();       //xDCS = 1,选择vs1003的数据接口
                
                 //向vs1003发送正弦测试命令:0x53 0xef 0x6e n 0x00 0x00 0x00 0x00
                 //其中n = 0x24, 设定vs1003所产生的正弦波的频率值,具体计算方法见vs1003的datasheet
            SPIPutChar(0x53);      
                SPIPutChar(0xef);      
                SPIPutChar(0x6e);      
                SPIPutChar(0x24);      
                SPIPutChar(0x00);      
                SPIPutChar(0x00);
                SPIPutChar(0x00);
                SPIPutChar(0x00);
       
                wait(500);
                Mp3DeselectData();//程序执行到这里后应该能从耳机听到一个单一频率的声音
          
                //退出正弦测试
                Mp3SelectData();
                SPIPutChar(0x45);
                SPIPutChar(0x78);
                SPIPutChar(0x69);
                SPIPutChar(0x74);
                SPIPutChar(0x00);
                SPIPutChar(0x00);
                SPIPutChar(0x00);
                SPIPutChar(0x00);
       
                wait(500);
                Mp3DeselectData();
       
                //再次进入正弦测试并设置n值为0x44,即将正弦波的频率设置为另外的值
                    Mp3SelectData();      
                SPIPutChar(0x53);      
                SPIPutChar(0xef);      
                SPIPutChar(0x6e);      
                SPIPutChar(0x44);      
                SPIPutChar(0x00);      
                SPIPutChar(0x00);
                SPIPutChar(0x00);
                SPIPutChar(0x00);
       
                wait(500);
                Mp3DeselectData();
       
                //退出正弦测试
                Mp3SelectData();
                SPIPutChar(0x45);
                SPIPutChar(0x78);
                SPIPutChar(0x69);
                SPIPutChar(0x74);
                SPIPutChar(0x00);
                SPIPutChar(0x00);
                SPIPutChar(0x00);
                SPIPutChar(0x00);
       
                wait(500);
                Mp3DeselectData();
}
 
 
 

回复

84

帖子

0

TA的资源

一粒金砂(中级)

7
 
播放MP3

这里的MP3的存储介质是SD卡。现在要做的事情是将MP3文件从SD卡中读出来,送到8962的缓冲区,缓冲区的大小设置为512Byte,一般一次读
        个扇区,然后将数据发往VS1003。由于VS1003有32字节的数据缓冲区,一次可以发32个字节的数据,然后检测DREQ,当DREQ
为高时送下一个32字节的数据,直到发完为止。DREQ为高表明VS1003可以接受新的数据,如果不考虑DREQ直接给VS1003发数据的话,会出现音乐断断续续的情况。
这里,先把音乐数据包含在程序里,存在data.h文件里。具体程序如下:
#include
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "utils/cmdline.h"
#include "utils/uartstdio.h"
#include "fatfs/src/ff.h"
#include "fatfs/src/diskio.h"
#include "data.h"
#include "vs1003.h"
int
main(void)
{
    unsigned long ulindex;
        unsigned short i;
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_8MHZ);




        vs1003_io_init();
        vs1003_init();
        VsSineTest();
        //vs1003_init();
        //UARTprintf("SysCtlClock:%d\n",SysCtlClockGet());
        while(1)
        {       
                ulindex=0;
                Mp3SelectData();

                while(ulindex < 15000)
                {
                         
                                while(VS_DREQ_READ() == 0);     //等待DREQ为高
                                for(i=0;i<32;i++)
                                {
                                        SPIPutChar(vsBeepMP3[ulindex]); //循环送数据到VS1003
                                        ulindex++;
                                }
                               
                                if(ulindex==14999)break;                       
                }       
                Mp3DeselectData();
        }
}


接下来要做的就是把数据存在SD卡里,然后边读数据边送数据,出现了一点问题,有待解决。
 
 
 

回复

2641

帖子

0

TA的资源

五彩晶圆(中级)

8
 
谢谢分享,非常好的帖子
 
 
 

回复

473

帖子

0

TA的资源

纯净的硅(中级)

9
 
这个蛮有意思,呵呵,年初在MCF51CN128上做过
 
个人签名Nicrosystem专业提供freescale、TI和STM32高性价比开发板、解决方案
http://nicrosystem.taobao.com
 
 

回复

1412

帖子

15

TA的资源

版主

10
 
 
个人签名https://bbs.eeworld.com.cn/thread-471646-1-1.html
欢迎加入我的团队
 
 

回复

5310

帖子

453

TA的资源

五彩晶圆(高级)

11
 
DVDD,AVDD管脚以及xReset,TEST(Pin 32)接+3.3V 应该没关系吧!
 
 
 

回复

1412

帖子

15

TA的资源

版主

12
 

原帖由 蓝雨夜 于 2011-1-11 10:22 发表 DVDD,AVDD管脚以及xReset,TEST(Pin 32)接+3.3V 应该没关系吧!

 

最好按照DATASHEET来,2.8v,2.5v

 
个人签名https://bbs.eeworld.com.cn/thread-471646-1-1.html
欢迎加入我的团队
 
 

回复

5310

帖子

453

TA的资源

五彩晶圆(高级)

13
 
最高3。6,我接个3。3应该没关系吧!

正弦测试就是没声音。。。。。。。。。。
 
 
 

回复

229

帖子

0

TA的资源

一粒金砂(中级)

14
 

好东西

MP3还没有做过 看来 已经有你们铺路了~~  呵呵 谢谢分享~~
 
 
 

回复

5310

帖子

453

TA的资源

五彩晶圆(高级)

15
 
郁闷!换了片VS1003B  正弦测试还是没有声音啊!
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

16
 
不错的帖子,学习了
 
 
 

回复

471

帖子

0

TA的资源

一粒金砂(高级)

17
 
看了就顶
 
 
 

回复

141

帖子

0

TA的资源

纯净的硅(初级)

18
 
8962 有一个 SPI接口吗  我怎么没有看到呢 求具体的引脚数 谢谢
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(初级)

19
 

lm3s8962模拟SPI驱动VS1003学习心得~~

帖子不错,谢谢分享、、、、

 
 
 

回复

55

帖子

0

TA的资源

一粒金砂(中级)

20
 
其实可以和SD卡并用一个SPI端口的   只是片选控制端不一样就可以了   VS1003和SD卡没有同时读取
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表