51单片机 | SPI协议与应用实例
————————————————————————————————————————————
SPI总线
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
参考链接:
http://blog.csdn.net/fly__chen/article/details/52724109
http://blog.csdn.net/skyflying2012/article/details/11910173
http://blog.sina.com.cn/s/blog_9cc7125c0100yk1s.html
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
简介:
- 串行外围设备接口
- 全双工三线同步,可以同时发出和接收串行数据
- 采用主从(Master Slave)架构,支持多Slave模式应用,一般仅支持单Slave
- 时钟由Master控制,在时钟移位脉冲下,数据按位传输,高位在前,低位在后
- 目前应用中可以达到几Mbps的水平
- 优点:与普通的串行设备相比,可以按位传输,甚至可以暂停。当没有时钟跳变时,从设备不采集和传送数据。不需要寻址操作。全双工通信。
- 缺点:没有应答机制确认。
特点:
- 提供频率可编程时钟
- 发送结束、中断标志;写冲突保护
- 总线竞争保护
- SPI总线工作的4种工作方式中,使用最广泛的是SPI0和SPI3方式
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
信号线情况:

- SCLK提供时钟脉冲,SDI/SDO基于此脉冲按位传输。当处于上升沿模式时,输出:通过SDO线在时钟上升沿时输出,在紧接着的下降沿被读取。输入同理。
- SS/CS是片选信号线,只有片选信号为使能信号时,对芯片的操作才有效,所以可以在同一总线上连接多个SPI设备
- SDI:slave → master,从机要发送给主机的数据
- SDO:master → slave,主机要发送给从机的数据
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
连接方式:
- 级联方式:此时所有设备的CS端都连在一起,只要选中一个设备,则全选。可以作为一个设备进行处理。

- 独立连接方式:设备独立操作,为被选通的从设备均处于高阻隔离状态。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
工作模式:
|
SPI模式 |
CPOL极性 |
CPHA相位 |
说明 |
|
0 |
0 |
0 |
第一个边沿上升沿 |
|
1 |
0 |
1 |
第二个边沿下降沿 |
|
2 |
1 |
0 |
第一个边沿下降沿 |
|
3 |
1 |
1 |
第二个边沿上升沿 |
CPOL=0:SCLK有效时为高电平(active-high)
CPOL=1:SCLK有效时为低电平(active-low)
CPHA=0:表示第一个边沿
CPHA=1:表示第二个边沿
Toggling edge为切换边沿,输出信号
Sampling edge为采样边沿,输入信号

时序图:


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SPI协议举例
- 主机8位寄存器存放的是1010 1010,从机存放的是0101 0101,将主从机数据交换
- SDI:slave → master
- SDO:master → slave
- 上升沿发送、下降沿接收
初始化就绪状态:
- 主机SBUFF = 1010 1010
- 从机SBUFF = 0101 0101
操作过程:如图所示,经过8个脉冲后,master和slave数据交换

SPI的8个时钟周期的数据:

————————————————————————————————————————————
基于SPI协议,DS1302显示时钟实例
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
实现效果:

实现代码:
#include <reg52.h>
typedef unsigned char uchar;
typedef unsigned int uint;
//写操作控制字节,D7=1,D0=0
uchar code write_address[] =
{
//秒,分,小时,日,月,星期,年
0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c
};
//读操作,D7=1,D0=1,地址同写操作
uchar code read_address[] =
{
0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d
};
uchar code table[] =
{
//0,1,2,3,4,5,6,7,8,9
0xfc, 0x60, 0xda, 0xf2, 0x66, 0xb6, 0xbe, 0xe0, 0xfe, 0xf6
};
//dat1和dat2存放读出来的时间,初始值写入12年5月9日1时1分1秒,dat1存放1234位,dat2存放567位
uchar dat1[] = {0x01, 0x01, 0x01, 0x09, 0x05, 0x02, 0x12};
uchar dat2[] = {0x01, 0x01, 0x01, 0x09, 0x05, 0x02, 0x12};
sbit rst = P3 ^ ;
sbit scl = P3 ^ ;
sbit sda = P3 ^ ;
sbit ACC7 = ACC ^ ;
void Delay(uint m)
{
while(m--);
}
/* SPI协议操作,读字节 */
uchar ReadByte()
{
uchar i;
for (i = ; i < ; ++i)
{
ACC = ACC >> ; //累加器左移1位,补上未知数x
ACC7 = sda; //从sda引脚写入ACC最高位
scl = ;
scl = ; //时钟下降沿读入
}
return ACC;
}
/* SPI协议操作,写字节 */
void WriteByte(uchar byte)
{
uchar i;
for (i = ; i < ; ++i)
{
byte >>= ; //byte左移1位存入CY
scl = ;
sda = CY; //从CY移入sda,发送给DS102
scl = ; //时钟上升沿写入
}
}
void Write1302(uchar address, uchar dat) //写地址子程序
{
rst = ;
scl = ;
rst = ; //rst上升沿开始写数据
WriteByte(address); //先写入地址控制字节
WriteByte(dat); //再写入数据字节
rst = ;
}
uchar Read1302(uchar address)
{
uchar temp;
rst = ;
scl = ;
rst = ; //读过程中保持rst高电平状态
WriteByte(address | 0x01); //写入地址并置R/W位为1(读)
temp = ReadByte(); //在单片机写入命令字节的最后一位的第一个下降沿处即读出数据
scl = ;
rst = ;
return temp;
}
void SetRST()
{
uchar i;
Write1302(0x8e, 0x00); //向10001110写保护寄存器,写入指令0x00
for (i = ; i < ; ++i)
Write1302(write_address[i], dat1[i]); //从秒到年各寄存器写入对应初始值
Write1302(0x8e, 0x80); //向写保护寄存器,写入数据0x80
}
void ReadTime()
{
uchar i, temp1, temp2, temp3;
temp3 = 0x80; //temp3存放时间寄存器地址
for (i = ; i < ; ++i) //分别读出秒分小时日月星期年
{
temp1 = Read1302(temp3);
temp2 = temp1;
dat1[i] = (temp1 >> ) & 0x0f; //读出的数据1234位存入dat1,屏蔽其他位
dat2[i] = (temp2 >> ) & 0x07; //读出的数据567位存入dat2,屏蔽其他位
temp3 = temp3 + 0x02; //下一个寄存器地址
}
}
void main()
{
rst = ;
SetRST(); //时钟建立
while()
{
ReadTime(); //读时间
P2 = 0xfe;
P1 = table[dat1[] % ];
Delay();
P2 = 0xfd;
P1 = table[dat2[] % ];
Delay();
P2 = 0xfb;
P1 = 0x02; // -
Delay();
P2 = 0xf7;
P1 = table[dat1[] % ];
Delay();
P2 = 0xef;
P1 = table[dat2[] % ];
Delay();
P2 = 0xdf;
P1 = 0x02; // -
Delay();
P2 = 0xbf;
P1 = table[dat1[] % ];
Delay();
P2 = 0x7f;
P1 = table[dat2[] % ];
Delay();
}
}

51单片机 | SPI协议与应用实例的更多相关文章
- [51单片机] SPI nRF24L01 无线简单程序 1
main.c #include <reg51.h> #include <api.h> #define uchar unsigned char /**************** ...
- 51单片机 | 1-Wire总线及应用实例
———————————————————————————————————————————— 1-Wire总线 - - - - - - - - - - - - - - - - - - - - - - - ...
- [51单片机] SPI nRF24L01无线 [可以放在2个单片机里实现通信]
main.c #include<reg51.h> #include"2401.h" #define uint unsigned int #define uchar un ...
- 51单片机I/O口直接输入输出实例(附调试及分析过程)
51单片机P0/P1/P2/P3口的区别: P0口要作为低8位地址总线和8位数据总线用,这种情况下P0口不能用作I/O,要先作为地址总线对外传送低8位的地址,然后作为数据总线对外交换数据: P1口只能 ...
- 51单片机 | I/O口直接输入输出实例
51单片机P0/P1/P2/P3口的区别: P0口要作为低8位地址总线和8位数据总线用,这种情况下P0口不能用作I/O,要先作为地址总线对外传送低8位的地址,然后作为数据总线对外交换数据: P1口只能 ...
- 51单片机 | 并行I/O口扩展实例(74LS244/74LS373/4071)
并行I/O口扩展实例 //<51单片机原理及应用(第二版)——基于Keil C与Proteus>第四章例4.4 I/O口不能完全用于输入/输出操作,当需要扩展外部存储器时,P0.P2口用作 ...
- 基于51单片机的CAN通讯协议C语言程序
//-----------------------函数声明,变量定义-------------------------------------------------------- #includ ...
- Windows 通用应用尝试开发 “51单片机汇编”总结
一.前言 终于完成windows通用应用“51单片机汇编”,半年前开始玩WindowsPhone开发的第一个真正意义上的App(还很多缺点=_=).开发从1月中旬考完试到今天,期间实习了半个月,玩了几 ...
- SPI协议及其工作原理详解
一.概述. SPI, Serial Perripheral Interface, 串行外围设备接口, 是 Motorola 公司推出的一种同步串行接口技术. SPI 总线在物理上是通过接在外围设备微控 ...
随机推荐
- redis特性与使用场景
一.8大特性 1.速度快 数据存储在内存,可达到10万OPS 2.可持久化,断电不丢数据 所有数据保存在内存中,对数据的更新异步的保存在硬盘中 3.多种数据结构 字符串.哈希.列表.集合.有序集 合位 ...
- 隐藏tomcat版本号
找到catalina.jar, cd /usr/local/tomcat/lib 解压catalina.jar unzip catalina.jar 会生成两个目录 修改配置文件:org/apache ...
- HDU 1251 统计难题 (字典树)(查询是否为前缀)
统计难题 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others)Total Submi ...
- COW
COW 时间限制: 1 Sec 内存限制: 64 MB提交: 41 解决: 18[提交][状态][讨论版] 题目描述 Bessie the cow has stumbled across an i ...
- 传统路径导出 VS 直接路径导出(oracle exp direct=y)
Oracle 传统的Export与Import依旧被保留到11g,而且9i与10g有很多依旧使用Export与Import方式进行备份与恢复的企业.从Oracle 7.3开始,传统的exp导出程序提供 ...
- FFT&NTT&多项式相关
打了FFT 感觉以后多项式不虚了 ~滑稽~ PS 关于详见没写完.... code #include<cmath> #include<cstdio> #include<c ...
- Ze_Min Tree 主席树
前言 主席树,也叫可持久化线段树,所以他的本质是颗线段树,而可持久化指的是这颗线段树可以访问过去某个时刻线段树上的信息. 应用 应用的比较多的是查询区间的第k大值(因为其他的数据结构不好做). 实现 ...
- 【进制转换】CODEVS 1740 进制计算器
#include<cstdio> #include<iostream> #include<string> using namespace std; string s ...
- 1.4(java学习笔记) 面向对象内存分析
首先介绍几个概念 栈: 1.栈是方法执行的内存模型,每调用一个方法都会创建一个栈帧. 2.jvm为每个线程创建一个栈,存放方法相关信息,栈属于线程私有不共享. 3.栈由系统自动分配,是连续的内存空 ...
- Exercise01_01
public class print{ public static void main(String[] args){ System.out.println("Welcome to Java ...