#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);
}
}
上一篇:Lpc系列ARM的中断向量表中实现方式
下一篇:关于STM中SPI运用的NSS引脚解读
推荐阅读最新更新时间:2024-03-16 16:19