一 前言
最近在调试stm32的SPI时候i,遇到了一个非常诡异的问题。中间花费了不少时间才把问题搞定。这中间暴露的问题值得反思。借此机会,还是梳理一下stm32的SPI的代码做一个总结吧。
二 初始化
1.SPI接口的初始化比较标准,和几乎所有的stm32外围接口一样,分为接口初始化和链接部分组成:
接口初始化:
/* SPI2 init function */
void MX_SPI2_Init(void)
{ /* USER CODE BEGIN SPI2_Init 0 */ /* USER CODE END SPI2_Init 0 */ /* USER CODE BEGIN SPI2_Init 1 */ /* USER CODE END SPI2_Init 1 */
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 7;
hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI2_Init 2 */ /* USER CODE END SPI2_Init 2 */

  链接:

  /* USER CODE END SPI2_MspInit 0 */
/* SPI2 clock enable */
__HAL_RCC_SPI2_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI2 GPIO Configuration
PB13 ------> SPI2_SCK
PB14 ------> SPI2_MISO
PB15 ------> SPI2_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* SPI2 DMA Init */
/* SPI2_TX Init */
hdma_spi2_tx.Instance = DMA1_Channel5;
hdma_spi2_tx.Init.Request = DMA_REQUEST_1;
hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi2_tx.Init.Mode = DMA_NORMAL;
hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK)
{
Error_Handler();
} __HAL_LINKDMA(spiHandle,hdmatx,hdma_spi2_tx); /* SPI2_RX Init */
hdma_spi2_rx.Instance = DMA1_Channel4;
hdma_spi2_rx.Init.Request = DMA_REQUEST_1;
hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi2_rx.Init.Mode = DMA_NORMAL;
hdma_spi2_rx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_spi2_rx) != HAL_OK)
{
Error_Handler();
} __HAL_LINKDMA(spiHandle,hdmarx,hdma_spi2_rx); /* SPI2 interrupt Init */
HAL_NVIC_SetPriority(SPI2_IRQn, 7, 0);
HAL_NVIC_EnableIRQ(SPI2_IRQn);
注意事项:
这里面调试的时候注意以下几个地方:
一个是接口不能被复用了。另外一个是接口硬件部分是通的。这两个可以通过GPIO的拉高拉地来测电平实现。
另外一个就是系统的主频要注意,尽量不要设置太高,因为有些SPI接口速率没那么高的。
 
三 数据收发:
 
1.数据发送:
HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
2.数据接收:
HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
3.注意事项:
其实,数据收发一般不会出问题,可是一旦出问题了,就不是小问题。这里,注意几个东西。
由于是DMA接收和发送,所以CS一定要拉地的时间尽量长,系统允许的话,开始的时候,尽量不要随意拉高CS。
否则会出现丢数据的情况。
 
四 总结
 
1.不要盲目详细计算机。它不会代替你思考的。遇到了问题,还是要凭借对代码的理解和实践出来的技能来判断的。

STM32 SPI DMA 源码解析及总结的更多相关文章

  1. dubbo源码解析-spi(4)

    前言 本篇是spi的第四篇,本篇讲解的是spi中增加的AOP,还是和上一篇一样,我们先从大家熟悉的spring引出AOP. AOP是老生常谈的话题了,思想都不会是一蹴而就的.比如架构设计从All in ...

  2. dubbo源码解析-spi(3)

    前言 在上一篇的末尾,我们提到了dubbo的spi中增加了IoC和AOP的功能.那么本篇就讲一下这个增加的IoC,spi部分预计会有四篇,因为这东西实在是太重要了.温故而知新,我们先来回顾一下,我们之 ...

  3. dubbo源码解析-spi(一)

    前言 虽然标题是dubbo源码解析,但是本篇并不会出现dubbo的源码,本篇和之前的dubbo源码解析-简单原理.与spring融合一样,为dubbo源码解析专题的知识预热篇. 插播面试题 你是否了解 ...

  4. 【Java实战】源码解析Java SPI(Service Provider Interface )机制原理

    一.背景知识 在阅读开源框架源码时,发现许多框架都支持SPI(Service Provider Interface ),前面有篇文章JDBC对Driver的加载时应用了SPI,参考[Hibernate ...

  5. Dubbo源码解析之SPI(一):扩展类的加载过程

    Dubbo是一款开源的.高性能且轻量级的Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用.智能容错和负载均衡,以及服务自动注册和发现. Dubbo最早是阿里公司内部的RPC框架,于 ...

  6. 5.2 dubbo-compiler源码解析

    ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class); final P ...

  7. 2.2 dubbo-spi源码解析

    package com.alibaba.dubbo.demo.test; import com.alibaba.dubbo.common.extension.ExtensionLoader; impo ...

  8. 第零章 dubbo源码解析目录

    第一章 第一个dubbo项目 第二章  dubbo内核之spi源码解析 2.1  jdk-spi的实现原理 2.2 dubbo-spi源码解析 第三章 dubbo内核之ioc源码解析 第四章 dubb ...

  9. Sentinel源码解析一(流程总览)

    引言 Sentinel作为ali开源的一款轻量级流控框架,主要以流量为切入点,从流量控制.熔断降级.系统负载保护等多个维度来帮助用户保护服务的稳定性.相比于Hystrix,Sentinel的设计更加简 ...

  10. [源码解析] TensorFlow 分布式环境(3)--- Worker 静态逻辑

    [源码解析] TensorFlow 分布式环境(3)--- Worker 静态逻辑 目录 [源码解析] TensorFlow 分布式环境(3)--- Worker 静态逻辑 1. 继承关系 1.1 角 ...

随机推荐

  1. 基于.NET的机械运动模拟应用开发

    1 简介 机械运动在物理学中,把一个物体相对于另一个物体位置的变化称作为机械运动,简称运动.机械运动是指一个物体相对于其他物体的位置发生改变,是自然界中最简单,最基本的运动形态. 自然界中一切物体都在 ...

  2. 28图图解Raft协议,so easy~~

    大家好,我是三友~~ 在之前写的<万字+20张图探秘Nacos注册中心核心实现原理> 这篇文章中我留了一个彩蛋 当文章点赞量突破28个,就单独写一篇关于Raft协议的文章 既然现在文章点赞 ...

  3. 【C语言深度解剖】预定义章节经典面试题讲解(offsetof宏模拟实现)【超详细的解释和注释】

    [C语言深度解剖]预定义章节经典面试题讲解(offsetof宏模拟实现)[超详细的解释和注释] 那么这里博主先安利一下一些干货满满的专栏啦! 作者: #西城s 这是我的主页:#西城s 在食用这篇博客之 ...

  4. mysql删除表中重复记录

    1.创建测试表,并插入数据 create table test( id int(11) primary key auto_increment comment '用户编号', username varc ...

  5. api接口调用

    api接口调用 CURL 是一个利用URL语法规定来传输文件和数据的工具,支持很多协议,如HTTP.FTP.TELNET等.最爽的是,PHP也支持 CURL 库.使用PHP的CURL 库可以简单和有效 ...

  6. Python中的UnboundLocalError是什么错误?如何解决?

      在一个月黑风高的夜晚,我们满心欢喜地写出以下代码: money = 10000 # 当前的财产,单位为元 def add_money(value): money += value print('当 ...

  7. 2024-02-03:用go语言,你有 k 个背包。给你一个下标从 0 开始的整数数组 weights, 其中 weights[i] 是第 i 个珠子的重量。同时给你整数 k, 请你按照如下规则将所有

    2024-02-03:用go语言,你有 k 个背包.给你一个下标从 0 开始的整数数组 weights, 其中 weights[i] 是第 i 个珠子的重量.同时给你整数 k, 请你按照如下规则将所有 ...

  8. Java浅谈BufferedReader

    既然Scanner简单好用,为什么要用BufferedReader呢? 主要原因是面对大量的读入显得较慢且不安全,这里体现在三个方面,一方面是解析的问题,好用意味着封装的更复杂,一拖n的接口解析起来会 ...

  9. ElasticSearch7.3学习(三十四)----生产环境集群部署总结

    1.集群部署 2.结点的三个角色 主结点:master节点主要用于集群的管理及索引 比如新增结点.分片分配.索引的新增和删除等. 数据结点:data 节点上保存了数据分片,它负责索引和搜索操作. 客户 ...

  10. Linux-rsync命令用法详解

    从字面意思上,rsync 可以理解为 remote sync(远程同步),但它不仅可以远程同步数据(类似于 scp 命令),还可以本地同步数据(类似于 cp 命令).不同于 cp 或 scp 的一点是 ...