一是想总结一下SPI总线的特点与注意点,二是总结一下SPI DMA的使用

一、SPI信号线说明

  通常SPI通过4个引脚与外部器件相连:

  • MISO:主设备输入/从设备输出引脚。该引脚在从模式下发送数据,在主模式下接收数据。
  • MOSI:主设备输出/从设备输入引脚。该引脚在主模式下发送数据,在从模式下接收数据。
  • SCK:串口时钟,作为主设备的输出,从设备的输入
  • NSS:从设备选择。这是一个可选的引脚,用来选择主/从设备。它的功能是用来作为“片选引脚”,让主设备可以单独地与特定从设备通讯,避免数据线上的冲突。

二、原理

  MOSI脚相互连接,MISO脚相互连接。这样,数据在主和从之间串行地传输(MSB位在前)。

  通信总是由主设备发起。主设备通过MOSI脚把数据发送给从设备,从设备通过MISO引脚回传数据。这意味全双工通信的数据输出和数据输入是用同一个时钟信号同步的;时钟信号由主设备通过SCK脚提供。

 
三、NSS说明与注意点
 
 

  NSS分为内部引脚和外部引脚。

  NSS外部引脚可以作为输入信号或者输出信号,输入信号一般用作硬件方式从机的片选,而输出信号一般用于主SPI去片选与之相连的从SPI。

  NSS从设备选择有两种模式:

1、软件模式

  可以通过设置SPI_CR1寄存器的SSM位来使能这种模式,当它为1时,NSS引脚上的电平由SSI决定。在这种模式下NSS外部引脚可以用作它用,而内部NSS信号电平可以通过写SPI_CR1的SSI位来驱动。 

2、硬件模式

两种方式:

(1)对于主SPI,NSS可以直接接高电平,对于从SPI,可以直接接低电平。  

(2)当STM32F10xxx工作为主SPI,并且NSS输出已经通过SPI_CR2寄存器的SSOE位使能,这时主机的NSS讲作为输出信号,引脚信号被拉低,所有NSS引脚与这个主SPI的NSS引脚相连并配置为硬件NSS的SPI设备,将自动变成从SPI设备。

  此时两个的NSS信号线可以接个上拉电阻直连。

四、DMA说明

  DMA是AMBA的先进高性能总线(AHB)上的设备,它有2个AHB端口:一个是从端口,用于配置DMA,另一个是主端口,使得DMA可以在不同的从设备之间传输数据。

  DMA的作用是在没有Cortex-M3核心的干预下,在后台完成数据传输。在传输数据的过程中,主处理器可以执行其它任务,只有在整个数据块传输结束后,需要处理这些数据时才会中断主处理器的操作。它可以在对系统性能产生较小影响的情况下,实现大量数据的传输。

 五、SPI_DMA的通信过程

  • 设置外设地址
  • 设置存储器地址
  • 设置传输数据量
  • 设置通道的配置信息
  • 使能DMA通道,启动传输
  • 发送时,在每次TXE被设置为’1’时发出DMA请求,DMA控制器则写数据至SPI_DR寄存器,TXE标志因此而被清除。
  • 接收时,在每次RXNE被设置为’1’时发出DMA请求,DMA控制器则从SPI_DR寄存器读出数据,RXNE标志因此而被清除。

六、相关代码

这里使用的是SPI1

SPI_DMA配置

 /*******************************************************************************
* Function Name : SPI1_DMA_Configuration
* Description : 配置SPI1_RX的DMA通道2,SPI1_TX的DMA通道3
* Input : None
* Output : None
* Return : None
* Attention :
*******************************************************************************/
void SPI1_DMA_Configuration( void )
{
DMA_InitTypeDef DMA_InitStructure; /* DMA1 Channel2 (triggered by SPI1 Rx event) Config */
DMA_DeInit(DMA1_Channel2);
DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_Addr; //设置 SPI1 发送外设(0x4001300C) 地址(目的地址)
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI1_RX_Buff; //设置 SRAM 存储地址(目的地址)
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //传输方向 外设-内存
DMA_InitStructure.DMA_BufferSize = SPI1_ReciveBufferSize; //设置 SPI1 发送长度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel2, &DMA_InitStructure); DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);
/* Enable SPI1 DMA RX request */
SPI1->CR2 |= <<; //接收缓冲区DMA使能
DMA_Cmd(DMA1_Channel2, ENABLE); /* DMA1 Channel3 (triggered by SPI1 Tx event) Config */
DMA_DeInit(DMA1_Channel3);
DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_Addr; //设置 接收外设(0x4001300C) 地址(源地址)
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI1_TX_Buff; //设置 SRAM 存储地址(源地址)
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //传输方向 内存-外设
DMA_InitStructure.DMA_BufferSize = SPI1_SendBufferSize; //设置 SPI1 接收长度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址增量(不变)
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址增量(变化)
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设传输宽度(字节)
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //内存传输宽度(字节)
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //传输方式,一次传输完停止,不重新加载
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //中断方式-高(三级)
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //内存到内存方式禁止
DMA_Init(DMA1_Channel3, &DMA_InitStructure); DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE); //开启 DMA1_Channel3 传输完成中断
DMA_ITConfig(DMA1_Channel3, DMA_IT_TE, ENABLE); //开启 DMA1_Channel3 传输错误中断
/* Enable SPI1 DMA TX request */
SPI1->CR2 |= <<; //发送缓冲区DMA使能
DMA_Cmd(DMA1_Channel3, DISABLE); //开启 DMA 通道 DMA1_Channel3
}

SPI发送

 /*******************************************************************************
* Function Name : SPI1_Send
* Description : SPI1的DMA方式发送
* Input : SPI1_TX_Buff[SPI1_SendBufferSize]
* Output : None
* Return : None
* Attention : 关闭DMA通道3之前必须等待TXE为1,等待忙标志为0
*******************************************************************************/
void SPI1_Send( u8 *buff, u32 len )
{
DMA1_Channel3->CPAR = SPI1_DR_Addr; //外设地址
DMA1_Channel3->CMAR = (u32) buff; //mem地址
DMA1_Channel3->CNDTR = len ; //传输长度
DMA1_Channel3->CCR = ( << ) | // 非存储器到存储器模式
( << ) | // 通道优先级高
( << ) | // 存储器数据宽度8bit
( << ) | // 存储器数据宽度8bit
( << ) | // 外设数据宽度8bit
( << ) | // 外设数据宽度8bit
( << ) | // 存储器地址增量模式
( << ) | // 外设地址增量模式(不增)
( << ) | // 非循环模式
( << ) | // 从存储器读
( << ) | // 允许传输错误中断
( << ) | // 允许半传输中断
( << ) | // 允许传输完成中断
(); // 通道开启
}

SPI接收

 /*******************************************************************************
* Function Name : SPI1_Recive
* Description : SPI1的DMA方式接收
* Input : None
* Output : SPI1_RX_Buff[SPI1_ReciveBufferSize]
* Return : None
* Attention : 必须要先关闭通道2,然后再配置通道2的参数
*******************************************************************************/
void SPI1_Recive( u8 *buff, u32 len )
{
DMA1_Channel2->CCR &= ~( << ); //关闭DMA通道2 DMA1_Channel2->CPAR = SPI1_DR_Addr; //外设地址
DMA1_Channel2->CMAR = (uint32_t)buff; //mem地址
DMA1_Channel2->CNDTR = len ; //传输长度
DMA1_Channel2->CCR = ( << ) | // 非存储器到存储器模式
( << ) | // 通道优先级高
( << ) | // 存储器数据宽度8bit
( << ) | // 存储器数据宽度8bit
( << ) | // 外设数据宽度8bit
( << ) | // 外设数据宽度8bit
( << ) | // 存储器地址增量模式
( << ) | // 外设地址增量模式(不增)
( << ) | // 非循环模式
( << ) | // 传输方向 外设-内存
( << ) | // 允许传输错误中断
( << ) | // 允许半传输中断
( << ) | // 允许传输完成中断
(); // 通道开启
}

STM32 SPI DMA 的使用的更多相关文章

  1. 【STM32】WS2812介绍、使用SPI+DMA发送数据

    这篇要使用到SPI+DMA,需要了解的话,可以参考我另两篇博客 时钟:https://www.cnblogs.com/PureHeart/p/11330967.html SPI+DMA通信:https ...

  2. STM32之DMA+ADC

    借用小甲鱼的经典:各位互联网的广大网友们.大家早上中午晚上好..(打下小广告,因为小甲鱼的视频真的很不错).每次看小甲鱼的视频自学都是比较轻松愉快的..我在想,如果小甲鱼出STM32的视频,我会一集不 ...

  3. STM32之DMA

    一.DMA简介 1.DMA简介 DMA(Direct Memory Access:直接内存存取)是一种可以大大减轻CPU工作量的数据转移方式. CPU有转移数据.计算.控制程序转移等很多功能,但其实转 ...

  4. The STM32 SPI and FPGA communication

    The STM32 SPI and FPGA communication STM32 spi bus communication SPI bus in the study, the protocol ...

  5. HOWTO: Use STM32 SPI half duplex mode

    HOWTO: Use STM32 SPI half duplex mode I’ve got my hands onto some STM32F030F4P6 ARM-Cortex M0 proces ...

  6. 关于STM32 SPI NSS的讨论

    NSS分为内部引脚和外部引脚. NSS外部引脚可以作为输入信号或者输出信号, 输入信号一般用作硬件方式从机的片选, 而输出信号一般用于主SPI去片选与之相连的从SPI. NSS从设备选择有两种模式: ...

  7. STM32使用DMA发送串口数据

    1.概述 上一篇文章<STM32使用DMA接收串口数据>讲解了如何使用DMA接收数据,使用DMA外设和串口外设,使用的中断是串口空闲中断.本篇文章主要讲解使用DMA发送数据,不会讲解基础的 ...

  8. STM32—SPI详解

    目录 一.什么是SPI 二.SPI协议 物理层 协议层 1.通讯时序图 2.起始和停止信号 3.数据有效性 4.通讯模式 三.STM32中的SPI 简介 功能框图 1.通讯引脚 2.时钟控制逻辑 3. ...

  9. STM32的DMA

    什么是DMA?其全称是:Direct Memory Access:根据ST公司提供的相关信息,DMA是STM32中一个独立与Cortex-M3内核的模块,有点类似与ADC.PWM.TIMER等模块:主 ...

随机推荐

  1. Visual Studio 2013 新功能 Memory Dump 分析器

    本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. TechEd2013 发现新功能 12月5日和6日,在国家会议中心参加了微软的 TechEd2013 ...

  2. 使用gdb调试Python进程

    使用gdb调试Python进程 有时我们会想调试一个正在运行的Python进程,或者一个Python进程的coredump.例如现在遇到一个mod_wsgi的进程僵死了,不接受请求,想看看究竟是运行到 ...

  3. [译]面向初学者的Asp.Net状态管理技术

    介绍 本文主要讲解Asp.Net应用程序中的状态管理技术(Asp.Net中有多种状态管理技术),并批判性地分析所有状态管理技术的优缺点. 背景 HTTP是无状态的协议.客户端发起一个请求,服务器响应完 ...

  4. [C++] socket -7 [邮槽]

    ::利用邮槽实现windons进程通信 ::一般情况下CreateMailslot()常被使用在进程通信的服务器上,在客户端则是用函数CreateFile()打开指定的邮槽之后进行相关的操作. ::将 ...

  5. C#课外实践——校园二手平台(技术篇2)

    说明:一个人的进步都是点点滴滴的积累起来的.接着总结这次的课外实践. 有时候,想这样,3个Combox,当第一个ComBox选择以后,第二个ComBox会根据第一个的选择结果来显示相对应的内容.其实你 ...

  6. JDK环境变量的配置方法

    1.打开我的电脑--属性--高级--环境变量 2.新建系统变量JAVA_HOME 变量名:JAVA_HOME 变量值:jdk的目录,比如d:/java 3. 选择“系统变量”中变量名为“Path”的环 ...

  7. PHP之負載均衡下的session共用

    最近忙於開發台灣運動彩券第四版的程式,所以已經很久沒有上來寫東西了,今天隨便寫點東西和大家分享. 首先說一下負載均衡,相信大家都知道負載均衡可以很好地解決網站大流量的問題,負載均衡就是把用戶的請求分發 ...

  8. TexturePacker压缩png的命令

    压缩png效果最好的当然是TinyPNG这种神器了,不过一般情况下TexturePacker压缩出来的也基本上能达到效果. 你需要先安装TP(TexturePacker的简称,以下TP无特殊说明均指T ...

  9. 实用的ajaxfileupload插件

    一.ajaxFileUpload是一个异步上传文件的jQuery插件. 传一个不知道什么版本的上来,以后不用到处找了. 语法:$.ajaxFileUpload([options]) options参数 ...

  10. sublime3 配置node build环境

    折腾了很久,原来如此简单 1.package control  安装nodejs 2.修改Nodejs.sublime-settings文件,将nodejs路径修改成自己的 3.sublime tex ...