当前位置: 首页 > news >正文

SPI控制8_8点阵屏

协议与硬件概述

SPI

SPI是串行外设接口(Serial Peripheral Interface)的缩写。是一种高速的(10Mbps)的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线。
image.png

引脚介绍

  • SCLK:串行时钟线,用于数据的同步。
  • MOSI(Master Output Slave Input):主机输出数据,从机输入数据。
  • MISO(Master Input Slave Output):主机输入数据,从机输出数据。
  • CS:(芯)片选(择)引脚,引脚低电平,从机工作有效;引脚高电平,从机工作无效。

全双工通信的数据输出和数据输入是用同一个时钟信号同步的。时钟信号由主设备通过SCK脚提供。
主机不能同时与多个从机通信。多机通信时,从机之间共用SCLK、MOSI、MISO三个引脚,主机选定与哪一从机通信是拉低该从机的CS片选信号引脚。
在之前的“读取红外键码”中,需要通过设置GPIO初始为高电平,下降沿触发,通过中断处理函数获取有效数据。
在本文中,不需要配置具体的读取过程,只需要同GPIO_Init一样,创建一个结构体,通过Init方法初始化即可。
只是因为,这款开发板配备了相关的硬件。读写操作由硬件自动完成。
同样情况的还有之前出现的USART,开发板也配备了相关的硬件。写操作是直接通过USART_SendData(USART1,Byte);发送一个字节数据。手动实现的字节流和字符串输出函数,也是在调用这个方法。并没有像“显示红外键码”时那样按位操作。
红外键码中需要实现的操作比较多,是因为开发板没有相关协议的设备和寄存器,那个接收器只是用来接收38K滤波,判断0和1的。所以在读取时,可以用1MHz的TIM频率进行输入捕获,而无需关注信号在空中的38KHz,这一部分由硬件已经完成了。

MAX7219

LED点阵屏配备了MAX7219驱动电路。
通过SPI发送的数据就需要这一部分解释到点阵屏上。
硬件对外只暴露了5根线:VCC、GND、DIN、CS、CLK。
只有DIN没有提过:串行数据输入端。
其实就是MOSI,点阵屏没必要向主机发送数据,所以就省掉了MISO这根线。
image.png

  • 在SPI通信中,SDI通常是输出,SDO是输入。

接线时需要将点阵屏的DIN连接到SPISPI_SDI引脚,SPISPI_SDO引脚闲置即可,因为用不到读入数据。

MAX7219和单片计算机连接有三条引线(DIN、CLK、LOAD),采用16位数据串行移位接收方式。即单片机将16位二进制数逐位发送到DIN端,在CLK上升沿到来前准备就绪,CLK的每个上升沿将一位数据移入MAX7219内移位寄存器,当16位数据移入完,在LOAD引脚信号上升沿将16位数据装入MAX7219内的相应位置,在MAX7219内部硬件动态扫描显示控制电路作用下实现动态显示。

文字中的LOAD指的就是原理图中的CS。
image.png
MAX7219是高位先行。先发送的第一个字节会作为地址,将第二个字节的数据写入到地址指向的寄存器。
接下来要做的,就是通过SPI协议,发送两个字节数据,第一个字节是地址,第二个字节是数据。

实现SPI控制LED点阵

SPI部分

SPI并没有直接控制灯的高低电平,而是告诉从机,让从机去实现。

初始化GPIO

先在原理图中找到对应引脚的接口:
image.png

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;//MISO
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);//SCK MOSI
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_7);

需要注意的就是:

  • 原理图的SPO对应SPI协议的MISO,而非MOSI。

配置SPI

前面提到了,SPI已经被集成到这款开发板中,我们不需要手动去实现具体的位操作过程。
只需要创建一个SPI_InitTypeDef类型的结构体,把结构体的配置项都给填上就可以。

SPI_InitTypeDef	SPI_InitStructure;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA  = SPI_CPHA_1Edge; 
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_Init(SPI1,&SPI_InitStructure);SPI_Cmd(SPI1,ENABLE);

上面的配置项需要在主机和从机之间提前约定好,才能有效地通信。
对于从机部分,已经焊死了。
我们需要对照从机的文档,对主机进行配置。
通过时钟极性CPOL和时钟相位CPHA来控制主设备的通信模式。
时钟极性CPOL定义时钟空闲状态的电平:

  • CPOL=0:表示SCLK为0时处于空闲态,高电平时为有效态。
  • CPOL=1:表示SCLK为1时处于空闲态,低电平时为有效态。

时钟相位CPHA定义数据的采集时间:

  • CPHA=0:在时钟的第1个跳变沿进行数据采样,第2个边沿发送数据。
  • CPHA=1:在时钟的第2个跳变沿进行数据采样,第1个边沿发送数据。

这两个选项需要对照从机的手册进行配置。
SPI_BaudRatePrescaler:波特率预分频器。SPI挂载在APB2上,为32MHz,需要调整到10Mhz以下。256分频也可以,因为用不到那么快的速度。
image.png
时序图中,空闲状态下,CLK是低电平,第一个上升沿将D15读入:

  • SPI_CPOL_LowSPI_CPHA_1Edge

在时序图中,先到达的是D15,也就是高位。
主机数据的发送顺序也应是先发送高位,配置为SPI_FirstBit_MSB
SPI_CRCPolynomial填写的是CRC校验公示的因子,设置为随机正数。
SPI_NSS设置由硬件控制还是软件控制。在此设置为软件(据课程老师说更常用)。

发送数据

这是SPI部分,看上去跟之前写的USART没有什么区别。

void SPI1_WriteByte(uint8_t TxData)
{while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == RESET);SPI_I2S_SendData(SPI1,TxData);
}

MAX7219部分

上面只是SPI方面的配置和使用。SPI是通信协议,我们要通过这个协议来告诉从机改干什么。
最开始有提到过,但从未使用的CS,现在有用了:在需要通信时拉低,告诉从机,传输要开始了。
需要先初始化相关的引脚:

void MAX7219_CS_Init()
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef	GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_SetBits(GPIOA,GPIO_Pin_4);
}

利用位带修改引脚的值。

void Write_MAX7219(uint8_t addr,uint8_t data)
{PAout(4) = 0;SPI1_WriteByte(addr);SPI1_WriteByte(data);Delay_ms(1);PAout(4) = 1;
}

写完数据,从机未必成功读完,需要给从机一点时间响应。
写成发送两次8字节,是因为这样更加直观。

设置显示选项

点阵屏的亮度、开关也可以设置。
在板载的硬件中,可以通过stm32提供的库函数修改。
在这种外设条件下,主机和从机之间的联系方式只有目前的SPI。
通过SPI发送2字节数据,第一个字节指定地址,第二个字节指定该地址填入的数据。
各内部功能寄存器含义如下:

  • 停机寄存器(地址0CH):当D0=0时,MAX721处于停机状态;当D0=1时,处于正常工作状态。
  • 显示测试寄存器(地址0FH):当D0=0时,MAX7219按设定模式正常工作;当D0=1时,处于测试状态。在该状态下,不管MAX7219处于什么模式,全部LED将按最大亮度显示。
  • 亮度寄存器(地址0AH):亮度可以用硬件和软件两种方法调节。亮度寄存器中的D0~D3位可以控制LED显示器的亮度。
  • 扫描界限寄存器(地址0BH):该寄存器中D0~D3位数据设定值为0~7H,设定值表示显示器动态扫描个数位1~8。
  • 译码方式寄存器(地址09H):该寄存器的8位二进制数的各位分别控制8个LED显示器的译码方式。当高电平时,选择BCD-B译码模式,当低电平时选择不译码模式(即送来数据为字型码)。
  • 内部RAM地址01~08H分别对应于DIG0~DIG7。

也就是说,通过SPI协议向指定的位置写值,实现修改设置和数据。

void MAX7219_Init()
{SPI1_Init();MAX7219_CS_Init();Write_MAX7219(0x0C,0x01);Write_MAX7219(0x0F,0x00);Write_MAX7219(0x0A,0x0f);Write_MAX7219(0x0B,0x07);Write_MAX7219(0x09,0x00);
}

对照上面的寄存器含义,该代码的含义为:

  • 停机寄存器:正常工作状态
  • 测试寄存器:按设定正常工作
  • 亮度寄存器:最大亮度显示
  • 扫描界限寄存器:显示到第8列,即全部显示
  • 译码方式寄存器:不译码,送来什么就显示什么

主函数显示笑脸

不同于点亮数码管。点亮数码管需要快速刷新,在一个瞬间只能点亮一个数字。停止刷新就不再显示。
该点阵屏的点亮是通过往寄存器写值,刷新显示操作交由外设硬件。只要寄存器值不变,现实的内容就不变 。我们只需要写一次数据即可。

uint8_t smile[8] = {0x3C,0x42,0xA5,0x81,0xA5,0x99,0x42,0x3C};
int main(void)
{MAX7219_Init();uint8_t i = 0;for(i = 1; i <=8; i++){Write_MAX7219(i,smile[i-1]);}while(1){}
}

IMG_20240215_221253.HEIC

参考

  • MAX7219点阵原理图.pdf
  • MAX7219中文.pdf
  • MAX7219原理及其应用.pdf
  • stm32 使用说明+笔记(必读).pdf
  • 32版开发板原理图.pdf

相关文章:

SPI控制8_8点阵屏

协议与硬件概述 SPI SPI是串行外设接口&#xff08;Serial Peripheral Interface&#xff09;的缩写。是一种高速的&#xff08;10Mbps&#xff09;的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;并且在芯片的管脚上只占用四根线。 引脚介绍 SCLK&#xff1a;…...

2.10

头文件&#xff1a; #include <sqlite3.h> 编译时候要加上-lsqlite3 gcc a.c -lsqlite3 1&#xff09;sqlite3_open 打开一个数据库&#xff0c;如果数据库不存在&#xff0c;则创建一个数据库 2&#xff09;sqlite3_close 关闭数据库&#xff0c;断开句柄所拥有的资…...

计算机服务器中了360后缀勒索病毒怎么办?360后缀勒索病毒处理流程

网络技术的不断应用与发展&#xff0c;为企业的生产运营提供了有利保障&#xff0c;越来越多的企业走向数字化办公模式&#xff0c;并且企业的发展离不开数据支撑&#xff0c;重视数据安全成为了众多企业关心的主要话题。春节前后&#xff0c;云天数据恢复中心接到很多企业的求…...

BigDecimal的常用API

BigDecimal用于解决浮点型运算时结果出现失真的问题。 这里0.20.1等于0.3就出现了失真 import java.math.BigDecimal; import java.math.RoundingMode;public class Test {public static void main(String[] args) {//BigDeciaml的使用&#xff1a;解决小数运算失真的问题doub…...

Android---Jetpack Compose学习005

动画 1. 简单值动画 示例&#xff1a;背景颜色在紫色和绿色之间&#xff0c;以动画形式切换。使用 animateColorAsState() val backgroundColor by animateColorAsState(if (tabPage TabPage.Home) Purple100 else Green300) 该句代码中&#xff0c;有一个 backgroundColo…...

安卓价值1-如何在电脑上运行ADB

ADB&#xff08;Android Debug Bridge&#xff09;是Android平台的调试工具&#xff0c;它是一个命令行工具&#xff0c;用于与连接到计算机的Android设备进行通信和控制。ADB提供了一系列命令&#xff0c;允许开发人员执行各种操作&#xff0c;包括但不限于&#xff1a; 1. 安…...

第三百四十七回

文章目录 1. 概念介绍2. 原理与方法2.1 知识对比2.2 使用方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"加密包crypto"相关的内容&#xff0c;本章回中将介绍characters包.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 在项目中会遇到获取字…...

23种设计模式之原型模式

目录 什么是原型模式 为什么使用原型模式 原型模式的基本结构 原型模式的实现步骤 实现代码&#xff08;含注释&#xff09; 使用场景 什么是原型模式 原型模式是一种创建型设计模式&#xff0c;该模式的核心思想是基于现有的对象创建新的对象&#xff0c;而不是从头开…...

揭秘Angular世界的奥秘:全面提升你的前端开发技能!

介绍&#xff1a;Angular是一个由Google维护的开源JavaScript框架&#xff0c;专为构建Web应用程序而设计&#xff0c;特别适合开发大型单页应用&#xff08;SPA&#xff09;。以下是对Angular的详细介绍&#xff1a; 技术栈&#xff1a;Angular使用HTML作为模板语言&#xff0…...

【开源】SpringBoot框架开发企业项目合同信息系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 合同审批模块2.3 合同签订模块2.4 合同预警模块2.5 数据可视化模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 合同审批表3.2.2 合同签订表3.2.3 合同预警表 四、系统展示五、核心代码5.1 查询合同…...

高斯伪谱C++封装库开源!

Windows x64/86 C无依赖运行高斯伪谱法求解最优控制问题&#xff0c;你只需要ElegantGP! Author: Y. F. Zhang His Github: https://github.com/ZYunfeii 写在前面 这个库在你下载它的那一时刻起不再依赖任何其他代码&#xff0c;直接可用来构建C的最优控制问题并进行求解。…...

Spring + Tomcat项目中nacos配置中文乱码问题解决

实际工作的时候碰到了nacos中文乱码的问题&#xff0c;一顿排查最终还是调源码解决了。下面为具体的源码流程&#xff0c;有碰到的可以参考下。 对于nacos配置来说&#xff0c;初始主要源码就在NacosConfigService类中。里面有初始化获取配置content以及设置对应监听器的操作。…...

Unity SRP 管线【第十讲:SRP/URP 图形API】

Unity 封装的图形API 文章目录 Unity 封装的图形API一、 CommandBuffer 要执行的图形命令列表1. CommandBuffer 属性2. CommandBuffer 常用图形API&#xff08;方法&#xff09;(1)设置(2)获取临时纹理 GetTemporaryRT以及释放(3)设置纹理为渲染目标 SetRenderTarget(4)Command…...

使用playwright进行自动化端到端测试

项目希望能接入自动化端到端测试提高可靠性&#xff0c;发现微软的 playwright 还挺好用的&#xff0c;推荐一下&#xff0c;顺便说下遇到的一些难点以及最佳实践。 难点 登录 项目不能帐号密码登录&#xff0c;只能扫二维码 临时方案是先自己扫码保存 cookie 用于测试&#…...

ES实战-相关性搜索

ES打分机制 1.TF-IDF 词频-逆文档频率 2.Okapi BM25 3.随机性分歧- DFR相似度 4.基于信息 - IB相似度 5.LM Dirichlet 相似度 6.LM Jelinek Mercer相似度 解释一个查询的结果集 curl -XPOST localhost:9200/get-together/_search?pretty -H Content-Type: application/json -…...

MQTT的学习与应用

文章目录 一、什么是MQTT二、MQTT协议特点三、MQTT应用领域四、安装Mosquitto五、如何学习 MQTT 一、什么是MQTT MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种轻量级的消息传输协议&#xff0c;设计用于在低带宽、不稳定的网络环境中进行高效的通信…...

编译原理实验1——词法分析(python实现)

文章目录 实验目的实现定义单词对应的种别码定义输出形式&#xff1a;三元式python代码实现运行结果检错处理 总结 实验目的 输入一个C语言代码串&#xff0c;输出单词流&#xff0c;识别对象包含关键字、标识符、整型浮点型字符串型常数、科学计数法、操作符和标点、注释等等。…...

C语言——oj刷题——模拟实现库函数strlen

目录 方法一&#xff1a;迭代法 方法二&#xff1a;递归法 方法三&#xff1a;指针算术法 方法四&#xff1a;汇编指令法 当我们使用C语言进行字符串操作时&#xff0c;经常会用到库函数strlen来获取字符串的长度。strlen函数的作用是计算一个以null字符结尾的字符串的长度…...

对进程与线程的理解

目录 1、进程/任务&#xff08;Process/Task&#xff09; 2、进程控制块抽象(PCB Process Control Block) 2.1、PCB重要属性 2.2、PCB中支持进程调度的一些属性 3、 内存分配 —— 内存管理&#xff08;Memory Manage&#xff09; 4、线程&#xff08;Thread&#xff09;…...

「数据结构」线性表

定义和基本操作 定义&#xff1a;相同数据类型的 n ( n ≥ 0 ) n(n \ge 0) n(n≥0)个数据元素的有限序列&#xff0c;其中n为表长&#xff0c;当n0时线性表是一个空表一般表示&#xff1a; L ( a 1 , a 2 , … … , a i , a i 1 , a n ) L(a_1,a_2,……,a_i,a_{i1},a_n) L(a…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

若依登录用户名和密码加密

/*** 获取公钥&#xff1a;前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...

32单片机——基本定时器

STM32F103有众多的定时器&#xff0c;其中包括2个基本定时器&#xff08;TIM6和TIM7&#xff09;、4个通用定时器&#xff08;TIM2~TIM5&#xff09;、2个高级控制定时器&#xff08;TIM1和TIM8&#xff09;&#xff0c;这些定时器彼此完全独立&#xff0c;不共享任何资源 1、定…...

Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解

文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一&#xff1a;HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二&#xff1a;Floyd 快慢指针法&#xff08;…...

Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解

文章目录 一、开启慢查询日志&#xff0c;定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...

C++ 类基础:封装、继承、多态与多线程模板实现

前言 C 是一门强大的面向对象编程语言&#xff0c;而类&#xff08;Class&#xff09;作为其核心特性之一&#xff0c;是理解和使用 C 的关键。本文将深入探讨 C 类的基本特性&#xff0c;包括封装、继承和多态&#xff0c;同时讨论类中的权限控制&#xff0c;并展示如何使用类…...

比较数据迁移后MySQL数据库和ClickHouse数据仓库中的表

设计一个MySQL数据库和Clickhouse数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...