`
ydbc
  • 浏览: 737924 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

STM32的SPI采用DMA方式传输测试

 
阅读更多

STM32的SPI采用DMA方式传输测试

文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.

环境:

主机:WIN7

开发环境:MDK4.23

MCU:STM32F103CBT6

说明:

参考链接:http://www.openedv.com/posts/list/3159.htm

SPI传输数据分为连续传输和非连续传输.

连续传输时序图:

非连续传输时序图:

非连续传输模式可以参考上篇文章:http://blog.csdn.net/jdh99/article/details/7598573

官方pdf关于连续和非连续传输的说明:
当在主模式下发送数据时,如果软件足够快,能够在检测到每次TXE的上升沿(或TXE中断),并立即在正在进行的传输结束之前写入SPI_DR寄存器,则能够实现连续的通信;此时,在每个数据项的传输之间的SPI时钟保持连续,同时BSY位不会被清除。

简而言之,就是要及时监测TXE.在SPI在1M以上波特率传输时,传输一位时间为1us,导致软件不能及时判断,此时可以用dma的方式来进行SPI传输.

源代码:

配置:

#define buffersize 512

#define SPI1_DR_Addr ( (u32)0x4001300C )

extern uint8_t SPI1_TX_Buff[buffersize];
extern uint8_t SPI1_RX_Buff[buffersize];

void SPI1_DMA_Configuration( void )
{

    RCC->AHBENR |= 1<<0 ;                     //DMA1时钟使能

	/*------------------配置SPI1_RX_DMA通道Channel2---------------------*/

    DMA1_Channel2->CCR &= ~( 1<<14 ) ;        //非存储器到存储器模式
	DMA1_Channel2->CCR |=    2<<12   ;        //通道优先级高
	DMA1_Channel2->CCR &= ~( 3<<10 ) ;        //存储器数据宽度8bit
	DMA1_Channel2->CCR &= ~( 3<<8  ) ;        //外设数据宽度8bit
	DMA1_Channel2->CCR |=    1<<7    ;        //存储器地址增量模式
	DMA1_Channel2->CCR &= ~( 1<<6  ) ;        //不执行外设地址增量模式
	DMA1_Channel2->CCR &= ~( 1<<5  ) ;        //执行循环操作
	DMA1_Channel2->CCR &= ~( 1<<4  ) ;        //从外设读

	DMA1_Channel2->CNDTR &= 0x0000   ;        //传输数量寄存器清零
	DMA1_Channel2->CNDTR = buffersize ;       //传输数量设置为buffersize个

	DMA1_Channel2->CPAR = SPI1_DR_Addr ;      //设置外设地址,注意PSIZE
	DMA1_Channel2->CMAR = (u32)SPI1_RX_Buff ; //设置DMA存储器地址,注意MSIZE

	/*------------------配置SPI1_TX_DMA通道Channel3---------------------*/

	DMA1_Channel3->CCR &= ~( 1<<14 ) ;        //非存储器到存储器模式
	DMA1_Channel3->CCR |=    0<<12   ;        //通道优先级最低
	DMA1_Channel3->CCR &= ~( 3<<10 ) ;        //存储器数据宽度8bit
	DMA1_Channel3->CCR &= ~( 3<<8 )  ;        //外设数据宽度8bit
	DMA1_Channel3->CCR |=    1<<7    ;        //存储器地址增量模式
	DMA1_Channel3->CCR &= ~( 1<<6 )  ;        //不执行外设地址增量模式
	DMA1_Channel3->CCR &= ~( 1<<5 ) ;         //不执行循环操作
	DMA1_Channel3->CCR |=    1<<4    ;        //从存储器读

	DMA1_Channel3->CNDTR &= 0x0000   ;        //传输数量寄存器清零
	DMA1_Channel3->CNDTR = buffersize ;       //传输数量设置为buffersize个
	
	DMA1_Channel3->CPAR = SPI1_DR_Addr ;      //设置外设地址,注意PSIZE
	DMA1_Channel3->CMAR = (uint32_t)SPI1_TX_Buff ; //设置DMA存储器地址,注意MSIZE				 
}


接收与发送:

void SPI1_ReceiveSendByte( u16 num )
{
	DMA1_Channel2->CNDTR = 0x0000   ;           //传输数量寄存器清零
	DMA1_Channel2->CNDTR = num ;         //传输数量设置为buffersize个

	DMA1_Channel3->CNDTR = 0x0000   ;           //传输数量寄存器清零
	DMA1_Channel3->CNDTR = num ;         //传输数量设置为buffersize个

	DMA1->IFCR = 0xF0 ;                         //清除通道2的标志位
	DMA1->IFCR = 0xF00 ;                        //清除通道3的标志位

	SPI1->DR ;									//接送前读一次SPI1->DR,保证接收缓冲区为空

	while( ( SPI1->SR & 0x02 ) == 0 );
	
	DMA1_Channel3->CCR |= 1 << 0 ;              //开启DMA通道3
	DMA1_Channel2->CCR |= 1 << 0 ;              //开启DMA通道2	

	while( ( DMA1->ISR & 0x20 ) == 0 );

	DMA1_Channel3->CCR &= ~( 1 << 0 ) ;         //关闭DMA通道3
	DMA1_Channel2->CCR &= ~( 1 << 0 ) ;         //关闭DMA通道2

}
//SPI发送一个字节
static uint8 SPI_SendByte(uint8 Data)
{
	#ifndef SPI_DMA
	
	// Loop while DR register in not emplty
	while( SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_TXE ) == RESET ) ;

	// Send byte through the SPI1 peripheral
	SPI_I2S_SendData( SPI1, Data ) ;

	// Wait to receive a byte
	while( SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_RXNE ) == RESET ) ;

	// Return the byte read from the SPI bus
	return SPI_I2S_ReceiveData( SPI1 ) ;
	
	#else

	SPI1_TX_Buff[0] = Data;
	SPI1_ReceiveSendByte(1);

	return (SPI1_RX_Buff[0]);
	#endif
}

//SPI读取Len字节
void SPI_ReadBytes( uint8 Addr, NtrxBufferPtr Buffer, uint8 Len )
{
	#ifndef SPI_DMA
	if( ( Len > 0x80 ) || ( Len == 0 ) )
		Len = 1 ;
	SPI_SendByte( Len ) ;
	SPI_SendByte( Addr ) ;
	while( Len-- )
    	{
    		*Buffer = SPI_SendByte( 0xFF ) ;
		Buffer ++ ;
	}
	#else

	uint8 i = 0;

	if( ( Len > 0x80 ) || ( Len == 0 ) )
		Len = 1 ;

	SPI1_TX_Buff[0] = Len;
	SPI1_TX_Buff[1] = Addr;

	SPI1_ReceiveSendByte(Len + 2);

	for (i = 0;i < Len;i++)
	{
	 	*Buffer++ = SPI1_RX_Buff[i + 2];	
	}
	#endif
}
分享到:
评论

相关推荐

    11-1_1.14寸IPS屏stm32硬件SPI_SPI驱动+DMA_1.14寸_SPI屏DMA_stm32spiDMA

    标题中的“11-1_1.14寸IPS屏stm32硬件SPI_SPI驱动+DMA_1.14寸_SPI屏DMA_stm32spiDMA”表明这是一个关于使用STM32微控制器通过硬件SPI(Serial Peripheral Interface)并结合DMA(Direct Memory Access)驱动1.14英寸...

    STM32 硬件SPI+DMA控制OLED屏幕

    通过设置DMA传输请求源、传输数据大小、地址增量方式等,可以实现数据的批量传输,显著提高系统性能。 3. **配置OLED屏幕**:OLED屏幕通常使用I2C或SPI接口,这里我们关注SPI。首先,需要初始化OLED驱动芯片,发送...

    STM32F4+W5500 利用SPI_DMA以太网进行通讯

    设置好SPI和DMA的相关参数后,启动DMA传输,CPU就可以专注于其他任务,而数据传输由DMA控制器自动完成。这样不仅提高了数据传输速率,还降低了CPU的功耗。 5. 实现步骤: - 初始化STM32F4的SPI接口,包括配置时钟...

    STM32G0 硬件SPI+DMA+LL库,最高通讯速率32MBit/s

    3. 优化DMA传输的中断处理,确保数据的及时处理和新的数据传输。 4. 检查信号完整性,确保连接线缆的质量和长度符合高速传输的要求。 经过逻辑分析仪验证,表明这个配置在实际应用中能够正确无误地传输数据,证明了...

    spi-dma.rar_SPI+DMA_STM32 DMA SPI_stm32 spi1 DMA_stm32 spi dma

    7. **安全性考虑**:在进行SPI-DMA传输时,需要确保SPI和DMA的配置不会发生冲突,例如,在数据传输过程中避免修改SPI或DMA的配置寄存器。 通过以上步骤,STM32能够利用SPI和DMA进行高效的串行通信,特别适用于大...

    STM32F4系列(F1类似),使用DMA驱动硬件8位SPI 高速推动OLED屏

    4. 设置DMA传输的源地址和目标地址:源地址通常是内存中的显示数据缓冲区,目标地址是SPI接口的数据寄存器。 5. 设置DMA传输长度:根据要发送的OLED数据量来设定。 6. 启动DMA传输:启动指定的DMA通道,数据传输...

    stm32f407通过SPI+DMA方式驱动WS2812

    6. 处理中断:设置DMA传输完成中断,当DMA完成向SPI的数据传输后,可以执行清除缓存、更新颜色、处理其他任务等操作。 7. 控制LED灯串:通过调整发送到DMA的数据,可以改变WS2812的亮度和颜色,实现各种动态效果。 ...

    STM32F103标准库SPI_DMA代码.rar

    4. 启动DMA传输:调用相关函数启动DMA传输,并在需要时开启SPI接口。 5. 处理中断:根据需求配置中断,如传输完成中断,然后编写中断服务程序以处理数据传输完成后的操作。 在压缩包中的代码示例,开发者可以学习...

    STM32f103+RGB-TFT_LCD(ST7735)+硬件SPI+DMA+CUBEMX配置

    这包括初始化SPI和DMA寄存器,设置传输参数,以及启动DMA传输。在显示图像时,将图像数据加载到DMA传输缓冲区,然后启动DMA传输。 5. 中断处理:设置中断服务程序以处理DMA传输完成事件。当传输完成后,可以清除...

    STM32F407标准库SPI_DMA代码.rar

    8. **同步机制**:由于SPI通信可能涉及多个设备,所以可能需要使用DMA传输完成标志或者特定的同步信号来协调不同设备的操作。 9. **调试技巧**:使用如STM32CubeIDE或Keil MDK等IDE进行代码调试,利用断点、变量...

    STM32F103X SPI2 DMA 驱动LCD.zip

    - 启动DMA传输:在需要更新LCD显示时,通过DMA发送数据到SPI2,由SPI2传输到LCD。 - 中断处理:当DMA传输完成时,可以通过中断服务程序进行后续操作,如清除传输标志,准备下一次传输。 6. **注意事项**: - SPI...

    SPI_DMA.rar_DMA STM32 SPI_SPI+DMA_STM32 DMA SPI_stm32 spi_stm32

    STM32是一款广泛应用的微控制器,它具有丰富的外设接口,包括串行外围接口(SPI)和直接存储器访问(DMA)。在这个项目中,我们关注的是如何利用STM32的SPI接口结合DMA进行数据传输。SPI是一种同步串行通信协议,...

    stm32h750使用SPI驱动lil9341,开启dma,移植好了lvgl

    在本文中,我们将深入探讨如何使用STM32H750微控制器通过SPI接口驱动LIL9341液晶显示屏,并结合DMA(直接存储器访问)技术,实现高效的图形库移植,例如LVGL,以达到100fps的刷新率。 STM32H750是意法半导体...

    STM32 SPI DMA驱动外部FLASH,寄存器操作,单发,单收,速度快

    STM32 SPI DMA驱动外部FLASH是一种高效的通信方式,它结合了SPI(Serial Peripheral Interface)串行接口和DMA(Direct Memory Access)直接内存访问技术,能够实现高速的数据传输,减轻CPU负担,提高系统的运行效率...

    stm32f407_SPI_DMA_TEST_2018.6.30.rar

    通过特定的测试程序,可以测量STM32F407通过SPI+DMA方式从TF卡读取和写入数据的速度,从而了解系统在实际应用中的性能。 6. 配置步骤:实现这个功能需要对STM32的GPIO、SPI和DMA寄存器进行初始化配置。首先,设置...

    STM32F767 SPI DMA 9341高速刷新

    STM32F767是意法半导体(STMicroelectronics)推出的一款高性能微控制器,属于Cortex-M7内核系列,具有丰富的外设接口和高速处理能力...在实际应用中,还可以根据需求调整SPI参数、优化DMA传输策略,以进一步优化性能。

    基于STM32的DMA传输实例

    本文将深入探讨基于STM32的DMA传输实例,以及如何结合串口进行数据通信。 首先,理解DMA的基本原理至关重要。DMA允许外围设备直接与内存交互,而无需CPU介入,从而减少了CPU的负载并提高了数据传输速率。在STM32中...

    STM32F407RCT6 spi+dma刷tft屏(ST7789)代码

    在使用DMA时,这个函数会触发DMA传输,而不是直接通过SPI接口发送数据。 5. **触摸屏驱动**:如果ST7789集成了触摸屏控制器,我们需要读取其返回的触摸坐标。这通常涉及到配置另一个GPIO引脚作为中断源,并编写中断...

    STM32HAL库+SPI+DMA驱动SW2812

    在这个函数中,使用`HAL_SPI_Transmit_DMA()`启动DMA传输,传入数据缓冲区地址和长度。为了确保数据正确传输,可以添加中断服务程序处理DMA完成中断,更新状态或启动下一轮数据发送。 SW2812的数据格式特殊,每个...

Global site tag (gtag.js) - Google Analytics