GD32F350.SPI软件片选模式

[复制链接]
1317|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 | 显示全部楼层
  1. void SPI1_PortInit(void)
  2. {
  3.         spi_parameter_struct spi_init_struct;
  4.        
  5.         rcu_periph_clock_enable(RCU_SPI0);
  6.         rcu_periph_clock_enable(RCU_GPIOA);
  7.         rcu_periph_clock_enable(RCU_GPIOB);
  8.        
  9.         gpio_af_set(GPIOB,GPIO_AF_0,GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);                                                        //sck, MISO, MOSI                                                                                                       
  10.        
  11.         gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_15);                                                //nss                                               
  12.         gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);        //sck, MISO, MOSI                                          

  13.         gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_15);                                //nss                                       
  14.         gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);                 //sck, MISO, MOSI
  15.        
  16.         GPIO_BOP(GPIOA) = (uint32_t)GPIO_PIN_15;                                                         //set High
  17.         spi_i2s_deinit(SPI0);
  18.         /* configure SPI0 parameter */
  19.         spi_init_struct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;         //全双工                                                       
  20.         spi_init_struct.device_mode          = SPI_MASTER;                                         //主机模式                                                       
  21.         spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT;                           //8bit                                                                       
  22.         spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;                                                               
  23.         spi_init_struct.nss                  = SPI_NSS_SOFT;                                //软件触发                                                                       
  24.         spi_init_struct.prescale             = SPI_PSC_8;
  25.         spi_init_struct.endian               = SPI_ENDIAN_MSB;
  26.        
  27.        
  28.         spi_init(SPI0, &spi_init_struct);
  29.         spi_enable(SPI0);
  30. }

 楼主| xiaoqi000 发表于 2022-12-31 23:47 | 显示全部楼层
最开始我是直接这样操作:
  1. void SPI1_Hardw_SendData(uint8_t  Addr,uint8_t  Regdata,uint32_t TimeOut)
  2. {
  3.         GPIO_BC(GPIOA) = (uint32_t)GPIO_PIN_15;
  4.                 while( RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_TBE) )
  5.         {
  6.                 if(TimeOut > 0) TimeOut--;
  7.                 else                                 break;                       
  8.         }
  9.        
  10.         Addr = Addr | 0x80;                                 //地址高位置1,表示写寄存器
  11.        
  12.         spi_i2s_data_transmit(SPI0,Addr);
  13.         while( RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_TBE) )
  14.         {
  15.                 if(TimeOut > 0) TimeOut--;
  16.                 else                                 break;                       
  17.         }
  18.         spi_i2s_data_transmit(SPI0,Regdata);
  19.         GPIO_BOP(GPIOA) = (uint32_t)GPIO_PIN_15;
  20. }
 楼主| xiaoqi000 发表于 2022-12-31 23:48 | 显示全部楼层
出来的波形错误,片选线被提前拉高,个人见解是数据在放入SPI_DATA寄存器后,SPI硬件自行去执行发数与时钟跳变这一些动作,而在程序上,数据存入SPI_DATA寄存器,就去执行片选线拉高动作,导致时序不正确,当时忘了记录现象;增加延时改进后就ok了
 楼主| xiaoqi000 发表于 2022-12-31 23:50 | 显示全部楼层
  1. void SPI1_Hardw_SendData(uint8_t  Addr,uint8_t  Regdata,uint32_t TimeOut)
  2. {
  3.         GPIO_BC(GPIOA) = (uint32_t)GPIO_PIN_15;
  4.         while( RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_TBE) )
  5.         {
  6.                 if(TimeOut > 0) TimeOut--;
  7.                 else                                 break;                       
  8.         }
  9.        
  10.         Addr = Addr | 0x80;                                 //地址高位置1,表示写寄存器
  11.         spi_i2s_data_transmit(SPI0,Addr);
  12.         while( RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_TBE) )
  13.         {
  14.                 if(TimeOut > 0) TimeOut--;
  15.                 else                                 break;                       
  16.         }
  17.         spi_i2s_data_transmit(SPI0,Regdata);
  18.         delay_1us(2);                                                                        //延时等待SPI发送完成
  19.         GPIO_BOP(GPIOA) = (uint32_t)GPIO_PIN_15;

  20. }
 楼主| xiaoqi000 发表于 2022-12-31 23:51 | 显示全部楼层
这里延时可以改进为判断SPI发送缓冲区空标志位(TBE)的状态来等待发送完成,发送缓冲区为空时, TBE置位。 通过写SPI_DATA寄存器将下一个待发送数据写入发送缓冲区来清除TBE置位。
当发送数据较多时,就可以引入SPI+DMA的方式来发送数据,为CPU减轻工作负担,去做其他事情。
jackcat 发表于 2023-1-6 13:35 | 显示全部楼层
为什么不使用硬件片选呢。              
qiufengsd 发表于 2023-1-9 15:58 | 显示全部楼层
不使用nss就行了。              
mikewalpole 发表于 2023-1-12 11:07 | 显示全部楼层
选定一个引脚作为片选的。              
benjaminka 发表于 2023-1-12 12:56 | 显示全部楼层
spi有什么问题的吗?              
olivem55arlowe 发表于 2023-1-12 13:55 | 显示全部楼层
不太习惯使用NSS功能。              
tpgf 发表于 2023-2-1 14:36 | 显示全部楼层
内部NSS的电平状态决定了设备的主从模式,内部NSS状态可以由NSS外部引脚控制,也可以由控制寄存器的SSI位控制
qcliu 发表于 2023-2-1 14:49 | 显示全部楼层
内部NSS决定了主模式还是从模式,它可以通过设置SSM位选择硬件管理或是软件管理
drer 发表于 2023-2-1 15:03 | 显示全部楼层
NSS外部引脚,主要作为输入引脚。如果是硬件管理(SSM=0),则当NSS引脚为低电平的时候,NSS状态为从模式,否则为主模式
coshi 发表于 2023-2-1 15:13 | 显示全部楼层
外部NSS引脚可以作为主设备的输出引脚(SSOE=1),此时主设备拉低外部NSS引脚,使其连接上的硬件模式(SSM=0)的设备进入从模式。
kxsi 发表于 2023-2-1 15:21 | 显示全部楼层
一般使用时,配置为软件管理模式(SSM=1),然后从机的CS片选引脚由一个IO控制(可以用空出来的NSS引脚)。
wiba 发表于 2023-2-1 15:44 | 显示全部楼层
在什么情况下 片选引脚会被提前拉高呢
LASTONE111 发表于 2023-5-5 13:59 | 显示全部楼层
为啥 MISO管脚也要进行输出配置  一般不是配置成输入吗
您需要登录后才可以回帖 登录 | 注册

本版积分规则

67

主题

821

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部