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的连接方式。
(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协议 (1)SCCB时序 (2)与I2C的区别 二、Verilog 实现 (1)设计要求 (2)设计要点 (3)模块完整代码 三、功能验证 (1)写…...
维度建模基础篇:从理论到核心组件解析
维度建模基础篇:从理论到核心组件解析 引言 在数据仓库与商业智能(BI)领域,维度建模(Dimensional Modeling)作为一种经典的数据组织方法论,自Kimball提出以来,已成为构建高效分析型系统的核心范式1,2,3。其以业务需求为导向,通过事实表与维度表的组合,实现对复杂…...
与中国联通技术共建:通过obdiag分析OceanBase DDL中的报错场景
中国联通软件研究院(简称联通软研院)在全面评估与广泛调研后,在 2021年底决定采用OceanBase 作为基础,自研分布式数据库产品CUDB(即China Unicom Database,中国联通数据库)。目前,该…...
大数据与网络安全讲座
🍅 点击文末小卡片 ,免费获取网络安全全套资料,资料在手,涨薪更快 大数据的价值为大家公认。业界通常以4个“V”来概括大数据的基本特征——Volume(数据体量巨大)、Variety(数据类型繁多)、Value(价值密度低)、Velocity(处理速度快…...
AtCoder Beginner Contest 395 E
点我写题 题意:给个有向图,从1出发,每次可以走一条有向边,花费为1,也可以选择把全部有向边翻转,花费x,问到n的最小花费 思路:最短路dp,定义dis[i][0/1]表示走到i为止&…...
Linux进程管理6 - CFS调度
0、CFS调度器 CFS调度器使用完全公平调度算法。 完全公平调度算法引入虚拟运行时间的概念:虚拟运行时间 = 实际运行时间 * nice_0_weight / 进程的权重。完全公平调度算法使用红黑树把进程按虚拟运行时间从小到大排序,每次调度选择虚拟运行时间最小的进程。时间片 操作系统进…...
张驰咨询:用六西格玛重构动力电池行业的BOM成本逻辑
在动力电池行业,BOM(物料清单)成本每降低1%,都可能改写企业的利润曲线。某头部企业的三元锂电池BOM成本曾较行业标杆高出11%,单电芯利润率被压缩至3%的生死线。然而,通过张驰咨询的六西格玛方法论ÿ…...
pyside6学习专栏(九):在PySide6中使用PySide6.QtCharts绘制6种不同的图表的示例代码
PySide6的QtCharts类支持绘制各种型状的图表,如面积区域图、饼状图、折线图、直方图、线条曲线图、离散点图等,下面的代码是采用示例数据绘制这6种图表的示例代码,并可实现动画显示效果,实际使用时参照代码中示例数据的格式将实际数据替换即可…...
SpringBoot获取YAML配置文件中的属性值(二):使用Environment环境组件读取值
Spring Boot 使用 Properties 和 YAML 配置文件文件,系列文章: 《Spring使用@Value注解与@PropertySource注解加载配置文件》 《SpringBoot获取YAML配置文件中的属性值(一):使用@Value注解、@ConfigurationProperties注解》 《SpringBoot获取YAML配置文件中的属性值(二)…...
14天 -- Redis 的持久化机制有哪些?Redis 主从复制的实现原理是什么? Redis 数据过期后的删除策略是什么?
Redis 的持久化机制有哪些? Redis 是一种高性能的键值存储系统,主要用于缓存、消息队列等场景。为了防止数据丢失,Redis 提供了多种持久化机制,主要包括以下两种: 1. RDB(Redis Database Backupÿ…...
《深度学习实战》第10集:联邦学习与隐私保护
第10集:联邦学习与隐私保护 2025年3月4日更新了代码,补充了实例程序运行截图 和 如何提高模型准确率的方法 系统梳理 集集精彩 代码验证 保证实战 随着数据隐私问题日益受到关注,联邦学习(Federated Learning) 作为一…...
如何解决跨域请求的问题(CORS)?
文章目录 1. 引言2. 理解 CORS2.1 CORS 基本概念2.2 同源策略与跨域分类 3. CORS 的核心机制3.1 预检请求(Preflight Request)3.2 简单请求 4. 服务器端配置 CORS4.1 关键响应头4.2 Node.js (Express) 示例4.3 其他后端语言配置 5. 前端处理 CORS 请求5.…...
【数据结构】二叉树总结篇
遍历 递归 递归三部曲: 1.参数和返回值 2.终止条件 3.单层逻辑(遍历顺序) var preorderTraversal function(root) { // 第一种let res[];const dfsfunction(root){if(rootnull)return ;//先序遍历所以从父节点开始res.push(root.val);//递归…...
软考-数据库开发工程师-3.1-数据结构-线性结构
第3章内容比较多,内容考试分数占比较大,6分左右 线性表 1、线性表的定义 一个线性表是n个元素的有限序列(n≥0),通常表示为(a1,a2, a3,…an). 2、线性表的顺序存储(顺序表) 是指用一组地址连续的存储单元依次存储线性表中的数据元…...
【五.LangChain技术与应用】【2.LangChain虚拟环境搭建(下):环境优化与调试】
一、Docker化部署:别让你的环境成为薛定谔的猫 经历过"在我机器上能跑"惨案的老铁都懂,传统虚拟环境就像个黑盒子。去年我帮客户部署LangChain应用,因为glibc版本差了0.1,整个服务直接崩成烟花。从那天起,我所有项目都强制上Docker! Dockerfile生存指南: #…...
deepseek+mermaid【自动生成流程图】
成果: 第一步打开deepseek官网(或百度版(更快一点)): 百度AI搜索 - 办公学习一站解决 第二步,生成对应的Mermaid流程图: 丢给deepseek代码,或题目要求 生成mermaid代码 第三步将代码复制到me…...
Java实现大数据量导出报表
一、实现方式 在Java中,导出数据到Excel有多种方式,每种方式都有其优缺点,适用于不同的场景。以下是常见的几种方式及其特点: 1.1 Apache POI Apache POI 是 Java 中最流行的库,支持读写 Excel 文件(包括…...
在 Element Plus 的 <el-select> 组件中,如果需要将 <el-option> 的默认值设置为 null。 用于枚举传值
文章目录 引言轻松实现 `<el-option>` 的默认值为 `null`I 实现方式监听清空事件 【推荐】使用 v-model 绑定 null添加一个值为 null 的选项处理 null 值的显示引言 背景:接口签名规则要求空串参与,空对象不参与签名计算 // 空字符串“” 参与签名组串,null不参与签…...
Spring Boot 接口 JSON 序列化优化:忽略 Null 值的九种解决方案详解
一、针对特定接口null的处理: 方法一:使用 JsonInclude 注解 1.1 类级别:在接口返回的 DTO 类或字段 上添加 JsonInclude 注解,强制忽略 null 值: 类级别:所有字段为 null 时不返回 JsonInclude(Js…...
解码未来!安徽艾德未来智能科技有限公司荣获“GAS消费电子科创奖-产品创新奖”!
在2025年“GAS消费电子科创奖”评选中,安徽艾德未来智能科技有限公司提交的“讯飞AI会议耳机iFLYBUDS Pro 2”,在技术创新性、设计创新性、工艺创新性、智能化创新性及原创性五大维度均获得评委的高度认可,荣获“产品创新奖”。 这一殊荣不仅…...
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.有效的括号题目描述思路:栈code 70.最小栈题目描述思路:双栈法code优化:单栈法code 71.字符串解码题目描述思路:栈code 73.每日温度题目描述思路:单调栈code 74.柱状图中最大的矩形题目描述思路࿱…...
TMS320F28P550SJ9学习笔记2:Sysconfig 配置与点亮LED
今日学习使用Sysconfig 对引脚进行配置,并点亮开发板上的LED4 与LED5 我的单片机开发板平台是 LAUNCHXL_F28P55x 我是在上文描述的驱动库C2000ware官方例程example的工程基础之上进行添加功能的 该例程路径如下:D:\C2000Ware_5_04_00_00\driverlib\f28p…...
STM32MP1xx的启动流程
https://wiki.st.com/stm32mpu/wiki/Boot_chain_overview 根据提供的知识库内容,以下是STM32 MPU启动链的详细解析: 1. 通用启动流程 STM32 MPU启动分为多阶段,逐步初始化外设和内存,并建立信任链: 1.1 ROM代码&…...
开源之夏经验分享|Koupleless 社区黄兴抗:在开源中培养工程思维
开源之夏经验分享|Koupleless 社区黄兴抗:在开源中培养工程思维 文|黄兴抗 电子信息工程专业 Koupleless 社区贡献者 就读于南昌师范学院,电子信息工程专业的大三学生。 本文 2634 字,预计阅读 7 分钟 今天 SOFAStack 邀…...
健康养生:开启活力人生的钥匙
在快节奏的现代生活中,健康养生已成为我们追求美好生活的关键。它不仅关乎身体的强健,更与心灵的宁静息息相关。 合理饮食是健康养生的基石。多吃蔬菜、水果,它们富含维生素与矿物质,为身体提供充足养分。全谷物食品也是不错的选…...
HTTP 与 HTTPS 协议:从基础到安全强化
引言 互联网的消息是如何传递的? 是在路由器上不断进行跳转 IP的目的是在寻址 HTTP 协议:互联网的基石 定义 HTTP(英文:HyperText Transfer Protocol,缩写:HTTP),即超文本传输协…...
项目工坊|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 是一种轻量级的数据库,广泛用于各种嵌入式系统、移动应用和小型项目。SQLite 的ALTER TABLE命令用于修改已存在的表结构,包括添加、删除或修改列,以及重命名表等操作。本文将详细解析SQLite的ALTER TABLE命令&…...
