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”表明这是一个关于使用STM32微控制器通过硬件SPI(Serial Peripheral Interface)并结合DMA(Direct Memory Access)驱动1.14英寸...
通过设置DMA传输请求源、传输数据大小、地址增量方式等,可以实现数据的批量传输,显著提高系统性能。 3. **配置OLED屏幕**:OLED屏幕通常使用I2C或SPI接口,这里我们关注SPI。首先,需要初始化OLED驱动芯片,发送...
设置好SPI和DMA的相关参数后,启动DMA传输,CPU就可以专注于其他任务,而数据传输由DMA控制器自动完成。这样不仅提高了数据传输速率,还降低了CPU的功耗。 5. 实现步骤: - 初始化STM32F4的SPI接口,包括配置时钟...
7. **安全性考虑**:在进行SPI-DMA传输时,需要确保SPI和DMA的配置不会发生冲突,例如,在数据传输过程中避免修改SPI或DMA的配置寄存器。 通过以上步骤,STM32能够利用SPI和DMA进行高效的串行通信,特别适用于大...
3. 优化DMA传输的中断处理,确保数据的及时处理和新的数据传输。 4. 检查信号完整性,确保连接线缆的质量和长度符合高速传输的要求。 经过逻辑分析仪验证,表明这个配置在实际应用中能够正确无误地传输数据,证明了...
4. 启动DMA传输:调用相关函数启动DMA传输,并在需要时开启SPI接口。 5. 处理中断:根据需求配置中断,如传输完成中断,然后编写中断服务程序以处理数据传输完成后的操作。 在压缩包中的代码示例,开发者可以学习...
4. 设置DMA传输的源地址和目标地址:源地址通常是内存中的显示数据缓冲区,目标地址是SPI接口的数据寄存器。 5. 设置DMA传输长度:根据要发送的OLED数据量来设定。 6. 启动DMA传输:启动指定的DMA通道,数据传输...
6. 处理中断:设置DMA传输完成中断,当DMA完成向SPI的数据传输后,可以执行清除缓存、更新颜色、处理其他任务等操作。 7. 控制LED灯串:通过调整发送到DMA的数据,可以改变WS2812的亮度和颜色,实现各种动态效果。 ...
这包括初始化SPI和DMA寄存器,设置传输参数,以及启动DMA传输。在显示图像时,将图像数据加载到DMA传输缓冲区,然后启动DMA传输。 5. 中断处理:设置中断服务程序以处理DMA传输完成事件。当传输完成后,可以清除...
8. **同步机制**:由于SPI通信可能涉及多个设备,所以可能需要使用DMA传输完成标志或者特定的同步信号来协调不同设备的操作。 9. **调试技巧**:使用如STM32CubeIDE或Keil MDK等IDE进行代码调试,利用断点、变量...
- 启动DMA传输:在需要更新LCD显示时,通过DMA发送数据到SPI2,由SPI2传输到LCD。 - 中断处理:当DMA传输完成时,可以通过中断服务程序进行后续操作,如清除传输标志,准备下一次传输。 6. **注意事项**: - SPI...
STM32是一款广泛应用的微控制器,它具有丰富的外设接口,包括串行外围接口(SPI)和直接存储器访问(DMA)。在这个项目中,我们关注的是如何利用STM32的SPI接口结合DMA进行数据传输。SPI是一种同步串行通信协议,...
在嵌入式系统开发中,STM32F103微控制器因其丰富的外设接口、高性能和低功耗而被广泛应用。在许多通信任务中,USART(通用同步/异步收发传输器)是实现串行通信的标准接口。然而,当需要大量数据交换时,单纯依赖CPU...
STM32 SPI DMA驱动外部FLASH是一种高效的通信方式,它结合了SPI(Serial Peripheral Interface)串行接口和DMA(Direct Memory Access)直接内存访问技术,能够实现高速的数据传输,减轻CPU负担,提高系统的运行效率...
在本文中,我们将深入探讨如何使用STM32H750微控制器通过SPI接口驱动LIL9341液晶显示屏,并结合DMA(直接存储器访问)技术,实现高效的图形库移植,例如LVGL,以达到100fps的刷新率。 STM32H750是意法半导体...
在程序中,通常会使用中断服务例程来处理DMA传输完成事件,然后更新显示缓冲区或执行其他必要的操作。 在“ssd1306_drivers-master”文件夹中,你可能找到以下组件: 1. `ssd1306.h`:头文件,包含了函数声明和...
通过特定的测试程序,可以测量STM32F407通过SPI+DMA方式从TF卡读取和写入数据的速度,从而了解系统在实际应用中的性能。 6. 配置步骤:实现这个功能需要对STM32的GPIO、SPI和DMA寄存器进行初始化配置。首先,设置...
本文将深入探讨基于STM32的DMA传输实例,以及如何结合串口进行数据通信。 首先,理解DMA的基本原理至关重要。DMA允许外围设备直接与内存交互,而无需CPU介入,从而减少了CPU的负载并提高了数据传输速率。在STM32中...
在使用DMA时,这个函数会触发DMA传输,而不是直接通过SPI接口发送数据。 5. **触摸屏驱动**:如果ST7789集成了触摸屏控制器,我们需要读取其返回的触摸坐标。这通常涉及到配置另一个GPIO引脚作为中断源,并编写中断...
STM32F767是意法半导体(STMicroelectronics)推出的一款高性能微控制器,属于Cortex-M7内核系列,具有丰富的外设接口和高速处理能力...在实际应用中,还可以根据需求调整SPI参数、优化DMA传输策略,以进一步优化性能。