转自:

1. https://www.yiboard.com/thread-782-1-1.html

2.https://mansfield-devine.com/speculatrix/2018/01/avr-basics-spi-on-the-atmega-part-1/

当AVR与其他器件进行数据交互时,我们需要选择采用哪种方式。这里可以使用UART、I2C等经典的串口方式,也可以选择串行外设接口(SPI)。我比较喜欢SPI总线方式。那么让我们来聊一聊这种总线形式。

关系

在SPI中的一个重要的概念就是主从关系。一个设备作为主机,负责产生时钟信号并启动每次通信。除了时钟之外,其他设备在很多方面都像主机一样操作,而且只有在被呼叫时才会回应。

一般情况下,SPI总线至少由四条线组成 - 也就是说,它需要每个器件的四个引脚。 他们是:

●    MOSI:主机输出,从机输入 - 数据从主机传输到从机。

●    MISO:主机输入,从机输出 - 用于从从机到主机的数据传输。

●    SCK:时钟线,有时也被标记为CLK。

●    SS:从机选择 - 有时也被标记为片选(CS);这根线激活从机并启动通信。

和其他总线不一样的是,SPI总线总是只有一根MOSI、一根MISO和一根SCK。但是该总线是设计用于连接多个设备。每个总线上只有一个主机设备(不同于提供多主设备模式的I2C)。但是你可以有多个从设备,每个都需要自己的SS线。

这被认为是SPI的弱势之一,尤其是当您尝试使用GPIO数目较少的微控制器时。它至少需要将四个引脚连接在一个从机设备上,每个附加的从设备需要另一个引脚。但是,这种总线方式非常简单,通讯速度可以很快。

专用硬件

谈到GPIO引脚,可以使用任何GPIO引脚来实现一种“软件模拟串行”方式的SPI。事实上,在使用移位寄存器等设备时,我已经做到了这一点。但是,您需要负责切换时钟引脚,以产生必要的脉冲,并将数据移入或移出数据引脚。这并不难,但像AVR微控制器这样的设备已经内置了硬件来为您做所有这些。

我使用ATMEGA328P进行实验,所以我将指出这一点,但所有这些都应该轻松转移到其他微控制器。我们来看看ATMEG328P的引脚分布。

<ignore_js_op>

ATmega_88-168-328_pinout.png (301.69 KB, 下载次数: 2)

下载附件  保存到相册

2018-1-25 10:52 上传

 

在右下角你会看到四个粉红色的标签,表明引脚16-19是我们的SPI引脚。当然,它们也是普通的GPIO,但是当启用SPI功能时,它们承担SPI的角色,我们稍后会看到。通过使用这些引脚分配的目的,你需要在代码中做更少的工作。

不同之处在于SS引脚。说实话,你用这个GPIO是非常随意的。即使启用SPI,您仍然必须将SS引脚设置为输出,并在适当的时刻将其切换为高电平或低电平。如果你想用另一个引脚,可以自己选择。如果你想要连接不止一个从设备,你必须使用其他的GPIO。

转移数据

在讨论如何使用SPI之前,让我们花点时间考虑它是如何工作的。

您可以将每个器件(主器件和从器件)的SPI部分视为一个移位寄存器,在每个时钟脉冲中,一次输入一位和输出一位。

当时钟滴答时,从主机的移位寄存器发送一位到从机上,其余位移位。从机的移位寄存器有足够的空间来接受这个位,因为在同一个时钟脉冲上,从机已经向主机发送了一位数据,并且也一起移动了。在八个时钟脉冲之后,两个器件已经交换了这些移位寄存器中的全部字节。

这就是SPI的秘密:每当主机发送数据时,无论数据是否有意义(通常不是),它都会返回。事实上,有很多时候,主机只是想刺激从机放弃一些数据,而这是通过发送任何东西来实现的。它可以是全0或全1,这并不重要 - 这只是让从机发送任何已经准备好的移位寄存器的一种方式。

启用S​​PI

像微控制器上的许多事情一样,SPI通过巧妙地使用寄存器来控制。和往常一样,在AVR中,宏(通过avr / io.h)定义了寄存器和其中的位,所以我们可以简单地使用这些名称来处理接口。

我们不会在这里详细介绍SPI,但是我们将看看能让您获得简单的SPI解决方案的关键要素。我们的重点在于使用AVR作为主设备。

SPCR - SPI控制寄存器

SPCR是建立SPI的关键寄存器。所有八位用于配置接口,它们是:

7
6
5
4
3
2
1
0
SPIE
SPE
DORD
MSTR
CPOL
CPHA
SPR1
SPR0

根据数据表,当ATMEGA328P上电时,SPCR设置为0。个人而言,我并不介意花费一个或两个时钟周期,在我的SPI设置例程开始时,写到:

  1. 1SPCR = 0;

复制代码

那我们来看看这些位的含义:

●    SPIE - SPI中断使能。将其设置为1时,只要另一个寄存器中的另一个位(SPSR中的SPIF精确)被置位,就会触发SPI中断。

●    SPE - SPI启用。这是至关重要的,因为它有效地打开SPI并使这些引脚承担SPI的角色。

●    DORD - 数据顺序。这控制数据是首先发送最高有效位(MSB - 即第7位)还是最低有效位(LSB,第0位)。在默认状态(0)是MSB,这就是我喜欢它。如果您以此方式滚动或者从属设备期望它,则将此设置为1为Little-Endian。

●    CPOL、CPHA - 时钟极性和时钟相位。这些需要更多的解释,我们马上就会谈到。

●    SPR1、SPR0 - SPI时钟频率。它们与SPSR寄存器中的SPI2X位一起使用来设置时钟速度,从而设置数据移动的速率。这是一个与处理器的振荡器时钟频率(Fosc)相关的预分频器。

相位和极性

时钟极性和相位的设置取决于从机的工作方式和期望值。有四种模式:

SPI模式
条件
前边沿
后边沿
0(0,0)
CPOL = 0,CPHA = 0
采样(上升沿)
设置(下降沿)
1(0,1)
CPOL = 0,CPHA = 1
设置(上升沿)
采样(下降沿)
2(1,0)
CPOL = 1,CPHA = 0
采样(下降沿)
设置(上升沿)
3(1,1)
CPOL = 1,CPHA = 1
设置(下降沿)
采样(上升沿)

您需要阅读从设备的数据表以了解其要求。例如,我最近搞砸了一个23LCV512的串行RAM芯片。其数据表说明如下:

The device is accessed via the SI pin, with data being clocked in on the rising edge of SCK.

数据在上升沿“锁存”(又称锁存或采样)意味着它必须是上表中的模式0或模式3。这取决于上升沿是被认为是“领先”还是“落后”。你怎么知道的?回到数据表。它应该显示时序图。这里是我们的RAM芯片的例子:

<ignore_js_op>

Serial_RAM_timing.png (254.14 KB, 下载次数: 2)

下载附件  保存到相册

2018-1-25 10:52 上传

 

在输入版本中的所有内容开始之前,看看SCK线路是如何变低的?当SCK变高时,'MSB'发生。所以这里的上升沿也是领先的,这意味着我们想要模式0,在很多圈子里也被称为0,0。

设置速度

设置SPCR中的SPR0和SPR1位以及SPSR中的SPI2X位可将时钟频率设置为用于运行微控制器(Fosc)的振荡器的特定频率的一小部分。所以,如果你像我一样在16MHz下运行你的处理器,并且设置一个预分频值(比如16),那么SPI总线将以1MHz运行。预分频值越大,SPI总线越慢。

你可能会认为你想尽可能快地走,但是你可能会遇到问题,特别是如果你的从机的电线很长。正如我在面包板上做了很多这样的事情,我倾向于使用第二个最慢的64位设置,推测我可以随时尝试提高速度。

SPI2X
SPR1
SPR0
SCK频率
0
0
0
Fosc / 4
0
0
1
Fosc / 16
0
1
0
Fosc / 64
0
1
1
Fosc / 128
1
0
0
Fosc / 2
1
0
1
Fosc / 8
1
1
0
Fosc / 32
1
1
1
Fosc / 64

SPSR - SPI状态寄存器

在这里我们只关心三个位,如果说实话,我主要关心的只有一个位。

7
6
5
4
3
2
1
0
SPIF
WCOL
-
-
-
-
-
SPI2X

●    SPIF - SPI中断标志。当数据传输和输入完成时自动设置。如果您已经使能了全局中断和SPCR中的SPIE位,则当该标志置位时将触发中断。处理该中断将自动清除该标志,就像读取SPI数据寄存器(SPDR)一样。所以大多数情况下,你只需要读取这个标志就可以了。

●    WCOL - 写入碰撞标志。

●    SPI2X - 时钟速度设置的一部分。

准备设置

在我们检查第三个寄存器之前,让我们来设置SPI。我将假定AVR将作为一个主机,我们不会搞乱中断,数据顺序将是MSB第一。我将要进行通讯的是串行RAM芯片,它的时钟极性(CPOL)为0,时钟相位(CPHA)为0。我将使用处理器速度的1/64作为总线的速度。

让我们配置SPCR的八位。我将逐一浏览所有八位数据 - 即使是我没有使用的数据 - 你可以看到:

  1. SPCR = 0;                 // just to be sure
  2. // SPCR |= (1 << SPIE);   // not using interrupts, so leaving this at 0
  3. SPCR |= (1 << SPE);       // enable SPI
  4. // SPCR |= (1 << DORD);   // we want to keep the default MSB first, so not using this
  5. SPCR |= (1 << MSTR);      // set master mode
  6. // SPCR |= (1 << CPOL);   // leaving this set to 0
  7. // SPCR |= (1 << CPHA);   // leaving this set to 0
  8. SPCR |= (1 << SPR1);      // using a prescaler setting of 64 (1,0) in this register
  9. // SPCR |= (1 << SPR0);

复制代码

这样我们就准备好了。 在第2部分中,我们将开始使用SPI总线。

ATMEGA的SPI总线 - 第1部分的更多相关文章

  1. ATMEGA的SPI总线 - 第2部分

    参考: 1.https://www.yiboard.com/thread-783-1-1.html 2.https://mansfield-devine.com/speculatrix/2018/01 ...

  2. SPI总线

    一.概述. SPI, Serial Perripheral Interface, 串行外围设备接口, 是 Motorola 公司推出的一种同步串行接口技术. SPI 总线在物理上是通过接在外围设备微控 ...

  3. MSP430单片机的两种SPI总线实现方式

    MSP430单片机上的SPI总线的实现方式分为两种:硬件实现和软件实现. 二者的抽象层次不同,硬件实现方式下程序员只需要完成总线协议的寄存器层,即一字节(char,8位二进制)数据,而软件实现方式下程 ...

  4. SPI总线协议及SPI时序图详解

    SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口.SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚 ...

  5. SPI总线(同步)

    一.SPI总线简介 串行外围设备接口SPI(serial peripheral interface)总线技术是Motorola公司推出的一种同步串行接口.SPI 用 于CPU与各种外围器件进行全双工. ...

  6. STM32学习笔记(八) SPI总线(操作外部flash)

    1. SPI总线简介 SPI全称串行外设接口,是一种高速,全双工,同步的外设总线:它工作在主从方式,常规需要至少4根线才能够正常工作.SPI作为基本的外设接口,在FLASH,EPPROM和一些数字通讯 ...

  7. SPI总线的特点、工作方式及常见错误解答

    1.SPI总线简介 SPI(serial peripheral interface,串行外围设备接口)总线技术是Motorola公司推出的一种同步串行接口.它用于CPU与各种外围器件进行全双工.同步串 ...

  8. SPI总线通信电路设计

    数据带宽=(总线频率×数据位宽)÷8 B表示带宽,F表示存储器时钟频率,D表示存储器数据总线位数,则带宽为: B(峰值带宽)=F(时钟频率MHz)×D(总线位数bit)/8 例如,PC-100的SDR ...

  9. linux内核SPI总线驱动分析(一)(转)

    linux内核SPI总线驱动分析(一)(转) 下面有两个大的模块: 一个是SPI总线驱动的分析            (研究了具体实现的过程) 另一个是SPI总线驱动的编写(不用研究具体的实现过程) ...

随机推荐

  1. 序列号,IMEI,IMSI,ICCID的含义

    什么是序列号? 序列号是一串标识你手机出生证明以及身材特征的信息,甚至还可用来识别是否为官方翻新机.你可以简单的将这一串数字分割为:aabccdddeef 的形式.拿iPhone 4为例 aa = 工 ...

  2. Mybatis通用Join的实现(最终版)

    你是否还在为mybatis的多表关联查询而写xml烦恼,是否还在为动态组装查询条件烦恼,是否还在为此没有合适的解决方案烦恼? mybatis-extension插件,解决开发过程中需要多表关联时需手写 ...

  3. Spark RDD中Runtime流程解析

    一.Runtime架构图 (1)从Spark  Runtime的角度讲,包括五大核心对象:Master.Worker.Executor.Driver.CoarseGrainedExecutorBack ...

  4. Anchors Piovt详解

    这个两个东西是RectTransform里面的两个属性,也是UGUI做UI自适应的重要工具,之前做的的时候,都只是调出效果即可,并没有深究其中的原理,现在决定来补上这个漏洞. 首选我们来看看Ancho ...

  5. 使用Javax.mail 发送邮件

    使用Javax.mail 发送邮件 详细说明都在代码中: 引入依赖  <!--sun定义的一套接收.发送电子邮件的API-->    <dependency>      < ...

  6. 使用Docker构建PHP7.4 + Swoole + Redis镜像

    使用Docker构建PHP7.4 + Swoole + Redis镜像 Docker是一个用于开发,交付和运行应用程序的开放平台.开发者可以利用Docker来快速交付,测试和部署代码,从而大大减少编写 ...

  7. 关于`ClawHub的技术分享`公众号

    生命不息,折腾不止! 该公众号的内容大部分为平时学习积累所整理的笔记,包括但不限于源码.原理.经验等. 如果感兴趣,也可以访问clawhub的博客主站https://clawhub.club

  8. 使用Telnet服务测试端口时,提示没有Telnet服务

    1.win7系统是默认不开启Telnet服务的,所以我们第一次使用时要手动开启Telnet服务 1)打开 控制面板 > 程序 > 程序功能 > 打开或关闭Windows功能,勾选上T ...

  9. 【Spring】IOC容器注解汇总,你想要的都在这儿了!!

    写在前面 之前,我们在[Spring]专题中更新了不少关于Spring注解相关的文章,有些小伙伴反馈说,看历史文章的话比较零散,经常会忘记自己看到哪一篇了.当打开一篇新文章时,总感觉自己似乎是看到过了 ...

  10. find 用正则表达式查找符合yyyy-mm-dd-bddd模式的目录

    yyyy-dd-mm-bddd模式解释: yyyy:年份,如2020 mm:月份,如03 dd:日期,如22 -b:意为备份,-b为固定字符串 ddd:三位序列号,从001~999 符合此格式的目录名 ...