————————————————————————————————————————————

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协议与应用实例的更多相关文章

  1. [51单片机] SPI nRF24L01 无线简单程序 1

    main.c #include <reg51.h> #include <api.h> #define uchar unsigned char /**************** ...

  2. 51单片机 | 1-Wire总线及应用实例

    ———————————————————————————————————————————— 1-Wire总线 - - - - - - - - - - - - - - - - - - - - - - - ...

  3. [51单片机] SPI nRF24L01无线 [可以放在2个单片机里实现通信]

    main.c #include<reg51.h> #include"2401.h" #define uint unsigned int #define uchar un ...

  4. 51单片机I/O口直接输入输出实例(附调试及分析过程)

    51单片机P0/P1/P2/P3口的区别: P0口要作为低8位地址总线和8位数据总线用,这种情况下P0口不能用作I/O,要先作为地址总线对外传送低8位的地址,然后作为数据总线对外交换数据: P1口只能 ...

  5. 51单片机 | I/O口直接输入输出实例

    51单片机P0/P1/P2/P3口的区别: P0口要作为低8位地址总线和8位数据总线用,这种情况下P0口不能用作I/O,要先作为地址总线对外传送低8位的地址,然后作为数据总线对外交换数据: P1口只能 ...

  6. 51单片机 | 并行I/O口扩展实例(74LS244/74LS373/4071)

    并行I/O口扩展实例 //<51单片机原理及应用(第二版)——基于Keil C与Proteus>第四章例4.4 I/O口不能完全用于输入/输出操作,当需要扩展外部存储器时,P0.P2口用作 ...

  7. 基于51单片机的CAN通讯协议C语言程序

      //-----------------------函数声明,变量定义-------------------------------------------------------- #includ ...

  8. Windows 通用应用尝试开发 “51单片机汇编”总结

    一.前言 终于完成windows通用应用“51单片机汇编”,半年前开始玩WindowsPhone开发的第一个真正意义上的App(还很多缺点=_=).开发从1月中旬考完试到今天,期间实习了半个月,玩了几 ...

  9. SPI协议及其工作原理详解

    一.概述. SPI, Serial Perripheral Interface, 串行外围设备接口, 是 Motorola 公司推出的一种同步串行接口技术. SPI 总线在物理上是通过接在外围设备微控 ...

随机推荐

  1. 【hdoj_1051】WoodenSticks

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1051 题意可以理解为:给定若干个二元数对,要将这些数对分为不同的组,同一组中的若干个二元数对可以排列成一个 ...

  2. win32 右键弹出菜单

    #define  CW_ABOUT  100 #define  CW_DOCUMENT 200 POINT t; GetCursorPos(&t); HMENU hMenu,hPopupMen ...

  3. 【转载】Synflood code

    ''' Syn flood program in python by Tequila/e credits to Silver Moon for base's of syn packets. r s s ...

  4. NYOJ 914 Yougth的最大化【二分/最大化平均值模板/01分数规划】

    914-Yougth的最大化 内存限制:64MB 时间限制:1000ms 特判: No 通过数:3 提交数:4 难度:4 题目描述: Yougth现在有n个物品的重量和价值分别是Wi和Vi,你能帮他从 ...

  5. HDU 1811 Rank of Tetris 【拓扑排序 + 并查集】

    自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球. 为了更好的符合那些爱好者的喜好,Lele又想了一个新点子:他将制作一个全球Tetris高手排行榜, ...

  6. UVALive 5097 Cross the Wall

    贪心思想,$dp$,斜率优化. 首先将人按照$w$从大到小排序,如果$w$一样,按$h$从大到小排.这样一来,某位置之后,比该位置$h$小的都是不需要考虑的. 因此,形成了如下图所示的结果: 即第一个 ...

  7. 揭秘响应式web设计

     0.引言 响应式web设计的作用主要使网页能在不同小大的显示窗口下依然优雅.当前的显示窗口有pc,ipad,iphone以及一些其他的设备.不同的显示窗口的分辨率各不相同,如何在不同的分辨率的情况下 ...

  8. 搭建基于Ant+Jmeter+jenkins的自动负载测试框架的若干问题记录及解决

    1.关于构建时使用的默认build.xml问题  如图,如果构建脚本build.xml不在workspace根目录.或者说构建脚本不叫build.xml.那么需要在高级里设置Build File选项的 ...

  9. 【对询问分块】【主席树】bzoj2683 简单题

    对操作序列分块,每S次暴力重建主席树. 当S=sqrt(n*log(n))时,复杂度为O(m*sqrt(n*log(n))). 在线的. #include<cstdio> #include ...

  10. 【分块】bzoj1858 [Scoi2010]序列操作

    分块 Or 线段树 分块的登峰造极之题 每块维护8个值: 包括左端点在内的最长1段: 包括右端点在内的最长1段: 该块内的最长1段: 该块内1的个数: 包括左端点在内的最长0段://这四个是因为可能有 ...