SPI通讯

news2024/10/3 0:57:09

1、介绍

SPI是高速、全双工、同步的通信总线。

SPI应用于存储芯片、AD转换器及LCD中。

同步、异步区别:是否有时钟线,例如SPI、I2C是同步通信,需要用到时钟线,串口是异步通信,没有时钟线。

SPI通信需要四根线:MISO MOSI SCLK(时钟) CS(片选)

 

MISO和MOSI有没有容易搞混的小伙伴,直接看英文记忆。

例如:MISO 英文全称为 Master input slave output,缩写MISO,主机输入从机输出。

2、时序

2、1如何配置LA2016显示波形

以之前开源项目里的触摸屏工程为例,那个工程触摸屏驱动是厂家写好的,把程序上传单片机,连接屏幕,看一下波形。

在LA2016波形仪器上选择四个通道,依次为MISO MOSI SCLK(时钟) CS(片选)。

 

连接四个通道至单片机的对应引脚,点击软件LA2016等待触发,点击屏幕触发,波形如下(没有设置):

 

调试了好久,都没有得到MISO MOSI 两个数据线上的波形,原因:

没有设置LA2016软件关于CPOL和CPHA!!!!!

这里CPOL和CPHA需要找到程序,看程序里是如何编写的,在LA2016波形显示软件上进行对应设置。

找到程序关于SPI初始化部分的函数,如下:

void SPI2_Init(void)    
{
    SPI_InitTypeDef  SPI_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
     
    //配置SPI2管脚
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
​
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_14;    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
    GPIO_Init(GPIOB, &GPIO_InitStructure);  
    
    //SPI2配置选项
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 ,ENABLE);
       
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI2, &SPI_InitStructure);
​
    //使能SPI2
    SPI_Cmd(SPI2, ENABLE);   
}

****时钟极性******

  1. CPOL = 0:时钟空闲IDLE为低电平 0;

  2. CPOL= 1:时钟空闲IDLE为高电平1;

    ****时钟相位******

    1. CPHA= 0:在时钟信号SCK的第一个跳变沿采样;

    2. CPHA= 1:在时钟信号SCK的第二个跳变沿采样;

看程序得知,CPOL =0;CPHA=1,软件上对应配置如下:

 

连接调试仪器与单片机对应引脚,上电,LA2016软件点击等待触发,触摸屏幕产生SPI通信,正确波形如下:

 

 注意:片选信号下降沿触发有效!

选取一小块波形,我们来看下通讯流程:

 

 流程:

1、主设备发起信号,将CS片选信号拉低。

2、主设备发送时钟信号,告诉从设备进行读数据写数据下降沿有效(图中的波形,有的是上升沿)。

3、主设备将要发送的数据发送到数据缓存区,缓存区通过移位寄存器、串行移位寄存器通过MOSI信号线一位一位发送出去,同时MISO将接收到的数据通过移位寄存器一位一位的移到接收缓存区。

4、从机通过自己的通过MISO线将内容发送出去,MOSI接收。

2、2实战看波形

找到正点原子HAL库SPI例子的代码,直接在上面改main函数。

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./USMART/usmart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./BSP/NORFLASH/norflash.h"
#include "./BSP/SPI/spi.h"
​
int main(void)
{
    uint8_t key;
    uint16_t i = 0;
    uint8_t rec_data = 0;
    
    HAL_Init();                         /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    delay_init(72);                     /* 延时初始化 */
    usart_init(115200);                 /* 串口初始化为115200 */
    usmart_dev.init(72);                /* 初始化USMART */
    led_init();                         /* 初始化LED */
    lcd_init();                         /* 初始化LCD */
    key_init();                         /* 初始化按键 */
    norflash_init();
    
    while (1)
    {
        key = key_scan(0);
​
        if (key == KEY1_PRES) /* KEY1按下,写入 */
        {
            NORFLASH_CS(0);
            spi2_read_write_byte(0x06);
            NORFLASH_CS(1);
            
        }
​
    }
}
​

注意看SPI初始化!!!!

 

看程序配置CPOL和CPHA,连接LA2016时配置软件。

测试下我们在main函数中写的代码,把程序上传到单片机,并连接LA2016和单片机引脚,点击触发没看波形如下:

 

最喜欢正点原子写的这个函数,可以同时读写:

uint8_t spi2_read_write_byte(uint8_t data)
{
    uint8_t rec_data = 0;
    
    HAL_SPI_TransmitReceive(&g_spi2_handler, &data, &rec_data, 1, 1000);
    
    return rec_data;
}

测试一下读数据,用一根杜邦线把MISO和MOSI连接起来。

看波形有数据收到!

 

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

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

相关文章

【数据结构】单链表(详解)

【数据结构】单链表(详解) 1.前言1.1本章节重点1.2 什么是单链表1.3 结构体设计1.4结构体传参 2. SList.h展示3. SList.c展示4. 各个接口函数的实现4.1 尾插4.2 打印4.3 头插4.3.1内存开辟函数4.3.2插入 4.4 尾删4.5 头删4.6 查找4.7 给定一个位置在这个…

今天面了个字节跳动拿35K出来的,真是砂纸擦屁股,给我露了一手啊

今年的金三银四已经快要结束了,很多小伙伴收获不错,拿到了心仪的 offer。 各大论坛和社区里也看见不少小伙伴慷慨地分享了常见的面试题和八股文,为此咱这里也统一做一次大整理和大归类,这也算是划重点了。 俗话说得好&#xff0c…

为什么选择学习python?

对于编程初学者来说,python更加简单易学,便于初学者入门~ 学Python之前:这玩意真有传说中那么好么? 学Python之后:唉呀妈呀,真香~ 别人花2天时间处理的Excel数据,你用Python 只花1小时&#…

若依移动端Ruoyi-App——字典使用

1. 引入dict 将若依前后端分离中的dict文件夹拷贝到api的system里 2.在页面中引入方法 import { getDicts } from "/api/system/dict/data"; 3. 前端 <span>{{statusType}}</span> 4. 加载数据字典 export default {data() {return {statusOptions…

LeetCode:剑指 Offer 58 - II. 左旋转字符串

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340; 算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 一、&#x1f331;剑指 Offer 58 - II. 左旋转字符串 题目描述&#xff1a;字符串的左旋…

正则表达式 - 电话号码

正则表达式是描述一组字符串特征的模式&#xff0c;用来匹配特定的字符串。 一、需求 写一个正则表达式匹配电话号码&#xff0c;并且括号、连字符或点号都是可选的。假定合规数据只包含以下15种匹配模式之一&#xff1a; xxxxxxx 8277019xxx.xxxx 82…

【Microsoft Edge】详解 Edge 的扩展程序

Edge 扩展程序 安装与卸载显示与隐藏开启与关闭导入与导出导出导入操作好处与优势 安装与卸载 可从 https://microsoftedge.microsoft.com/addons?hlzh-CN 获取你想要的扩展程序。 也可以使用 Chrome Web Store &#xff0c;但出于某些原因&#xff0c;需要科学上网。 获取后…

初赛-排列组合概念

1.加法原理: 完成一个工程可以有n类办法&#xff0c;a[i](1<i<n) 代表第i类方法的数目。 那么完成这件事共有 S a[1]a[2]...a[n]种不同的方法。 2.乘法原理: 完成一个工程需要分n个步骤&#xff0c;a[i](1<i<n) 代表第i个步骤的不同方法数目。 那么完成这件…

DnsAddressResolverGroupFactory.create(DnsAddressResolverGroupFactory.java:33)

今天处理了一个dubb升级造成的包冲突&#xff0c;记录下&#xff0c;希望能帮到一些有同样问题的小伙伴&#xff0c;并且将自己解决包冲突的想法总结下 背景&#xff1a; 因为dubbo出现安全漏洞&#xff0c;公司的安全组要求将dubbo的版本由2.7.3-SNAPSHOT 升级到 2.7.3.7-RE…

Windows 10, version 22H2 (2023年3月) 简体中文版、英文版下载

Windows 10, version 22H2 (updated March 2023) 简体中文版、英文版下载 Windows 10 22H2 2023 年 3 月更新 Windows 10 是微软公司推出的一款操作系统&#xff0c;是 Windows 系列操作系统的最新版本&#xff0c;于2015年7月正式发布。Windows 10 被设计为既适用于桌面电脑和…

ActiveMQ使用(二):在JavaScript中使用mqtt.js

ActiveMQ使用(二):在JavaScript中使用mqtt.js 1. 环境准备 jQuery-1.10 下载地址:https://www.jsdelivr.com/package/npm/jquery-1.10.2?tabfilesmqtt.js 4.3.7: 下载地址:https://www.jsdelivr.com/package/npm/mqtt 2. 相关代码 <!DOCTYPE html> <html lang&q…

引用【C++初阶】

目录 一、引用 1、概念 2、特性 3、常引用 4、使用常景 5、传值与传引用的效率性能比较 6、指针和引用的区别 一、引用 1、概念 引用不是新定义一个变量&#xff0c;而是给已存在的变量取一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的…

线程方法,生命周期,线程状态,Synchronized,

package com.hspedu.method;/*** author 韩顺平* version 1.0*/ public class ThreadMethod01 {public static void main(String[] args) throws InterruptedException {//测试相关的方法T t new T();t.setName("老韩");t.setPriority(Thread.MIN_PRIORITY);//设置优…

初识网络安全应急响应

初识网络安全应急响应 1.应急响应的基本能力2.应急响应的基本流程 1.应急响应的基本能力 一、数据采集、存储和检索 能对全流量数据协议进行还原&#xff1b;能对还原的数据进行存储&#xff1b;能对存储的数据快速检索。 二、事件发现 能发现高级可持续威胁&#xff08;AP…

【Redis】Redis十大数据类型—集合set

介绍 set类型是一个无序并唯一的键值集合&#xff0c;set的存储顺序不会按照插入的先后顺序进行存储。 一个集合最多可以存储2^32-1个元素。 set类型除了支持集合内的增删改查&#xff0c;同时还支持多个集合取交集、并集、差集。 Set 类型和 List 类型的区别如下&#xff1…

cgroups 实践

CPU 限制 1. 创建测试的 cgroup 在 /sys/fs/cgroup/cpu 下面创建自己的 cgroups 测试目录&#xff0c;该目录会自动创建一些文件&#xff0c;对进程或者线程的控制都可以通过修改这些文件内容自动完成。 tasks&#xff1a;被 cgroup 管理的进程 cpu.cfs_period_us&#xff1a…

多线程(九):JUC组件

在来时juc组件前&#xff0c;我们先把上一章遗漏的部分给补上。 synchronized 实现策略&#xff1a;锁升级&#xff1a; 无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁 还有一个 &#xff1a; 锁消除 锁消除即删除不必要的加锁操作。JVM在运行时&#xff0c;对一些“…

C++内联函数详解

目录 如何定义内联函数&#xff1f; 内联函数的优势 内联函数的缺点 内联函数的使用场景 示例代码 总结 在C中&#xff0c;内联函数是一种特殊的函数&#xff0c;它的作用是在程序编译时将函数的代码直接嵌入到调用该函数的代码中&#xff0c;从而避免了函数调用的开销。这…

C语言 非本地跳转实现native层TryCatch

前言 最近研究native hook的技术&#xff0c;了解到了这个非本地跳转&#xff0c;本文就是介绍他&#xff0c;对于解决native crash非常有用。 非本地跳转介绍 C语言的本地跳转是指goto、break、continue等语句&#xff0c;但是这个语句最大局限就是只能实现函数内部的跳转。…

深度学习 - 40. N-Gram 采样与 Session 数据获取 For EGES

目录 一.引言 二.订单数据预处理 1.数据样例 2.订单数据处理 3.用户 Session 构建 三.构造 sku_id 游走序列 1.获取完整 Session List 2.统计 sku_id 转移词频 3.构建 sku_id 图 4.游走构造 sku 序列 四.商品侧信息预处理 1.读取商品信息 2.Left Join 匹配侧信息 …