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 总线在物理上是通过接在外围设备微控 ...
随机推荐
- 使用jsonp进行跨域请求
使用jsonp进行跨域请求 在实际的业务中很多时候需要用到跨域请求,然而jsonp为我们提供了一种非常方便的跨域请求的方式,具体实现代码如下: $.ajax({ type:"get" ...
- ASP.NET中怎样将页面设为首页,加入收藏
1.文字js脚本事件:<span onClick="var strHref=window.location.href;this.style.behavior=’url(#default ...
- NYOJ 6.喷水装置(一)-贪心
喷水装置(一) 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 现有一块草坪,长为20米,宽为2米,要在横中心线上放置半径为Ri的喷水装置,每个喷水装置的效果都会让以 ...
- (4)java基础知识
一.注释 java的注释方法主要有三种 1.单行注释 // 2.多行注释 /* 内容 */ 3.文档注释 /** * * */ 这种方法注释用于生成一份API文档,主要说明 方法的功能.参数.返回值 ...
- CF 990C. Bracket Sequences Concatenation Problem【栈/括号匹配】
[链接]:CF [题意]: 给出n个字符串,保证只包含'('和')',求从中取2个字符串链接后形成正确的括号序列的方案数(每个串都可以重复使用)(像'()()'和'(())'这样的都是合法的,像')( ...
- HDU 2256 Problem of Precision (矩阵快速幂)(推算)
Problem of Precision Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- 51nod 最长单增子序列(动态规划)
最长单增子序列 (LIS Longest Increasing Subsequence)给定一个数列,从中删掉任意若干项剩余的序列叫做它的一个子序列,求它的最长的子序列,满足子序列中的元素是单调递增的 ...
- Proxy(2016山东省省赛C)(最短路)(spfa)
问题 C: Proxy 时间限制: 2 Sec 内存限制: 128 MB提交: 17 解决: 5[提交][状态][讨论版] 题目描述 Because of the GFW (Great Firew ...
- hihocoder1062 最近公共祖先·一
#1062 : 最近公共祖先·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho最近发现了一个神奇的网站!虽然还不够像58同城那样神奇,但这个网站仍然让小Ho乐在 ...
- ( 转 ) 优化 Group By -- MYSQL一次千万级连表查询优化
概述: 交代一下背景,这算是一次项目经验吧,属于公司一个已上线平台的功能,这算是离职人员挖下的坑,随着数据越来越多,原本的SQL查询变得越来越慢,用户体验特别差,因此SQL优化任务交到了我手上. 这个 ...