日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > 單片機(jī) > 單片機(jī)
[導(dǎo)讀]STM32-IIC 配置解說(原創(chuàng))STM32 - I2C 簡(jiǎn)介 :I2C 總線接口連接微控制器和串行 I2C 總線。它提供多主機(jī)功能,控制所有 I2C總線特定的時(shí)序、協(xié)議、仲裁和定時(shí)。支持標(biāo)準(zhǔn)和快速兩種模式,另外 STM32的 I2C 可以使用

STM32-IIC 配置解說(原創(chuàng))STM32 - I2C 簡(jiǎn)介 :I2C 總線接口連接微控制器和串行 I2C 總線。它提供多主機(jī)功能,控制所有 I2C總線特定的時(shí)序、協(xié)議、仲裁和定時(shí)。支持標(biāo)準(zhǔn)和快速兩種模式,另外 STM32的 I2C 可以使用 DMA 方式操作。本文主要以一個(gè)實(shí)例來介紹 STM32-I2C 的配置方式和具體在工程中通過調(diào)用哪些庫(kù)函數(shù)來實(shí)現(xiàn)I2C 器件的通信。實(shí)例:寫入數(shù)據(jù)到器件 AT24C02 并將存入的數(shù)據(jù)讀出好,我們先來講講 STM32 I2C 模塊的端口基本配置,由 STM32 中文參考手冊(cè)可以查到在使用 I2C 時(shí)對(duì)應(yīng)的引腳要配置成哪種模式。 SCL 和 SDA 引腳都配置成開漏復(fù)用輸出
本人用的是 STM32F103VET6,它有 2 個(gè) I2C 接口。 I/O 口定義為 PB6-I2C_SCL,
PCB7-I2C1_SDA; PB10-I2C_SCL, PB11-I2C_SDA,由手冊(cè)可以查出對(duì)應(yīng)的端口。
圖文如下:
調(diào)用庫(kù)函數(shù)將 I2C 端口配置好(本文使用的是 PB6、 PB7 端口):
程序代碼如下:

void I2C_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //GPIO 結(jié)構(gòu)體定義
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能 I2C 的 IO 口

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 開漏輸出
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化結(jié)構(gòu)體配置
}

void I2C_Mode_config(void)
{

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);

I2C_InitTypeDef I2C_InitStructure;

I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

I2C_InitStructure.I2C_OwnAddress1 =0x0A;

I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;

I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

I2C_InitStructure.I2C_ClockSpeed = 400000;

I2C_Cmd(I2C1, ENABLE);

I2C_Init(I2C1, &I2C_InitStructure);
}
好了, STM32 內(nèi)部的 I2C 模塊工作模式就這樣被設(shè)好了,接下來需要完成與外部器件
AT24C02( EEPROM)進(jìn)行通信。將分兩部分進(jìn)行代碼解析,第一部分是:對(duì) AT24C02 進(jìn)
行寫操作,第二部分:對(duì) AT24C02 進(jìn)行讀操作。
第一部分(寫):
備注: I2C_PageSize 為宏定義 #define I2C_PageSize 8 ;

void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)
{
u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;
Addr = WriteAddr % I2C_PageSize;//查看輸入的地址是不是 8 的整數(shù)倍
count = I2C_PageSize - Addr;//表示距離下一頁(yè)頁(yè)首地址的距離(步伐數(shù))
NumOfPage = NumByteToWrite / I2C_PageSize;//算出一共有多少頁(yè)
NumOfSingle = NumByteToWrite % I2C_PageSize;//算出不夠一頁(yè)的數(shù)據(jù)的余數(shù)
if(Addr == 0) //如果輸入的地址是首頁(yè)地址
{
if(NumOfPage == 0) //如果不足一頁(yè)數(shù)據(jù)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//調(diào)用寫函數(shù), NumOfSingle 不
夠一頁(yè)的余數(shù)作為實(shí)參
I2C_EE_WaitEepromStandbyState();//等待 EEPROM 器件完成內(nèi)部操作
}

else //如果數(shù)據(jù)有一頁(yè)以上
{
while(NumOfPage--)//用一個(gè) while 循環(huán),執(zhí)行頁(yè)寫循環(huán)操作,有多少頁(yè)就寫多少次
{
I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize); //調(diào)用寫函數(shù),將
I2C_PageSize 變量作為實(shí)
參執(zhí)行頁(yè)寫
I2C_EE_WaitEepromStandbyState();//等待 EEPROM 器件完成內(nèi)部操作
WriteAddr += I2C_PageSize;//每執(zhí)行完一次頁(yè)寫對(duì)應(yīng)的地址也需要移 8 個(gè)位
pBuffer += I2C_PageSize;//數(shù)據(jù)指針移 8 個(gè)位
}
if(NumOfSingle!=0)//如果有不足一頁(yè)的數(shù)據(jù)余數(shù)則執(zhí)行
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//調(diào)用寫函數(shù), NumOfSingle
不夠一頁(yè)的余數(shù)作為實(shí)參
I2C_EE_WaitEepromStandbyState();//等待 EEPROM 器件完成內(nèi)部操作
}
}
}
else //輸入的地址不是首頁(yè)地址
{
if(NumOfPage== 0) //如果不足一頁(yè)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//調(diào)用寫函數(shù), NumOfSingle 不
夠一頁(yè)的余數(shù)作為實(shí)參
I2C_EE_WaitEepromStandbyState();//等待 EEPROM 器件完成內(nèi)部操作
}
else//如果有一頁(yè)或一頁(yè)以上
{
NumByteToWrite -= count;//將地址后續(xù)的缺省位置補(bǔ)上數(shù)據(jù),數(shù)據(jù)的多少就是 count
的值, NumByteToWrite 變量的值就是補(bǔ)上數(shù)據(jù)之后
還剩下未發(fā)送的數(shù)量
NumOfPage = NumByteToWrite / I2C_PageSize;//剩余的頁(yè)數(shù)
NumOfSingle = NumByteToWrite % I2C_PageSize;//不足一頁(yè)的數(shù)據(jù)數(shù)量
if(count != 0)//將地址后續(xù)的缺省位置補(bǔ)上數(shù)據(jù)
{
I2C_EE_PageWrite(pBuffer, WriteAddr, count);//調(diào)用寫函數(shù),以 count 為實(shí)參,將地
址缺省下來的部分地址給填充
上數(shù)據(jù)
I2C_EE_WaitEepromStandbyState();//等待 EEPROM 器件完成內(nèi)部操作
WriteAddr += count;//加上 count 后,地址就移位到下一頁(yè)的首地址
pBuffer += count;//數(shù)據(jù)指針移 count 個(gè)位
}
while(NumOfPage--)//將剩余的頁(yè)數(shù)數(shù)據(jù)寫入 EEPROM
{
I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);//調(diào)用寫函數(shù),將
I2C_PageSize 變量作為實(shí)
參執(zhí)行頁(yè)寫
I2C_EE_WaitEepromStandbyState();//等待 EEPROM 器件完成內(nèi)部操作
WriteAddr += I2C_PageSize;//將地址移 8 個(gè)位
pBuffer += I2C_PageSize; //將數(shù)據(jù)指針移 8 個(gè)位
}
if(NumOfSingle != 0)//將不足一頁(yè)的數(shù)據(jù)寫入 EEPROM
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//調(diào)用寫函數(shù), NumOfSingle
不夠一頁(yè)的余數(shù)作為實(shí)參
I2C_EE_WaitEepromStandbyState();//等待 EEPROM 器件完成內(nèi)部操作
}
}
}
}

在以上寫操作里面我們拿經(jīng)常被調(diào)用的 I2C_EE_PageWrite 函數(shù)還有
I2C_EE_WaitEepromStandbyState 函數(shù)并結(jié)合 STM32 中文參考手冊(cè)圖文進(jìn)行對(duì)照分析
請(qǐng)讀者在讀 I2C_EE_PageWrite 函數(shù)時(shí)請(qǐng)結(jié)合上述時(shí)序圖和下述代碼聯(lián)系一起看!
注: EEPROM_ADDRESS 為器件的地址,大家按照自己具體器件地址寫入即可,
例: #define EEPROM_ADDRESS 0xA0

void I2C_EE_PageWrite(u8* pBuffer, u8 WriteAddr, u8 NumByteToWrite)
{
I2C_GenerateSTART(I2C1, ENABLE);//產(chǎn)生起始位
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //清除 EV5
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//發(fā)送器件地

while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
//ADDR=1,清除 EV6
I2C_SendData(I2C1, WriteAddr); //EEPROM 的具體存儲(chǔ)地址位置
while(! I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//移位寄
存器非空,數(shù)據(jù)寄存器已經(jīng)空,產(chǎn)生 EV8,發(fā)送數(shù)據(jù)到 DR 既可清除該事件
while(NumByteToWrite--) //利用 while 循環(huán) 發(fā)送數(shù)據(jù)
{
I2C_SendData(I2C1, *pBuffer); //發(fā)送數(shù)據(jù)
pBuffer++; //數(shù)據(jù)指針移位
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//清除
EV8
}
I2C_GenerateSTOP(I2C1, ENABLE);//產(chǎn)生停止信號(hào)
}

I2C_EE_WaitEepromStandbyState 這個(gè)函數(shù),在每調(diào)用完寫操作函數(shù)后都調(diào)用這個(gè)函數(shù),這
個(gè)函數(shù)是用來檢測(cè) EEPROM 器件是否已經(jīng)完成內(nèi)部寫的操作,判斷器件完成操作后在進(jìn)行
下一步的操作!代碼如下:

void I2C_EE_WaitEepromStandbyState(void)
{
vu16 SR1_Tmp = 0;
do
{
I2C_GenerateSTART(I2C1, ENABLE);//產(chǎn)生起始信號(hào)
SR1_Tmp = I2C_ReadRegister(I2C1, I2C_Register_SR1);//讀 SR1 寄存器
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//發(fā)送器件
地址清除事

}while(!(I2C_ReadRegister(I2C1, I2C_Register_SR1) & 0x0002));//如果接收不到從機(jī)的應(yīng)
答( NACK)則說明 EEPROM 器件還在工作,直到完成操作跳出循環(huán)體!
I2C_ClearFlag(I2C1, I2C_FLAG_AF);//清除 AF 標(biāo)志位
I2C_GenerateSTOP(I2C1, ENABLE); //產(chǎn)生停止信號(hào)
}
第二部分(讀):
由以上 AT24C02 讀時(shí)序圖可以知道:讀部分需要產(chǎn)生兩次起始信號(hào)
另外:主設(shè)備在從從設(shè)備接收到最后一個(gè)字節(jié)后發(fā)送一個(gè) NACK 。接收到 NACK 后,從設(shè)備
釋放對(duì) SCL 和 SDA 線的控制;主設(shè)備就可以發(fā)送一個(gè)停止/ 重起始條件。
● 為了在收到最后一個(gè)字節(jié)后產(chǎn)生一個(gè) NACK 脈沖,在讀倒數(shù)第二個(gè)數(shù)據(jù)字節(jié)之后(在倒
數(shù)第二個(gè) RxNE 事件之后)必須清除 ACK 位。
● 為了產(chǎn)生一個(gè)停止/ 重起始條件,軟件必須在讀倒數(shù)第二個(gè)數(shù)據(jù)字節(jié)之后(在倒數(shù)第二
個(gè) RxNE 事件之后)設(shè)置 STOP/START 位。
● 只接收一個(gè)字節(jié)時(shí),剛好在 EV6 之后(EV6_1 時(shí),清除 ADDR 之后)要關(guān)閉應(yīng)答和停止條
件的產(chǎn)生位。
請(qǐng)讀者將代碼和圖結(jié)合在一起看!

void I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)//需要兩個(gè)起
始信號(hào)
{
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); //調(diào)用庫(kù)函數(shù)檢測(cè) I2C 器件是否處
于 BUSY 狀態(tài)
I2C_GenerateSTART(I2C1, ENABLE);//開啟信號(hào)
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));//清除 EV5
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//寫入器
件地址
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//清
除 EV6
I2C_SendData(I2C1, ReadAddr); //發(fā)送讀的地址
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//清除 EV8
I2C_GenerateSTART(I2C1, ENABLE);//開啟信號(hào)
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));//清除 EV5
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver);//將器件地址
傳出,主機(jī)為讀
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//清除
EV6
while(NumByteToRead)
{
if(NumByteToRead == 1)//只剩下最后一個(gè)數(shù)據(jù)時(shí)進(jìn)入 if 語句
{
I2C_AcknowledgeConfig(I2C1, DISABLE);//最后有一個(gè)數(shù)據(jù)時(shí)關(guān)閉應(yīng)答位
I2C_GenerateSTOP(I2C1, ENABLE);//最后一個(gè)數(shù)據(jù)時(shí)使能停止位
}
if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) //讀取數(shù)據(jù)
{
*pBuffer = I2C_ReceiveData(I2C1);//調(diào)用庫(kù)函數(shù)將數(shù)據(jù)取出到 pBuffer
pBuffer++; //指針移位
NumByteToRead--;//字節(jié)數(shù)減 1
}
}
I2C_AcknowledgeConfig(I2C1, ENABLE);//將應(yīng)答位使能回去,等待下次通信
}
STM32-IIC 配置解說到此告一段落!
如果有不正確的地方也請(qǐng)各位多多指教,本人及時(shí)糾正;歡
迎大家來和我相互交流學(xué)習(xí),謝謝大家。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

在嵌入式開發(fā)中,STM32的時(shí)鐘系統(tǒng)因其靈活性和復(fù)雜性成為開發(fā)者關(guān)注的焦點(diǎn)。然而,看似簡(jiǎn)單的時(shí)鐘配置背后,隱藏著諸多易被忽視的陷阱,輕則導(dǎo)致系統(tǒng)不穩(wěn)定,重則引發(fā)硬件損壞。本文從時(shí)鐘源選擇、PLL配置、總線時(shí)鐘分配等關(guān)鍵環(huán)...

關(guān)鍵字: STM32 時(shí)鐘系統(tǒng)

在嵌入式系統(tǒng)開發(fā)中,STM32系列微控制器的內(nèi)部溫度傳感器因其低成本、高集成度特性,廣泛應(yīng)用于設(shè)備自檢、環(huán)境監(jiān)測(cè)等場(chǎng)景。然而,受芯片工藝差異和電源噪聲影響,其原始數(shù)據(jù)存在±1.5℃的固有誤差。本文從硬件配置、校準(zhǔn)算法、軟...

關(guān)鍵字: STM32 溫度傳感器

在能源效率與智能化需求雙重驅(qū)動(dòng)下,AC-DC轉(zhuǎn)換器的數(shù)字控制技術(shù)正經(jīng)歷從傳統(tǒng)模擬方案向全數(shù)字架構(gòu)的深刻變革。基于STM32微控制器的PFM(脈沖頻率調(diào)制)+PWM(脈沖寬度調(diào)制)混合調(diào)制策略,結(jié)合動(dòng)態(tài)電壓調(diào)整(Dynam...

關(guān)鍵字: AC-DC STM32

當(dāng)前智能家居產(chǎn)品需求不斷增長(zhǎng) ,在這一背景下 ,對(duì)現(xiàn)有澆花裝置缺陷進(jìn)行了改進(jìn) ,設(shè)計(jì)出基于STM32單片機(jī)的全 自動(dòng)家用澆花機(jī)器人。該設(shè)計(jì)主要由機(jī)械結(jié)構(gòu)和控制系統(tǒng)構(gòu)成 ,機(jī)械結(jié)構(gòu)通過麥克納姆輪底盤與噴灑裝置的結(jié)合實(shí)現(xiàn)機(jī)器...

關(guān)鍵字: STM32 麥克納姆輪 安全可靠 通過性強(qiáng)

用c++編程似乎是讓你的Arduino項(xiàng)目起步的障礙嗎?您想要一種更直觀的微控制器編程方式嗎?那你需要了解一下Visuino!這個(gè)圖形化編程平臺(tái)將復(fù)雜電子項(xiàng)目的創(chuàng)建變成了拖動(dòng)和連接塊的簡(jiǎn)單任務(wù)。在本文中,我們將帶您完成使...

關(guān)鍵字: Visuino Arduino ESP32 STM32

基于STM32與LoRa技術(shù)的無線傳感網(wǎng)絡(luò)憑借其低功耗、廣覆蓋、抗干擾等特性,成為環(huán)境監(jiān)測(cè)、工業(yè)自動(dòng)化等場(chǎng)景的核心解決方案。然而,如何在復(fù)雜電磁環(huán)境中實(shí)現(xiàn)高效休眠調(diào)度與動(dòng)態(tài)信道優(yōu)化,成為提升網(wǎng)絡(luò)能效與可靠性的關(guān)鍵挑戰(zhàn)。本...

關(guān)鍵字: STM32 LoRa

在實(shí)時(shí)控制系統(tǒng)、高速通信協(xié)議處理及高精度數(shù)據(jù)采集等對(duì)時(shí)間敏感的應(yīng)用場(chǎng)景中,中斷響應(yīng)延遲的優(yōu)化直接決定了系統(tǒng)的可靠性與性能上限。STM32系列微控制器憑借其靈活的嵌套向量中斷控制器(NVIC)、多通道直接內(nèi)存訪問(DMA)...

關(guān)鍵字: STM32 DMA

數(shù)字電源技術(shù)向高功率密度、高效率與高動(dòng)態(tài)響應(yīng)方向加速演進(jìn),STM32微控制器憑借其基于DSP庫(kù)的算法加速能力與對(duì)LLC諧振變換器的精準(zhǔn)控制架構(gòu),成為優(yōu)化電源動(dòng)態(tài)性能的核心平臺(tái)。相較于傳統(tǒng)模擬控制或通用型數(shù)字控制器,STM...

關(guān)鍵字: STM32 數(shù)字電源

STM32微控制器憑借其針對(duì)電機(jī)控制場(chǎng)景的深度優(yōu)化,成為高精度、高可靠性驅(qū)動(dòng)系統(tǒng)的核心選擇。相較于通用型MCU,STM32在電機(jī)控制領(lǐng)域的核心優(yōu)勢(shì)集中體現(xiàn)在FOC(磁場(chǎng)定向控制)算法的硬件加速引擎與PWM死區(qū)時(shí)間的動(dòng)態(tài)補(bǔ)...

關(guān)鍵字: STM32 電機(jī)控制

無線充電技術(shù)加速滲透消費(fèi)電子與汽車電子領(lǐng)域,基于Qi協(xié)議的無線充電發(fā)射端開發(fā)成為智能設(shè)備能量補(bǔ)給的核心課題。傳統(tǒng)模擬控制方案存在響應(yīng)滯后、參數(shù)調(diào)整困難等問題,而基于STM32的數(shù)字PID控制結(jié)合FOD(Foreign O...

關(guān)鍵字: STM32 無線充電
關(guān)閉