首页 » 智能 » 51入门系列教程| 协议协议(SPI篇)_边缘_时钟

51入门系列教程| 协议协议(SPI篇)_边缘_时钟

神尊大人 2024-10-30 03:11:50 0

扫一扫用手机浏览

文章目录 [+]

先说说硬件构造,看这个图

标准的SPI总线接口一样平常会有4根通信线路,一条总线上,也可以挂多个SPI从设备

51入门系列教程| 协议协议(SPI篇)_边缘_时钟 智能

(1)MOSI(master out slave in)

主器件输出从器件输入,大略点理解便是主设备向从设备发送数据,也有些器件称之为SDO,便是输出的意思。

(2)MISO(master in slave out)

主器件输入从器件输出,也便是主设备读取从设备的数据,其余一种称法是SDI,也便是输入的意思。

(3)SCLK

和IIC一样,无论是主器件还是从器件,所有数据的传输都因此这条线路上的时钟为参照,以是SPI和IIC都是属于同步串行接口。
SCK、CLK乱七八糟的叫法也不少,不过还算比较好辨认。

(4)/SSx

IIC可以通过寻址来找到总线上的特定器件,SPI则是用这根线来使能须要操作的设备。
设备多的话,也可能会利用多个IO或者数据选择器、译码器之类。
有些器件标记为/CS之类,实在便是一个器件使能端,这4个端口是一个标准SPI的接口。
可以看出来,站在主器件的态度,数据的发送和吸收是两条不同的线路。
和同一时候只能单向通畅的IIC接口比较,SPI的速率能够提升不少。
以上是标准SPI物理接口的基本情形,但是现在很多器件都是标准SPI的变种。
变种一、三线SPI,譬如大名鼎鼎的时钟芯片DS1302

只用到了SCLK、IO和/RST三个端口,实在便是省略了标准接口中只能够单向传输的MISO和MOSI。
直接做成了能够双向传输的I/O,实在细细看DS1302的时序。
和SPI一样一样的,变种二、奇葩三线SPI、五线SPI。
还有很多记不起来的芯片和一些LCD屏幕,譬如一些小尺寸LCD,只须要写数据,就可能会用到/SS、SCLK、MOSI;譬如一些多受控管脚的IC,除了/SS、SCLK、MOSI、MISO外。
可能还会添加DCx管脚用于受控指令的传输,这里百家争鸣,朵朵奇葩,啥都有。
变种三、Quad SPI,这个是非常有针对性的变种。
便是为了数据传输的速率,实在Quad SPI便是标准SPI硬件接口,只不过把数据发送模式分成了多种模式。

这些模式中,可以将原来只能够单向传输的MOSI和MISO都调度成双向传输,就能达到数据传输速率更加的效果。
乃至把某些掌握管脚也用于数据传输,那速率便是杠杠滴了。
譬如一些Quad SPI Nor Flash之类的芯片,无论哪种SPI,实在它们的基本构造都是类似的。
主从设备内部都是一个移位寄存器,连接起来构成一个环形的拓扑。

再来看看通信的协议,须要发送/吸收的数据,都在每个SCLK的边沿进行传输。
传输的数据为8位,按位传输,高位在前,低位在后,在主器件产生的从器件使能旗子暗记浸染下,两个双向移位寄存器进行数据交流。
假设主机的buff=0xaa,从机的buff=0x55,上升沿发送、低落沿吸收、高位先发送。
每个时钟的上升沿移动数据

是不是很大略呀?通信时序很大略。
但是moto对时钟SCLK做了一些比较故意思的约束,通过CPOL,CPHA对SCLK的限定,实现SPI的四种不同模式。
CPOL(Clock Polarity,时钟极性),用来设置时钟的空闲状态:

为1时,时钟空闲时为高电平

为0时,时钟空闲时为低电平

CPHA(Clock Phase,时钟相位),用来配置数据传输的时钟边沿

为0时,在时钟周期的第一边沿传输数据(或者理解为前一边沿)

为1时,在时钟周期的第二边沿传输数据(或者理解为后一边沿)

模式配置Mode 0CPOL=0,CPHA=0Mode 1CPOL=0,CPHA=1Mode 2CPOL=1,CPHA=0Mode 3CPOL=1,CPHA=1

这里值得引起把稳的地方是,对第一边沿和第二边沿的理解。
当CPOL=0,也便是时钟空闲为低电平时,第一边沿该当是时钟由低电平变成高电平的边沿,也便是第一个上升沿,那么第二边沿便是低落沿了。
同理,当CPOL=1,也便是时钟空闲为高电平时,第一边沿该当是时钟由高电平变成低电平的边沿,也便是第一个低落沿。
那么第二边沿便是上升沿了,

下面把四种模式的示意图bia出来

大家可以比拟笔墨和图片,瞧瞧这四种模式,好了,啰嗦了半天。
来点好玩的吧!
手头上SPI的器件不多,专门跑去ADI官网申请了一篇SPI接口的AD。
AD7685,SPI接口的16位AD转换器,便是这货

电路图

随手画的,勿喷啊!
简便起见,没有利用压随器,直接分压接入。
不过要把稳AD7685的输入阻抗哀求,数据端口SDI直接连到高电平。
实在是一个三线制的SPI接口,看看AD7685的时序吧!

一次传输16位AD数据,在第一个上升沿进行第一位数据的传输。
所以是Mode 0的SPI器件,也便是 CPOL=0,CPHA=0。
51无需去理会CPOL和CPHA,只须要知道AD7685的哀求即可,上代码:

#include <reg51.h>

#define Vref 5.0

sbit smgbit1 = P3^7;

sbit smgbit2 = P3^6;

sbit SCK=P2^2;

sbit SDO=P2^1;

sbit CNV=P2^0;

sbit dp = P1^7;

smgdisp_cache[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xf8,0x80,0x90};

unsigned int timer_count,Vol,count;

unsigned char temp=0;

float Voltage;

void delay_ms(unsigned int xms)

{

unsigned int i,j;

for(i=xms;i>0;i--)

{

for(j=124;j>0;j--);

}

}

unsigned int adconvert(void)

{

int result;

unsigned char i;

CNV=0;

delay_ms(2);

CNV=1;

delay_ms(2);

for(i=0;i<16;i++) //SPI的数据传输哟

{

SCK=1;

CNV=0;

result=result<<1;

if(SDO)

result=result|0x01;

SCK=0;

}

return(result);

}

void init()

{

smgbit1 = 0;

smgbit2 = 1;

TMOD=0x01;//设置定时器0为事情办法1

TH0=0xfc;

TL0=0X66;

EA=1;//开总中断

ET0=1;//开定时器0中断

TR0=1;//启动定时器0

}

void SMG_Dis()

{

if(smgbit2){

P1 = smgdisp_cache[temp%10];

}

if(smgbit1){

P1 = smgdisp_cache[temp/10];

dp = 0;

}

}

void time0() interrupt 1

{ P1 = 0xff; //肃清鬼影

timer_count++;

if(timer_count == 100)

{count++;

Vol = adconvert();

Voltage = VrefVol/65535;

temp = (unsigned char)(Voltage10.0);

timer_count = 0;

}

smgbit1 = ~smgbit1;

smgbit2 = ~smgbit2;

SMG_Dis();

TF0 = 0;

TH0 = 0xfc;

TL0 = 0x66;

}

void main()

{ init();

while(1){

}

}

采集AD值,通过数码管显示,数码管用定时器扫描

GIF显示从0-2.5v的采样,溘然想起手上还有个点阵LED模块。

这货彷佛也是个SPI接口呢

MAX7219LED驱动IC,赶紧看看数据手册

果真,看看时序

依然还是模式0啊,写好代码

#include <reg51.h>

#include <intrins.h>

#define uchar unsigned char

#define uint unsigned int

//定义Max7219端口

sbit Max7219_pinCLK = P2^2;

sbit Max7219_pinCS = P2^1;

sbit Max7219_pinDIN = P2^0;

void Delay_xms(uint x)

{

uint i,j;

for(i=0;i<x;i++)

for(j=0;j<112;j++);

}

//--------------------------------------------

//功能:向MAX7219(U3)写入字节SPI

//入口参数:DATA

//出口参数:无

//解释:

void Write_Max7219_byte(uchar DATA)

{

uchar i;

Max7219_pinCS=0;

for(i=8;i>=1;i--)

{

Max7219_pinCLK=0;

Max7219_pinDIN=DATA&0x80;

DATA=DATA<<1;

Max7219_pinCLK=1;

}

}

//-------------------------------------------

//功能:向MAX7219写入数据

//入口参数:address、dat

//出口参数:无

//解释:

void Write_Max7219(uchar address,uchar dat)

{

Max7219_pinCS=0;

Write_Max7219_byte(address); //写入地址,即数码管编号

Write_Max7219_byte(dat); //写入数据,即数码管显示数字

Max7219_pinCS=1;

}

void Init_MAX7219(void)

{

Write_Max7219(0x09, 0x00); //译码办法:BCD码

Write_Max7219(0x0a, 0x00); //亮度

Write_Max7219(0x0b, 0x07); //扫描界线;8个数码管显示

Write_Max7219(0x0c, 0x01); //掉电模式:0,普通模式:1

Write_Max7219(0x0f, 0x00); //显示测试:1;测试结束,正常显示:0

}

void main(void)

{

uchar i,j;

uchar temp[]={0x00,0x66,0x99,0x81,0x42,0x24,0x18,0x00};//LED点阵取模,❤型

Init_MAX7219();

while(1)

{

for(i=1;i<9;i++)

Write_Max7219(i,temp[i-1]);

for(i=1;i<16;i++){

Write_Max7219(0x0a, i);

Delay_xms(50);}

for(i=15;i>0;i--){

Write_Max7219(0x0a, i);

Delay_xms(50);}

}

}

上个图

实在代码还是可以闪烁的,只须要向MAX7219干系寄存器通过SPI写入值即可

SPI比较IIC而言的话大略不少啊,本日就先到这里。

理解更多51系列教程,请关注“云汉电子社区”官方微信"大众年夜众号ickeybbs,或者登录云汉电子社区官方网站(bbs.ickey.cn)

标签:

相关文章