關於stm32通信協議:軟體模擬SPI、軟體模擬I2C的總結

2021-01-06 電子工程世界

趁著幫老師代上嵌入式實驗課的機會,又重新熟悉了一遍stm32的通信協議:串口協議、SPI協議、I2C協議、RS485協議。大概半年前,是過了一遍的,但也只停留於讀了遍代碼,跑了下例程,最近又過了一遍(自己仔細的看了一遍,老師還給我們講了一遍,自己又講了一遍),然後還寫了一遍軟體模擬SPI、軟體模擬I2C的代碼,才徹底的懂了個皮毛 ,:)。稍微總結下吧,總結的不好,都是自己的理解,僅供參考,主要說軟體模擬SPI、I2C,硬體SPI和硬體I2C就不說了。


串口協議

串口協議沒什麼可說的,現在常用的串口協議,是基於以前的RS232的協議,因為RS232的引腳太多而改進過來的。

物理層只用三根引腳:TXD、RXD、GND(最好接,不然有點影響),然後TXD接RXD、RXD接TXD、GND接GND(這裡我第一次接錯過的,所以寫出來),通過有兩個收發引腳就能看出,串口協議是支持全雙工的;

協議層的話,就是起始信號(1個0表示)+數據包(5、6、7、8位可選)+校驗位(無、0、1、奇、偶可選)+停止信號(0.5、1、1.5、2個1表示)。

串口協議,很常見,多用於列印調試信息,也比較簡單;


RS485協議

RS485協議,協議層未改,只是在串口協議的物理層做了修改,外接了一個物理收發器,然後在通信雙方的兩條A、B線加了電阻,通過測A、B線的電壓差來傳送高低電平信號,所以485通信協議的特點就是抗幹擾性強、傳輸距離遠,可以組網。由於是通過A線、B線的電壓差傳輸高低電平信號,所以是半雙工的,同一時刻只能發送或者接收。物理連接方式:A線接A線,B線接B線。


如何理解半雙工、全雙工,我看到網上一個很好的例子可以幫助理解。就是說,把半雙工通信比作是對講機通信,全雙工就是手機通信,對講機同一時刻只能說或者是聽,而手機是可以同時說、聽的。


前面兩個協議比較簡單,而SPI協議、I2C協議稍微麻煩點,主要說一下。


SPI協議

SPI協議,多應用於ADC、DA、LCD等設備與MCU間,要求通信速率較高的場合。一般需要4根信號線,分別是MOSI、MISO、SCK、CS線。但是!敲黑板!有可能可以只用3根,當你通過SPI和DA設備通信的時候,MISO線就可以不要了,然後我們老師更誇張,說如果你只連一個DA設備的話,那麼CS線也可以不要,這裡我有點不敢苟同,因為畢竟片選線是控制通訊開始結束的,但這種思想是可取的了,規則是死的,人是活的,要活學活用,這裡當時聽到老師講這點的時候還是有點震撼的。扯的有點遠了。。。但其實,這裡要說的軟體模擬。


還是回到正題,接著說軟體模擬SPI,當MCU的SPI外設不夠用的時候,我們就會用GPIO去模擬SPI的方式,去和支持SPI的從設備通信。下面直接貼代碼了,代碼已經調通的了。我做的實驗是用F429IGT6通過軟體模擬SPI讀寫一款W25Q128的FLASH晶片,模擬的是模式3(CPOL=1,CPHA=1),有兩點原因:①模式3的SCK空閒電平為高電平,由高電平向低電平翻轉快,而且容易;②模式3在偶數邊沿採樣,防止第一個信號沒採到。


首先,是GPIO的初始化,CS引腳、MOSI引腳、MISO引腳、SCK引腳。除了MISO引腳配成輸入模式,其餘三個引腳都配成輸出模式(推輓輸出)。


void SPI_FLASH_Init(void)

{

/*定義一個GPIO_InitTypeDef類型的(基本IO)結構體*/

  GPIO_InitTypeDef GPIO_InitStructure;

  

  /***** 使能 GPIO 時鐘 *****/

 /* 使能 FLASH_SPI引腳的GPIO時鐘< SPI_CS; SPI_MOSI; SPI_MISO; SPI_SCK > ( F口 )*/

  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOF, ENABLE);


/* < 配置 SPI_FLASH_SPI 引腳: SCK; MISO; MOSI > */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7  | GPIO_Pin_9;

 /* 設置引腳模式為 SPI_5 復用功能*/

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; 

/* 設置引腳速率為50MHz */   

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   

  /* 設置引腳的輸出類型為推輓輸出*/

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  /* 設置引腳為無上拉 下拉模式*/

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;  

  /* 調用庫函數,使用上面配置的GPIO_InitStructure初始化GPIO_F*/

GPIO_Init(GPIOF, &GPIO_InitStructure);

  

/* < 配置 SPI_FLASH_SPI 引腳: CS > */

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

GPIO_Init(GPIOF, &GPIO_InitStructure);


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;

GPIO_Init(GPIOF, &GPIO_InitStructure);

GPIOF->BSRRL = GPIO_Pin_6;//拉高CS線

GPIO_SetBits(GPIOF, GPIO_Pin_7);//拉高時鐘線,模擬模式3


}


接下來,就是基本的發送、接收函數了。延時是用Symtick來延時,為了延時精確,符合W25Q128晶片數據手冊的時序,理論上應該也可以用軟體延時(未嘗試)。


//軟體模擬SPI寫(發送)

void Soft_SPI_Write(uint8_t a)

{

uint8_t cnt;

for(cnt=0;cnt<8;cnt++)

{

GPIO_ResetBits(GPIOF, GPIO_Pin_7);//拉低CLK

Delay_us(10);//這個延時時間任意,但要大於晶片數據手冊上的(納秒級的)

if(a &0x80)

{

GPIO_SetBits(GPIOF, GPIO_Pin_9);

}

else

{

GPIO_ResetBits(GPIOF, GPIO_Pin_9);

}

a <<= 1;

Delay_us(10);

GPIO_SetBits(GPIOF, GPIO_Pin_7);//拉高CLK

Delay_us(10);

}

}


//軟體模擬SPI讀(接收)

uint8_t Soft_SPI_Read(void)

{

uint8_t cnt;

uint8_t Rxdata = 0;

for(cnt=0;cnt<8;cnt++)

{

GPIO_ResetBits(GPIOF, GPIO_Pin_7);//拉低CLK

Delay_us(10);

Rxdata <<= 1;

if(GPIO_ReadInputDataBit(GPIOF, GPIO_Pin_8))

{

Rxdata |= 0x01;

}

GPIO_SetBits(GPIOF, GPIO_Pin_7);//拉高CLK

Delay_us(10);

}

return Rxdata;

}


然後是,W25Q128晶片的等待準備好的函數。通過讀取該晶片的BUSY位是否為1(繁忙)實現,這款FLAH 是這樣的,你要根據你要執行的操作找到要發送的指令是哪個,以及對應的時序,按照它的時序來,注意時序線上的時間。


void Soft_WaitFlahToBeReady(void)

{

u8 FLASH_Status = 0x01;

GPIOF->BSRRH = GPIO_Pin_6;  //**CS低**

Soft_SPI_Write(0x05);

do

{

Soft_SPI_Write(0xFF);

FLASH_Status = Soft_SPI_Read();

}

while((FLASH_Status & 0x01) == 1);


printf("rn 繁忙狀態位為: 0x%Xrn", FLASH_Status);

GPIOF->BSRRL = GPIO_Pin_6;  //**CS高**


}


再是,FLASH 的扇區擦除函數了,所有的FLASH每次寫入前都要進行擦除。


void Soft_Flash_SectorErase(u32 EraseAddr)

{

GPIOF->BSRRH = GPIO_Pin_6;  //**CS低**

Soft_SPI_Write(0x06);//寫使能指令

GPIOF->BSRRL = GPIO_Pin_6;  //**CS高**


GPIOF->BSRRH = GPIO_Pin_6;  //**CS低**

Soft_SPI_Write(0x20);//扇區擦除指令

Soft_SPI_Write((EraseAddr & 0xFF0000) >> 16);

Soft_SPI_Write((EraseAddr & 0xFF00) >> 8);

Soft_SPI_Write((EraseAddr & 0xFF));

GPIOF->BSRRL = GPIO_Pin_6;  //**CS高**

Soft_WaitFlahToBeReady();

}


再就是,頁寫入函數了,這款FLASH晶片支持三種寫入方式,單字節寫入、頁寫入(<256Bytes)、多字節寫入(基於頁寫入)。顯然,頁寫入方式比單字節寫入快,這裡我只做了頁寫入的方式,用於驗證是否成功,多字節寫入的方式可以在此方式上拓展,秉火的例程上有,可以參考。


void Soft_SPIFlashPageWrite(u8* Pbuffer,u32 Writeaddr,u16 NumberByteToWrite)

{

GPIOF->BSRRH = GPIO_Pin_6;  //**CS低**

Soft_SPI_Write(0x06);//寫使能指令

GPIOF->BSRRL = GPIO_Pin_6;  //**CS高**


GPIOF->BSRRH = GPIO_Pin_6;  //**CS低**

Soft_SPI_Write(0x02);//寫頁寫入指令


Soft_SPI_Write((Writeaddr & 0xFF0000) >> 16);

Soft_SPI_Write((Writeaddr & 0xFF00) >> 8);

Soft_SPI_Write((Writeaddr & 0xFF));

if(NumberByteToWrite > 256)

{

NumberByteToWrite = 256;

printf("寫入的字節數大於256");

}

while(NumberByteToWrite--)

{

Soft_SPI_Write(*Pbuffer);

Pbuffer++;

}

GPIOF->BSRRL = GPIO_Pin_6;  //**CS高**

Soft_WaitFlahToBeReady();

}


最後就是讀FLASH函數了,該晶片支持多字節一直讀。


void Soft_SPIFlashRead(u8* Pbuffer,u32 ReadAddr,u16 NumberByteToRead)

{


GPIOF->BSRRH = GPIO_Pin_6;  //**CS低**

Delay_us(10);

Soft_SPI_Write(0x03);//寫讀使能指令


Soft_SPI_Write((ReadAddr & 0xFF0000) >> 16);

Soft_SPI_Write((ReadAddr & 0xFF00) >> 8);

Soft_SPI_Write((ReadAddr & 0xFF));

while(NumberByteToRead--)

{

//Soft_SPI_Write(0xFF);//這裡一開始是加了的,因為SPI是全雙工的,

*Pbuffer = Soft_SPI_Read();//但是加了,讀就有問題,然後仔細看了時序圖,發現其實不加也可以

Pbuffer++;

}

GPIOF->BSRRL = GPIO_Pin_6;  //**CS高**

}

關鍵字:stm32  通信協議  軟體模擬SPI  軟體模擬I2C 編輯:什麼魚 引用地址:http://news.eeworld.com.cn/mcu/ic473289.html

相關焦點

  • 關於調試stm32和stm8(51單片機)的i2c和spi協議的之間的區別
    在調試STM32的i2c和io口模擬spi協議時發現時序是很關鍵的。stm32在72M運行下可以實現i2c或者spi協議,但並不代表把相同的代碼移植到51單片機上就會成功的跑起來,因為51單片機的速讀最塊8M,所以在時序上會產生很多大的區別。經過測試,在stm32上的spi協議時鐘線可達到20Khz,移植到51後,頻率會降到<10hz。
  • stm32與FPGA通信代碼實現方案spi
    spi_cs_data為低時數據接收,發送的方法跟接收是對稱的,所以在spi_cs_data為高的期間,一旦spi_scl的下降沿到來,就要將剛剛接收的數據存入數據發送寄存器進行din_reg中,仍然是等到spi_cs_data低電平期間一旦spi_scl下降沿到來時就將din_reg中並行數據轉換成串行數據並經過spi_sdo埠輸出給stm32,有事經過位寬個通信時鐘後數據發送完畢,spi_cs_data
  • STM32——硬體和軟體I2C協議
    I2C協議I2C 通訊協議(Inter-Integrated Circuit)是由 Phiilps 公司開發的,由於它引腳少,硬體實現簡單,可擴展性強,不需要 USART、CAN 等通訊協議的外部收發設備,現在被廣泛地使用在系統內多個集成電路(IC)間的通訊。
  • STM32F10x_SPI(硬體接口 + 軟體模擬)讀寫Flash(25Q16)
    Ⅰ、寫在前面SPI(Serial Perripheral Interface)串行外設通信接口,主要實現設備(主從)之間的通信。硬體上由CS、SCK、MISO、MOSI四根通信線連接而成。關於SPI更多介紹不再詳細描述,本文主要以STM32F103為主機、W25Q16為從機進行SPI通信實驗。
  • I2C 協議之軟體模擬時序
    在 I2C 總線上面,每個器件都有自己相應的 I2C 地址,所以在兩個器件之間進行通信的時候,都要首先呼叫你想要通信的器件地址,然後等待相應的從器件進行應答之後才開始通信。首先我們來看一下,一個 I2C 信號傳輸的一個過程,如圖:
  • 關於stm32硬體spi的miso口配置
    在我們剛使用spi時,對於spi的io口配置可能會有一些疑惑吧,miso明明是一個輸入口卻配置成了復用推輓輸出,是不是會有一點疑惑呢? 關鍵字:stm32  硬體spi  miso口配置 編輯:什麼魚 引用地址:http://news.eeworld.com.cn/mcu/ic459417.html 推薦閱讀
  • stm32通過spi連接esp8266的hspi 開發
    esp8266模塊本身發布的時候默認裡邊燒寫的是AT固件,雖然硬體上有spi的引腳,但是並不支持spi的通信,如果要支持spi的通信,自行修改編譯esp8266的sdk,寫自己需要的代碼來實現。本身sdk中有相關的例程,根據例程的代碼修改調試就可以實現相應的功能。使用spi的好處,第一 可以節省一個串口,因為stm的串口資源是比較有限的。
  • 單片機,硬體IIC和軟體IIC的區別
    所謂硬體I2C對應晶片上的I2C外設,有相應I2C驅動電路,其所使用的I2C管腳也是專用的;軟體I2C一般是用GPIO管腳,用軟體控制管腳狀態以模擬I2C通信波形。硬體I2C的效率要遠高於軟體的,而軟體I2C由於不受管腳限制,接口比較靈活。模擬I2C 是通過GPIO,軟體模擬寄存器的工作方式,而硬體(固件)I2C是直接調用內部寄存器進行配置。
  • spi與i2c總線有什麼區別
    SPI,是一種高速的,全雙工,同步的通信總線,並且在晶片的管腳上只佔用四根線,節約了晶片的管腳,同時為PCB的布局上節省空間,提供方便,正是出於這種簡單易用的特性,如今越來越多的晶片集成了這種通信協議,比如AT91RM9200。
  • 《rt-thread驅動框架分析》-i2c驅動
    驅動層:分為硬體I2C驅動和軟體I2C驅動。核心層: ①其中bit_ops是RTT為軟體I2C提供的中間層,它的作用:為底層模擬I2C驅動提供回調接口,為核心層提供統一I2C通信接口。②而硬體I2C則直接對接核心層,提供統一I2C通信接口。③RTT在核心層上,也像pin驅動那樣,封裝了一套API(虛線箭頭),供用戶直接使用。
  • STM32—cubeMX+HAL庫的SPI接口使用
    摘要: 本文主要介紹STM32的SPI接口、cubeMX軟體配置SPI接口和分析SPI相關代碼。STM32之SPI簡介:(1)SPI協議【Serial Peripheral Interface】   串行外圍設備接口,是一種高速全雙工的通信總線。
  • STM32 SPI詳解
    3.5、軟體設置極性和相位SPI分主設備和從設備,兩者通過SPI協議通訊。SPI,是一種高速的,全雙工,同步的通信總線,並且在晶片的管腳上只佔用四根線,節約了晶片的管腳,同時為PCB的布局上節省空間,提供方便,正是出於這種簡單易用的特性,現在越來越多的晶片集成了這種通信協議,STM32也有SPI接口。
  • STM32F103編程學習——I2C通信
    主要特徵I2C通信分主從設備,總線上可以有多個從設備,通信由主設備發起,通過不同地址尋址方式與從設備通信。可根據不同硬體進行軟體配置。工程配置利用cube mx軟體配置系統時鐘,i2c外設等相關配置。為了防止意外擦寫,特將WP引腳信號引出通過軟體來控制,每次在需要寫數據到eeprom中去時,需要先將該信號拉低,否則防寫。配置好上述基本設置後,生成工程,添加應用代碼即可實現i2c讀寫操作。
  • I2C 總線協議的簡單總結
    含CPU的智能器件,地址由軟體初始化時定義,但不能與其它的器件有衝突;    2. 不含CPU的非智能器件,由廠家在器件內部固化,不可改變。低三位為引腳設定地址,可以由外部引腳來設定(並非所有器件都可以設定); 關鍵字:I2C  總線協議  簡單總結 編輯:什麼魚 引用地址:http://news.eeworld.com.cn/qrs/article_26504.html 本網站轉載的所有的文章
  • Synchro 4D在BIM施工進度模擬與管控中的應用總結「軟體篇」
    那麼,如何運用BIM技術實現可視化施工進度模擬?如何將BIM技術融入到現場施工進度管控中去?如何使用高效的BIM施工進度模擬軟體輔助進度管理?今天,給大家帶來Synchro 4D施工進度模擬軟體在BIM施工進度模擬中的應用經驗與方法分享。
  • STM32_SPI讀寫Flash
    今天講解「STM32F103 SPI讀寫Flash」,其實這第一階段主要是講解STM32的SPI功能,所有今天的重點是SPI,關於FLASH我應該要在後面再次講述。今天提供並講解的軟體工程,基於軟體工程「A0.0.0(STM32F10x_TIM延時)」修改而來。若不知道如何而來,請關注微信公眾號「EmbeddDeveloper」獲取更多信息。
  • STM32系列之SPI_NSS的理解
    大多數的SPI從機的片選有效為低電平,當某一從機的NSS引腳為低電平時,該機被選中,就可以和主機通過SPI通信了。所有的主機和從機其實都有片選信號,只有片選了,才能工作。但是主機的片選是通過軟體配置完成的,讀完下面的幾段,希望能給您說清楚。在STM32中,當要配置為slave時,只要將它的NSS引腳配置為低電平即可。
  • 踏踏實實搞清 stm32 SPI總線 基礎和編程
    >全雙工 一主控多從 8或16位數據通信SPI總線時序介紹:看下下圖應該就會了使用stm32 spi需要以下的步驟1.管腳因為復用的,故先配置好管腳、並打開spi時鐘2.設置spi的工作模式通過 SPI1_CR1 來設置,設置SPI1主機模式,設置數據格式8位,然後通過 CPOL 和 CPHA 位來設置 SCK時鐘極性及採樣方式。
  • STM32 SPI筆記(基於寄存器)
    1.說在前面:最近嘗試操作VS1053音頻模塊 使用的數據傳輸方法使用SPI協議,打算學一下SPI的配置方式2.SPI2-1:SPI(Secial Periperal interface),作為四線的通信接口,有著MISO MOSI SCLK和CS
  • 如何模擬三菱PLC編程軟體
    今天這篇文章主要的講的是如何模擬三菱PLC編程軟體。關於現在三菱PLC的編程軟體(GX Developer,GX Works)基本自帶模擬功能,而且操作簡單,可以實現與PLC同等功能,包括軟元件和緩衝儲存器。