基于stm32的spi接口dma 数据收发实例解析
一 前记
SPI接口平时用的比较少,再加上对CUBEMX不是很熟悉,这里踩了不少坑才把问题解决。针对遇到了不少问题,是要值得梳理一下了。
二 源码解析
1 SPI的DMA发送端配置:

2 主函数源码:
uint32_t g_spi_cnt = 0; void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
g_spi_cnt++; }
2 主函数源码: /**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */
SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_SPI2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
uart1_test();
memset(TX_Data,0x01,DATA_SIZE);
/* USER CODE END 2 */
HAL_SPI_Transmit_DMA(&hspi2, TX_Data, sizeof(TX_Data));
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
HAL_Delay(1000);
mprintf("g_spi_master_dma_cnt 2.18h is:0x%x \n\r",g_spi_cnt%0xff);
for (uint32_t iss = 0; iss < DATA_SIZE; iss++)
{
/* code */
TX_Data[iss] = g_spi_cnt%0xff;
}
dump8(TX_Data,sizeof(TX_Data));
HAL_SPI_Transmit_DMA(&hspi2, TX_Data, sizeof(TX_Data));
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
3 SPI的DMA接收端配置:

4 SPI SLAVE源码:
#define DATA_SIZE 64
uint8_t RX_Data[DATA_SIZE];
uint32_t g_spi_cnt = 0; void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef * hspi)
{
HAL_SPI_Receive_DMA(&hspi2, RX_Data, DATA_SIZE);
dump8(RX_Data,10);
g_spi_cnt++;
mprintf("g_spi_slave_cnt 2.18hh is:%d \n\r",g_spi_cnt); } /**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */
SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_SPI2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
uart1_test();
/* USER CODE END 2 */
memset(RX_Data,0x00,sizeof(RX_Data));
HAL_SPI_Receive_DMA(&hspi2, RX_Data, sizeof(RX_Data));
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
//HAL_Delay(200); /* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
三 总结
1 DMA的配置模式,
笔者刚开始根据网上的资料,配置了circular模式,发现接收侧一直收到莫名其妙的数据,并且数据经常出错。

修改成了normal模式之后,接收到的数据就对了。关于这两种模式的区别,我已经在前文中介绍过了。
2 SPI位宽设置:
这里遇到的另外一个大问题就是SPI位宽,cube软件默认是4bit,加入按照这个模式设置,你会发现只收到后四个bit的数据,前四个bit为零。
所以,把这个改称8bit是一个必备的。如下图所示:

3 感触:
stm32 CUBE MX是一个比较强大的工具,可这个不是意味着你可以没带基础的话随便使用它,理解协议和里面的每一个含义,才能不至于掉入坑里面。
再者,进去了能否出来,这个要考验你的编码水平和经验了。
基于stm32的spi接口dma 数据收发实例解析的更多相关文章
- STM32与物联网02-网络数据收发
在上一节中,介绍了 ESP8266 的使用方法.不过上一节中都是通过串口调试工具手动发送信息的方式来操作 ESP8266 ,这肯定不能用于实际开发.因此,本节介绍如何编写合适的程序来和 ESP8266 ...
- HAL UART DMA 数据收发
UART使用DMA进行数据收发,实现功能,串口2发送指令到上位机,上位机返回数据给串口2,串口2收到数据后由串口1进行转发,该功能为实验功能 1.UART与DMA通道进行绑定 void HAL_UAR ...
- java接口传递数据的实例
我们要讲E类中的数据变化通知A类,这样通过接口F来实现.具体原理就是E的每次数据改变都让其通知接口:而A类继承接口,所以每次E的调用接口都会触发A类的数据更改事件的触发. 首先创建一个类E: publ ...
- 基于ssh框架的highcharts前后台数据交互实例
Highcharts 是一个用纯JavaScript编写的一个图表库, 能够很简单便捷的在web网站或是web应用程序添加有交互性的图表,并且免费提供给个人学习.个人网站和非商业用途使用.HighCh ...
- STM32的SPI口的DMA读写[原创www.cnblogs.com/helesheng]
SPI是我最常用的接口之一,连接管脚仅为4根:在常见的芯片间通信方式中,速度远优于UART.I2C等其他接口.STM32的SPI口的同步时钟最快可到PCLK的二分之一,单个字节或字的通信时间都在us以 ...
- linux驱动基础系列--Linux下Spi接口Wifi驱动分析
前言 本文纯粹的纸上谈兵,我并未在实际开发过程中遇到需要编写或调试这类驱动的时候,本文仅仅是根据源码分析后的记录!基于内核版本:2.6.35.6 .主要是想对spi接口的wifi驱动框架有一个整体的把 ...
- 嵌入式物联网之SPI接口原理与配置
本实验采用W25Q64芯片 W25Q64是华邦公司推出的大容量SPI FLASH产品,其容量为64Mb.该25Q系列的器件在灵活性和性能方面远远超过普通的串行闪存器件.W25Q64将8M字节的容量分为 ...
- 基于Stm32的MP3播放器设计与实现
原创博文,转载请注明出处 这是我高级电子技术试验课做的作业,拿来共享一下.项目在安福莱例程基础之上进行的功能完善,里面的部分内容可参考安福莱mp3例程.当然用的板子也是安福莱的板子,因为算起来总共做了 ...
- C#从基于FTPS的FTP server下载数据 (FtpWebRequest 的使用)SSL 加密
FTPS,亦或是FTPES, 是FTP协议的一种扩展,用于对TLS和SSL协议的支持. 本文讲述了如何从一个基于FTPS的Server中下载数据的实例. 任何地方,如有纰漏,欢迎诸位道友指教. ...
- stm32 DMA数据搬运 [操作寄存器+库函数](转)
源:stm32 DMA数据搬运 [操作寄存器+库函数] DMA(Direct Memory Access)常译为“存储器直接存取”.早在Intel的8086平台上就有了DMA应用了. ...
随机推荐
- c#树结构转npoi复杂表头
Vue 前端框架框架中采用树结构打印表头,为了前后端适配NPOI导出. 这里重点做树结构转换 NPOI 复杂表头的结构数据( 跨行.跨列),其它具体导出功能请参考 https://www.cnblo ...
- git操作 手写稿
- 在Visual Studio中部署GDAL库的C++版本(包括SQLite、PROJ等依赖)
本文介绍在Visual Studio软件中配置.编译C++环境下GDAL库.SQLite环境与PROJ库的详细方法. GDAL库是一个非常方便的地理数据处理库,但其在C++环境下的配置与编译流 ...
- 数学微积分,学习笔记,等价无穷小的证明:(1+x)^a-1 ~ ax
\(\lim_{x \to 0} \frac{\sqrt[n]{1+x} -1}{\frac{x}{n} } =1\)的证明 \[\lim_{x \to 0} \frac{\sqrt[n]{1+x} ...
- HBase执行stop-hbash.sh关闭命令等待时间过长
问题描述 执行stop-hbase.sh时,等待很长时间都没结束(出来很多"...") 解决办法: hbase-daemons.sh stop masterhbase-daemon ...
- LVM(逻辑卷管理器)
目录 一.LVM概述 二.基本术语 三.PE.PV.VG.LV之间的关系 四.LVM的工作原理 五.LVM的使用 1.部署逻辑卷 第一步: 还原快照,并在虚拟机添加两块新硬盘设备,开机 第二步: 让新 ...
- Python中`yield`关键字详解
Python中`yield`关键字有什么用? Python中yield关键字有什么用? 它能做什么? 例如,我试图理解这段代码1: def _get_child_candidates(self, di ...
- Java并发编程实例--14.在一个同步类中安排独立属性
当你使用synchronized关键字去保护一个代码块时,你必须传入一个对象的引用. 正常来讲,你讲使用this关键字去引用执行这个方法的对象,但是你可以使用其他对象的引用. 通常的,这些对象将会是专 ...
- IntelliJ IDE使用指南
下载IDEA 注释模板 #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}; ...
- KPTP 汇报模板
1.什么是KPTP 它是由4个单词:Keep.Problem.Try.Plan的首字母组成的. K:keep,今天做了哪些工作: P:problem,遇到了哪些问题: T:try,计划尝试如何解决这些 ...