最近使用407的SPI3连接一个16位的DA芯片,设置SPI3为单向只发送,从设备DA芯片的时序要求如下:片选SYNC的第一个下降沿启动写周期。SCLK必须在24个时钟下降沿后,才能将SYNC重新拉高。如果在第24个SCLK下降沿之前拉高SYNC,写入的数据无效。如果拉高SYNC前有超过24个SCLK下降沿,输入数据同样无效。
我在代码中明明是写之前拉低片选,写完24位数据再拉高,但是片选信号总是在发送过程中就直接拉高了,片选信号引脚使用的普通IO软件操作,实际波形图如下:
第一路信号:时钟SCLK;
第二路信号:片选,使用的是GPIOF8;
第三路信号:主设备输出MOSI,发送的数据是0xAAA1,数据正确。
摘出配置程序如下:
#define AD5754R_CS_HIGH() GPIO_SetBits(GPIOF,GPIO_Pin_8)
#define AD5754R_CS_LOW() GPIO_ResetBits(GPIOF,GPIO_Pin_8)
unsigned char AD5754R_Init(void)
{
unsigned char status = 0;
GPIO_InitTypeDef GPIO_InitStructure;/* 配置CPU板上使用LDAC引脚(PB15)为输出模式的GPIO管脚*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); /*使能LDAC引脚使用的GPIOB时钟*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); /*使能SYNC引脚使用的GPIOF时钟*/
/* 配置LDAC引脚的具体GPIO模式 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_Init(GPIOB, &GPIO_InitStructure); /*CPU板使用的LDAC引脚的GPIO口初始化*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_Init(GPIOF, &GPIO_InitStructure); /*CPU板使用的SYNC引脚的GPIO口初始化*/
AD5754R_LDAC_LOW();//LDAC初始设置成低电平,寻址的DAC输出在SYNC的上升沿更新
AD5754R_CS_HIGH(); //SYNC初始化高电平,传数据时再拉低
status = AD5754R_SPI_Init(0, 1000000, 1, 1);
//4个参数:发送优先方式(MSB/LSB)、时钟频率、时钟极性、时钟相位
return(status); //返回初始化结果,1:成功 0:初始化失败
}
unsigned char AD5754R_SPI_Init(unsigned char lsbFirst, //这几个参数只是做一个指示,具体设置在SPI初始化结构体中进行
unsigned long clockFreq,
unsigned char clockPol,
unsigned char clockPha)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* 使能 SPI3 和 GPIO 时钟 */
/* SPI3_MOSI - PC12,SPI3_SCK - PC10,SPI3_NSS - PA15 */
// RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能GPIOA时钟,SPI3_NSS - PA15
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); //使能GPIOC时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE); //使能SPI3时钟
/* SPI3引脚复用映射 */
GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_SPI3); //SPI3_SCK - PC10
GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_SPI3); //SPI3_MOSI - PC12
/* 配置引脚模式类型 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; //CPOL=0,对应SCK引脚要下拉
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
/* 指定SPI3引脚: SCK 、MOSI*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_12;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* SPI3 配置 */
// 时钟信号的下降捕捉数据
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx; //只有主机发送
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主机模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //数据帧格式,一次发送一个字节
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //CPOL=0
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //CPHA=1
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS片选信号软件控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; //波特率参数设置
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //最高位优先
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_Init(SPI3, &SPI_InitStructure); //写入配置信息,初始化SPI3结束
SPI_Cmd(SPI3, ENABLE); /* 使能 SPI3 */
return(1); //初始化成功,返回1
}
//------------------SPI写操作,8位数据帧格式,循环发三次共计24位数据,24位数据字格式已经在相关函数配置好,送该函数发送-------------
void AD5754R_SPI_Write(unsigned char* data, //指向数据数组data[]
unsigned char bytesNumber) //bytesNumber=3
{
unsigned char i=0;
AD5754R_CS_LOW(); //片选先拉高再拉低,产生一个下降沿启动写周期
for(i=0;i<bytesNumber;i++) //写入三个字节,24位数据
{
/* Loop while DR register in not empty */
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI3, data); //通过SPI3发送数据
}
AD5754R_CS_HIGH();
}
各位有没有碰到类似情况,片选信号不受控制拉高,之前按照网上一些参照用的NSS引脚设置软件输出模式是这个情况,现在改成普通IO引脚片选还这样,求帮忙分析。 |