GD32F350.SPI软件片选模式

在开始使用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电平状态

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);
}

最开始我是直接这样操作:

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;
}

出来的波形错误,片选线被提前拉高,个人见解是数据在放入SPI_DATA寄存器后,SPI硬件自行去执行发数与时钟跳变这一些动作,而在程序上,数据存入SPI_DATA寄存器,就去执行片选线拉高动作,导致时序不正确,当时忘了记录现象;增加延时改进后就ok了

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;

}

这里延时可以改进为判断SPI发送缓冲区空标志位(TBE)的状态来等待发送完成,发送缓冲区为空时, TBE置位。 通过写SPI_DATA寄存器将下一个待发送数据写入发送缓冲区来清除TBE置位。
当发送数据较多时,就可以引入SPI+DMA的方式来发送数据,为CPU减轻工作负担,去做其他事情。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
根据提供的引用内容,我可以给你介绍一下GD32F350芯片中的SPI DMA FLASH。 GD32F350芯片是一款基于ARM Cortex-M3内核的微控制器,它具有SPI(串行外设接口)和DMA(直接内存访问)功能。SPI是一种用于在芯片之间进行通信的串行通信协议,而DMA是一种用于在外设和内存之间传输数据的技术。 在GD32F350芯片中,可以使用SPI DMA来实现对FLASH存储器的读写操作。通过使用SPI DMA,可以减轻CPU的工作负担,提高数据传输的效率。 以下是一个使用SPI DMA进行FLASH读取的示例代码: ```c #include "gd32f3x0.h" #define FLASH_BASE_ADDR 0x08000000 void spi_dma_flash_read(uint32_t addr, uint8_t *data, uint32_t size) { /* 配置SPI DMA传输 */ dma_single_data_mode_init(DMA0, DMA_CH2, (uint32_t)&SPI_DATA(SPI1), (uint32_t)data, DMA_DIR_PERIPHERAL_TO_MEMORY); dma_channel_enable(DMA0, DMA_CH2); /* 配置SPI数据长度 */ spi_i2s_data_length_config(SPI1, size); /* 配置SPI地址 */ spi_i2s_data_transmit(SPI1, addr); /* 等待SPI DMA传输完成 */ while (RESET == dma_flag_get(DMA0, DMA_CH2, DMA_FLAG_FTF)) { } /* 关闭SPI DMA传输 */ dma_channel_disable(DMA0, DMA_CH2); } int main(void) { uint8_t data[256]; /* 初始化SPI和DMA */ spi_dma_flash_init(); dma_config(); /* 从FLASH读取数据 */ spi_dma_flash_read(FLASH_BASE_ADDR, data, sizeof(data)); /* 处理读取到的数据 */ while (1) { } } ``` 在这个示例代码中,`spi_dma_flash_read`函数用于从FLASH中读取数据。首先,配置SPI DMA传输,然后设置SPI数据长度和地址,最后等待SPI DMA传输完成。读取到的数据存储在`data`数组中,你可以根据需要进行进一步处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mapoplus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值