历史上的今天
返回首页

历史上的今天

今天是:2024年10月09日(星期三)

正在发生

2020年10月09日 | STM32的SPI采用DMA方式传输测试

2020-10-09 来源:eefocus

环境:

主机: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

}

推荐阅读

史海拾趣

Heyco公司的发展小趣事

随着全球化趋势的加剧,Heyco开始积极拓展海外市场。公司在欧洲市场取得长足发展的同时,也逐步进入北美和亚太地区。通过在全球各地建立销售网络和生产基地,Heyco实现了产品的全球化生产和销售。这一战略不仅提升了公司的市场份额,还进一步巩固了其在电子工业备品备件销售领域的领先地位。

Gauthier Connectique公司的发展小趣事
使用红外线遥控器对电路进行信号测试。观察电路是否能够准确接收并响应遥控器发出的指令。如有问题,需检查电路连接、元器件性能等是否存在问题。
DAYA公司的发展小趣事

大雅智能深知,品质是企业立足之本。因此,在产品研发和生产过程中,大雅智能始终坚持严格的质量控制标准,确保每一台产品都符合高品质要求。同时,大雅智能还建立了完善的售后服务体系,为用户提供及时、专业的技术支持和维修服务。正是这份对品质的执着追求,让大雅智能在消费者中赢得了良好的口碑。

Horn公司的发展小趣事

在追求经济效益的同时,Horn公司也注重可持续发展。公司积极采用环保材料和绿色生产工艺,减少对环境的影响。此外,Horn公司还注重人才培养和团队建设,为公司的长期发展奠定了坚实的人才基础。展望未来,Horn公司将继续秉承“创新、质量、服务”的企业理念,致力于成为切削工具行业的领导者,为全球客户提供更加优质的产品和服务。

GE (General Electric)公司的发展小趣事
如故障难以排查,可查阅电气原理图电路图,根据电路图逐一检查各元件和线路。
CAMDENBOSS公司的发展小趣事

CAMDENBOSS公司深知人才是企业发展的核心动力。因此,公司注重人才培养和团队建设,通过提供丰富的培训和学习机会,不断提升员工的技能和素质。同时,公司还建立了完善的激励机制和晋升通道,鼓励员工积极创新、勇攀高峰。这些举措不仅增强了员工的归属感和凝聚力,也为公司的长远发展奠定了坚实的基础。

请注意,以上故事均基于虚构和假设,并非CAMDENBOSS公司的真实历史。如果您需要了解该公司的真实发展情况,建议查阅相关资料或联系该公司进行了解。

问答坊 | AI 解惑

labview教材 (word格式)

labview教材 (word格式) …

查看全部问答>

扫频仪校正问题,请高手解答!

BT3C扫频仪校正扫频信号时,得不到矩形的波形。相应的设置为:全扫,频标50M,衰减为0,观测到的扫频信号中间有个突起的波峰,两边有一些小突起,然后最边上有一小段平线。 按理应该看到的是基本是一个矩形,可是为什么得不到呢?应该如何调整,还 ...…

查看全部问答>

了解一下AATI 原厂的手机产品应用框图!

AnalogicTech offers a complete portfolio of products for smartphones and other handheld equipment to fully optimize available energy, minimize losses, and prolong battery life.   For Li-ion polymer batteries, linear & ...…

查看全部问答>

高速串行接口的编码技术(8B10B)

高速串行接口的编码技术(8B10B)…

查看全部问答>

LED驱动电源设计考量--teleda

LED由于环保、寿命长、光电效率高等众多优点,近年来在各行业应用得以快速发展,LED的驱动电源成了关注热点,理论上,LED的使用寿命在10万小时以上,但在实际应用过程中,由于驱动电源的设计及驱动方式选择不当,使LED极易损坏.随着LED的应用日益广泛,LED ...…

查看全部问答>

windows mobile 6中MessageBox.Show()调用的参数问题!

我用的是windows mobile 6的系统,但是调用MessageBox这个函数却无法使用后面两个参数即:MessageBoxButtons,MessageBoxIcon. 程序中也无法包含System.Windows.Forms.MessageButtons..这个命名空间。 但是我的系统里其他的程序(windows mobile ...…

查看全部问答>

高分求教驱动问题(如牵涉到技术核心可以有偿付款)

大家好,我最近在帮一个朋友写一鼠标过滤驱动,需要拦截鼠标的按键,以及按下按键时候的鼠标坐标。这样才可以把鼠标的所有动作给回放出来。 现在碰到的问题是,如何在不需要应用程序作为辅助的情况下面,直接在驱动程序中就得到鼠标的坐标。(现在 ...…

查看全部问答>

关于win CE用CAB打包问题

我用CAB打包后,出的错误Log文件的内容是 “Error: Section [SourceDisksFiles] - file D:\\Program Files\\HelloCE\\HelloCE\\bin\\Debug\\HelloCE.exe cannot have a drive or pathname” 请问是什么原因?谢谢…

查看全部问答>

如何构建一个IRP命令使U盘弹出?

如何构建一个IRP命令使U盘弹出? 我想在U盘已经插入电脑上的情况下,构建一个IRP命令将U盘弹出,但不知道怎么做? 向大家请教…

查看全部问答>

pda设备号

请问各位大侠,我用vc2005做的windows mobile 下的软件,想做个简单的加密,请问该如何获得设备的一个唯一的号呢?…

查看全部问答>