打印

SPI的NSS引脚在硬件模式下如何配置拉高拉低?

[复制链接]
10601|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
liersong001|  楼主 | 2012-5-6 11:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32外接了一篇AD7327芯片,使用SPI2接口通信,7327在进行每个寄存器的配置和数据读取时需要先把CS管教拉低,单个寄存器配置完成和数据读取完成后腰拉高CS,下次通信时再拉低。电路中把STM32的NSS脚和AD7327的CS脚直接连接,使用SPI的硬件配置NSS管教模式,现在不知道如何在每次通信完后拉高NSS,使用SPI_SSOutputCmd()函数完全没有效果,求教各位前辈如何处理。
void SPI2_Config(void)
{
u8 i;   
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//双线全双工模式,或改为双线单向接收
   SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//SPI主模式
   SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;//16位模式
   SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行时钟稳态:时钟悬空高
   SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;//数据捕获于第一个时钟沿   SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS由外部管脚管理,在主模式下拉低NSS通知其他从设备
   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;//16分频,2MHz波特率
   SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//高位开始传输
SPI_InitStructure.SPI_CRCPolynomial = 7;  //CRC多项式不设置,缺省值
   

SPI_Init(SPI2, &SPI_InitStructure);
SPI_CalculateCRC(SPI2,DISABLE);
SPI_SSOutputCmd(SPI2, ENABLE);
SPI_Cmd(SPI2, ENABLE);  
   
SPI_SSOutputCmd(SPI2, DISABLE);
   
for (i = 40; i != 0; i--)
   {   
   }

SPI_SSOutputCmd(SPI2, ENABLE);
SPI_I2S_SendData(SPI2 , 0xAAA0);     //范围寄存器1
for (i = 40; i != 0; i--)
   {   
   }
SPI_SSOutputCmd(SPI2, DISABLE);
for (i = 40; i != 0; i--)
   {   
   }

SPI_SSOutputCmd(SPI2, ENABLE);
SPI_I2S_SendData(SPI2 , 0xEAA0);    //范围寄存器2
for (i = 40; i != 0; i--)
   {   
   }
SPI_SSOutputCmd(SPI2, DISABLE);
for (i = 40; i != 0; i--)
   {   
   }

SPI_SSOutputCmd(SPI2, ENABLE);
SPI_I2S_SendData(SPI2 , 0xFF80);     //配置队列寄存器
for (i = 40; i != 0; i--)
   {   
   }
SPI_SSOutputCmd(SPI2, DISABLE);
for (i = 40; i != 0; i--)
   {   
   }
SPI_SSOutputCmd(SPI2, ENABLE);
SPI_I2S_SendData(SPI2 , 0x9638);    //控制寄存器
for (i = 40; i != 0; i--)
   {   
   }
SPI_SSOutputCmd(SPI2, DISABLE);
for (i = 40; i != 0; i--)
   {   
   }

// GPIO_ResetBits(GPIOB, PB_AD_IN);
SPI_I2S_ClearITPendingBit(SPI2, SPI_IT_CRCERR);   
// SPI_Cmd(SPI2, DISABLE);
SPI_SSOutputCmd(SPI2, DISABLE);
}
沙发
airwill| | 2012-5-6 12:53 | 只看该作者
是的, 使用SPI_SSOutputCmd()函数完全没有效果.
关于这个问题, 论坛里以前就讨论过, 没有办法, 软件实现吧
直接 IO 端口置高, 置低.

使用特权

评论回复
板凳
liersong001|  楼主 | 2012-5-6 14:07 | 只看该作者
哦,我看到那个帖子了。https://bbs.21ic.com/viewthread.p ... highlight=SPI%2BNSS
软件实现SPI接口就没什么用了,有点不好啊。

使用特权

评论回复
地板
liersong001|  楼主 | 2012-5-6 17:15 | 只看该作者
直接软件实现SPI速度太低了啊,读一个16位的数据要30us,波特率只有500KHz,不行啊,太慢了,前辈们看看我这段程序能不能优化下?波特率怎么能达到2M?
s16 SPI_Read(void)
{
        u8 i;
        s16   spi_read;
        GPIO_SetBits(GPIOB,PB_AD_CS);//CS=1
//        nop(2);
        GPIO_ResetBits(GPIOB,PB_AD_CS);//CS=0
//        nop(2);
        GPIO_ResetBits(GPIOB,PB_AD_IN);//PB_AD_IN=0
        if(GPIO_ReadInputDataBit(GPIOB,PB_AD_OUT))//if(AD_DOUT)
        {
                spi_read =spi_read|0x0001;         
                spi_read=spi_read<<1;
        }
               
        GPIO_SetBits(GPIOB,PB_AD_SCLK);//AD_CLK_ON;
        for(i=0;i<15;i++)
    {       
                if(GPIOA->IDR&0X2000)
               
        //        if(GPIO_ReadInputDataBit(GPIOB,PB_AD_OUT))
                {
                        spi_read=spi_read|0x0001;
                }
                GPIO_ResetBits(GPIOB,PB_AD_SCLK);               
                spi_read = spi_read<<1;
                GPIO_SetBits(GPIOB,PB_AD_SCLK);
        }   
        GPIO_SetBits(GPIOB,PB_AD_CS);//CS=1
        return spi_read;
}

使用特权

评论回复
5
liersong001|  楼主 | 2012-5-6 17:23 | 只看该作者
芯片跑的32M的频率

使用特权

评论回复
6
liersong001|  楼主 | 2012-5-6 20:50 | 只看该作者
有木有可以优化的地方 啊?求教。

使用特权

评论回复
7
香水城| | 2012-5-6 22:23 | 只看该作者
GPIO_SetBits()   GPIO_SetBits()   是什么?  不要调用函数,直接操作寄存器。

使用特权

评论回复
8
liersong001|  楼主 | 2012-5-7 08:44 | 只看该作者
直接操作寄存器的话要这个样子,GPIOB->IDR = GPIOB->IDR|0X00001000或者GPIOB->IDR = GPIOB->IDR&0X0000EFFF还增加了一个与/或的运算,能不能直接操作IO口寄存器的某一位?还有,spi_read=spi_read|0x0001;和spi_read = spi_read<<1;还能不能优化?

使用特权

评论回复
9
liersong001|  楼主 | 2012-5-7 08:54 | 只看该作者
哦,不好意思,找到直接操作的寄存器了,直接设置GPIOB->BSRR就可以了。spi_read=spi_read|0x0001;和spi_read = spi_read<<1;还能不能优化?

使用特权

评论回复
10
acgean| | 2012-5-7 08:55 | 只看该作者
这个简单, 利用 BitBand 功能,看我的处理:

#define  SPINSS (*(u32*)(PERIPH_BB_BASE+((GPIOA_BASE+8)*32)+15*4))    // PA15


然后程序里面:

        SPINSS = 1;
......
            SPINSS = 0;

使用特权

评论回复
11
liersong001|  楼主 | 2012-5-7 09:22 | 只看该作者
现在程序改成了这个样子
s16 SPI_Read(void)
{
        u8 i;
        s16   spi_read;
        GPIOB->BSRR = 0x00001000;                //GPIO_SetBits(GPIOB,PB_AD_CS);//CS=1
        nop(2);
        GPIOB->BRR = 0x00001000;                        //GPIO_ResetBits(GPIOB,PB_AD_CS);//CS=0
        nop(2);
        GPIOB->BRR = 0x00008000;                //GPIO_ResetBits(GPIOB,PB_AD_IN);//PB_AD_IN=0
        if(GPIOB->IDR&0X2000)                        //if(GPIO_ReadInputDataBit(GPIOB,PB_AD_OUT))//if(AD_DOUT)
        {
                spi_read =spi_read|0x0001;         
                spi_read=spi_read<<1;
        }
               
        GPIOB->BSRR = 0x00002000;                //GPIO_SetBits(GPIOB,PB_AD_SCLK);//AD_CLK_ON;
        for(i=0;i<15;i++)
    {       
                if(GPIOB->IDR&0X2000)  //        if(GPIO_ReadInputDataBit(GPIOB,PB_AD_OUT))
               
                {
                        spi_read=spi_read|0x0001;
                }
                GPIOB->BRR = 0x00002000;                                        //GPIO_ResetBits(GPIOB,PB_AD_SCLK);               
                spi_read = spi_read<<1;
                GPIOB->BSRR = 0x00002000;                        //GPIO_SetBits(GPIOB,PB_AD_SCLK);
        }   
                GPIOB->BSRR = 0x00001000;                        //GPIO_SetBits(GPIOB,PB_AD_CS);//CS=1
        return spi_read;
}
波特率只有700KHz左右,怎么才能再提高呢?

使用特权

评论回复
12
liersong001|  楼主 | 2012-5-7 09:26 | 只看该作者
10# acgean 您的这种方式在端口SPI复用的情况下能拉低NSS吗?

使用特权

评论回复
13
acgean| | 2012-5-7 09:34 | 只看该作者
NSS 需要 推挽或开漏方式,复用方式无效

使用特权

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

本版积分规则

个人签名:

74

主题

342

帖子

2

粉丝