打印

DIY优盘的MP3模块闪亮登场

[复制链接]
8676|25
手机看帖
扫描二维码
随时随地手机跟帖
沙发
古道热肠|  楼主 | 2009-3-5 10:28 | 只看该作者

驱动程序源代码

//古道热肠U盘开发板-VS1003B音乐播放模块驱动
//主办单位:www.21ic.com
//项目负责人:古道热肠
//作者邮箱:xg_2004_sy@126.com
//完成日期:2008-02-27
//备注:

#include <AT91SAM7S64.H>                    /* AT91SAM7S64 definitions */
#include <lib_AT91SAM7s64.h>

#include "..Board.h"

#include "english_6x8_pixel.h"
//#include "DriverLCD_Nokia5110.h"

#include "VS1003.h"
#include "DriverBeep.h"

#define uchar unsigned char
#define uint unsigned short int
#define ulong unsigned long

#define Macro_SetVS1003B_SDIN_High()      AT91F_PIO_SetOutput( AT91C_BASE_PIOA, VS1003B_SDIN )
#define Macro_SetVS1003B_SDIN_Low()      AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, VS1003B_SDIN)

#define Macro_SetVS1003B_SCLK_High()      AT91F_PIO_SetOutput( AT91C_BASE_PIOA, VS1003B_SCLK) 
#define Macro_SetVS1003B_SCLK_Low()      AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, VS1003B_SCLK) 

#define Macro_SetVS1003B_XCS_High()      AT91F_PIO_SetOutput( AT91C_BASE_PIOA, VS1003B_XCS)
#define Macro_SetVS1003B_XCS_Low()      AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, VS1003B_XCS)

#define Macro_SetVS1003B_XDCS_High()      AT91F_PIO_SetOutput( AT91C_BASE_PIOA, VS1003B_XDCS) 
#define Macro_SetVS1003B_XDCS_Low()      AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, VS1003B_XDCS) 

#define Macro_SetVS1003B_XRESET_High()  AT91F_PIO_SetOutput( AT91C_BASE_PIOA, VS1003B_XRESET)
#define Macro_SetVS1003B_XRESET_Low()      AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, VS1003B_XRESET)

//#define Macro_SetVS1003B_PC_High()        ;//LCD_PC = 1
//#define Macro_SetVS1003B_PC_Low()        ;//LCD_PC = 0

//#define Macro_SetBeep_High()        AT91F_PIO_SetOutput( AT91C_BASE_PIOA, Beep_Pin) 
//#define Macro_SetBeep_Low()            AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, Beep_Pin) 

#define uint8 unsigned char

 
#define Mp3PutInReset()  Macro_SetVS1003B_XRESET_Low()
 
#define Mp3ReleaseFromReset()  Macro_SetVS1003B_XRESET_High() 
 
 
#define Mp3SelectControl()  Macro_SetVS1003B_XCS_Low()
 
#define Mp3DeselectControl()   Macro_SetVS1003B_XCS_High() 
 

#define Mp3SelectData()        Macro_SetVS1003B_XDCS_Low()

#define Mp3DeselectData()    Macro_SetVS1003B_XDCS_High()



#define Macro_Set_SI_High()      Macro_SetVS1003B_SDIN_High()
#define Macro_Set_SI_Low()      Macro_SetVS1003B_SDIN_Low() 
#define Macro_Set_CLK_High()      Macro_SetVS1003B_SCLK_High()
#define Macro_Set_CLK_Low()      Macro_SetVS1003B_SCLK_Low()

//获取vs1003b芯片spi接口的数据输出引脚的值
bool GetVS1003B_SO_Value(void)
{
    unsigned int  n;
    
    n = AT91F_PIO_GetInput( AT91C_BASE_PIOA);

    return((n&VS1003B_SDO) );
         
}
//获取vs1003b芯片spi接口的数据输出引脚的值
bool GetVS1003B_DREQ_Value(void)
{
    unsigned int  n;
    
    n = AT91F_PIO_GetInput( AT91C_BASE_PIOA);

    return((n&VS1003B_DREQ) );
         
}


void wait(uchar ucDelayCount)
{
    uchar ucTempCount;
    uchar uci;

    for(ucTempCount=0; ucTempCount<ucDelayCount; ucTempCount++)
    {
        uci = 230;
        while(uci--)
        {
//            _nop_();
           }
    }
}

//#define wait(x) Delay(x)
/**********************************************************/
/*  函数名称 :   MSPI_Init                                */
/*  函数功能 : 初始化SPI接口,设置为主机。               */
/*  参数     :  无                                        */
/*  返回值   :  无                                        */
/*--------------------------------------------------------*/
void  MSPI_Init(void)
{  
//    c_SPI_SO = 1;
//    MP3_DREQ = 1;
}

/**********************************************************/
/*  函数名称 :  InitPortVS1003                            */
/*  函数功能 : MCU与vs1003接口的初始化                   */
/*  参数     :  无                                        */
/*  返回值   :  无                                        */
/*--------------------------------------------------------*/
void  InitPortVS1003(void)
{
    MSPI_Init();//SPI口的初始化
//    IODIR &= 0xfffeffff;   //其他接口线的设置,其中dreq 为输入口
//    IODIR |= MP3_XRESET | MP3_XCS | MP3_XDCS;//xRESET,xCS,xDS均为输出口
//    IOSET |= MP3_XRESET | MP3_XCS | MP3_XDCS;//xRESET,xCS,xDS默认输出高电平    
//    MP3_DREQ = 1;        //置为输入

    Macro_SetVS1003B_XRESET_High();
    Macro_SetVS1003B_XCS_High();
    Macro_SetVS1003B_XDCS_High();
}

//uint8 SD_SPI_ReadByte(void);
//void SD_SPI_WriteByte(uint8 ucSendData);

//#define SPI_RecByte()  SD_SPI_ReadByte()
//#define SPIPutChar(x) SD_SPI_WriteByte(x)

#if 1
/**********************************************************/
/*  函数名称 :  SPIPutChar                                */
/*  函数功能 : 通过SPI发送一个字节的数据                 */
/*  参数     :  待发送的字节数据                          */
/*  返回值   :  无                                        */
/*--------------------------------------------------------*/
void  SPIPutChar(unsigned char ucSendData)
{      
//    S0SPDR = c;
//    while((S0SPSR & 0x80) == 0);     //等待SPI将数据发送完毕
    uchar ucCount;
    uchar ucMaskCode;

    ucMaskCode = 0x80;
    for(ucCount=0; ucCount<8; ucCount++)
    {
        Macro_Set_CLK_Low();

        if(ucMaskCode & ucSendData)
        {
            Macro_Set_SI_High();
        }
        else
        {
            Macro_Set_SI_Low();
        }

        Macro_Set_CLK_High();
        ucMaskCode >>= 1;

    }
}

/*******************************************************************************************************************
** 函数名称: INT8U SPI_RecByte()                Name:      INT8U SPI_RecByte()
** 功能描述: 从SPI接口接收一个字节                Function: receive a byte from SPI interface
** 输   入: 无                                    Input:      NULL
** 输   出: 收到的字节                            Output:      the byte that be received
********************************************************************************************************************/
static uchar SPI_RecByte(void)
{
    uchar ucReadData;
    uchar ucCount;

    ucReadData = 0;
    Macro_Set_SI_High();

    for(ucCount=0; ucCount<8; ucCount++)
    {
        ucReadData <<= 1;
            //降低时钟频率
        Macro_Set_CLK_Low();

    
        if(GetVS1003B_SO_Value())
        {
            ucReadData |= 0x01;
        }
        Macro_Set_CLK_High();

    }

    return(ucReadData);
}

#endif

/*************************************************************/
/*  函数名称 :  Mp3WriteRegister                             */
/*  函数功能 : 写vs1003寄存器                               */
/*  参数     :  寄存器地址,待写数据的高8位,待写数据的低8位 */
/*  返回值   :  无                                           */
/*-----------------------------------------------------------*/
void Mp3WriteRegister(unsigned char addressbyte, unsigned char highbyte, unsigned char lowbyte)
{
    Mp3DeselectData();
    Mp3SelectControl();//XCS = 0
    SPIPutChar(VS_WRITE_COMMAND); //发送写寄存器命令
    SPIPutChar(addressbyte);      //发送寄存器的地址
    SPIPutChar(highbyte);         //发送待写数据的高8位
    SPIPutChar(lowbyte);          //发送待写数据的低8位
    Mp3DeselectControl();
}

/*************************************************************/
/*  函数名称 :  Mp3ReadRegister                              */
/*  函数功能 : 写vs1003寄存器                               */
/*  参数     :  寄存器地址                     */
/*  返回值   :  vs1003的16位寄存器的值                       */
/*-----------------------------------------------------------*/
unsigned int Mp3ReadRegister(unsigned char addressbyte)
{
    unsigned int resultvalue = 0;
    uchar ucReadValue;

    Mp3DeselectData();
    Mp3SelectControl();//XCS = 0
    SPIPutChar(VS_READ_COMMAND); //发送读寄存器命令
    SPIPutChar((addressbyte));     //发送寄存器的地址

//    SPIPutChar(0xff);         //发送读时钟
//    resultvalue = (SPI_RESULT_BYTE) << 8;//读取高8位数据
    ucReadValue = SPI_RecByte();
    resultvalue = ucReadValue<<8;
//    SPIPutChar(0xff);           //发送读时钟
//    resultvalue |= (SPI_RESULT_BYTE);  //读取低8位数据
    ucReadValue = SPI_RecByte();
    resultvalue |= ucReadValue;

    Mp3DeselectControl();              
    return resultvalue;                 //返回16位寄存器的值
}

/**********************************************************/
/*  函数名称 :  Mp3SoftReset                              */
/*  函数功能 : vs1003软件复位                            */
/*  参数     :  无                                        */
/*  返回值   :  无                                        */
/*--------------------------------------------------------*/
void Mp3SoftReset(void)
{
    Mp3WriteRegister (SPI_MODE, 0x08, 0x04); //软件复位

    wait(1); //延时1ms
    while (GetVS1003B_DREQ_Value() == 0); //等待软件复位结束
    Mp3WriteRegister(SPI_CLOCKF, 0x98, 0x00);//设置vs1003的时钟,3倍频
    Mp3WriteRegister (SPI_AUDATA, 0xBB, 0x81); //采样率48k,立体声
    Mp3WriteRegister(SPI_BASS, 0x00, 0x55);//设置重音
    Mp3SetVolume(50,50);//设置音量
    wait(1); //延时1ms
        
        //向vs1003发送4个字节无效数据,用以启动SPI发送
       Mp3SelectData();
    SPIPutChar(0);
    SPIPutChar(0);
    SPIPutChar(0);
    SPIPutChar(0);
    Mp3DeselectData();

}
/**********************************************************/
/*  函数名称 :  Mp3Reset                                  */
/*  函数功能 : vs1003硬件复位                            */
/*  参数     :  无                                        */
/*  返回值   :  无                                        */
/*--------------------------------------------------------*/
void Mp3Reset(void)
{    
    Mp3PutInReset();//xReset = 0   复位vs1003      
    wait(200);//延时100ms
    SPIPutChar(0xff);//发送一个字节的无效数据,启动SPI传输
    Mp3DeselectControl();   //xCS = 1
    Mp3DeselectData();     //xDCS = 1
    Mp3ReleaseFromReset(); //xRESET = 1
    wait(200);            //延时100ms
    while (GetVS1003B_DREQ_Value()== 0);//等待DREQ为高

    wait(200);            //延时100ms
     Mp3SetVolume(50,50);  
    Mp3SoftReset();//vs1003软复位
}


bool CheckVS1003B_DRQ(void)
{
    bool bResult;

    bResult =GetVS1003B_DREQ_Value();
    return(bResult);
}

/***********************************************************/
/*  函数名称 :  VsSineTest                                 */
/*  函数功能 : vs1003正弦测试,将该函数放在while循环中,  */
/*              如果能持续听到一高一低的声音,证明测试通过 */                            
/*  参数     :  无                                         */
/*  返回值   :  无                                         */
/*---------------------------------------------------------*/
void VsSineTest(void)
{
    Mp3PutInReset();  //xReset = 0   复位vs1003
    wait(200);        //延时100ms        
    SPIPutChar(0xff);//发送一个字节的无效数据,启动SPI传输
    Mp3DeselectControl();  
    Mp3DeselectData();     
    Mp3ReleaseFromReset(); 
    wait(200);                   
    Mp3SetVolume(50,50);  

     Mp3WriteRegister(SPI_MODE,0x08,0x20);//进入vs1003的测试模式
    while (GetVS1003B_DREQ_Value() == 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);
    wait(250);
    wait(250);
    Mp3DeselectData();//程序执行到这里后应该能从耳机听到一个单一频率的声音
  
        //退出正弦测试
    Mp3SelectData();
    SPIPutChar(0x45);
    SPIPutChar(0x78);
    SPIPutChar(0x69);
    SPIPutChar(0x74);
    SPIPutChar(0x00);
    SPIPutChar(0x00);
    SPIPutChar(0x00);
    SPIPutChar(0x00);
//    wait(500);
    wait(250);
    wait(250);

    Mp3DeselectData();

        //再次进入正弦测试并设置n值为0x44,即将正弦波的频率设置为另外的值
    Mp3SelectData();       
    SPIPutChar(0x53);      
    SPIPutChar(0xef);      
    SPIPutChar(0x6e);      
    SPIPutChar(0x44);      
    SPIPutChar(0x00);      
    SPIPutChar(0x00);
    SPIPutChar(0x00);
    SPIPutChar(0x00);
//    wait(500);
    wait(250);
    wait(250);

    Mp3DeselectData(); 

    //退出正弦测试
    Mp3SelectData();
    SPIPutChar(0x45);
    SPIPutChar(0x78);
    SPIPutChar(0x69);
    SPIPutChar(0x74);
    SPIPutChar(0x00);
    SPIPutChar(0x00);
    SPIPutChar(0x00);
    SPIPutChar(0x00);
//    wait(500);
    wait(250);
    wait(250);

    Mp3DeselectData();
 }

void test_1003_PlayMP3File();

void TestVS1003B(void)
{
    Mp3Reset();
    VsSineTest();
    Mp3SoftReset();
    test_1003_PlayMP3File();
}

//写寄存器,参数,地址和数据
void VS1003B_WriteCMD(unsigned char addr, unsigned int dat)
{
/*
    VS1003B_XDCS_H();
    VS1003B_XCS_L();
    VS1003B_WriteByte(0x02);
    //delay_Nus(20);
    VS1003B_WriteByte(addr);
    VS1003B_WriteByte(dat>>8);
    VS1003B_WriteByte(dat);
    //delay_Nus(200);
    VS1003B_XCS_H();
*/
    Mp3WriteRegister(addr,dat>>8,dat);
}

//读寄存器,参数 地址 返回内容
unsigned int VS1003B_ReadCMD(unsigned char addr)
{
/*
    unsigned int temp;
    unsigned char temp1;
    VS1003B_XDCS_H();
    VS1003B_XCS_L();
    VS1003B_WriteByte(0x03);
    //delay_Nus(20);
    VS1003B_WriteByte(addr);
    temp=  VS1003B_ReadByte();
    temp=temp<<8;
    temp1= VS1003B_ReadByte();
    temp=temp|temp1;;
    VS1003B_XCS_H();
    return temp;
*/
    return(Mp3ReadRegister(addr));
}

//写数据,音乐数据
void VS1003B_WriteDAT(unsigned char dat)
{
//    VS1003B_XDCS_L();
//    VS1003B_WriteByte(dat);
//    VS1003B_XDCS_H();
//    VS1003B_XCS_H();

       Mp3SelectData();
    SPIPutChar(dat);
    Mp3DeselectData();
    Mp3DeselectControl();

}

//开启环绕声
void VS1003B_SetVirtualSurroundOn(void)
{
    uchar ucRepeatCount;
    uint uiModeValue;

    ucRepeatCount =0;

    while(1)//写时钟寄存器
    {
        uiModeValue = VS1003B_ReadCMD(0x00);
        if(uiModeValue & 0x0001)
        {
            break;
        }
        else
        {
            uiModeValue |= 0x0001;
            VS1003B_WriteCMD(0,uiModeValue);
        }
        ucRepeatCount++;
        if(ucRepeatCount++ >10 )break;
    }

}

//关闭环绕声
void VS1003B_SetVirtualSurroundOff(void)
{
    uchar ucRepeatCount;
    uint uiModeValue;

    ucRepeatCount =0;

    while(1)//写时钟寄存器
    {
        uiModeValue = VS1003B_ReadCMD(0x00);
        if(uiModeValue & 0x0001)
        {
            break;
        }
        else
        {
            uiModeValue |= 0x0001;
            VS1003B_WriteCMD(0,uiModeValue);
        }
        ucRepeatCount++;
        if(ucRepeatCount++ >10 )break;
    }

}

//增强重音
//入口参数    1.强度0-15
//            2.频率0-15 (X10Hz)
void VS1003B_SetBassEnhance(uchar ucValue, uchar ucFrequencyID)
{
    uchar ucRepeatCount;
    uint uiWriteValue;
    uint uiReadValue;    

    ucRepeatCount =0;

    uiWriteValue = VS1003B_ReadCMD(0x02);

    uiWriteValue &= 0xFF00;
    uiWriteValue |= ucValue<<4;
    uiWriteValue &= (ucFrequencyID & 0x0F);

    while(1)//写时钟寄存器
    {

        VS1003B_WriteCMD(2,uiWriteValue);
        uiReadValue = VS1003B_ReadCMD(0x02);
        
        if(uiReadValue == uiWriteValue)
        {
            break;
        }
        ucRepeatCount++;
        if(ucRepeatCount++ >10 )break;
    }

}


 uint uiVolumeCount;        //当前音量值

//VS1003初始化,0成功 1失败
unsigned char VS1003B_Init()
{
    unsigned char retry;
/*
    PORT_INI();
    DDRB|=0xa0;
    VS1003B_DDR &=~(1<<VS1003B_DREQ);
    //delay_Nus(50);
    VS1003B_XCS_H();
    VS1003B_XDCS_H();
    VS1003B_XRESET_L();
    VS1003B_Delay(0xffff);
    VS1003B_XRESET_H();//使能芯片
    VS1003B_SPI_Low();//先以低频操作
    VS1003B_Delay(0xffff);//延时
*/
Mp3Reset();

    retry=0;
    while(VS1003B_ReadCMD(0x00) != 0x0800)//写mode寄存器
    {
        VS1003B_WriteCMD(0x00,0x0800);
        if(retry++ >10 )break;//{PORTB|=_BV(PB1);break;}
    }
    retry=0;
    /*while(VS1003B_ReadCMD(0x02) != 0x75)//写mode寄存器
    {
        VS1003B_WriteCMD(0x02,0x75);
        if(retry++ >10 )break;//{PORTB|=_BV(PB1);break;}
    }*/
    retry=0;
    while(VS1003B_ReadCMD(0x03) != 0x9800)//写时钟寄存器
    {
        VS1003B_WriteCMD(0x03,0x9800);
        if(retry++ >10 )break;
    }
    retry=0;
//    while(VS1003B_ReadCMD(0x0b) != 0x1111)//设音量
//    {
//        VS1003B_WriteCMD(0x0b,0x1111);
//        if(retry++ >10 )break;
//    }
    while(VS1003B_ReadCMD(0x0b) != uiVolumeCount)//设音量
    {
        VS1003B_WriteCMD(0x0b,uiVolumeCount);
        if(retry++ >10 )break;
    }

//    VS1003B_SPI_High();//提高速度,全速运行
    if(retry > 10)return 1;
    return 0;
}

//VS1003软件复位
void VS1003B_SoftReset()
{
    VS1003B_WriteCMD(0x00,0x0804);//写复位
//    VS1003B_Delay(0xffff);//延时,至少1.35ms
    wait(2);
}

使用特权

评论回复
板凳
古道热肠|  楼主 | 2009-3-5 10:29 | 只看该作者

贴个打包的,下载方便.

使用特权

评论回复
地板
starwx| | 2009-3-5 10:43 | 只看该作者

支持热肠斑竹

又拿出好东西来了,哈哈

使用特权

评论回复
5
bob.xue| | 2009-3-6 00:36 | 只看该作者

似乎双面板

使用特权

评论回复
6
xwj| | 2009-3-6 00:40 | 只看该作者

赞!

使用特权

评论回复
7
goooog| | 2009-3-6 10:03 | 只看该作者

再赞!

热肠真热!
很好的小东西。

使用特权

评论回复
8
zcx11| | 2010-4-20 10:54 | 只看该作者
赞一下。

使用特权

评论回复
9
在心一方| | 2010-4-22 16:11 | 只看该作者
厉害

使用特权

评论回复
10
renls13| | 2010-6-1 10:06 | 只看该作者
谢了
在论坛上时间不长
却总能看到热肠的帖子

使用特权

评论回复
11
zlulu2006| | 2010-6-4 15:37 | 只看该作者
现在还看不懂,以后慢慢学习……

使用特权

评论回复
12
123jj| | 2010-8-3 18:34 | 只看该作者
热肠很热心!

使用特权

评论回复
13
bluecup| | 2010-8-5 15:51 | 只看该作者
这东西我也做了一个,呵呵

使用特权

评论回复
14
shoolang| | 2010-8-5 22:15 | 只看该作者
开眼啦!

使用特权

评论回复
15
ningling_21| | 2010-8-6 12:51 | 只看该作者
不错,顶起!

使用特权

评论回复
16
青竹子洋洋| | 2011-7-4 11:21 | 只看该作者
好东西啊。。。。原理图在哪。。

使用特权

评论回复
17
lirui5528| | 2011-7-6 12:31 | 只看该作者
我知道了,我现在很多基础的东西都没有学会,我要好好学习啊!!!!

使用特权

评论回复
18
afei9527| | 2011-8-6 00:36 | 只看该作者
热肠真热!
很好的小东西。

使用特权

评论回复
19
青竹子洋洋| | 2011-9-9 09:35 | 只看该作者
狂赞啊

使用特权

评论回复
20
我是北丐| | 2011-9-10 16:15 | 只看该作者
顶~

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

284

主题

6411

帖子

16

粉丝