打印

GD32F350.SPI软件片选模式

[复制链接]
902|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xiaoqi000|  楼主 | 2022-12-31 23:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在开始使用GD32F350G8的硬件SPI时对于NSS功能下的主从模式有点迷惑,
需求为主机模式下对从机发送数据,片选线低有效
手册上说If the application wants to use NSS line to control the SPI slave, NSS should be configured to hardware output mode (SWNSSEN=0, NSSDRV=1). NSS goes low after SPI is enabled.
这里的问题是在开启NSS硬件输出模式后,使能SPI,NSS引脚是一直低的状态,不能满足需求,但也说到可以选择通用IO来作为片选线:
The application may also use a general purpose IO as NSS pin to realize more flexible NSS.
疑惑点在于我的SPI控制线是采用对应硬件SPI的IO口,
后面发现可以不配置NSS片选线,直接控制NSS电平状态

使用特权

评论回复
沙发
xiaoqi000|  楼主 | 2022-12-31 23:45 | 只看该作者
void SPI1_PortInit(void)
{
        spi_parameter_struct spi_init_struct;
       
        rcu_periph_clock_enable(RCU_SPI0);
        rcu_periph_clock_enable(RCU_GPIOA);
        rcu_periph_clock_enable(RCU_GPIOB);
       
        gpio_af_set(GPIOB,GPIO_AF_0,GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);                                                        //sck, MISO, MOSI                                                                                                       
       
        gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_15);                                                //nss                                               
        gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);        //sck, MISO, MOSI                                          

        gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_15);                                //nss                                       
        gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);                 //sck, MISO, MOSI
       
        GPIO_BOP(GPIOA) = (uint32_t)GPIO_PIN_15;                                                         //set High
        spi_i2s_deinit(SPI0);
        /* configure SPI0 parameter */
        spi_init_struct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;         //全双工                                                       
        spi_init_struct.device_mode          = SPI_MASTER;                                         //主机模式                                                       
        spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT;                           //8bit                                                                       
        spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;                                                               
        spi_init_struct.nss                  = SPI_NSS_SOFT;                                //软件触发                                                                       
        spi_init_struct.prescale             = SPI_PSC_8;
        spi_init_struct.endian               = SPI_ENDIAN_MSB;
       
       
        spi_init(SPI0, &spi_init_struct);
        spi_enable(SPI0);
}

使用特权

评论回复
板凳
xiaoqi000|  楼主 | 2022-12-31 23:47 | 只看该作者
最开始我是直接这样操作:
void SPI1_Hardw_SendData(uint8_t  Addr,uint8_t  Regdata,uint32_t TimeOut)
{
        GPIO_BC(GPIOA) = (uint32_t)GPIO_PIN_15;
                while( RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_TBE) )
        {
                if(TimeOut > 0) TimeOut--;
                else                                 break;                       
        }
       
        Addr = Addr | 0x80;                                 //地址高位置1,表示写寄存器
       
        spi_i2s_data_transmit(SPI0,Addr);
        while( RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_TBE) )
        {
                if(TimeOut > 0) TimeOut--;
                else                                 break;                       
        }
        spi_i2s_data_transmit(SPI0,Regdata);
        GPIO_BOP(GPIOA) = (uint32_t)GPIO_PIN_15;
}

使用特权

评论回复
地板
xiaoqi000|  楼主 | 2022-12-31 23:48 | 只看该作者
出来的波形错误,片选线被提前拉高,个人见解是数据在放入SPI_DATA寄存器后,SPI硬件自行去执行发数与时钟跳变这一些动作,而在程序上,数据存入SPI_DATA寄存器,就去执行片选线拉高动作,导致时序不正确,当时忘了记录现象;增加延时改进后就ok了

使用特权

评论回复
5
xiaoqi000|  楼主 | 2022-12-31 23:50 | 只看该作者
void SPI1_Hardw_SendData(uint8_t  Addr,uint8_t  Regdata,uint32_t TimeOut)
{
        GPIO_BC(GPIOA) = (uint32_t)GPIO_PIN_15;
        while( RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_TBE) )
        {
                if(TimeOut > 0) TimeOut--;
                else                                 break;                       
        }
       
        Addr = Addr | 0x80;                                 //地址高位置1,表示写寄存器
        spi_i2s_data_transmit(SPI0,Addr);
        while( RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_TBE) )
        {
                if(TimeOut > 0) TimeOut--;
                else                                 break;                       
        }
        spi_i2s_data_transmit(SPI0,Regdata);
        delay_1us(2);                                                                        //延时等待SPI发送完成
        GPIO_BOP(GPIOA) = (uint32_t)GPIO_PIN_15;

}

使用特权

评论回复
6
xiaoqi000|  楼主 | 2022-12-31 23:51 | 只看该作者
这里延时可以改进为判断SPI发送缓冲区空标志位(TBE)的状态来等待发送完成,发送缓冲区为空时, TBE置位。 通过写SPI_DATA寄存器将下一个待发送数据写入发送缓冲区来清除TBE置位。
当发送数据较多时,就可以引入SPI+DMA的方式来发送数据,为CPU减轻工作负担,去做其他事情。

使用特权

评论回复
7
jackcat| | 2023-1-6 13:35 | 只看该作者
为什么不使用硬件片选呢。              

使用特权

评论回复
8
qiufengsd| | 2023-1-9 15:58 | 只看该作者
不使用nss就行了。              

使用特权

评论回复
9
mikewalpole| | 2023-1-12 11:07 | 只看该作者
选定一个引脚作为片选的。              

使用特权

评论回复
10
benjaminka| | 2023-1-12 12:56 | 只看该作者
spi有什么问题的吗?              

使用特权

评论回复
11
olivem55arlowe| | 2023-1-12 13:55 | 只看该作者
不太习惯使用NSS功能。              

使用特权

评论回复
12
tpgf| | 2023-2-1 14:36 | 只看该作者
内部NSS的电平状态决定了设备的主从模式,内部NSS状态可以由NSS外部引脚控制,也可以由控制寄存器的SSI位控制

使用特权

评论回复
13
qcliu| | 2023-2-1 14:49 | 只看该作者
内部NSS决定了主模式还是从模式,它可以通过设置SSM位选择硬件管理或是软件管理

使用特权

评论回复
14
drer| | 2023-2-1 15:03 | 只看该作者
NSS外部引脚,主要作为输入引脚。如果是硬件管理(SSM=0),则当NSS引脚为低电平的时候,NSS状态为从模式,否则为主模式

使用特权

评论回复
15
coshi| | 2023-2-1 15:13 | 只看该作者
外部NSS引脚可以作为主设备的输出引脚(SSOE=1),此时主设备拉低外部NSS引脚,使其连接上的硬件模式(SSM=0)的设备进入从模式。

使用特权

评论回复
16
kxsi| | 2023-2-1 15:21 | 只看该作者
一般使用时,配置为软件管理模式(SSM=1),然后从机的CS片选引脚由一个IO控制(可以用空出来的NSS引脚)。

使用特权

评论回复
17
wiba| | 2023-2-1 15:44 | 只看该作者
在什么情况下 片选引脚会被提前拉高呢

使用特权

评论回复
18
LASTONE111| | 2023-5-5 13:59 | 只看该作者
为啥 MISO管脚也要进行输出配置  一般不是配置成输入吗

使用特权

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

本版积分规则

47

主题

687

帖子

0

粉丝