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

发布者:czm721002最新更新时间:2018-12-12 来源: eefocus关键字:LPC1768  SPI  外设控制  PCM1796 手机看文章 扫描二维码
随时随地手机看文章

#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);

}


}


关键字:LPC1768  SPI  外设控制  PCM1796 引用地址:LPC1768 SPI 外设控制DA(PCM1796)调试记录

上一篇:Lpc系列ARM的中断向量表中实现方式
下一篇:关于STM中SPI运用的NSS引脚解读

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

模拟SPI实现和调试流程
一般来说,所有的spi通信设备都可以使用模拟spi来实现,而且模拟spi的好处就是不需要针对每一款mcu去重新熟悉其spi控制器的配置,只要简单配置一下spi_clk、spi_cs、spi_mosi、spi_miso四个引脚的输入输出即可,具有很好的可移植性。 下面我以stm32为例,简单讲解一下模拟spi的实现和调试流程,实例中spi以上升沿来进行收发数据 1、首先先贴出代码 //初始化spi_clk、spi_cs、spi_mosi、spi_miso四个io //spi_cs GPIO_Initure.Pin=SIMULATE_SPI_CS_PIN; //PC10 GPIO_Initure.Mode=
[单片机]
基于AT91 M42800A设计的LED显示系统
    最近,笔者在某工厂大型生产线上基于现场总线的物流呼叫系统项目中发现,由于所需要显示的信息流比较大,用现有的基于AT89C51芯片组成的LED显示屏控制系统,由于受到微处理器的处理速度、体系架构、寻址范围、外围接口资源等诸多限制,已难以在要求显示较多像素、显示内容帧频较高、动态显示效果复杂的情况下,得到良好的动态视觉效果。针对以上情况,在利用现有资源的基础上,重新设计和研制了一种全新的,由32位高性能ARM微处理器组成的LED显示屏控制系统,并通过RS485接口与现场总线中的上位机进行实时数据通信,实现整个系统的信息显示。 1 系统硬件结构     该系统的硬件组成框图如图1所示。图1中,微处理器是Atmel公司生产的A
[单片机]
基于AT91 M42800A设计的LED显示系统
STM32自带的SPI实现对外部FLASH(W25Q128)的读写
实验功能:通过KEY1按键来控制W25Q128的写入,通过另外一个按键KEY0来控制W25Q128的读取。 硬件电路: 软件配置: //以下是SPI模块的初始化代码,配置成主机模式 //SPI口初始化 //这里针是对SPI1的初始化 void SPI1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟 RCC_APB2PeriphClockCmd(RCC_
[单片机]
数字温度传感器系统接口:SPI、I2C 、SMBus如何选
  对于需要经常进行数据流传输的系统数据,SPI是首选,因为它拥有较快的时钟速率,速率可从几兆赫兹到几十兆赫兹。然而,对于系统管理活动,如读取温度传感器的读数和查询多个从器件的状态,或者需要多个主器件共存于同一系统总线上(系统冗余常会要求这一点),或者面向低功耗应用,这时I2C 或 SMBus将是首选接口。   图1:数字温度传感器简化框图   下面几部分将介绍每种串行总线及其优缺点。   1. SPI   SPI 是一种四线制串行总线接口,为主/从结构,四条导线分别为串行时钟(SCLK)、主出从入(MOSI)、主入从出(MISO)和从选(SS)信号。主器件为时钟提供者,可发起读从器件或写从器件操作。这时主器件将与一个从器件进行
[嵌入式]
STM32的SPI时钟
1)fPCLK不是CPU频率,而是外设总线的频率。 2)STM32的SPI时钟最快是18MHz,这是芯片设计时决定的。 3)STM32的SPI1在APB2上,SPI2和SPI3在APB1上,APB1的最高频率是36MHz,APB2的最高频率是72MHz;因此,为了不超过最高18MHz的设计要求,配置SPI2和SPI3时可以使用fPCLK/2的选项,而配置SPI1时则不能使用fPCLK/2的选项。
[单片机]
AMetal平台如何快速实现SPI Flash功能
摘要:SPI NOR Flash是一种片外扩展存储器,可用来存储图片、字库等大量数据,其种类繁多,应用广泛,用户每次使用时都需耗费大量时间阅读相关的手册。如何快速实现类似的相关功能呢?下文做详细介绍。 由于SPI NOR Flash种类繁多,我们每次使用SPI NOR Flash时,都耗费许多时间在阅读相关的手册上。AMetal助你快速实现Flash功能!即使不阅读Flash芯片手册,也能顺利使用,可以把专注力投入到应用优化和算法中,提升产品质量。 AMetal平台提供了IS25xx、MX25xx等系列SPI NOR Flash的组件,提供初始化函数及丰富的功能接口。 本次介绍所使用的SPI NOR Flash为:I
[嵌入式]
AMetal平台如何快速实现<font color='red'>SPI</font> Flash功能
Stm32作为主设备使用DMA接收SPI数据
DMA发送中断和DMA接收中断必须都打开,如果接受中断不开,貌似只能接收一次成功。同时DMA接收比发送优先级要高,这条没有测试过!!! 以下代码在stm32f407上测试通过 #include spi_dma.h #include stm32f4xx_dma.h #include stm32f4xx.h #include spi.h #include SRAM.h #include data_process.h #include stdio.h #define DMA2_TX_STREAM DMA2_Stream3 #define DMA2_TX_CHANNEL DMA_Channel_3 #def
[单片机]
PIC单片机与串行闪存的SPI接口设计
  引  言   PIC单片机以性能稳定、品种众多等特点在工业控制、仪器仪表、家电、通信等领域得到广泛应用。虽然很多型号自身集成了存储器,但在很多情况下难以满足系统对大容量存储的要求,需要外扩非易失性的存储器。与并行Flash存储器相比,串行Flash存储器占用MCU引脚少,体积小,易于扩展,接线简单,工作可靠,故而越来越多地应用在各类电子产品和工业测控系统中。本文主要讨论PIC16F877A单片机与串行闪存M25P16之间的SPI通信,在要求大容量数据存储且MCU引脚资源有限的情况下具有实用价值。   1  SPI工作原理   SPI(Serial Peripheral Interface)是一种常用的串行通信协议,用于M
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

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

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