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

Verilog:SCCB控制器

目录

一、SCCB协议

(1)SCCB时序

(2)与I2C的区别

二、Verilog 实现

        (1)设计要求

        (2)设计要点

        (3)模块完整代码

三、功能验证

        (1)写数据

        (2)读数据 


一、SCCB协议

        SCCB(Serial Camera Control Bus) 是一种用于摄像头模块配置的通信协议(如 ov5640摄像头),由 OmniVision 公司提出。它类似于 I2C 协议,时钟线 SIO_C 即 SCL,数据线 SIO_D 即 SDA。但在某些细节上有所不同。SCCB 主要用于配置摄像头传感器的寄存器,例如设置分辨率、帧率、曝光时间等。

        本文目的在于设计一个适用于 ov5640 摄像头模块的 SCCB 控制器,以实现对 ov5640 寄存器的读写操作,属于双线SCCB的连接方式

三线SCCB(一主多从)
双线SCCB(一主一从)

(1)SCCB时序

        由于SCCB与I2C时序非常相似,这里只简单介绍一下:

        主设备向从设备特定地址写入数据(三相写),数据线上依次为:起始位、7bit从地址+写命令0、X、8bit字节地址、X、8bit写入数据、X、停止位(X指不关心,不同于I2C需要ACK应答)

        主设备读取从设备特定地址数据(两相写+两相读),数据线上依次为:起始位、7bit从设备地址+写命令0、X、8bit字节地址、X、停止位2、起始位2、7bit从设备地址+读命令1、X、8bit读取数据、无应答、停止位

(蓝色表示读写操作都有的公共状态,红色表示各自的特殊状态,与后面状态机的设计有关系)

(2)与I2C的区别

1.写数据:不同于I2C需要ACK应答,用X代替,表示不关心该位数据。

2.读数据:同样用X代替ACK应答位。同时在第二次起始位前多了一个中间停止位。

二、Verilog 实现

        (1)设计要求

                1. 实现对 ov5640 寄存器的读写操作 (ov5640 设备7位地址:7'b0111_100)

                2. 速度采用400KHz

        (2)设计要点

                设计要点其实和I2C控制器没有区别,主要为将应答位ACK修改为X、添加中间停止位状态、状态跳转顺序的调整。所以只需要在 I2C 控制器的基础上进行一些修改,因此这里不再赘述,而I2C控制器的设计可以参考我另一篇笔记  Verilog:I2C控制器 (代码也是根据这个进行修改)

        需要特别注意的是 ov5640 的寄存器地址均为16位即两个字节,因此写寄存器地址时需要分两次写,先写高8位再写低8位,不要忘了中间还有一个X位(ACK)。

        (3)模块完整代码

`timescale 1ns / 1ps
// 适用于ov5640 SCCB通信 寄存器(字节)地址16位,数据8位
module SCCB_ctrl(input  wire clk,                //系统时钟100MHzinput  wire rst_n,              //复位inout  wire sda,                //双向数据线(inout)output wire scl,                //输出时钟线input  wire rw_ctrl,            //读写使能信号(0写1读)input  wire work_start,         //SCCB启动信号input  wire [6:0] slave_addr,   //7bit从设备地址input  wire [15:0] byte_addr,   //16bit字地址 input  wire [7:0] w_data,       //8bit待写数据output reg  [7:0] r_data,       //8bit读取数据output reg  work_done           //SCCB读写完成信号
);
//sda传输方向控制
reg  sda_oe;            //sda输出使能,为1表示sda作输出
reg  sda_out;           //sda输出信号线
wire sda_in;            //sda输入寄存器
assign sda_in = sda;    //sda作输入直接读
assign sda = sda_oe ? (sda_out ? 1'bz : 1'b0) : 1'bz; //作输入需确保总线信号互不干扰对外呈高阻态,空闲和输出1时输出高阻态,因为sda线有上拉电阻//状态机参数
reg [4:0] state;        //当前状态
reg [4:0] next_state;   //下一状态
localparam  //--------------------------------------------公共状态IDLE          = 5'd0,  //空闲START         = 5'd1,  //起始位W_SLAVE_ADDR  = 5'd2,  //写7位从设备地址+写命令0ACK1          = 5'd3,  //应答1W_H_BYTE_ADDR = 5'd4,  //写高8位字地址ACK2          = 5'd5,  //应答2W_L_BYTE_ADDR = 5'd6,  //写低8位字地址ACK3          = 5'd7,  //应答3(状态转移时进行读写判断)STOP          = 5'd8,  //停止位//--------------------------------------------写操作特殊状态W_DATA        = 5'd9,  //写8位数据W_ACK         = 5'd10, //写应答           //--------------------------------------------读操作特殊状态STOP2         = 5'd11, //中间停止位START2        = 5'd12, //中间起始位                         R_SLAVE_ADDR  = 5'd13, //写7位从设备地址+读命令1 R_ACK         = 5'd14, //读应答 R_DATA        = 5'd15, //读8位数据位        N_ACK         = 5'd16; //无应答//计数器及参数
reg clk_div;
reg [7:0] cnt_clk; //分频计数
reg [3:0] cnt_bit; //位计数器
localparam  cnt_max_400khz = 8'd125; //400khz分频翻转计算值
wire scl_half_1;
wire scl_half_0;
wire scl_ack_jump;
assign scl_half_1  = (cnt_clk == cnt_max_400khz >> 1 && clk_div==1'b1);     //scl高电平中点(起始位、ACK接收、停止位时刻)
assign scl_half_0  = (cnt_clk == cnt_max_400khz >> 1 && clk_div==1'b0);     //scl低电平中点(数据读写时刻)
assign scl_ack_jump=((cnt_clk ==(cnt_max_400khz >> 1)-5) && clk_div==1'b0); //scl低电平中点前5clk周期---
//---(ACK状态的下一状态跳转时刻,因为跳转都是由输入转输出状态,快一周期让输出状态赶上紧跟着的第一个scl_half_0,避免错过第1位数据)//数据寄存器
reg [7:0] w_data_buf;       //写入数据寄存器
reg [7:0] r_data_buf;       //读出数据寄存器
reg [7:0] w_slave_addr_buf; //从设备地址寄存器(地址存高7位,0位为写命令0)
reg [7:0] r_slave_addr_buf; //从设备地址寄存器(地址存高7位,0位为读命令1)
reg [7:0] H_byte_addr_buf;  //字地址高8位寄存器
reg [7:0] L_byte_addr_buf;  //字地址低8位寄存器
reg work_en;                //工作使能信号//*************************************** MAIN CODE ***************************************//
//数据复位、开始工作时寄存数据(避免传输中途数据不稳定)
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginw_slave_addr_buf <= 8'b0000_0000;//0位为写命令0r_slave_addr_buf <= 8'b0000_0001;//0位为读命令1H_byte_addr_buf  <= 8'b0;L_byte_addr_buf  <= 8'b0;w_data_buf       <= 8'b0;end else if (work_start) beginw_slave_addr_buf [7:1] <= slave_addr; //地址存高7位r_slave_addr_buf [7:1] <= slave_addr; //地址存高7位w_data_buf       <= w_data;H_byte_addr_buf  <= byte_addr[15:8];L_byte_addr_buf  <= byte_addr[7:0];end
end//分频计数器(400khz时钟scl)
always @(posedge clk or negedge rst_n) beginif (!work_en || !rst_n) begincnt_clk <= 8'd1;clk_div <= 1'b1;end else if (cnt_clk == cnt_max_400khz) begincnt_clk <= 8'd1;clk_div <= ~clk_div;end else cnt_clk <= cnt_clk + 8'd1;
end
assign scl = clk_div;//两段式状态机
always @(posedge clk or negedge rst_n) begin //state状态转移if (!rst_n) state <= IDLE;else state <= next_state;
end
always @(posedge clk or negedge rst_n) begin //state状态执行操作if (!rst_n) beginsda_oe     <= 1'b0;//sda默认不使能输出(高阻态经上拉为1)sda_out    <= 1'b1;//sda默认输出1避免输出0work_en    <= 1'b0;work_done  <= 1'b0;cnt_bit    <= 4'd0;next_state <= IDLE;end elsecase(state)//---------------------空闲----------------------//IDLE: beginsda_oe    <= 1'b0;sda_out   <= 1'b1; work_done <= 1'b0; if (work_start) begin //开始工作work_en    <= 1'b1; //工作使能信号work_en(工作时持续为1)next_state <= START;endend //--------------------起始位1--------------------//START: beginsda_oe <= 1'b1;//sda输出使能if (scl_half_1) beginsda_out <= 1'b0;//sda输出起始位0next_state <= W_SLAVE_ADDR;endend//--------------7bit从地址+写命令0---------------//W_SLAVE_ADDR: beginsda_oe <= 1'b1;//sda输出使能if (scl_half_0) beginif (cnt_bit != 4'd8) beginsda_out <= w_slave_addr_buf[7-cnt_bit];//sda输出设备地址(从高到低)cnt_bit <= cnt_bit + 4'd1;end else beginnext_state <= ACK1;cnt_bit <= 4'd0;endendend//--------------------应答1---------------------//ACK1: begin sda_oe <= 1'b0;//sda输出失能作输入if (scl_ack_jump) next_state <= W_H_BYTE_ADDR;end//-----------------高8bit字节地址-----------------//W_H_BYTE_ADDR: beginsda_oe <= 1'b1;//sda输出使能if (scl_half_0) beginif (cnt_bit != 4'd8) beginsda_out <= H_byte_addr_buf[7-cnt_bit];//sda输出字节地址(从高到低)cnt_bit <= cnt_bit + 4'd1;end else beginnext_state <= ACK2;cnt_bit <= 4'd0;endendend//--------------------应答2---------------------//ACK2: begin sda_oe <= 1'b0;//sda输出失能作输入if (scl_ack_jump) next_state <= W_L_BYTE_ADDR;end//-----------------低8bit字节地址-----------------//W_L_BYTE_ADDR: beginsda_oe <= 1'b1;//sda输出使能if (scl_half_0) beginif (cnt_bit != 4'd8) beginsda_out <= L_byte_addr_buf[7-cnt_bit];//sda输出字节地址(从高到低)cnt_bit <= cnt_bit + 4'd1;end else beginnext_state <= ACK3;cnt_bit <= 4'd0;endendend//--------------------应答3---------------------//ACK3: beginsda_oe <= 1'b0;//sda输出失能作输入if (scl_ack_jump) beginnext_state <= rw_ctrl ? STOP2 : W_DATA; //读写操作判断(0写1读)sda_out    <= rw_ctrl ? 1'b0 : sda_out; //停止位要输出0跳1,转状态时提前置0end end //--------------------停止位--------------------//STOP: beginsda_oe <= 1'b1;//sda输出使能if (scl_half_1) beginsda_out    <= 1'b1;work_done  <= 1'b1;//工作结束信号置1(在STOP转IDLE时清0)work_en    <= 1'b0;//工作使能信号置0next_state <= IDLE;endend//----------------写操作特殊状态-----------------////-----------------8bit写入数据-----------------//W_DATA: begin               sda_oe <= 1'b1;//sda输出使能if (scl_half_0) beginif (cnt_bit != 4'd8) beginsda_out <= w_data_buf[7-cnt_bit];//sda输出写入数据(从高到低)cnt_bit <= cnt_bit + 4'd1;end else beginnext_state <= W_ACK;cnt_bit <= 4'd0;endendend//-------------------写应答---------------------//W_ACK: begin sda_oe <= 1'b0;//sda输出失能作输入 if (scl_ack_jump) beginsda_out    <= 1'b0;  //停止位要输出0跳1,转状态时提前置0next_state <= STOP;endend //----------------读操作特殊状态-----------------////------------------中间停止位------------------//STOP2: beginsda_oe <= 1'b1;//sda输出使能if (scl_half_1) beginsda_out    <= 1'b1;next_state <= START2;endend//-------------------起始位2--------------------//START2: beginsda_oe <= 1'b1;//sda输出使能if (scl_half_1) beginsda_out    <= 1'b0;//sda输出起始位0next_state <= R_SLAVE_ADDR;endend//--------------7bit从地址+读命令1---------------//R_SLAVE_ADDR: beginsda_oe <= 1'b1;//sda输出使能if (scl_half_0) beginif (cnt_bit != 4'd8) beginsda_out <= r_slave_addr_buf[7-cnt_bit];//sda输出设备地址(从高到低)cnt_bit <= cnt_bit + 4'd1;end else beginnext_state <= R_ACK;cnt_bit <= 4'd0;endendend//-------------------读应答---------------------//R_ACK: begin sda_oe <= 1'b0;//sda输出失能作输入if (scl_ack_jump) next_state <= R_DATA;end //-----------------8bit读取数据-----------------//R_DATA: beginsda_oe <= 1'b0;//sda输出失能作输入if (scl_half_1 && cnt_bit!=4'd8) begin      r_data_buf[7-cnt_bit] <= sda_in;//sda在scl高电平中点读取数据(从高到低)cnt_bit <= cnt_bit + 4'd1;end if (scl_ack_jump && cnt_bit==4'd8) begin //提前转状态,因为无应答会在scl_half_0输出          next_state <= N_ACK;cnt_bit <= 4'd0;r_data <= r_data_buf;//从寄存器取出读取的数据endend//--------------------无应答--------------------//  N_ACK: begin sda_oe  <= 1'b1;//sda输出使能if (scl_half_0)sda_out <= 1'b1;if (scl_ack_jump) beginsda_out <= 1'b0;//停止位要输出0跳1,转状态时提前置0next_state <= STOP;end enddefault: next_state <= IDLE;endcase 
end
endmodule

三、功能验证

        验证方法:

                SCCB 读写 ov5640 的仿真略显麻烦,还需一个从设备模块以模拟 ov5640 行为。因此我选择直接上板调试:用拨码开关进行读写控制、写入数据设置,按钮发送工作启动信号 (按钮经过软件消抖处理),进行一次写数据操作后再将进行读数据操作,并将数据返回到LED灯上进行验证,同时调用Vivado的ILA进行在线调试,抓取波形检查时序。(关于ILA的使用可以参考我的另一篇笔记:Vivado:使用 ILA 进行在线调试 )

        FPGA开发板上的操作及现象为:

                拨码开关设置好待写入数据 8'h41 (0100_0001),rw_ctrl的拨码开关打向0,按下按钮发送启动信号,向从设备写入数据。接着 rw_ctrl 的拨码开关打向1,再次按下按钮发送启动信号,从从设备读取数,此时LED被立刻点亮,点亮情况为 8'h41 (0100_0001),说明模块功能成功实现了对 ov5640 寄存器的读写操作。

        下面对ILA抓取到的波形进行分析:

        (1)写数据

                向 ov5640(设备地址0111_100)地址为 16'h3820 (0011_1000_0010_0000) 的寄存器写入数据 8'h41 (0100_0001)。可以看到sda数据正确传输,同时从设备虽然不需要应答但也正常进行接收应答。(应答位的毛刺个人认为是从设备的应答信号持续时间不够长导致,从设备发送应答后开始接收主设备发送的数据,sda保持高阻态,因此主设备这边接收到了高电平。但并不影响i2c功能,因为sda数据是在scl高电平中点进行接收)

        (2)读数据 

                从 ov5640(设备地址0111_100)地址为 16'h3820 (0011_1000_0010_0000) 的寄存器读取数据。发现主设备成功读取到了之前向从设备写入的数据 8'h41 (0100_0001)。

                到此,所设计SCCB控制器功能验证结束,成功实现对ov5640 寄存器的读写操作。

相关文章:

Verilog:SCCB控制器

目录 一、SCCB协议 &#xff08;1&#xff09;SCCB时序 &#xff08;2&#xff09;与I2C的区别 二、Verilog 实现 &#xff08;1&#xff09;设计要求 &#xff08;2&#xff09;设计要点 &#xff08;3&#xff09;模块完整代码 三、功能验证 &#xff08;1&#xff09;写…...

维度建模基础篇:从理论到核心组件解析

维度建模基础篇:从理论到核心组件解析 引言 在数据仓库与商业智能(BI)领域,维度建模​(Dimensional Modeling)作为一种经典的数据组织方法论,自Kimball提出以来,已成为构建高效分析型系统的核心范式1,2,3。其以业务需求为导向,通过事实表与维度表的组合,实现对复杂…...

与中国联通技术共建:通过obdiag分析OceanBase DDL中的报错场景

中国联通软件研究院&#xff08;简称联通软研院&#xff09;在全面评估与广泛调研后&#xff0c;在 2021年底决定采用OceanBase 作为基础&#xff0c;自研分布式数据库产品CUDB&#xff08;即China Unicom Database&#xff0c;中国联通数据库&#xff09;。目前&#xff0c;该…...

大数据与网络安全讲座

&#x1f345; 点击文末小卡片 &#xff0c;免费获取网络安全全套资料&#xff0c;资料在手&#xff0c;涨薪更快 大数据的价值为大家公认。业界通常以4个“V”来概括大数据的基本特征——Volume(数据体量巨大)、Variety(数据类型繁多)、Value(价值密度低)、Velocity(处理速度快…...

AtCoder Beginner Contest 395 E

点我写题 题意&#xff1a;给个有向图&#xff0c;从1出发&#xff0c;每次可以走一条有向边&#xff0c;花费为1&#xff0c;也可以选择把全部有向边翻转&#xff0c;花费x&#xff0c;问到n的最小花费 思路&#xff1a;最短路dp&#xff0c;定义dis[i][0/1]表示走到i为止&…...

Linux进程管理6 - CFS调度

0、CFS调度器 CFS调度器使用完全公平调度算法。 完全公平调度算法引入虚拟运行时间的概念:虚拟运行时间 = 实际运行时间 * nice_0_weight / 进程的权重。完全公平调度算法使用红黑树把进程按虚拟运行时间从小到大排序,每次调度选择虚拟运行时间最小的进程。时间片 操作系统进…...

张驰咨询:用六西格玛重构动力电池行业的BOM成本逻辑

在动力电池行业&#xff0c;BOM&#xff08;物料清单&#xff09;成本每降低1%&#xff0c;都可能改写企业的利润曲线。某头部企业的三元锂电池BOM成本曾较行业标杆高出11%&#xff0c;单电芯利润率被压缩至3%的生死线。然而&#xff0c;通过张驰咨询的六西格玛方法论&#xff…...

pyside6学习专栏(九):在PySide6中使用PySide6.QtCharts绘制6种不同的图表的示例代码

PySide6的QtCharts类支持绘制各种型状的图表&#xff0c;如面积区域图、饼状图、折线图、直方图、线条曲线图、离散点图等&#xff0c;下面的代码是采用示例数据绘制这6种图表的示例代码,并可实现动画显示效果&#xff0c;实际使用时参照代码中示例数据的格式将实际数据替换即可…...

SpringBoot获取YAML配置文件中的属性值(二):使用Environment环境组件读取值

Spring Boot 使用 Properties 和 YAML 配置文件文件,系列文章: 《Spring使用@Value注解与@PropertySource注解加载配置文件》 《SpringBoot获取YAML配置文件中的属性值(一):使用@Value注解、@ConfigurationProperties注解》 《SpringBoot获取YAML配置文件中的属性值(二)…...

14天 -- Redis 的持久化机制有哪些?Redis 主从复制的实现原理是什么? Redis 数据过期后的删除策略是什么?

Redis 的持久化机制有哪些&#xff1f; Redis 是一种高性能的键值存储系统&#xff0c;主要用于缓存、消息队列等场景。为了防止数据丢失&#xff0c;Redis 提供了多种持久化机制&#xff0c;主要包括以下两种&#xff1a; 1. RDB&#xff08;Redis Database Backup&#xff…...

《深度学习实战》第10集:联邦学习与隐私保护

第10集&#xff1a;联邦学习与隐私保护 2025年3月4日更新了代码&#xff0c;补充了实例程序运行截图 和 如何提高模型准确率的方法 系统梳理 集集精彩 代码验证 保证实战 随着数据隐私问题日益受到关注&#xff0c;联邦学习&#xff08;Federated Learning&#xff09; 作为一…...

如何解决跨域请求的问题(CORS)?

文章目录 1. 引言2. 理解 CORS2.1 CORS 基本概念2.2 同源策略与跨域分类 3. CORS 的核心机制3.1 预检请求&#xff08;Preflight Request&#xff09;3.2 简单请求 4. 服务器端配置 CORS4.1 关键响应头4.2 Node.js (Express) 示例4.3 其他后端语言配置 5. 前端处理 CORS 请求5.…...

【数据结构】二叉树总结篇

遍历 递归 递归三部曲&#xff1a; 1.参数和返回值 2.终止条件 3.单层逻辑&#xff08;遍历顺序&#xff09; var preorderTraversal function(root) { // 第一种let res[];const dfsfunction(root){if(rootnull)return ;//先序遍历所以从父节点开始res.push(root.val);//递归…...

软考-数据库开发工程师-3.1-数据结构-线性结构

第3章内容比较多&#xff0c;内容考试分数占比较大&#xff0c;6分左右 线性表 1、线性表的定义 一个线性表是n个元素的有限序列(n≥0)&#xff0c;通常表示为(a1&#xff0c;a2, a3,…an). 2、线性表的顺序存储(顺序表) 是指用一组地址连续的存储单元依次存储线性表中的数据元…...

【五.LangChain技术与应用】【2.LangChain虚拟环境搭建(下):环境优化与调试】

一、Docker化部署:别让你的环境成为薛定谔的猫 经历过"在我机器上能跑"惨案的老铁都懂,传统虚拟环境就像个黑盒子。去年我帮客户部署LangChain应用,因为glibc版本差了0.1,整个服务直接崩成烟花。从那天起,我所有项目都强制上Docker! Dockerfile生存指南: #…...

deepseek+mermaid【自动生成流程图】

成果&#xff1a; 第一步打开deepseek官网(或百度版&#xff08;更快一点&#xff09;)&#xff1a; 百度AI搜索 - 办公学习一站解决 第二步&#xff0c;生成对应的Mermaid流程图&#xff1a; 丢给deepseek代码&#xff0c;或题目要求 生成mermaid代码 第三步将代码复制到me…...

Java实现大数据量导出报表

一、实现方式 在Java中&#xff0c;导出数据到Excel有多种方式&#xff0c;每种方式都有其优缺点&#xff0c;适用于不同的场景。以下是常见的几种方式及其特点&#xff1a; 1.1 Apache POI Apache POI 是 Java 中最流行的库&#xff0c;支持读写 Excel 文件&#xff08;包括…...

在 Element Plus 的 <el-select> 组件中,如果需要将 <el-option> 的默认值设置为 null。 用于枚举传值

文章目录 引言轻松实现 `<el-option>` 的默认值为 `null`I 实现方式监听清空事件 【推荐】使用 v-model 绑定 null添加一个值为 null 的选项处理 null 值的显示引言 背景:接口签名规则要求空串参与,空对象不参与签名计算 // 空字符串“” 参与签名组串,null不参与签…...

Spring Boot 接口 JSON 序列化优化:忽略 Null 值的九种解决方案详解

一、针对特定接口null的处理&#xff1a; 方法一&#xff1a;使用 JsonInclude 注解 1.1 类级别&#xff1a;在接口返回的 ‌DTO 类或字段‌ 上添加 JsonInclude 注解&#xff0c;强制忽略 null 值&#xff1a; 类级别&#xff1a;所有字段为 null 时不返回 JsonInclude(Js…...

解码未来!安徽艾德未来智能科技有限公司荣获“GAS消费电子科创奖-产品创新奖”!

在2025年“GAS消费电子科创奖”评选中&#xff0c;安徽艾德未来智能科技有限公司提交的“讯飞AI会议耳机iFLYBUDS Pro 2”&#xff0c;在技术创新性、设计创新性、工艺创新性、智能化创新性及原创性五大维度均获得评委的高度认可&#xff0c;荣获“产品创新奖”。 这一殊荣不仅…...

Velox 之 Expression

Round 函数 velox/functions/prestosql/Arithmetic.h template <typename T> struct RoundFunction {template <typename TInput>FOLLY_ALWAYS_INLINE voidcall(TInput& result, const TInput& a, const int32_t b = 0) {result = round(a, b);} };/// R…...

【零基础到精通Java合集】第二十四集:ZGC收集器详解

课程标题:ZGC收集器——突破停顿时间极限的下一代垃圾回收器(15分钟) 目标:掌握ZGC的核心技术原理、适用场景与调优策略,理解其如何实现亚毫秒级停顿 0-1分钟:课程引入与ZGC设计目标 以“高速公路无障碍通行”类比ZGC核心思想:通过染色指针与读屏障技术,实现垃圾回收…...

力扣hot100刷题——栈

文章目录 69.有效的括号题目描述思路&#xff1a;栈code 70.最小栈题目描述思路&#xff1a;双栈法code优化&#xff1a;单栈法code 71.字符串解码题目描述思路&#xff1a;栈code 73.每日温度题目描述思路&#xff1a;单调栈code 74.柱状图中最大的矩形题目描述思路&#xff1…...

TMS320F28P550SJ9学习笔记2:Sysconfig 配置与点亮LED

今日学习使用Sysconfig 对引脚进行配置&#xff0c;并点亮开发板上的LED4 与LED5 我的单片机开发板平台是 LAUNCHXL_F28P55x 我是在上文描述的驱动库C2000ware官方例程example的工程基础之上进行添加功能的 该例程路径如下&#xff1a;D:\C2000Ware_5_04_00_00\driverlib\f28p…...

STM32MP1xx的启动流程

https://wiki.st.com/stm32mpu/wiki/Boot_chain_overview 根据提供的知识库内容&#xff0c;以下是STM32 MPU启动链的详细解析&#xff1a; 1. 通用启动流程 STM32 MPU启动分为多阶段&#xff0c;逐步初始化外设和内存&#xff0c;并建立信任链&#xff1a; 1.1 ROM代码&…...

开源之夏经验分享|Koupleless 社区黄兴抗:在开源中培养工程思维

开源之夏经验分享&#xff5c;Koupleless 社区黄兴抗&#xff1a;在开源中培养工程思维 文|黄兴抗 电子信息工程专业 Koupleless 社区贡献者 就读于南昌师范学院&#xff0c;电子信息工程专业的大三学生。 本文 2634 字&#xff0c;预计阅读 7​ 分钟​ 今天 SOFAStack 邀…...

健康养生:开启活力人生的钥匙

在快节奏的现代生活中&#xff0c;健康养生已成为我们追求美好生活的关键。它不仅关乎身体的强健&#xff0c;更与心灵的宁静息息相关。 合理饮食是健康养生的基石。多吃蔬菜、水果&#xff0c;它们富含维生素与矿物质&#xff0c;为身体提供充足养分。全谷物食品也是不错的选…...

HTTP 与 HTTPS 协议:从基础到安全强化

引言 互联网的消息是如何传递的&#xff1f; 是在路由器上不断进行跳转 IP的目的是在寻址 HTTP 协议&#xff1a;互联网的基石 定义 HTTP&#xff08;英文&#xff1a;HyperText Transfer Protocol&#xff0c;缩写&#xff1a;HTTP&#xff09;&#xff0c;即超文本传输协…...

项目工坊|Python驱动淘宝信息爬虫

目录 前言 1 完整代码 2 代码解读 2.1 导入模块 2.2 定义 TaoBao 类 2.3 search_infor_price_from_web 方法 2.3.1 获取下载路径 2.3.2 设置浏览器选项 2.3.3 反爬虫处理 2.3.4 启动浏览器 2.3.5 修改浏览器属性 2.3.6 设置下载行为 2.3.7 打开淘宝登录页面 2.3.…...

SQLite Alter 命令详解

SQLite Alter 命令详解 SQLite 是一种轻量级的数据库&#xff0c;广泛用于各种嵌入式系统、移动应用和小型项目。SQLite 的ALTER TABLE命令用于修改已存在的表结构&#xff0c;包括添加、删除或修改列&#xff0c;以及重命名表等操作。本文将详细解析SQLite的ALTER TABLE命令&…...