LPC1768 SPI 外设控制DA(PCM1796)调试记录

来源:互联网 发布:成都大数据培训 编辑:程序博客网 时间:2024/05/17 04:56

2015年2月2日 15:25:31

 

先上传下PCM1796的PDF,这里就不截图了

 

 

 

 

 

 

{CSDN:CODE:


/*******************************************************
DA:PCM1796初始化
2015年1月29日 11:43:18
CopyRight @ ZengZhi

**********************************************************/

#include "DA1796.h"
#define SPI_ID          (2)


#define    SPI2_CS      (1 << 16)                                        /* P0.16口为片选脚              */
#define    CE2_Low()    (LPC_GPIO0->FIOCLR |=  SPI2_CS)                   /* 选中从器件                   */
#define    CE2_High()   (LPC_GPIO0->FIOSET |=  SPI2_CS)


#define    SPI3_CS      (1 << 21)                                        /* P1.21口为片选脚              */
#define    CE3_Low()    (LPC_GPIO1->FIOCLR |=  SPI3_CS)                   /* 选中从器件                   */
#define    CE3_High()   (LPC_GPIO1->FIOSET |=  SPI3_CS)

#define  RESET_1796()   (LPC_GPIO4->FIOCLR |=  (1<<28))
#define  WORK_1796()    (LPC_GPIO4->FIOSET |=  (1<<28))


volatile uint8_t   RcvFlag = 0;                                         /* 接收到新数据标志              */
volatile uint8_t   RcvData = 0;                                         /* 接收到的数据                 */


//U47
void  SSP1_Init_SPI1(void)
{
    LPC_SC->PCONP |= (1 << 21);                                         /* 打开SSP0电源                 */
    /**
    P0.6:SPI1_SEL
    P0.7:SPI1_CLK
    P0.8:SPI1_MISO
    P0.9:SPI1_MOSI
    **/
    /* SSEL1 | SCK1 |MISO1 | MOSI1 设置管脚功能                 */
    LPC_PINCON->PINSEL0 |= (0x02ul << 12) | (0x02ul << 14) | (0x02ul << 16) |(0x02ul << 18);
    /*
    * 设置数据长度为8位,帧格式SPI,SCK高有效,第一个时钟沿采样,位速率为默认值
    */
    LPC_SSP1 ->CR0 = (0x01 << 8)                                         /* SCR  设置SPI时钟分频   25M/(0x24 * (0x01+1))      */
                     | (0x00 << 7)                                         /* CPHA 时钟输出相位            */
                     | (0x00 << 6)                                         /* CPOL 时钟输出极性            */
                     | (0x00 << 4)                                         /* FRF  帧格式 00=SPI           */
                     | (0x0F << 0);                                        /* DSS  数据长度,16bit       */

    LPC_SSP1->CR1 = (0x00 << 3)                                         /* SOD  从机输出禁能,0=允许     */
                    | (0x00 << 2)                                         /* MS   主从选择,0=主机,1=从机  */
                    | (0x01 << 1)                                         /* SSE  SSP使能                 */
                    | (0x00 << 0);                                        /* LBM  回写模式                */
    LPC_SSP1->CPSR = 0x24; //0x52;                                              /* 设置SSP从PCLK获得的分频值,   */
    /* 主模式下有效, 最小值为0x02   */
}


/*********************************************************************************************************
** Function name:      SSP_SendData
** Descriptions:       SSP接口向SSP总线发送数据
** input parameters:   data        待发送的数据
** output parameters:  返回值为读取的数据
*********************************************************************************************************/
uint16_t  SSP1_SendData(uint16_t data)
{
    while ((LPC_SSP1->SR & 0x02) == 0);                                 /* 等待发送FIFO留出空间         */
    LPC_SSP0->DR = data;
    while ((LPC_SSP1->SR & 0x10) == 0x10);                              /* 等待数据帧发送完毕           */
    return ((uint16_t)LPC_SSP1->DR);
}

void SSPSendCmd_SPI1(uint8_t addr,uint8_t ndata)
{
    uint16_t data = (0<<15) | (addr<<8) | (ndata);
    SSP1_SendData(data);
}

 

 

/*********************************************************************************************************
** Function name:     SSP0_Init
** Descriptions:      将SSP控制器设置为主机
** input parameters:  无
** output parameters: 无
**********************************************************************************************************/
void  SSP0_Init_SPI3(void)
{
    LPC_SC->PCONP |= (1 << 21);                                         /* 打开SSP0电源                 */

    /**
    P1.21:SPI3_SEL
    P1.20:SPI3_CLK
    P1.23:SPI3_MISO
    P1.24:SPI3_MOSI
    **/
    /* SSEL0 | SCK0 |MISO0 | MOSI0 设置管脚功能          U2       */
    LPC_PINCON->PINSEL3 |= (0x03ul << 8) | (0x03ul << 10) | (0x03ul << 14) |(0x03ul << 16);

    /*
    * 设置数据长度为8位,帧格式SPI,SCK高有效,第一个时钟沿采样,位速率为默认值
    */
    LPC_SSP0->CR0 = (0x01 << 8)                                         /* SCR  设置SPI时钟分频   25M/(0x24 * (0x01+1))      */
                    | (0x00 << 7)                                         /* CPHA 时钟输出相位            */
                    | (0x00 << 6)                                         /* CPOL 时钟输出极性            */
                    | (0x00 << 4)                                         /* FRF  帧格式 00=SPI           */
                    | (0x0F << 0);                                        /* DSS  数据长度,16bit       */

    LPC_SSP0->CR1 = (0x00 << 3)                                         /* SOD  从机输出禁能,0=允许     */
                    | (0x00 << 2)                                         /* MS   主从选择,0=主机,1=从机  */
                    | (0x01 << 1)                                         /* SSE  SSP使能                 */
                    | (0x00 << 0);                                        /* LBM  回写模式                */
    LPC_SSP0->CPSR = 0x24; //0x52;                                              /* 设置SSP从PCLK获得的分频值,   */
    /* 主模式下有效, 最小值为0x02   */
}

/*********************************************************************************************************
** Function name:      SSP_SendData
** Descriptions:       SSP接口向SSP总线发送数据
** input parameters:   data        待发送的数据
** output parameters:  返回值为读取的数据
*********************************************************************************************************/
uint16_t  SSP0_SendData(uint16_t data)
{
    while ((LPC_SSP0->SR & 0x02) == 0);                                 /* 等待发送FIFO留出空间         */
    LPC_SSP0->DR = data;
    while ((LPC_SSP0->SR & 0x10) == 0x10);                              /* 等待数据帧发送完毕           */
    return ((uint16_t)LPC_SSP0->DR);
}

void SSPSendCmd_SPI3(uint8_t addr,uint8_t ndata)
{
    uint16_t data = (0<<15) | (addr<<8) | (ndata);
    SSP0_SendData(data);
}

 


/*********************************************************************************************************
** Function name:       SPI_IRQHandler
** Descriptions:        SPI中断服务函数
** input parameters:    无
** output parameters:   无
** Returned value:      无
*********************************************************************************************************/
void  SPI_IRQHandler(void)
{
    uint32_t tmp = 0;
    /*
     * SPI读取数据寄存器之前,必须先读SPSR寄存器,清零SPIF位。
     */
    tmp     = LPC_SPI->SPSR;
    RcvData = LPC_SPI->SPDR;                                            /* 接收数据                     */
    RcvFlag = 0x01;                                                     /* 接收到新数据                 */
    LPC_SPI->SPINT = 0x01;                                              /* 清除标志位                   */
    tmp = tmp;
}

 


//初始化SPI
void InitSPI2(void)
{
    LPC_SC->PCONP |= (1 << 8);//I2C0

    /* 初始化SPI2引脚  SPI外设时钟 25M   */
    LPC_PINCON->PINSEL0 |= (0x03ul << 30);                             /* 设置P0.15脚为SCK脚           */
    LPC_PINCON->PINSEL1 &= ~(0x03 << 0);                                /*P0.16为GPIO*/
    LPC_GPIO0->FIODIR   |=  SPI2_CS;                                    /* 设置SPI的片选引脚            */
    LPC_PINCON->PINSEL1 |=  (0x03 << 2) | (0x03 << 4);                 /* 设置P0.17、P0.18             */
    /* 引脚为SPI引脚                */


    /* 初始化SPI寄存器  PCM1796 SCK 最大10M    */
    LPC_SPI->SPCCR  =  0x48;                                            /* 设置SPI时钟分频 在主机模式下此值必须大于8的偶数    2.5M         */
    LPC_SPI->SPCR   =   (1 << 2) |                                      /* SPI控制器每次传输   PCM1796 传输数据16bit         */
                        /* 发送和接收多位数据            */
                        (0 << 3) |                                      /* CPHA = 0, 数据在SCK          */
                        /* 的第一个时钟沿采样           */
                        (0 << 4) |                                      /* CPOL = 0, SCK 为高有效       */
                        (1 << 5) |                                      /* MSTR = 1, SPI 处于主模式     */
                        (0 << 6) |                                      /* LSBF = 0, SPI 数据           */
                        /* 传输MSB (位7)在先            */
                        (1 << 7)|                                       /* SPIE = 0, SPI 中断被使能     */
                        (0x00 << 8);                                 //  8-11位控制传输数据的位数

    NVIC_EnableIRQ(SPI_IRQn);                                           /* 初始化SPI的中断接口           */
    NVIC_SetPriority(SPI_IRQn, 4);
}


/*********************************************************************************************************
** 函数名称:  SPISndByte
** 函数功能:  通过硬件SPI接口发送一个字节
** 入口参数:  data
** 出口参数:  无
PCM1796 操作写数据都是16位,读数据是低8位有效
bit15: 1-R  0-W
bit14-8:addr
bit7-0:data
*********************************************************************************************************/
void SPI2SndByte(uint8_t addr,uint8_t ndata)
{
    uint32_t temp = 0;
    addr = addr & 0x7F;
    uint16_t SPI_data = (0<<15) | (addr<<8) | (ndata);

    CE2_Low();

    LPC_SPI->SPDR = SPI_data;
    while (0 == (LPC_SPI->SPSR & 0x80));                                /* 等待SPIF置位,               */
    /* 即等待数据发送完毕           */
    temp   = (uint32_t)LPC_SPI->SPSR;                                   /* 通过读S0SPSR,               */
    /* 清除SPIF标志                 */

    CE2_High();

    temp = temp;
}

 

//发送读命令
void SPIReadCmd(uint8_t SpiID,uint8_t addr)
{
    uint32_t temp = 0;
    uint8_t ndata = 0;
    addr = addr & 0x7F;
    uint16_t SPI_data = (1<<15) | (addr<<8) | (ndata);
    if(2 == SpiID)
        CE2_Low();
    else if(3 == SpiID)
        CE3_Low();
    else
        return;
    LPC_SPI->SPDR = SPI_data;
    while (0 == (LPC_SPI->SPSR & 0x80));                                /* 等待SPIF置位,               */
    /* 即等待数据发送完毕           */
    temp   = (uint32_t)LPC_SPI->SPSR;                                   /* 通过读S0SPSR,               */
    /* 清除SPIF标志                 */
    if(2 == SpiID)
        CE2_High();
    else if(3 == SpiID)
        CE3_High();
    else
        return;

    temp = temp;
}

 

/* 在配置FIODIR为输出后,会将默认为低电平,此时接到复位,将芯片会复位*/
//注意1796复位管脚连接到P4.28  至少20ns的低电平复位
void Init1796(void)
{
    //配置P4.28为GPIO口
//    int nRet = 0;
//    LPC_GPIO4->FIODIR |= (0x00000000|(1<<28)); //方向控制
//    LPC_GPIO4->FIOPIN |=  (0x00000000|(1<<28));
//    LPC_PINCON->PINSEL9 |= (0x02<<24);  //内部不上拉也不下拉
//    while(1) {
//        RESET_1796();
//        for( nRet = 0; nRet<1000; nRet++);
//        WORK_1796();
//        for( nRet = 0; nRet<1000; nRet++);
//    }
// U1
    InitSPI2();
    //先读23号寄存器
    while(1) {
        RcvFlag = 0;
        RcvData = 0;
        SPIReadCmd(SPI_ID,PCM1796_REG23_ADDR);
        if((RcvFlag == 1) && (RcvData == 0x1f))
            break;
    }

    SPI2SndByte(PCM1796_REG20_ADDR,0x40);    //复位PCM1796
    for(int i = 0; i<1000; i++);  //复位后短暂延时
////////////////////////////////////////////
 while(1) {
        RcvFlag = 0;
        RcvData = 0;
        SPIReadCmd(SPI_ID,PCM1796_REG18_ADDR);
        if((RcvFlag == 1))
            break;
    }
 while(1) {
        RcvFlag = 0;
        RcvData = 0;
        SPIReadCmd(SPI_ID,PCM1796_REG19_ADDR);
        if((RcvFlag == 1))
            break;
    }
 while(1) {
        RcvFlag = 0;
        RcvData = 0;
        SPIReadCmd(SPI_ID,PCM1796_REG20_ADDR);
        if((RcvFlag == 1))
            break;
    }
 while(1) {
        RcvFlag = 0;
        RcvData = 0;
        SPIReadCmd(SPI_ID,PCM1796_REG21_ADDR);
        if((RcvFlag == 1))
            break;
    }
 
/////////////////////////////////////////////////////
//    SPI2SndByte(PCM1796_REG16_ADDR,0xFF);    //不衰减
//    SPI2SndByte(PCM1796_REG17_ADDR,0xFF);

    SPI2SndByte(PCM1796_REG18_ADDR,0x36);        //0b10110100  48k 24bit 左对齐
    while(1) {
        RcvFlag = 0;
        RcvData = 0;
//        SPIReadCmd(SPI_ID,PCM1796_REG18_ADDR);
//        if((RcvFlag == 1) && (RcvData == 0x36))
//            break;
    }
    SPI2SndByte(PCM1796_REG19_ADDR,0x20);
    while(1) {
        RcvFlag = 0;
        RcvData = 0;
        SPIReadCmd(SPI_ID,PCM1796_REG19_ADDR);
        if((RcvFlag == 1)  && (RcvData == 0x20))
            break;
    }
//    SPI2SndByte(PCM1796_REG20_ADDR,0x01);
    SPI2SndByte(PCM1796_REG20_ADDR,0x02);
    while(1) {
        RcvFlag = 0;
        RcvData = 0;
        SPIReadCmd(SPI_ID,PCM1796_REG20_ADDR);
        if((RcvFlag == 1) && (RcvData == 0x02))
            break;
    }

    SPI2SndByte(PCM1796_REG21_ADDR,0x01);
    while(1) {
        RcvFlag = 0;
        RcvData = 0;
        SPIReadCmd(SPI_ID,PCM1796_REG21_ADDR);
        if((RcvFlag == 1)  && (RcvData == 0x01))
            break;
    }
//初始化U2
    SSP0_Init_SPI3();
    SSPSendCmd_SPI3(PCM1796_REG20_ADDR,0x40);    //复位PCM1796
    SSPSendCmd_SPI3(PCM1796_REG20_ADDR,0x00);
    SSPSendCmd_SPI3(PCM1796_REG20_ADDR,0x02);//|0x08|0x04
    SSPSendCmd_SPI3(PCM1796_REG18_ADDR,0x36);
    SSPSendCmd_SPI3(PCM1796_REG19_ADDR,0x20);
    SSPSendCmd_SPI3(PCM1796_REG21_ADDR,0x01);

//U47
    SSP1_Init_SPI1();
    SSPSendCmd_SPI1(PCM1796_REG20_ADDR,0x40);    //复位PCM1796
    SSPSendCmd_SPI1(PCM1796_REG20_ADDR,0x00);
    SSPSendCmd_SPI1(PCM1796_REG20_ADDR,0x02);
    SSPSendCmd_SPI1(PCM1796_REG18_ADDR,0x36);
    SSPSendCmd_SPI1(PCM1796_REG19_ADDR,0x20);
    SSPSendCmd_SPI1(PCM1796_REG21_ADDR,0x01);
}

 

 

 

 

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0 0