【51单片机快速入门指南】5:软件SPI

目录

  • 硬知识
    • SPI协议简介
    • SPI接口介绍
    • SPI接口连接图
    • SPI数据传输方向
    • SPI传输模式
  • 软件SPI程序源码
    • Soft_SPI.c
    • Soft_SPI.h

普中51-单核-A2
STC89C52
Keil uVision V5.29.0.0
PK51 Prof.Developers Kit Version:9.60.0.0
上位机:Vofa+ 1.3.10


       源于软件模拟SPI接口程序代码(4种模式)—— 内陆的咸水鱼,有改动。

硬知识

SPI协议简介

       SPI的通信原理很简单,一般主从方式工作,这种模式通常有一个主设备和一个或多个从设备,通常采用的是4根线,它们是MISO(数据输入,针对主机来说)、MOSI(数据输出,针对主机来说)、SCLK(时钟,主机产生)、CS/SS(片选,一般由主机发送或者直接使能,通常为低电平有效

SPI接口介绍

       SCK:时钟信号,由主设备产生,所以主设备SCK信号为输出模式,从设备的SCK信号为输入模式。
       CS:片选信号,由主设备控制从设备,,所以主设备CS信号为输出模式,从设备的CS信号为输入模式。
       MOSI:主设备数据输出,从设备数据输入,所以主设备MOSI信号为输出模式,从设备的MOSI信号为输入模式。
       MISO:主设备数据输入,从设备数据输出,所以主设备MISO信号为输入模式,从设备的MISO信号为输出模式。

SPI接口连接图

在这里插入图片描述
       注意:MOSI和MISO不能交叉连接(可以把主从机理解为一个整体系统,MOSI为系统主机发送从机接收的数据线,MISO为主机接收从机发送的数据线)

SPI数据传输方向

       SPI作为全双工的的串行通信协议,数据传输时高位在前,低位在后。主机和从机公用由主机产生的SCK信号,所以在每个时钟周期内主机和从机有1bit的数据交换(因为MOSI和MISO数据线上的数据都是在时钟的边沿处被采样)。如下图:
在这里插入图片描述
       SPI协议规定数据采样是在SCK的上升沿或下降沿时刻(由SPI模式决定,下面会说到),观察上图,在SCK的边沿处(上升沿或下降沿),主机会在MISO数据线上采样(接收来从机的数据),从机会在MOSI数据线上采样(接收来自主机的数据),所以每个时钟周期中会有一bit的数据交换。
在这里插入图片描述

SPI传输模式

       SPI总线传输一共有4种模式,这4种模式分别由时钟极性(CPOL)和时钟相位(CPHA)来定义。
在这里插入图片描述
       CPOL:规定了SCK时钟信号空闲状态的电平
       CPHA:规定了数据是在SCK时钟的上升沿还是下降沿被采样
在这里插入图片描述
       模式0:CPOL=0,CPHA =0 SCK空闲为低电平,数据在SCK的上升沿被采样(提取数据)
       模式1:CPOL=0,CPHA =1 SCK空闲为低电平,数据在SCK的下降沿被采样(提取数据)
       模式2:CPOL=1,CPHA =0 SCK空闲为高电平,数据在SCK的下降沿被采样(提取数据)
       模式3:CPOL=1,CPHA =1 SCK空闲为高电平,数据在SCK的上升沿被采样(提取数据)

       以模式0为例:SCK空闲为低电平,数据在SCK的上升沿被采样(提取数据),在SCK的下降沿切换数据线的数据。
在这里插入图片描述
◐在时钟的第1个上升沿(游标1处)(采样点)

       MOSI上数据为1,则在此边沿从机采样(提取)数据为1,采样点在MOSI数据线的中间。

       MISO上数据为0,则在此边沿主机采样(提取)数据为0,采样点在MISO数据线的中间。

◐在时钟的第1个下降沿(游标2处)(切换点)

       MOSI上数据由1切换为0,,数据在时钟下降沿时切换数据。

       MISO上数据由0切换为1,,数据在时钟下降沿时切换数据。

◐在时钟的第2~8个上升沿(采样点),主机在MISO上采样数据,从机在MOSI上采样数据。

◐在时钟的第2~8个下降沿(切换点),主机在MISO上切换数据,从机在MOSI上切换数据

以下内容摘自SPI总线协议及SPI时序图详解 —— Ady Lee
在这里插入图片描述
这里主要详解模式0(CPOL=0,CPHA=0)的时序:
在这里插入图片描述
       我们来关注SCK的第一个时钟周期,在时钟的前沿采样数据(上升沿,第一个时钟沿),在时钟的后沿输出数据(下降沿,第二个时钟沿)。
       首先来看主器件,主器件的输出口(MOSI)输出的数据bit1,在时钟的前沿被从器件采样,那主器件是在何时刻输出bit1的呢?bit1的输出时刻实际上在SCK信号有效以前,比 SCK的上升沿还要早半个时钟周期。bit1的输出时刻与SSEL信号没有关系
       再来看从器件,主器件的输入口MISO同样是在时钟的前沿采样从器件输出的bit1的,那从器件又是在何时刻输出bit1的呢?从器件是在SSEL信号有效后,立即输出bit1,尽管此时SCK信号还没有起效
       关于上面的主器件和从器件输出bit1位的时刻,可以从以下两图中得到验证。
在这里插入图片描述
       注意上图中,CS信号有效后(低电平有效,注意CS下降沿后发生的情况),故意用延时程序延时了一段时间,之后再向数据寄存器写入了要发送的数据,来观察主器件输出bit1的情况(MOSI)。
       可以看出,bit1(值为1)是在SCK信号有效之前的半个时钟周期的时刻开始输出的(与CS信号无关),到了SCK的第一个时钟周期的上升沿正好被从器件采样。
在这里插入图片描述
上图中,注意看CS和MISO信号。我们可以看出,CS信号有效后,从器件立刻输出了bit1(值为1)。
       通常我们进行的spi操作都是16位的。下图记录了第一个字节和第二个字节间的相互衔接的过程。
       第一个字节的最后一位在SCK的上升沿被采样,随后的SCK下降沿,从器件就输出了第二个字节的第一位。
在这里插入图片描述

软件SPI程序源码

Soft_SPI.c

#include "Soft_SPI.h"void SPI_Delay()	//每步的间隔 用于等待电平稳定和控制通讯速率
{}//MOSI拉高 移植时需修改
void MOSI_H()
{SOFT_SPI_MOSI = 1;
}//MOSI拉低 移植时需修改
void MOSI_L()
{SOFT_SPI_MOSI = 0;
}//MISO拉高 移植时需修改
void MISO_H()
{SOFT_SPI_MISO = 1;
}//MISO拉低 移植时需修改
void MISO_L()
{SOFT_SPI_MISO = 0;
}//SCK拉高 移植时需修改
void SPI_SCK_H()
{SOFT_SPI_SCK = 1;
}//SCK拉低 移植时需修改
void SPI_SCK_L()
{SOFT_SPI_SCK = 0;
}//读取MISO电平 移植时需修改
uint8_t MISO_Read()
{SOFT_SPI_MISO = 1;SPI_Delay();return SOFT_SPI_MISO;
}//空闲时时钟极性(CPOL)		0为低电平 1为高电平
//数据有效时钟缘相位(CPHA)	0为奇数缘 1为偶数缘/* CPOL = 0, CPHA = 0, MSB first */
uint8_t SOFT_SPI_RW_MODE0(uint8_t write_dat)
{uint8_t i, read_dat = 0;SPI_SCK_L();for( i = 0; i < 8; i++ ){read_dat <<= 1;  read_dat |= MISO_Read();if(write_dat & 0x80)MOSI_H();  else                    MOSI_L();  write_dat <<= 1;SPI_Delay();SPI_SCK_H(); SPI_Delay();SPI_SCK_L(); }return read_dat;
}/* CPOL=0,CPHA=1, MSB first */
uint8_t SOFT_SPI_RW_MODE1(uint8_t write_dat) 
{uint8_t i, read_dat = 0;SPI_SCK_L();for(i = 0; i < 8; i++)	//循环8次{if(write_dat & 0x80)MOSI_H();		//若最到位为高,则输出高else      MOSI_L();		//若最到位为低,则输出低write_dat <<= 1;	//低一位移位到最高位SPI_Delay();SPI_SCK_H();		//拉高时钟SPI_Delay();read_dat <<= 1;		//数据左移read_dat |= MISO_Read();SPI_SCK_L();		//拉低时钟}return read_dat;		//返回数据
}/* CPOL=1,CPHA=0, MSB first */
uint8_t SOFT_SPI_RW_MODE2(uint8_t write_dat) 
{uint8_t i, read_dat = 0;SPI_SCK_H();for(i = 0; i < 8; i++)	// 循环8次{read_dat <<= 1;     //数据左移read_dat |= MISO_Read();  if(write_dat & 0x80)MOSI_H();		//若最到位为高,则输出高else      MOSI_L();		//若最到位为低,则输出低write_dat <<= 1;	//低一位移位到最高位SPI_Delay();SPI_SCK_L();		//拉低时钟SPI_Delay();SPI_SCK_H();		//拉高时钟}return read_dat;		//返回数据
}/* CPOL = 1, CPHA = 1, MSB first */
uint8_t SOFT_SPI_RW_MODE3(uint8_t write_dat)
{uint8_t i, read_dat = 0;SPI_SCK_H();for( i = 0; i < 8; i++ ){if(write_dat & 0x80)MOSI_H();  else                    MOSI_L();  write_dat <<= 1;SPI_Delay();	SPI_SCK_L(); SPI_Delay();read_dat <<= 1;  read_dat |= MISO_Read(); SPI_SCK_H(); }return read_dat;
}

Soft_SPI.h

#ifndef SOFT_SPI_H_
#define SOFT_SPI_H_#include <STC89C5xRC.H>
#include "stdint.h"sbit SOFT_SPI_SCK	= P3^2;
sbit SOFT_SPI_MOSI	= P1^0;
sbit SOFT_SPI_MISO	= P1^0;//MOSI拉高 移植时需修改
void MOSI_H();
//MOSI拉低 移植时需修改
void MOSI_L();
//MISO拉高 移植时需修改
void MISO_H();
//MISO拉低 移植时需修改
void MISO_L();
//SCK拉高 移植时需修改
void SPI_SCK_H();
//SCK拉低 移植时需修改
void SPI_SCK_L();
//读取MISO电平 移植时需修改
uint8_t MISO_Read();void SPI_Delay();	//每步的间隔 用于等待电平稳定和控制通讯速率uint8_t SOFT_SPI_RW_MODE0(uint8_t write_dat);
uint8_t SOFT_SPI_RW_MODE1(uint8_t write_dat);
uint8_t SOFT_SPI_RW_MODE2(uint8_t write_dat);
uint8_t SOFT_SPI_RW_MODE3(uint8_t write_dat);#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400375.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

svn搭建本地服务端

使用VisualSVN Server来完成,下载地址:https://www.visualsvn.com/server/download/ 我安装的版本是3.3.1,安装的时候选择了标准版本&#xff0c;另外一个版本需要付费(日志跟踪、VDFS等功能)更多可以参考https://www.visualsvn.com/server/licensing/安装完成之后&#xff0c;…

hdu 4612 边连通度缩点+树的最长路径

思路&#xff1a;将以桥为分界的所有连通分支进行缩点&#xff0c;得到一颗树&#xff0c;求出树的直径。再用树上的点减去直径&#xff0c;再减一 #pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #incl…

c++ primer 4.4节练习答案

练习4.13 a) d3.0, i3 b) i3, d3.5 练习4.14 第一个&#xff1a;非法&#xff0c;42是一个右值&#xff0c;右值不能当做左值使用 第二个&#xff1a;返回值总为真 练习4.15 pi是指针类型&#xff0c;不可将int类型指针赋值给int型&#xff0c;可做如下修改 dval ival 0; pi …

详解Ubuntu Server下启动/停止/重启MySQL数据库的三种方式(ubuntu 16.04)

启动mysql&#xff1a; 方式一&#xff1a;sudo /etc/init.d/mysql start 方式二&#xff1a;sudo service mysql start 停止mysql&#xff1a; 方式一&#xff1a;sudo /etc/init.d/mysql stop 方式二&#xff1a;sudo service mysql stop 重启mysql&#xff1a; 方式一…

【51单片机快速入门指南】5.1:SPI与DS1302时钟芯片

目录硬知识DS1302 简介DS1302 使用控制寄存器日历/时钟寄存器DS1302 的读写时序电路设计示例程序DS1302.cDS1302.h测试程序main.c实验现象普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 硬知识 摘自《普中 51 单片机开发攻略》…

006_Select.sql查询语句

--创建一个部门表 CREATE TABLE tb2_dapt(DEPTNO INT PRIMARY KEY, --部门编号DNAME VARCHAR(20) NOT NULL, --部门名称LOC VARCHAR(20) NOT NULL --部门地址 ) --插入数据 INSERT INTO tb2_dapt (DEPTNO, DNAME, LOC) VALUES(10,财务部,北京); INSERT INTO tb2_dapt (DEPTN…

【格局视野】三色需求与工作层次

三色需求 人们的社会经济生活本身就是一个互相交换&#xff0c;价值传递的循环&#xff0c;但这个循环有一个核心&#xff0c;这个核心就是社会大众的需求&#xff0c;也可以称为市场需求&#xff0c;围绕这个需求产生了层级递进的需求关系。 第一个层次是蓝色需求 是最基础的社…

关于linux-Centos 7下mysql 5.7.9的rpm包的安装方式

环境介绍>>>>>>>>>>>>>>>>>> 操作系统&#xff1a;Centos 7.1 mysql数据库版本&#xff1a;mysql5.7.9 mysql官方网站&#xff1a;http://www.mysql.com 原文地址&#xff1a;http://www.cnblogs.com/5201351/p/4912614…

【51单片机快速入门指南】5.2:SPI读取 12位ADC XPT2046 芯片

目录硬知识ADC 简介分辨率转换误差转换速率ADC 转换原理逐次逼近型 ADC双积分型 ADCXPT2046 芯片介绍参考电压内部参考电压外部参考电压输入工作模式单端工作模式差分工作模式温度测量电池电压测量压力测量数字接口笔中断输出转换周期16 时钟周期转换数字时序15 时钟周期转换数…

flask中 app.run(host='0.0.0.0', port=5000, debug=False) 不能用外网ip访问的解决办法

pycharm 2018开启debug模式和修改host&#xff1a; 在Pycharm 2018中&#xff0c;如果想要开启debug模式和更改端口号&#xff0c;则需要编辑项目配置。直接在app.run中更改是无效的。示例图如下&#xff1a; 将 app.run() 改成 app.run(debugFalse) 保存文件&#xff0c…

开发第一个spring boot应用

为什么80%的码农都做不了架构师&#xff1f;>>> 我们来用spring boot开发一个简单的“hello world”web应用&#xff0c;使用maven构建。开始之前&#xff0c;先检查你的java与maven的版本&#xff0c;看是否是spring boot1.3支持的版本&#xff1a; $ java -versi…

机器学习中规则化和模型选择知识

1 问题 模型选择问题&#xff1a;对于一个学习问题&#xff0c;可以有多种模型选择。比如要拟合一组样本点&#xff0c;可以使用线性回归&#xff0c;也可以用多项式回归。那么使用哪种模型好呢&#xff08;能够在偏差和方差之间达到平衡最优&#xff09;&#xff1f; 还有一类…

涛神的城堡

涛神的城堡 Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other) Total Submission(s) : 54 Accepted Submission(s) : 13 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description 涛神有一个城堡给游客参观&#…

【51单片机快速入门指南】5.3:SPI控制晶联讯JLX12864G_08602 LCD屏幕

目录示例程序JLX12864G_08602.cJLX12864G_08602.hJLX12864G_08602_Font.cJLX12864G_08602_Font.h测试程序main.c效果STC12LE5A60S2 12MHz Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 示例程序 stdint.h见【51单片机快速入门指南】1&#xff1a;基础知…

Python flask 开发工具和框架安装

https://www.cnblogs.com/Brambling/p/7124286.html

Android二维码之创建

由于微信的推出二维码走进了我们的生活&#xff0c;并且越来越多的人们正在发挥着自己的想象力去使用它&#xff0c;来方便我们的生活&#xff0c;我曾经听说过一个笑话&#xff0c;当我们死后&#xff0c;墓碑上不再有墓志铭&#xff0c;而会出现一个记录你一生信息的二维码&a…

n个台阶,一个人每次最多走m步,算法实现

今天去公司面试做到这个面试题&#xff0c;想了半天还是想到了用递归&#xff0c;回来重新调整一下代码 public class Climb { private int step; public int total; public Climb(int step) { this.step step; } public void climb(int left){ …

如何开展软件架构之概念架构

如何开展软件架构之概念架构 到目前为止&#xff0c;我们已经完成了需求的分析过程&#xff0c;总结来说&#xff0c;主要的步聚是 一&#xff09;需求结构化&#xff0c; 二&#xff09;分析约束影响 三&#xff09;重点关注质量需求。 那么接下来的阶段则是系统的概念架构了&…

【51单片机快速入门指南】6.1:LCD1602的八线、四线控制及自定义符号,完美兼容Proteus仿真

目录硬知识显示特性接口定义操作时序写操作时序读操作时序寄存器忙标志位BF地址计数器&#xff08;AC&#xff09;显示数据寄存器&#xff08;DDRAM&#xff09;CGROMCGRAM指令清屏指令光标归位指令进入模式设置指令显示开关控制指令设定显示屏或光标移动方向指令功能设定指令设…

在MAC OS 下配置python + Flask ,并支持pyCharm编辑器

https://www.cnblogs.com/lgphp/p/3841098.html 在MAC OS 下配置python Flask ,并支持pyCharm编辑器 flask是一个micro framework &#xff0c;伸缩性很强。可以部署到openshift 的PAAS里。这个框架上手非常快。喜欢的可以试试。 若实在MAC里&#xff0c;python已经默认安装了…