【STM32项目实战】一文了解单片机的SPI驱动外设功能
前言:在前面我有文章介绍了关于单片机的SPI外设CUBEMX配置,但是要想使用好SPI这个外设我们还必须对其原理性的时序有一个详细的了解,所以这篇文章就补充一下SPI比较偏向底层的时序性的逻辑。
1,SPI简介
SPI是MCU最常见的对外通信口之一,由摩托罗拉在上世纪80年代中开发,用于嵌入式系统中器件之间的短距离数据通信,标准模式使用四条信号线。目前常见的应用器件有:LCD模组、以太网模块、SPI串行Flash和很多传感器等,大部分SD卡都具有SPI操作模式
其采用主从模式(Master Slave)架构:支持多 slave 模式应用,般仅支持单 Master。时钟由 Master 控制,在时钟移位脉冲下,数据按位传输,高位在前,低位在后(MSB frst):SPI接口有2根单向数据线,为全双工通信,目前应用中的数据速率可达几 Mbps 的水平。
总结一下关键特点:
-
同步通信:通信双方共享一个时钟信号
-
全双工传输:支持同时发送与接收
-
速度快:常见支持几MHz甚至几十MHz
-
多从机支持:主机通过CS片选控制多个从设备
2,SPI的物理接口
文章上面第一个章节我们有提到SPI的标准模式使用四条信号线,比如下面这个图,其中的CSS片选线如果只有一个从机就可以忽略不计(单从机也就是说可以使用三根线),如果有多个从机那么CSS片选线的数量等于从机的数量
主从机内部结构简化图:
3,SPI通信原理详解
按照时钟极性和相位(CPOL & CPHA)可以将SPI协议分成4种模式:
值得注意的是:发送和接收必须使用相同的时钟配置,否则会出现数据偏移或失真。
详细的4种模式的时序示意图:
4,MCU中的SPI外设结构
以 STM32 MCU 为例,SPI模块一般包括以下部分:
-
寄存器控制:用于配置波特率、主从模式、CPOL/CPHA等参数
-
TX/RX 缓冲器:发送与接收使用各自的 FIFO
-
状态寄存器:可判断是否发送完成、是否接收到数据等
-
中断控制:可设置中断方式发送/接收
-
DMA支持:支持高速数据传输而不占用CPU
常用寄存器:
-
SPI_CR1
:控制寄存器(如主从、CPOL、CPHA) -
SPI_SR
:状态寄存器(如TXE/RXNE位) -
SPI_DR
:数据寄存器(发送/接收)
当然,想了解MCU的SPI外设的特性,主要还是得看对应某一款芯片的参考手册。下面就以STM32F4的参考手册为例。
SPI框图:
5,基于STM32G474的SPI配置示例
都是CUBEMX生成的,大家看看参考一下就可以了。。。
spi.c
/* USER CODE BEGIN Header */
/********************************************************************************* @file spi.c* @brief This file provides code for the configuration* of the SPI instances.******************************************************************************* @attention** Copyright (c) 2025 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "spi.h"/* USER CODE BEGIN 0 *//* USER CODE END 0 */SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_tx;
DMA_HandleTypeDef hdma_spi1_rx;// #define SPI_DMA_BUFFER_SIZE 16// uint8_t spi_tx_buffer[SPI_DMA_BUFFER_SIZE];
// uint8_t spi_rx_buffer[SPI_DMA_BUFFER_SIZE];
/* spi1 init function */
void MX_SPI1_Init(void)
{/* USER CODE BEGIN spi1_Init 0 *//* USER CODE END spi1_Init 0 *//* USER CODE BEGIN spi1_Init 1 *//* USER CODE END spi1_Init 1 */hspi1.Instance = SPI1;hspi1.Init.Mode = SPI_MODE_MASTER;hspi1.Init.Direction = SPI_DIRECTION_2LINES;hspi1.Init.DataSize = SPI_DATASIZE_16BIT;hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;hspi1.Init.NSS = SPI_NSS_SOFT;hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;hspi1.Init.TIMode = SPI_TIMODE_DISABLE;hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;hspi1.Init.CRCPolynomial = 7;hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;if (HAL_SPI_Init(&hspi1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN SPI1_Init 2 */}void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(spiHandle->Instance==SPI1){/* USER CODE BEGIN SPI1_MspInit 0 *//* USER CODE END SPI1_MspInit 0 *//* SPI1 clock enable */__HAL_RCC_SPI1_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_DMA1_CLK_ENABLE();/**SPI1 GPIO ConfigurationPB5 ------> SPI1_SCKPB6 ------> SPI1_MISOPB7 ------> SPI1_MOSI*/GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* USER CODE BEGIN SPI1_MspInit 1 *//* SPI1 interrupt Init */HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);HAL_NVIC_EnableIRQ(SPI1_IRQn);/* USER CODE END SPI1_MspInit 1 */}
}void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{if(spiHandle->Instance==SPI1){/* USER CODE BEGIN SPI1_MspDeInit 0 *//* USER CODE END SPI1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_SPI1_CLK_DISABLE();/**SPI1 GPIO ConfigurationPB5 ------> SPI1_SCKPB6 ------> SPI1_MISOPB7 ------> SPI1_MOSI*/HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);/* SPI1 interrupt Deinit */HAL_NVIC_DisableIRQ(SPI1_IRQn);/* USER CODE BEGIN SPI1_MspDeInit 1 *//* USER CODE END SPI1_MspDeInit 1 */}
}/* USER CODE BEGIN 1 */
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{if (hspi == &hspi1){// printf("SPI1 DMA Transfer Completed!\r\n");}
}/* USER CODE END 1 */
spi.h
/* USER CODE BEGIN Header */
/********************************************************************************* @file spi.h* @brief This file contains all the function prototypes for* the spi.c file******************************************************************************* @attention** Copyright (c) 2025 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __SPI_H__
#define __SPI_H__#ifdef __cplusplus
extern "C" {
#endif/* Includes ------------------------------------------------------------------*/
#include "main.h"/* USER CODE BEGIN Includes *//* USER CODE END Includes */extern SPI_HandleTypeDef hspi1;
extern DMA_HandleTypeDef hdma_spi1_tx;
extern DMA_HandleTypeDef hdma_spi1_rx;/* USER CODE BEGIN Private defines *//* USER CODE END Private defines */void MX_SPI1_Init(void);/* USER CODE BEGIN Prototypes *//* USER CODE END Prototypes */#ifdef __cplusplus
}
#endif#endif /* __SPI_H__ */
完结。。。
相关文章:
【STM32项目实战】一文了解单片机的SPI驱动外设功能
前言:在前面我有文章介绍了关于单片机的SPI外设CUBEMX配置,但是要想使用好SPI这个外设我们还必须对其原理性的时序有一个详细的了解,所以这篇文章就补充一下SPI比较偏向底层的时序性的逻辑。 1,SPI简介 SPI是MCU最常见的对外通信…...
C++学习之路,从0到精通的征途:priority_queue类的模拟实现
目录 一.priority_queue的介绍 二.仿函数 1.仿函数的介绍 2.仿函数的特点 3.实现两个简单的仿函数 三.priority_queue的接口实现 1.成员变量 2.push 3.pop 4.top 5.size 6.empty 7.构造函数 四.代码总览 priority_queue.h test.cpp 一.priority_queue的介绍 源…...
智能交互电子沙盘,重塑未来指挥体系
在军事演习室、应急指挥中心或城市规划馆中,传统沙盘曾是不可或缺的工具。然而,随着数字化浪潮席卷,“纸上谈兵”式的静态模型已无法满足现代指挥对实时性、交互性、立体化的需求。智能交互电子沙盘系统应运而生,它融合了GIS地理信…...
银河麒麟安装QT
1、从官网现在安装包 上述是商业版,免费版如下,有两种可以选择,分别是Linux x64 和 LinuxARM64 . 然后在线安装即可,和Windows系统安装步骤一样。...
Vue 实现 Hls、Flv 协议视频播放
在当今的互联网内容生态中,视频已成为重要的信息传播载体。Hls(HTTP Live Streaming)和 Flv(Flash Video)作为广泛使用的视频传输协议,分别在移动端和 Web 端有着出色的表现。对于使用 Vue 框架进行开发的项…...
javascript:void(0) 是一个常见的 JavaScript 伪协议
javascript:void(0) 是一个常见的 JavaScript 伪协议,下面从几个方面详细解释其含义和用途。 基本含义 javascript: 是一种伪协议,它告诉浏览器后面跟随的是一段 JavaScript 代码。void 是 JavaScript 中的一个操作符,void(0) 的作用是对给…...
suna界面实现原理分析(三):Terminal工具调用可视化
suna目前的agent执行可视化界面主要有个实时界面,一个是前面介绍的浏览器访问界面,分析参考:suna工具调用可视化界面实现原理分析(二)-CSDN博客 下面的Terminal界面,对应的分析参考: 前端知识-…...
ai大模型学习1
一、监督学习:老师带学生的模式 核心机制:模型像学生一样,通过“带答案的习题”(即带标签的数据集)学习规律。例如,给模型看1000张标有“猫”“狗”的图片,让它学会区分两者的特征24。 典…...
精益数据分析(43/126):媒体网站商业模式的盈利与指标解析
精益数据分析(43/126):媒体网站商业模式的盈利与指标解析 在创业和数据分析的学习旅程中,我们不断探索各种商业模式的奥秘,今天让我们一同深入《精益数据分析》,聚焦媒体网站商业模式,剖析其盈…...
深度学习:图神经网络GNN、GCN及其在推荐系统的应用
什么是图(Graph)? 在数学和计算机科学中,图 (Graph) 是一种抽象数据结构,用于表示对象之间的成对关系。一个图通常定义为一个有序对 G (V, E),其中: V 是 顶点 (Vertices) 或 节点 (Nodes) 的…...
深入理解 Web 架构:从基础到实践
文章目录 引言一、Web 架构基础概念客户端 - 服务器模型HTTP 协议 二、常见 Web 架构模式单体架构微服务架构 三、Web 架构常见问题及解决方法性能问题安全问题 四、Web 架构思维导图五、总结 引言 在当今数字化的时代,Web 应用无处不在。无论是社交媒体平台、电子商…...
蓝桥杯-通电(最小生成树java)
题目 思路 这道题其实也挺容易看出来是最小生成树的。我当时做的时候确实是能看出来是考的最小生成树,union(),find()那些方法我也能写出来,但是,我完全不知道怎么去利用给你的输入数据,去求解题目,也就是知…...
代码随想录算法训练营第60期第二十八天打卡
今天我们继续回溯算法章节,昨天我们重点讲的是组合问题,我们完美使用递归三部曲以及递归回溯相结合的方法来解决,当然昨天最有难度的还是去重操作,那个大家要多思考一下,那么今天我们就继续探讨回溯算法。 第一题对应…...
vscode远程服务器连接----过程尝试写入的管道不存在
通过跳板机连接远程服务器时,报错---过程尝试写入的管道不存在 过程尝试写入的管道不存在报错解决报错内容解决方法1. 测试网络连接连接是否正常2. 检查跳板机并打开权限3. 通过跳板机登录到目标服务器4.配置文件范例 注:校外连接学校内网服务器报错 过程…...
C++ - 仿 RabbitMQ 实现消息队列(1)(环境搭建)
C - 仿 RabbitMQ 实现消息队列(1)(环境搭建) 什么是消息队列核心特点核心组件工作原理常见消息队列实现应用场景优缺点 项目配置开发环境技术选型 更换软件源安装一些工具安装epel 软件源安装 lrzsz 传输工具安装git安装 cmake安装…...
多模态核心模型
1.BLIP的原理? BLIP是一种统一视觉语言理解和生成的预训练模型。BLIP的特点在于它采用了一种编码器-解码器混合架构(MED),并且引入了CapFilt机制来提高数据质量和模型性能。BLIP的主要组成部分包括: MED架构:包括单模态编码器、…...
Kubernetes笔记(1)Kubernetes入门
Kubernetes入门 一、容器技术二、Kubernetes介绍1. Kubernetes核心资源2. Kubernetes集群架构2.1 Master2.2 Node 一、容器技术 随着技术发展,应用程序的部署经历了从物理机到虚拟机,再到容器的转变。 物理机:物理机会运行多个程序…...
【coze】意图识别(售前售后问题、搜索引擎去广告)
【coze】(售前售后问题、搜索引擎去广告) 1、创建意图识别工作流(1)创建工作流(2)添加意图识别节点(3)配置意图识别节点(4)运行看效果(5ÿ…...
Vue3 中用 canvas 封装抽奖转盘组件:设定中奖概率及奖项图标和名称
在 Web 应用开发中,抽奖功能是提升用户参与度的常用手段。使用 Vue3 结合 canvas 技术,我们可以轻松实现一个高度自定义的抽奖转盘组件,不仅能设定中奖概率,还能灵活配置奖项图标和名称。本文将详细介绍该组件的实现原理、步骤&am…...
vue3+vite+AI大模型实现谷歌插件-web诊断
vue3viteAI大模型实现谷歌插件-web诊断 一、前言二、实现思路1、功模块构图2、数据交互图 三、技术栈简介1、Web端2、服务端 四、主要功能实现1、Web端【1】谷歌插件vue全局配置文件【2】加载web诊断工具至当前页面【3】全局捕获异常错误 2、Server端【1】websock管理模块【2】…...
高频PCB设计如何选择PCB层数?
以四层板为例,可以第一层和第二层画信号,作为信号层。 第三层可以走电源,然后第四层走GND 但是更可以第一层和第三层画信号。第二层可以走电源,然后第四层走GND 用中间的电源层以及地层可以起到屏蔽的作用,有效降低寄…...
第100+40步 ChatGPT学习:R语言实现多轮建模
回顾一下什么叫多轮建模: 要综合判断一个模型好不好,一次随机抽样是不行的,得多次抽样建模,看看整体的性能如何才行(特别是对于这种小训练集)。 所以我的思路是,随机抽取训练集和验证集2000次…...
DolphinScheduler-3.2.0集群部署教程
详见: DolphinScheduler-3.2.0集群部署教程Centos7 DolphinScheduler集群部署...
如何设计Kafka的高可用跨机房容灾方案?(需要实战,未实战,纯理论)
1. 双活多中心架构设计 startuml 机房A <--> [Kafka Cluster A] : 万兆光纤 机房B <--> [Kafka Cluster B] : 专线网络 机房C <--> [Kafka Cluster C] : VPN隧道[Kafka Cluster A] <-.-> [Kafka Cluster B] : MirrorMaker2双向镜像 [Kafka Cluster B]…...
[人机交互]协作与通信的设计
零.要点 – 解释协作与通信的含义 – 描述人们在协作与通信中使用的社会机制的主要类型 – 概述存在的各种群件系统 – 讨论学科研究和与社交相关的理论,对设计的启示 一.解释协作与通信的含义 1.1什么是通信 通信是个体之间的信息交换的过程 – 按照所 交换信息的…...
LXwhat-嘉立创
一 电路板简介 什么是PCB? 印刷电路板 什么是SMT? 表面贴装技术 有关电路板的几个专业名词 覆铜腐蚀走线多层板 为什么要画电路板? 杜邦线:接线杂乱、虚接、有可能短路洞洞板:考验焊功(虚焊)、异型元器件不适配自己画板:整齐有序、适配异型元器件、紧凑优雅、有成就感(输…...
决 策 树
1 决策树模型 假如你正在运营一家猫咪领养中心,并拥有一些特征数据,你想训练一个分类器来快速判断一只动物是否为猫。这里有十个训练样本,有关于动物耳朵形状、面部形状、是否有胡须的特征,你想要预测这种动物是否为猫࿱…...
ts axios中报 Property ‘code‘ does not exist on type ‘AxiosResponse<any, any>‘
ts语法有严格的格式,如果我们在处理响应数据时,出现了axios响应中非默认字段,就会出现标题那样的警告,我们可以通过创建axios.dt.ts解决这个问题 下面是我在开发中遇到的警告,code并不是axios默认返回的字段࿰…...
【AI】用AI将文档、文字一键生成PPT的方法(百度的自由画布版)
前提: 最近看了个书,周末要参加读书会,要分享这本书的内容。一般来说,我都是写好了内容文档,然后在网上找一些模板套上去。 最近发现,有些网站已经可以按照文档,自动生成PPT模板了,里…...
爬虫技术-利用Python和Selenium批量下载动态渲染网页中的标准文本文件
近日工作需要整理信息安全的各项标准文件,这些文件通常发布在在官方网站,供社会各界下载和参考。 这些页面中,标准文本文件常以Word(.doc/.docx)或PDF格式提供下载。由于文件数量庞大,手动逐条点击下载效率…...
CUDA编程 - 如何在 GPU 上使用 C++ 函数重载 - cppOverload
这里写目录标题 一、完整代码与例程目的二、代码拆解与复用 2.1、函数重载: 2.2、函数指针声明: 2.3、函数指针赋值与内核启动: 2.4、CUDA API调用:2.4.1、cudaFuncSetCacheConfig:2.4.2、cud…...
AI教你学VUE——Gemini版
前端开发学习路线图 (针对编程新手,主攻 Vue 框架) 总原则:先夯实基础,再深入框架。 想象一下建房子,地基不牢,上面的高楼(框架)是盖不起来的。HTML、CSS、JavaScript 就是前端的地基。 阶段一…...
力扣热题100,力扣49.字母异位词分组力扣128.最长连续序列力扣.盛水最多的容器力扣42.接雨水(单调栈)
目录 力扣49.字母异位词分组 力扣128.最长连续序列 力扣.盛水最多的容器 力扣42.接雨水(单调栈) 1.包的命名规范: java的命名规范 全部采用小写 结尾不能加负数 声明包: 位置必须在首行 类: 字母数字下划线,美元符号 不能数字开头 不能有中文 不能以关键字命名 区…...
react naive 网络框架源码解析
本文取 react native 两个区别很大的版本做分析(0.76.5、0.53.3) 一、0.76.5 版fetch 全流程排查 1、JS 端的实现 随手写一个fetch,点开。 我们这里常用的还是手机端,因此选择 react-native,react-native-windows …...
DID在元宇宙的应用爆发:数字身份资产化与跨平台迁移——解析Decentraland等项目的虚拟身份全链路实现
元宇宙的兴起催生了多维度的数字身份需求,但传统虚拟身份系统受限于中心化架构,面临数据孤岛、身份碎片化、资产归属模糊等核心挑战。本文以Decentraland、The Sandbox、Somnium Space等顶级元宇宙平台为研究对象,探讨去中心化身份࿰…...
MySQL的内置函数与复杂查询
目录 前言 一、聚合函数 1.1日期函数 1.2字符串函数 1.3数学函数 1.4其它函数 二、关键字周边 2.1关键字的生效顺序 2.2数据源 2.3可以使用聚合函数的关键字 前言 在前面几篇文章中,讲解了有关MySQL数据库、数据库表的创建、数据库表的数据操作等等。本文我…...
mysql中select 1 from的作用
在MySQL中,SELECT 1 FROM ... 是一个常见的SQL写法,通常用于以下场景: 1. 作用与原理 SELECT 1 的本质是返回一个常数值(即数字1),且不依赖表中的实际数据。 它的核心作用是快速验证逻辑条件是否成立&…...
Linux中 du (详解)、 df (详解)和 free(详解)以及它们的区别
目录 du命令 df命令 free命令 du/df/free区别 Tree du命令 功能:用于计算文件或目录所占用的磁盘空间大小。它会递归地遍历指定目录下的所有文件和子目录,统计它们占用的磁盘块数,从而得出占用的空间大小。常用选项: -h&…...
ETL交通行业案例丨某大型铁路运输集团ETL数据集成实践
在广袤的祖国边疆,一条条钢铁动脉承载着区域经济发展的重要使命。某大型铁路运输集团作为区域交通枢纽的运营主体,管辖着横跨多个省、区的铁路网络,运营里程超3000公里,每日承载着数以万计的客货运输任务。随着"数字中国&quo…...
【数据挖掘】Apriori算法
Apriori算法是经典的关联规则挖掘算法,用于从事务型数据库中发现频繁项集和强关联规则,特别常用于购物篮分析等场景。 🧠 核心思想(Apriori原则) 一个项集是频繁的,前提是它的所有子集也必须是频繁的。 即&…...
7.9/Q1,Charls最新文章解读
文章题目:Association between urbanization levels and frailty among middle-aged and older adults in China: evidence from the CHARLS DOI:10.1186/s12916-025-03961-y 中文标题:中国中老年人城市化水平与虚弱程度之间的关联࿱…...
从入门到登峰-嵌入式Tracker定位算法全景之旅 Part 7 |TinyML 定位:深度模型在 MCU 上的部署
Part 7 |TinyML 定位:深度模型在 MCU 上的部署 本章聚焦如何在 ESP32-S3 平台上,通过 TinyML 将深度学习模型应用到定位场景,包括特征提取、模型剪枝与量化、TensorFlow Lite for Microcontrollers 部署,以及在线微调与自适应策略。 一、为什么要用 TinyML? 非线性特征挖…...
Codeforces Round 1023 (Div. 2) ABC
链接 Dashboard - Codeforces Round 1023 (Div. 2) - Codeforces A 将数组a分成两组,使得gcd(b) ! gcd(c) 思路 gcd(a,b) < min(a,b) 求数组a的max,min 如果数组a都一样无解 (即max min 否则有解:让是max的一组&…...
56. 合并区间
给定若干个区间的集合,将重叠的区间合并后,放入一个数组中返回。 具体思路就是按左端点排序后合并区间,因为按左端点排序后,可以确保每次合并都是以最小元素为合并后区间的起始,并且按左端点排序可以方便合并ÿ…...
Docker安装使用
1.Docker简介 Docker是一个开源的应用容器引擎;是一个轻量级容器技术; Docker支持将软件编译成一个镜像;然后在镜像中各种软件做好配置,将镜像发布出去,其他使用者可以直接使用这个镜像; 运行中的这个镜…...
Linux/AndroidOS中进程间的通信线程间的同步 - POSIX IPC
1 什么是POSIX? POSIX(Portable Operating System Interface)即可移植操作系统接口,它是IEEE为要在各种UNIX操作系统上运行软件,而定义API的一系列标准的总称。以下为你展开介绍: 产生背景:在…...
5.2创新架构
一、MoE(Mixture of Experts,混合专家模型) 了解混合专家模型架构,与 Dense 架构相比有什么优劣 是一种提升大模型推理效率和参数利用率的关键技术 核心思想:在模型中增加多个“专家模块”(Experts&#x…...
驱动开发系列57 - Linux Graphics QXL显卡驱动代码分析(四)显示区域更新
一:概述 前面在介绍了显示模式设置(分辨率,刷新率)之后,本文继续分析下,显示区域的绘制,详细看看虚拟机的画面是如何由QXL显卡绘制出来的。 二:相关数据结构介绍 struct qxl_moni…...
疗愈服务预约小程序源码介绍
基于ThinkPHP、FastAdmin和UniApp开发的疗愈服务预约小程序源码,这款小程序在功能设计和用户体验上都表现出色,为疗愈行业提供了一种全新的服务模式。 该小程序源码采用了ThinkPHP作为后端框架,保证了系统的稳定性和高效性。同时,…...
力扣118,1920题解
记录 2525.5.6 题目: 思路: 用一个二维数组dp[numRows][numRows]保存每一次动态规划的结果 1.令dp[0][0]1(第一列) 2.找规律 3.得到如下规律(以下情况均为列数大于1) if(col0){ dp[row][col]1 } else { dp[row][col]dp[row-1][col-1]dp[row-1][col] }…...