标题: 第5章 单片机SPI通信 [打印本页]
作者: wul 时间: 2016-3-28 02:11
标题: 第5章 单片机SPI通信
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硬接口(单主多从)
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)的组合可形成四种不同的数据传输时序,如下图所示。
前沿采样后沿输出
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:主机输出时钟速率选择,见下表。
说明: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进行写操作时,数据将被直接写入移位寄存器并启动发送过程。
3 SPI接口运用举例
(1)单主机-单从机通信方式(从机不用片选),硬件电路如图所示。
程序功能说明:
计算机向主单片机(1号)发送一个字节数据,主单片机的串口每次收到1个字节数据后就立 刻将这个字节通过SPI口发送到从单片机(2号),同时,主单片机收到从单片机发回的一个 字节,并把收到的这个字节通过串口发送到计算机,可使用串口助手观察实验结果。 从单片机SPI口收到数据后,把收到的数据(SPDAT中读出的内容)放到自己的移位寄存器中
(对SPDAT写入数据),当下一次主单片机发送一个字节过来时把数据发回到主单片机,R/C
时钟频率22.1184MHz,计算机串口波特率设置为9600、n、8、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; // 清零串口发送中断标志
}
}
}
#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硬接口(单主单从_从机使用片选)
我们使用片选的目的是要实现多机选择,如果只有一个从机就没有必要多使用一条片选线
了,因此程序中在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硬接口(互为主从)
程序功能说明:
1号单片机与2号单片机互为主从,分别通过串口与计算机相连,静态时2个单片机都设置为 需要片选的从机方式,如果哪个单片机收到计算机发来的数据,就设置为主机方式,拉低/SS 片选线选中从机,并发送数据给从机,主机收到从机的返回数据发计算机,从机收到主机的数 据也发计算机,总体效果是2个计算机串口可以对传数据。本实验在硬件上需要2个计算机串 口,串口助手可用STC_ISP打开2个串口助手窗口,R/C时钟频率22.1184MHz,波特率为9600、n、
8、1。
完整代码请参见教材P186-P187。
(4)STC-SPI硬接口(单主多从),硬件电路如图所示。
•功能与程序请参见教材P188-P190。
作者: aking991 时间: 2018-1-27 14:40
很好,学习了,不过有点少,再多点会更好,谢谢了
作者: friend114 时间: 2018-12-4 19:48
很好,学习了,不过有点少,再多点会更好,谢谢了
作者: 杨梅味的苹果 时间: 2019-4-24 21:13
感谢作者,很有帮助
作者: 许超越 时间: 2020-3-12 09:54
感谢作者,帮助很大
作者: longfu 时间: 2020-7-31 13:58
不错,值得学习
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |