单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 18160|回复: 3
收起左侧

第5章 单片机SPI通信

[复制链接]
wul 发表于 2016-3-28 02:11 | 显示全部楼层 |阅读模式
51单片机轻松入门—基于STC15W4K系列(C语言版)
李友全
编著:http://www.51hei.com/bbs/dpj-37954-1.html


5章 单片机SPI通信
1 接口定义
2 SPI接口相关寄存器
3 SPI接口运用举例

(1)单主机-单从机通信方式(从机不用片选)

(2)STC-SPI硬接口(单主单从_从机使用片选)

(3)STC-SPI硬接口(互为主从)

(4)STC-SPI硬接口(单主多从)

%E7%AC%AC5%E7%AB%A0-spi%E9%80%9A%E4%BF%A1-5.jpg 1 接口定义

UART串口通信速度一般只能到达115200位/秒,SPI通信数据速率可达8MHz

(16M位/秒)以上的水平。 SPI接口共有4根信号线,分别是:设备选择线(片选)、时钟线、串行数据输出 线、串行数据输入线,如下图所示。

① MOSI(Master Out Slave In):主器件数据输出,从器件数据输入,用于主器件到从
器件的数据传输。
② MISO(Master In Slave Out):主器件数据输入,从器件数据输出,用于从器件到主 器件的数据传输。
③ SCLK (SPI Clock) :时钟信号,只能由主器件产生。
④ /SS:设备选择线(片选),由主器件控制,当从器件片选信号输入低电平时为选中状 态,/SS是针对从器件而言的,作为主器件,不需要使用/SS。
单片机为了和外设进行数据交换,根据外设工作要求,单片机输出时钟信号有几种不同的状 态。

(1)时钟极性(CPOL)定义了时钟空闲状态的电平。 CPOL=0:时钟空闲状态为低电平。 CPOL=1:时钟空闲状态为高电平。

(2)时钟相位(CPHA)定义数据的采样时刻。 CPHA=0:单片机在每个时钟周期的第一个跳变沿(上升或下降) 采样外部数据,第二个

跳变沿输出数据。
CPHA=1:在每个时钟周期的第一个跳变沿(上升或下降) 输出数据,第二个跳变沿采样 外部数据。

时钟极性(CPOL)和时钟相位(CPHA)的组合可形成四种不同的数据传输时序,如下图所示。

前沿采样后沿输出

0.png

2 SPI接口相关寄存器
表5-1 SPCTL控制寄存器(复位值为0000 0100B)

位号

D7

D6

D5

D4

D3

D2

D1

D0

位名称

SSIG

SPEN

DORD

MSTR

CPOL

CPHA

SPR1

SPR0

典型设置举例:
l 2个单片机3线制主从通信(从机不用片选线),主机设置:0xF0(1111 0000), 从机设置:0xE0(1110 0000)。
l 2个单片机4线制通信(从机使用片选线),主机设置:0xF0(1111 0000), 从机设置:0x60(0110 0000)。
l 2个单片机互为主从4线制通信(从机使用片选线),主机设置:0xF0(1111 0000), 从机设置:0x60(0110 0000)。

各位详细说明:

SSIG :/SS引脚忽略控制位。
1:忽略/SS引脚,由D4(MSTR)位确定器件为主机还是从机,MSTR=1(主机),MSTR=0(从机)。
0:作从机且使用片选线时设为0,同时将D4(MSTR)位设0成为从机,当片选线/SS为低时芯片 选中,可正常通信,当片选线/SS为高时芯片没选中,不参与通信。
SPEN :SPI使能位。1:使能SPI。0:禁止SPI,所有SPI引脚都作为普通IO口使用。

DORD:设定数据发送和接收的顺序。1:低位在前,高位在后。 0:高位在前,低位在后。 MSTR :MSTR=1(主机),MSTR=0(从机)。 CPOL:时钟极性。1:SPI空闲时,时钟线为高电平。0:SPI空闲时,时钟线为低电平。 CPHA:时钟相位选择。1:时钟前沿输出,后沿采样。0:时钟前沿采样,后沿输出。

SPR1与SPR0:主机输出时钟速率选择,见下表。
0.png

说明:SYS_clk表示CPU运行时钟,若没进行分频设置(默认值),SYS_clk就是内部R/C时钟

或外部晶振频率,作为主机方式,上面4种配置方式都可以稳定工作,但建议时钟频率一般不 要超过3M,这样既可增强SPI传输稳定性又能减小高频信号对电路板上其它器件产生干扰。对 于从机,时钟速率设置无效,它完全是由主机时钟频率控制,从机能接受的时钟频率要求控 制在SYS_clk/4以内,比如主机和从机都使用内部R/C时钟33.1776MHZ,主机和从机最高允许

时钟频率率33.1776/4≈8.3MHz。


表5-3 SPSTAT状态寄存器(复位值为00xx xxxxB)

位号

D7

D6

D5

D4

D3

D2

D1

D0

位名称

SPIF

WOCL

-

-

-

-

-

-

SPIF:SPI传输完成标志。当一次传输完成时,SPIF被置1,此时,如果SPI中断被打开

(ESPI=1,EA=1),则产生中断,SPIF标志通过软件向其写入1而清零,比如:SPSTAT=0xC0; 执行后SPSTAT=0x00。
WOCL:SPI写冲突标志。当一个数据还在传输,又向数据寄存器SPDAT写入数据时,WOCL被 置1,WOCL标志通过软件向其写入1而清零。
表5-4 SPDAT数据寄存器(复位值为0000 0000B)

位号

D7

D6

D5

D4

D3

D2

D1

D0

位名称

MSB







LSB

位7~0:保存SPI通信数据字节。MSB为最高位,LSB为最低位。例如,主机发送数据:
SPDAT=tmpdata; // 将tmpdata变量中的数据发送出去,执行此命令后硬件电路自动输出
tmpdata变量数据并接收从机数据。

重点说明:如下图所示,SPDAT是SPI接口内部移位寄存器配备的一个数据缓冲寄存器,其物 理地址与移位寄存器一样,当对SPDAT进行读操作时,读取的是缓冲寄存器中的内容,当对 SPDAT进行写操作时,数据将被直接写入移位寄存器并启动发送过程。

0.png
3 SPI接口运用举例

(1)单主机-单从机通信方式(从机不用片选),硬件电路如图所示。

0.png
程序功能说明:
计算机向主单片机(1号)发送一个字节数据,主单片机的串口每次收到1个字节数据后就立 刻将这个字节通过SPI口发送到从单片机(2号),同时,主单片机收到从单片机发回的一个 字节,并把收到的这个字节通过串口发送到计算机,可使用串口助手观察实验结果。 从单片机SPI口收到数据后,把收到的数据(SPDAT中读出的内容)放到自己的移位寄存器中
(对SPDAT写入数据),当下一次主单片机发送一个字节过来时把数据发回到主单片机,R/C

时钟频率22.1184MHz,计算机串口波特率设置为9600、n、8、1,十六进制发送与接收。


主单片机(1号)程序代码:


#include "STC15W4K.H"

//

注意宏定义后面没分号

bit SPI_Receive;
//
SPI 端口收到数据标志位
unsigned char SPI_buffer;
//
保存SPI端口收到的数据
/**************************************************************************
- 功能描述:STC15单片机串口1初始化,使用T1方式2自重载方式做波特率发生器
**************************************************************************/
void UART_init(void) // 9600bps@22.1184MHz
{
// 下面代码设置定时器1
TMOD |= 0x20; // 0010 0000 定时器1工作于方式2(8位自动重装方式) TH1 = 0xFA; // 波特率:9600 /22.1184MHZ
TL1 = 0xFA; // 波特率:9600 /22.1184MHZ TR1 = 1;
// 下面代码设置定串口
AUXR = 0x00; // 很关键,使用定时器1作为波特率发生器,S1ST2=0
SCON = 0x50; // 01010 0000 SM0.SM1=01(最普遍的8位通信),REN=1(允许接受)
}
void Switch_port() // 根据硬件连接切换端口
{
AUXR1&=0XF3; //1111 0011
AUXR1|=0X04; //0000 0100
}
void port_mode() // 端口模式
{
P0M1=0x00; P0M0=0x00;P1M1=0x00; P1M0=0x00;P2M1=0x00; P2M0=0x00;P3M1=0x00; P3M0=0x00; P4M1=0x00; P4M0=0x00;P5M1=0x00; P5M0=0x00;P6M1=0x00; P6M0=0x00;P7M1=0x00; P7M0=0x00;
}

void main(void)
{
unsigned char tmpdata,SPI_status;
port_mode(); // 所有IO口设为准双向弱上拉方式。 UART_init(); // 初始化串口2C9600bps@22.1184MHz],9600bps@22.1184MHz
SPCTL=0xF0; // 主机 (或SPCTL=0xFC; )
Switch_port(); // 端口切换
while(1) // 主循环
{
if(RI) // 判串口是否收到数据
{
tmpdata=SBUF; // 读取串口中收到的数据 RI=0;
P35=!P35; // 串口接收数据指示灯,调试时观察串口工作是否正常
SPDAT=tmpdata; // 将数据发送到从机SPI SPI_status=0;
while(SPI_status==0)
{
SPI_status=SPSTAT; // 等待SPIF=1即等待SPI发送完毕 SPI_status=SPI_status&0x80;
}
SPSTAT=0xC0; // 清0标志位SPIF和WCOL SPI_buffer=SPDAT; // 保存收到的数据
SBUF=SPI_buffer; // 将接收到的数据从串口发送到计算机
while(TI==0); // 等待发送完毕
TI=0; // 清零串口发送中断标志
}
}
}

从单片机(2号)程序代码:


#include "STC15W4K.H"
//
注意宏定义后面没分号
bit SPI_Receive;
//
SPI 端口收到数据标志位
unsigned char SPI_buffer;
//
保存SPI端口收到的数据
void port_mode() {}
//
端口模式,与主单片机相同
void main(void)



{



port_mode();
//
所有IO口设为准双向弱上拉方式。
SPCTL=0xE0;
//
从机 (或SPCTL=0xEC; )
IE2=IE2|0x02;
//
ESPI(IE2.1)=1,允许SPIF产生中断
EA=1;
//
开总中断
SPI_Receive=0;
//
清标志字
while(1)
//
主循环
{



if (SPI_Receive)


// 判收是否收到主机SPI发来的数据
{



SPI_Receive=0;


// 清0主单片机SPI端口收到数据标志位
SPDAT=SPI_buffer; // 将收到数据送SPDAT,准备下一次通讯时发回
}
}
}
void SPI(void) interrupt 9
{
SPSTAT=0xC0; // 清0标志位SPIF和WCOL SPI_buffer=SPDAT; // 保存收到的数据 SPI_Receive=1; // 设置SPI端口收到数据标志
}
(2)STC-SPI硬接口(单主单从_从机使用片选)

0.png
我们使用片选的目的是要实现多机选择,如果只有一个从机就没有必要多使用一条片选线
了,因此程序中在SPI传输前打开片选(拉低从机SS),SPI传输完成后关闭片选(拉高 从机SS),当然也可以不关闭。只有很少一点代码与上例不同,如下所示。
sbit P2_4=P2^4;
#ifdef MASTER
SPCTL=0xf0; // 1111 0000
#else
SPCTL=0x60; // 0110 0000
#endif
………
P2_4=0; // 打开从机片选 SPDAT=tmpdata; // SPI 发送数据
…… // 等待SPI发送完毕
P2_4=1; // 关闭从机片选


(3)STC-SPI硬接口(互为主从)
0.png
程序功能说明:

1号单片机与2号单片机互为主从,分别通过串口与计算机相连,静态时2个单片机都设置为 需要片选的从机方式,如果哪个单片机收到计算机发来的数据,就设置为主机方式,拉低/SS 片选线选中从机,并发送数据给从机,主机收到从机的返回数据发计算机,从机收到主机的数 据也发计算机,总体效果是2个计算机串口可以对传数据。本实验在硬件上需要2个计算机串 口,串口助手可用STC_ISP打开2个串口助手窗口,R/C时钟频率22.1184MHz,波特率为9600、n、

8、1。

完整代码请参见教材P186-P187。

(4)STC-SPI硬接口(单主多从),硬件电路如图所示。

0.png

•功能与程序请参见教材P188-P190。
回复

使用道具 举报

aking991 发表于 2018-1-27 14:40 | 显示全部楼层
很好,学习了,不过有点少,再多点会更好,谢谢了
回复

使用道具 举报

无效楼层,该帖已经被删除
friend114 发表于 2018-12-4 19:48 | 显示全部楼层
很好,学习了,不过有点少,再多点会更好,谢谢了
回复

使用道具 举报

杨梅味的苹果 发表于 2019-4-24 21:13 | 显示全部楼层
感谢作者,很有帮助
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|单片机论坛 |51黑电子论坛技术交流 QQ 管理员QQ:125739409;技术交流QQ群636986012

Powered by 单片机教程网

快速回复 返回顶部 返回列表