STM32之SPI總線

一、SPI總線概述

1、SPI總線介紹

SPI是一種通信協議,它是摩托羅拉公司研發出來的一種通信協議,就有自己的特點(串行,并行,單工,半雙工,全雙工,同步異步)。它主要應用于音視頻的開發. SPI是串行外設接口(Serial Peripheral Interface)的縮寫,是一種高速的,全雙工,同步的通信總線,并且在芯片的管腳上只占用四根線,節約了芯片的管腳,同時為PCB的布局上節省空間,提供方便,正是出于這種簡單易用的特性,越來越多的芯片集成了這種通信協議.

一般的通信速度可以達到幾十Mhz

SPI(Serial Peripheral Interface)是一種串行外設接口標準,用于在微控制器或其他數字設備之間進行通信。它被廣泛應用于各種應用領域,如通信、嵌入式系統和傳感器網絡等。

?2、SPI總線接口與物理拓撲結構

SPI按照接線的不同分為3線SPI與4線SPI。

同步串行全雙工

同步串行半雙工

物理上的連接是怎么樣的?

使用SPI協議重點是知道里面的一個時序的情況,如果知道了這種情況,完全可以實現這種協議。

SPI協議是一種一主多從的形式:

可以通過片選線來選中不同的從機

時鐘線(信號)只能由主機控制,從機受到主機發出的時鐘信號來做出相應的處理

針對主機而言:

當時鐘線產生上升沿時接收數據,當時鐘線產生下降沿時發送數據

當時鐘線產生下降沿時接收數據,當時鐘線產生上升沿時發送數據

3、SPI總線通信原理

SPI可以配置為4種模式(SPI控制器)

MODE0-MODE3

4、SPI總線數據格式

8位的數據,高位先發

SPI的通信過程其實就是數據交換的過程

首先需要拉低片選線

再根據當前的邊沿決定是發送數據還是接收數據(上升沿發送,下降沿接收)

結束本次通信拉高片選線

用IO口來實現SPI協議?

寫偽代碼(不是真正可以實現的,不過可以實現相應的邏輯)

當前選擇模式0:CPHA = 0, CPOL = 0,下降沿發送數據,上升沿接收數據

SCK, MOSI, MISO,CS

U8 Data = 0;//0000 0000
CS = 0;//選中這個芯片
SCK = 1;
for(i =0; i <8 ;i++)
{SCK = 0;MOSI = 0/1;SCK = 1;Data <<= 1;//空出低位的操作,data = 0000 0100if(MISO){Data |= 1;//0000 0001}
}

二、SPI控制器

1、SPI的控制器特征

基于三條線的全雙工同步傳輸(通過一個標志位的切換達到所謂的雙工通信)
???
基于雙線的單工同步傳輸,其中一條可作為雙向數據線
???
8 位或 16 位傳輸幀格式選擇
??? 主模式或從模式操作
???
多主模式功能
???
8 個主模式波特率預分頻器(最大值為 fPCLK/2)fpclk就是看當前用的SPI是在哪根總線上
???
從模式頻率(最大值為 fPCLK/2
???
對于主模式和從模式都可實現更快的通信
???
對于主模式和從模式都可通過硬件或軟件進行 NSSCS管腳) 管理:動態切換主 /從操作
??? 可編程的時鐘極性和相位
???
可編程的數據順序,最先移位 MSB LSB
?????? 可觸發中斷的專用發送和接收標志
??? SPI 總線忙狀態標志
???
SPI TI 模式
???
用于確保可靠通信的硬件 CRC 功能:
在發送模式下可將 CRC 值作為最后一個字節發送
根據收到的最后一個字節自動進行 CRC 錯誤校驗
可觸發中斷的主模式故障、上溢和 CRC 錯誤標志
具有 DMA 功能的 1 字節發送和接收緩沖器:發送和接收請求

2、SPI控制器框架分析

SPI接口:STM32的SPI控制器有多個SPI接口,每個SPI接口可以連接多個SPI從設備。每個SPI接口都包含用于發送和接收數據的寄存器。SPI接口提供了多種配置選項,如時鐘極性、時鐘相位、數據位數等。

主設備和從設備:在SPI通信中,系統中的一個設備充當主設備,它發起和控制數據傳輸。其他設備則充當從設備,它們響應主設備的命令并提供數據。主設備通過選擇從設備來確定與之通信的目標。

緩沖器和寄存器:SPI控制器使用緩沖器和寄存器來存儲發送和接收的數據。主設備通過將數據寫入發送緩沖器來發送數據,從設備通過讀取接收緩沖器來接收數據。SPI控制器還包含用于控制和配置的寄存器。

時鐘設置:SPI控制器使用時鐘信號來同步數據傳輸。時鐘信號由主設備控制,可以通過配置時鐘極性和相位來設置時鐘信號的工作方式。

SPI控制器的工作流程如下:

  1. 主設備選擇從設備并開始傳輸。
  2. 主設備將數據寫入發送緩沖器。
  3. 主設備發送時鐘信號,從設備接收數據。
  4. 從設備將接收到的數據存儲到接收緩沖器。
  5. 主設備繼續發送數據并重復上述過程,直到傳輸完成。

3、相關寄存器

SPI 控制寄存器 1 (SPI_CR1) (不用于 I 2 S 模式)
SPI 數據寄存器 (SPI_DR)
SPI 狀態寄存器 (SPI_SR)

SR寄存器用于提示當前能不能發生或者接收下一個字節的數據

等到發送緩沖區為空就可以繼續發下一個字節的數據

等到接收緩沖區為空就可以繼續接收下一個字節的數據

三、W25Q64芯片

1、芯片介紹

W25Q64 (64M-bit) , W25Q16(16M-bit) 和 W25Q32(32M-bit) 是為系統提供一個最小的空間、引腳和功耗的存儲器解決方案的串行 Flash 存儲器。 25Q 系列比普通的串行 Flash 存儲器更靈活,性能更優越。基于雙倍/四倍的 SPI,它們能夠可以立即完成提供數據給 RAM, 包括存儲聲音、文本和數據。芯片支持的工作電壓 2.7V 3.6V,正常工作時電流小于 5mA,掉電時低于 1uA。所有芯片提供標準的封裝。W25Q64/16/32 由每頁 256 字節組成。 每頁的 256 字節用一次頁編程指令即可完成。每次可以擦 16 頁(1個扇區)、 128 頁(32KB 塊)、 256 頁( 64KB 塊)和全片擦除。

256字節 = 1頁

16頁 = 1個扇區

16個扇區 =? 1個塊

W25Q64 的內存空間結構: 一頁 256 字節, 4K(4096 字節) 為一個扇區, 16 個扇區為 1 塊, 容量為 8M 字節, 共有 128 個塊, 2048 個扇區。

FLASH: 可讀可寫,只能寫入0不能寫入1,只有把1變0的能力

擦除的概念:寫數據之前要先擦除,擦除就是全部數據變為1

1111 1111

1010 1010

當前W25Q64這個芯片最少擦除4096字節(就是一個扇區),然后去使用

具有唯一的 64 位識別序列號。

● SPI 串行存儲器系列 ???????????????????????????????????????? ●靈活的 4KB 扇區結構
-W25Q64:64M 位/8M 字節 ????????????????????????????????????-統一的扇區擦除( 4K 字節)

-W25Q16:16M 位/2M 字節 ????????????????????????????????????-塊擦除( 32K 和 64K 字節)
-W25Q32:32M 位/4M 字節 ????????????????????????????????????-一次編程 256 字節

-每 256 字節可編程頁 ???????????????????????????????????????????-至少 100,000 寫/擦除周期
-數據保存 20 年

2、芯片管腳說明

CS -- 片選

DO -- 數據輸出(MISO)

DI -- 數據輸入(MOSI)

Clk -- 時鐘線

3、芯片工作原理

W25Q64/16/32兼容的SPI 總線包含四個信號:串行時鐘( CLK)、片選端( /CS)、串行數據輸入( DI)和串行數據輸出( DO)。標準的 SPI 用 DI 輸入引腳在 CLK 的上升沿連續的寫命令、地址或數據到芯片內。 DO 輸出在 CLK 的下降沿從芯片內讀出數據或狀態。
?? ?支持 SPI 總線的工作模式 0( 0, 0)和 3( 1, 1)。模式 0 和模式 3 的主要區別在于常態時的 CLK
信號,當 SPI 主機已準備好數據還沒傳輸到串行 Flash 中,對于模式 0 CLK 信號常態為低.串行時鐘輸入引腳為串行輸入和輸出操作提供時序。(見 SPI 操作)設備數據傳輸是從高位開始, 數據傳輸的格式為8bit, 數據采樣從第二個時間邊沿開始, 空閑狀態時, 時鐘線 clk 為高電平。
當前這個器件可用的SPI時序符合前面所講到的模式0和模式3
模式0/3:上升沿接收數據,下降沿發送數據
模式1/2:上升沿發送數據,下降沿接收數據
支持模式0的一般就會支持模式3,支持模式1的一般就會支持模式2

4、芯片操作時序

讀ID的時序

拉低片選線(CS)

DI線就是代表代碼里需要發送的數據

DO線就代表代碼里接收到的數據

讀取制造商/設備 ID 指令可以讀取,制造商 ID 和特定的設備 ID。 讀取之間, 拉低 CS 片選信號, 接著發送指令代碼“90h” , 緊隨其后的是一個 24 位地址(A23-A0)000000h。之后, 設備發出華邦子制造商 ID(EFh) 和設備ID(w25q64 為 16h)。如果 24 位地址設置為 000001 h 的設備 ID 會先發出,然后跟著制造商 ID。制造商和設備 ID 可以連續讀取。完成指令后, 片選信號/ CS 拉高。

寫使能

拉低片選

接著發0x06的寫使能指令

拉高片選

讀狀態寄存器

先拉低片選

接著發05這條指令代表存儲芯片當前需要去讀狀態寄存器1

接下來就可以讀回來狀態寄存器的8個位了

拉高片選

扇區擦除

扇區擦除指令可以擦除指定一個扇區(4 k 字節)內所有數據, 將內存空間恢復到 0xFF 狀態。 寫入扇區擦除指令之前必須執行設備寫使能(發送設備寫使能指令 0x06)并判斷狀態寄存器(狀態寄存器位最低位必須等于 0 才能操作)發送的扇區擦除指令前, 先拉低/ CS, 接著發送扇區擦除指令碼”20 h”, 和 24 位地址(A23-A0), 地址發送完畢后,拉高片選線 CS/,, 并判斷狀態位,等待擦除結束。 擦除一個扇區的最少需要 150ms 時間。

寫使能

判斷狀態寄存器的第0位

先拉低片選

發送0x20的指令

發送24位的地址(當前你要擦除的地址是哪里--首地址),這個地址只能是4096的倍數

拉高片選線

頁編程指令

頁編程指令允許從一個字節到 256 字節的數據編程(一頁)(編程之前必須保證內存空間是 0XFF--要先擦除)。允許寫入指令之前,必須先發送設備寫使能指令。 寫使能開啟后, 設備才能接收編程指令。 開啟頁編程先拉底/ CS, 然后發送指令代碼“02 h”, 接著發送一個 24 位地址(開始存放數據的地址)(A23-A0)(發送 3 次,每次 8 位) 和至少一個數據字節(數據字節不能超過 256字節)。 數據字節發送完畢, 需要拉高片選線 CS/,并判斷狀態位, 等待寫入結束。進行頁編程時,如果數據字節數超過了 256 字節, 地址將自動回到頁的起始地址, 覆蓋掉之前的數據。 在某些情況下,數據字節小于 256 字節(同一頁內), 也可以正常對其他字節存放, 不會有任何影響。如果存放超過 256 字節的數據, 需要分次編程存放。

寫使能

拉低片選

發送頁編程指令(0x02)

發送24位的地址

發送需要存下來的數據(不能超過當前頁的最大地址,如果超過則會回到當前頁的起始地址開始存放)

拉高片選

判斷當前寫入完成沒有(讀狀態寄存器1的第0位)

讀數據

讀取數據指令允許按順序讀取一個字節的內存數據。當片選 CS/拉低之后, 緊隨其后是一個 24 位的地址(A23-A0)(需要發送 3 次, 每次 8 個字節, 先發高位)。芯片收到地址后,將要讀的數據按字節大小轉移出去, 數據是先轉移高位,對于單片機,時鐘下降沿發送數據,上升沿接收數據。 讀數據時, 地址會自動增加允許連續的讀取數據這意味著讀取整個內存的數據,只要用一個指令就可以讀完。 數據讀取完成之后, 片選信號/ CS 拉高。讀取數據的指令序列,如上圖所示。 如果一個讀數據指令而發出的時候, 設備正在擦除扇區,或者(忙= 1), 該讀指令將該讀指令將被忽略,也不會對當前周期有什么影響。

拉低片選

先發一個0x03的指令

發送要從哪個地址開始讀取數據(24位的地址)

再去讀取數據

拉高片選

四、模擬SPI

#include "spi.h"/************************************
函數功能:初始化SPI的管腳
函數形參:void
函數返回值:void
函數說明:CS -- 	PB14: 推挽輸出(可以選中也可以釋放--有低電平也有高電平)
MISO -- PA6: 浮空輸入
MOSI -- PA7: 推挽輸出
SCK --	PA5: 推挽輸出
作者:
日期:
************************************/
void Spi_Port_Init(void)
{//打開GPIOA和GPIOB的時鐘RCC->AHB1ENR |= 0x3 << 0;//配置輸出//配置的是PA5--SCKGPIOA->MODER &= ~(0X3 << 10);GPIOA->MODER |= (0X1 << 10);//配置的是PA7--MOSIGPIOA->MODER &= ~(0X3 << 14);GPIOA->MODER |= (0X1 << 14);//配置的是PB14--CSGPIOB->MODER &= ~(0X3 << 28);GPIOB->MODER |= (0X1 << 28);//配置輸入GPIOA->MODER &= ~(0X3 << 12);//把速度配置為50MhzGPIOA->OSPEEDR &= ~(0X3F << 10);GPIOA->OSPEEDR |= (0X2A << 10);
}/************************************
函數功能:模擬SPI來讀寫數據
函數形參:u8 data -- 需要發送的數據
函數返回值:u8 -- 接收回來的數據可以通過返回值給調用者
函數說明:data = 1011 0011
高位先發
下降沿發送數據,上升沿接收數據
作者:
日期:
************************************/
u8 Spi_Change_Data(u8 data)
{u8 rec_data = 0;u8 i = 0;for(i = 0; i < 8; i++){SCK_L;//代表產生下降沿可以開始發送數據//1011 0011 & //0100 0000//spi不需要加延時if(data & (0x80 >> i)){MOSI_H;}else{MOSI_L;}SCK_H;//代表產生上升沿可以開始接收數據rec_data <<= 1;//可以空出最低位if(MISO){rec_data |= 1;}}return rec_data;
}
#ifndef __SPI_H_
#define __SPI_H_#include "stm32f4xx.h"
#include "io_bit.h"#define SCK_H  	(GPIOA->ODR |= 0X1 << 5)
#define SCK_L  	(GPIOA->ODR &= ~(0X1 << 5))
#define MOSI_H  (GPIOA->ODR |= 0X1 << 7)
#define MOSI_L  (GPIOA->ODR &= ~(0X1 << 7))
#define CS_H  	(GPIOB->ODR |= 0X1 << 14)
#define CS_L 	(GPIOB->ODR &= ~(0X1 << 14))
#define MISO    PAin(6)void Spi_Port_Init(void);
u8 Spi_Change_Data(u8 data);
#endif

五、SPI控制器

1、硬件設計

CS: 推挽輸出(可以選中也可以釋放--有低電平也有高電平)

MISO: 浮空輸入

MOSI: 推挽輸出

SCK : 推挽輸出

2、軟件設計

GPIO口配置

SPI配置

#include "spi.h"/************************************
函數功能:初始化SPI的管腳
函數形參:void
函數返回值:void
函數說明:CS -- 	PB14: 推挽輸出(可以選中也可以釋放--有低電平也有高電平)
MISO -- PA6: 浮空輸入
MOSI -- PA7: 推挽輸出
SCK --	PA5: 推挽輸出
作者:li
日期:2021.8.6
************************************/
void Spi_Port_Init(void)
{//打開GPIOA和GPIOB的時鐘RCC->AHB1ENR |= 0x3 << 0;//PA5-7配置為復用功能GPIOA->MODER &= ~(0X3F << 10);GPIOA->MODER |= (0X2A << 10);//復用到SPI1GPIOA->AFR[0] &= ~(0XFFF << 20);GPIOA->AFR[0] |= (0X555 << 20);//把速度配置為50MhzGPIOA->OSPEEDR &= ~(0X3F << 10);GPIOA->OSPEEDR |= (0X2A << 10);//配置的是PB14--CSGPIOB->MODER &= ~(0X3 << 28);GPIOB->MODER |= (0X1 << 28);//打開SPI1的時鐘RCC->APB2ENR |= 0X1 << 12;SPI1->CR1 = 0;/*選擇雙線單向通信數據模式為發送 /接收選擇 8 位數據幀格式全雙工(發送和接收)先發送 MSBfPCLK/2下降沿發送數據,上升沿接收數據*///使能軟件從器件管理SPI1->CR1 |= 0X3 << 8;//主模式SPI1->CR1 |= 0X1 << 2;//使能外設SPI1->CR1 |= 0X1 << 6;
}/************************************
函數功能:
函數形參:u8 data -- 需要發送的數據
函數返回值:u8 -- 接收回來的數據可以通過返回值給調用者
函數說明:data = 1011 0011
高位先發
下降沿發送數據,上升沿接收數據
作者:
日期:
************************************/
u8 Spi_Change_Data(u8 data)
{u8 rec_data = 0;while(!(SPI1->SR & 0X1 << 1))//當前發送緩沖區為空才能跳出循環{}SPI1->DR = data;//發送數據while(!(SPI1->SR & 0X1 << 0))//當前接收緩沖區為空才能跳出循環{}rec_data = SPI1->DR;//接收數據return rec_data;
}
#ifndef __SPI_H_
#define __SPI_H_#include "stm32f4xx.h"
#include "io_bit.h"#define SCK_H  	(GPIOA->ODR |= 0X1 << 5)
#define SCK_L  	(GPIOA->ODR &= ~(0X1 << 5))
#define MOSI_H  (GPIOA->ODR |= 0X1 << 7)
#define MOSI_L  (GPIOA->ODR &= ~(0X1 << 7))
#define CS_H  	(GPIOB->ODR |= 0X1 << 14)
#define CS_L 	(GPIOB->ODR &= ~(0X1 << 14))
#define MISO    PAin(6)void Spi_Port_Init(void);
u8 Spi_Change_Data(u8 data);
#endif
#include "w25q64.h"/************************************
函數功能:讀廠商ID
函數形參:void
函數返回值:void
函數說明:發送的指令是0x90
正常接收到的是0xef16
作者:
日期:
************************************/
void Read_ID(void)
{u16 w25q64_id = 0;CS_L;//拉低CS的片選信號也就是選中這一個芯片Spi_Change_Data(0x90);//發送讀ID的指令//發送24位的0Spi_Change_Data(0);Spi_Change_Data(0);Spi_Change_Data(0);w25q64_id = Spi_Change_Data(0);//得到廠商ID為EFh,此時發什么不重要w25q64_id <<= 8;//把接收到的數據存放到16位數據中的高8位w25q64_id |= Spi_Change_Data(0xff);CS_H;//拉高片選,表示這一次通信結束printf("%#x\r\n",w25q64_id);	
}/************************************
函數功能:寫使能
函數形參:void
函數返回值:void
函數說明:發送的指令是0x06
作者:
日期:
************************************/
void Write_Enable(void)
{CS_L;Spi_Change_Data(0X06);CS_H;
}/************************************
函數功能:讀狀態寄存器1
函數形參:void
函數返回值:u8
函數說明:發送的指令是0x05
作者:
日期:
************************************/
u8 Read_Register1(void)
{u8 reg = 0;CS_L;Spi_Change_Data(0X05);reg = Spi_Change_Data(0);CS_H;return reg;
}/************************************
函數功能:扇區擦除
函數形參:u32 addr
函數返回值:void
函數說明:發送的指令是0x20
地址只能是4096的倍數
00000000 00000000 00010000 00000000
作者:
日期:
************************************/
void Sector_Erase(u32 addr)
{u8 *p = (u8*)&addr;//現在是得到32位里的最低8位u8 ret;Write_Enable();//直到不忙才可以往下執行do{ret = Read_Register1();}while(ret & 0x1 << 0);CS_L;Spi_Change_Data(0x20);//發送這24位的地址數據Spi_Change_Data(p[2]);Spi_Change_Data(p[1]);Spi_Change_Data(p[0]);CS_H;//直到不忙才可以往下執行do{ret = Read_Register1();}while(ret & 0x1 << 0);	
}/************************************
函數功能:頁編程
函數形參:u32 addr--從這一頁的哪個位置開始寫入數據
u8 *str, -- 需要寫入的數據
u8 len --數據的長度
函數返回值:void
函數說明:發送的指令是0x02
當前擦除了哪一個扇區就可以在當前扇區的某一頁寫入數據
最大寫入256字節
作者:
日期:
************************************/
void Page_Program(u32 addr,u8 *str,u8 len)
{u8 *p = (u8*)&addr;//現在是得到32位里的最低8位u8 ret;Write_Enable();//直到不忙才可以往下執行do{ret = Read_Register1();}while(ret & 0x1 << 0);CS_L;Spi_Change_Data(0x02);//發送這24位的地址數據Spi_Change_Data(p[2]);Spi_Change_Data(p[1]);Spi_Change_Data(p[0]);while(len--){Spi_Change_Data(*str);str++;}CS_H;//直到不忙才可以往下執行do{ret = Read_Register1();}while(ret & 0x1 << 0);}/************************************
函數功能:讀數據
函數形參:u32 addr--從這一頁的哪個位置開始讀取數據
u8 *str, -- 讀取到的數據存放的地方
u8 len -- 數據的長度
函數返回值:void
函數說明:發送的指令是0x03
可以一直讀到芯片最后
作者:
日期:
************************************/
void Read_Data(u32 addr,u8 *str,u8 len)
{u8 *p = (u8*)&addr;//現在是得到32位里的最低8位u8 ret;CS_L;Spi_Change_Data(0x03);//發送這24位的地址數據Spi_Change_Data(p[2]);Spi_Change_Data(p[1]);Spi_Change_Data(p[0]);while(len--){*str = Spi_Change_Data(0);str++;}CS_H;
}/************************************
函數功能:跨頁寫
函數形參:u32 addr--從這一頁的哪個位置開始讀取數據
u8 *str, -- 讀取到的數據存放的地方
u8 len -- 數據的長度
函數返回值:void
函數說明:一次性可以發送多于256字節的數據到FLASH里
問題:當前的頁編程不能超過本頁的最大地址
解決:
需要判斷什么時候到達本頁的最大地址了
如果已經到了則地址自動跳轉到下一頁判斷這一頁還剩多少空間,如果不夠再去換頁寫入作者:
日期:
************************************/
void Page_AutoWrite(u32 addr,u8 *str,u8 len)//addr = 0,len = 289
{u16 less_len = 0;less_len = 256 - addr % 256;//判斷任意一頁還剩多少空間可以寫//如果剩余的空間足夠存下要寫入的數據則寫入數據長度為當前數據長度if(less_len>=len){less_len = len;}while(1){//寫入數據Page_Program(addr,str,less_len);//判斷當前頁剩余空間是不是已經等于要寫入數據的長度,如果相等則不需要換頁if(less_len == len){break;}//"4564654"addr +=  less_len;//代表當前地址的偏移str += less_len;//加上已經寫入的長度可以去到未寫入的數據的位置len = len - less_len;//代表未寫入的數據長度less_len = 256;//當前如果能跑到這一步,肯定是到下一頁的起始地址了if(less_len>=len)//1024{less_len = len;}}
}
#ifndef __W25Q64_H_
#define __W25Q64_H_#include "stm32f4xx.h"
#include "io_bit.h"
#include "spi.h"
#include "stdio.h"void Read_ID(void);
void Sector_Erase(u32 addr);
void Page_Program(u32 addr,u8 *str,u8 len);
void Read_Data(u32 addr,u8 *str,u8 len);
void Page_AutoWrite(u32 addr,u8 *str,u8 len);#endif

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/211184.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/211184.shtml
英文地址,請注明出處:http://en.pswp.cn/news/211184.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ffprobe命令行超詳細使用詳解

本文做為閱讀ffprobe源碼的前課程。為了之后方便理解ffprobe的源碼,咱們先從ffprobe的命令學習。 課程內容如下: 文章目錄 一、ffprobe主要選項說明1、每次使用ffprobe都打印編譯環境的信息,太煩了2、如何分析媒體文件中存在的流信息3、如何指定查詢某路流信息4、查看輸入文…

CS106L2023 and CS106B 環境配置(詳細教程)

1.問題&#xff1a; &#xff08;1&#xff09;CS106L 運行./setup.sh 腳本時出錯 &#xff08;windows 請下載git&#xff0c;在git bash 打開運行&#xff09; &#xff08;2&#xff09;CS106B&#xff0c;QT構建 構建錯誤&#xff1a;一般構建錯誤&#xff0c;例如 Erro…

【Java+MySQL】前后端連接小白教程

目錄 &#x1f36d;【IntelliJ IDEA】操作 &#x1f36d;1. 連接MySQL數據庫 &#x1f308;1.1 錯誤解決 &#x1f36d;2. 操作MySQL數據庫 &#x1f308;2.1 雙擊查看表數據 &#x1f308;2.2 編寫SQL腳本 &#x1f36d;【IntelliJ IDEA】 IntelliJ IDEA是由JetBrains公司…

2013年全國碩士研究生入學統一考試管理類專業學位聯考數學試題——解析版

文章目錄 2013 級考研管理類聯考數學真題一、問題求解&#xff08;本大題共 15 小題&#xff0c;每小題 3 分&#xff0c;共 45 分&#xff09;下列每題給出 5 個選項中&#xff0c;只有一個是符合要求的&#xff0c;請在答題卡上將所選擇的字母涂黑。真題&#xff08;2013-01&…

Django自定義中間件

自定義中間件 傳統方法的的五大鉤子函數&#xff1a;&#xff08;需要調用MiddlewareMixin類&#xff09; process_request&#xff0c;請求剛到來&#xff0c;執行視圖之前&#xff1b;正序 process_view&#xff0c;路由轉發到視圖&#xff0c;執行視圖之前&#xff1b;正序…

【Linux】地址空間

本片博客將重點回答三個問題 什么是地址空間&#xff1f; 地址空間是如何設計的&#xff1f; 為什么要有地址空間&#xff1f; 程序地址空間排布圖 在32位下&#xff0c;一個進程的地址空間&#xff0c;取值范圍是0x0000 0000~ 0xFFFF FFFF 回答三個問題之前我們先來證明地址空…

【Python數據結構與算法】—— 搜索算法 | 期末復習不掛科系列

? &#x1f308;個人主頁: Aileen_0v0&#x1f525;系列專欄: 數據結構與算法&#x1f4ab;個人格言:"沒有羅馬,那就自己創造羅馬~" 這篇博客主要探索的是計算機科學常見問題---搜索算法 “時間緊&#xff0c;任務重&#xff01;” 話不多說&#xff0c;開始今天…

HarmonyOS--ArkTS(0)--目錄

官方API文檔&#xff1a; HarmonyOS應用開發官網 - 華為HarmonyOS打造全場景新服務 華為開發者官方網站_創新從這里開始

MySQL的鎖機制

1.簡介 MySQL的隔離性是由鎖機制來保證的。鎖是計算機協調多個進程或線程并發地訪問某一資源你的機制。當多線程并發地訪問某個數據時&#xff0c;尤其是在涉及金錢等安全敏感性數據的時候&#xff0c;需要保證數據在任意時刻最多只有一個線程可以對其進行修改&#xff0c;從而…

Android 分享小結

關于作者&#xff1a;CSDN內容合伙人、技術專家&#xff0c; 從零開始做日活千萬級APP。 專注于分享各領域原創系列文章 &#xff0c;擅長java后端、移動開發、商業變現、人工智能等&#xff0c;希望大家多多支持。 目錄 一、導讀二、微信 分享 三、 QQ 、QQ空間&#xff08;Qz…

MATLAB基礎運算

矩陣和數字相乘 就是矩陣里面每個元素跟這個數字乘一遍&#xff0c;無論是點乘還是叉乘&#xff0c;對于這個都一樣。 >> Aones(3) A 1 1 11 1 11 1 1 >> 10*A ans 10 10 1010 10 1010 10 10 矩陣和矩陣叉乘 能不能相…

C++普通函數與函數模板的調用規則

調用規則 如果函數模板和普通函數都可以實現&#xff0c;優先調用普通函數可以通過空模板參數列表來強制調用函數模板函數模板也可以重載如果函數模板可以產生更好的匹配&#xff0c;優先調用函數模板 總結&#xff1a;既然提供了函數模板&#xff0c;最好就不要提供普通函數…

CSS 如何居中 DIV

如何居中 div&#xff1f; 水平居中&#xff1a;給 div 設置一個寬度&#xff0c;然后添加 margin:0 auto 屬性 div {width: 200px;margin: 0 auto; }水平居中&#xff0c;利用 text-align:center 實現 .container {background: rgba(0, 0, 0, 0.5);text-align: center;font…

基于ssm鐵嶺河醫院醫患管理系統論文

摘 要 21世紀的今天&#xff0c;隨著社會的不斷發展與進步&#xff0c;人們對于信息科學化的認識&#xff0c;已由低層次向高層次發展&#xff0c;由原來的感性認識向理性認識提高&#xff0c;管理工作的重要性已逐漸被人們所認識&#xff0c;科學化的管理&#xff0c;使信息存…

logback的使用

1 logback概述 SLF4J與其它日志組件調用關系圖如下所示。 SLF4J&#xff0c;即Java中的簡單日志門面&#xff08;Simple Logging Facade for Java&#xff09;&#xff0c;不是具體的日志解決方案&#xff0c;它只服務于各種各樣的日志系統。 SLF4J最常用的日志實現框架是&am…

2023 CCF中國軟件大會(CCF ChinaSoft) “區塊鏈可靠性分析”論壇成功召開

2023年12月1日上午&#xff0c;2023年度CCF中國軟件大會區塊鏈可靠性分析論壇成功召開。 本次論壇由中山大學鄭子彬、澳門科技大學張濤、中科院軟件所蔡彥和中山大學陳嘉弛四位老師聯合組織舉辦。本論壇重點關注區塊鏈可靠性&#xff0c;邀請了近年來在區塊鏈可靠性研究方面有先…

【postgresql】ERROR: INSERT has more expressions than target columns

執行下面sql insert into apply_account_cancellation3 select * from pply_account_cancellation; 返回下面錯誤信息 insert into apply_account_cancellation3 select * from apply_account_cancellation > ERROR: INSERT has more expressions than target colu…

【Rust】第二節:入門(如入)

1 說明 包含"Hello, world!“以及"Hello, cargo!” 環境&#xff1a;MacOS 2 Hello world 2.1 運行 1、建一個目錄 2、用vscode打開 3、新建文件main.js 4、輸入 fn main(){println!("Hello, world!"); }5、打開終端&#xff0c;執行rustc main.rs 6、…

Java:字節流 文件輸出與讀入方法 并 實現文件拷貝

文章目錄 字節 流FileOutputStream換行 與 續寫FileInputstream實現 文件拷貝&#xff08;字節數組 讀入方法&#xff09;字節流 編碼 字節 流 FileOutputStream 創建對象&#xff0c;指定位置&#xff08;產生數據傳輸通道&#xff09; 參數可以是File對象&#xff0c;也可以…

特征驅動開發

FDD 方法來自于一個大型的新加坡銀行項目。FDD 的創立者 Jeff De Luca 和 Peter Coad 分別是這個項目的項目經理和首席架構設計師。在 Jeff 和 Peter 接手項目時&#xff0c;客戶已經經歷了一次項目的失敗&#xff0c;從用戶到高層都對這個項目持懷疑的態度&#xff0c;項目組士…