在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

【GD32 MCU 入門(mén)教程】GD32 MCU 常見(jiàn)外設(shè)介紹(7)I2C 模塊介紹

聚沃科技 ? 2024-08-16 09:54 ? 次閱讀

7.1.I2C 基礎(chǔ)知識(shí)

I2C(Inter-Integrated Circuit)總線(xiàn)是一種由Philips公司開(kāi)發(fā)的兩線(xiàn)式串行總線(xiàn),用于內(nèi)部IC控制的具有多端控制能力的雙線(xiàn)雙向串行數(shù)據(jù)總線(xiàn)系統(tǒng),能夠用于替代標(biāo)準(zhǔn)的并行總線(xiàn),連接各種集成 電路和功能模塊。I2C器件能夠減少電路間的連接,減少電路板的尺寸,降低硬件成本并提高系統(tǒng)的可靠性。I2C總線(xiàn)傳輸模式具有向下兼容性,傳輸速率標(biāo)準(zhǔn)模式下可達(dá)100kbps,快速模式下可 達(dá)400kbps,高速模式下可達(dá)3.4Mbps。

為了清楚起見(jiàn),在此對(duì)I2C通信中關(guān)于設(shè)備的基本概念進(jìn)行簡(jiǎn)要講解。

① 發(fā)送設(shè)備:發(fā)送數(shù)據(jù)到總線(xiàn)上的設(shè)備。

② 接收設(shè)備:從總線(xiàn)上接收數(shù)據(jù)的設(shè)備。

③ 主設(shè)備:?jiǎn)?dòng)數(shù)據(jù)傳輸并產(chǎn)生時(shí)鐘信號(hào)的設(shè)備。

④ 從設(shè)備:被主設(shè)備尋址的設(shè)備。

多主:多個(gè)主設(shè)備可以嘗試在不破壞信息的前提下同時(shí)控制線(xiàn)。

同步:同步兩個(gè)或更多設(shè)備之間的時(shí)鐘信號(hào)的過(guò)程。

仲裁:如果超過(guò)一個(gè)主設(shè)備同時(shí)試圖控制總線(xiàn),只有一個(gè)主設(shè)備被允許,且獲勝主設(shè)備的信息不被破壞。

(1)I2C設(shè)備連接原理 I2C設(shè)備連接示意圖如設(shè)備連接示意圖所示。I2C總線(xiàn)是由數(shù)據(jù)線(xiàn)SDA和時(shí)鐘線(xiàn)SCL構(gòu)成的串行總線(xiàn),可發(fā)送和接收數(shù)據(jù)。在GD32 MCU與被控IC(集成電路)之間、IC與IC之間進(jìn)行雙向傳送,最高傳送速率1Mbps。各種設(shè)備均并聯(lián)在總線(xiàn)上,兩條總線(xiàn)都被上拉電阻上拉到VCC,所有設(shè)備地位對(duì)等,都可作為主機(jī)或從機(jī),就像電話(huà)機(jī)一樣只要撥通各自的號(hào)碼就能正常工作,所以,每個(gè)設(shè)備都有唯一的地址。在信息的傳輸過(guò)程中,I2C總線(xiàn)上并接的每個(gè)設(shè)備既是主設(shè)備(或從設(shè)備),又是發(fā)送設(shè)備(或接收設(shè)備),這取決于它所要完成的功能。每個(gè)設(shè)備都可以把總線(xiàn)接地拉低,卻不允許把總線(xiàn)電平直接連到VCC上置高。把總線(xiàn)電平拉低稱(chēng)為占用總線(xiàn),總線(xiàn)電平為高等待被拉低則稱(chēng)為總線(xiàn)被釋放。

I2C 設(shè)備連接示意圖

輸入圖片說(shuō)明

由于SDA和SCL均為雙向I/O線(xiàn),都是開(kāi)漏極端(輸出1時(shí),為高阻狀態(tài)),因此I2C總線(xiàn)上的所有設(shè)備的SDA和SCL引腳都要外接上拉電阻。

(2)I2C數(shù)據(jù)通信協(xié)議

I2C數(shù)據(jù)通信時(shí)序圖如I2C數(shù)據(jù)通信時(shí)序圖所示。下面首先介紹起始位和停止位,起始位和停止位都是由主設(shè)備產(chǎn)生的,如圖中虛線(xiàn)所示。當(dāng)SCL時(shí)鐘線(xiàn)為高電平時(shí),SDA數(shù)據(jù)線(xiàn)上由高到低的跳變,產(chǎn)生一個(gè)開(kāi)始信號(hào),即起始位。當(dāng)SCL時(shí)鐘線(xiàn)為高電平時(shí),SDA數(shù)據(jù)線(xiàn)上由低到高的跳變,將產(chǎn)生一個(gè)停止信號(hào),即停止位。起始位之后,總線(xiàn)被認(rèn)為忙,即有數(shù)據(jù)在傳輸,傳輸?shù)牡谝粋€(gè)字節(jié),即7位從地址和R/ ̄W 位。當(dāng)R/ ̄W位為0時(shí),主機(jī)向從機(jī)發(fā)送數(shù)據(jù);當(dāng)R/ ̄W位為1時(shí),主機(jī)接收來(lái)自從機(jī)的數(shù)據(jù)。在每個(gè)字節(jié)后的第九個(gè)SCL時(shí)鐘上,接收機(jī)發(fā)送ACK位。停止位之后,總線(xiàn)被認(rèn)為閑,空閑狀態(tài)時(shí),SDA和SCL都是高電平。

注意:當(dāng)SCL位為高電平時(shí),SDA的數(shù)據(jù)必須保持穩(wěn)定,否則,由于起始位和停止位的電氣邊沿特性,SDA上數(shù)據(jù)發(fā)生改變將被識(shí)別為起始位或停止位。所以,只有當(dāng)SCL為低電平時(shí)才允許SDA上的數(shù)據(jù)改變。

I2C 數(shù)據(jù)通信時(shí)序圖

輸入圖片說(shuō)明

I2C總線(xiàn)上每位數(shù)據(jù)傳輸?shù)氖疽鈭D

輸入圖片說(shuō)明

(3)I2C的尋址方式 GD32 MCU的I2C模塊支持7位和10位兩種尋址模式,7位尋址模式最多尋址128個(gè)設(shè)備,10位尋址模式最多尋址1024個(gè)設(shè)備。I2C總線(xiàn)理論上可以允許的最大設(shè)備數(shù)是以總線(xiàn)上所有器件的電容總和不超過(guò)400pF為限(其中,包括連線(xiàn)本身的電容和其連接端的引出等效電容),總線(xiàn)上所有器件要依靠SDA發(fā)送的地址信號(hào)尋址,不需要片選信號(hào)。

① 7位尋址模式

如圖下圖所示為7位地址方式下的I2C數(shù)據(jù)傳輸格式,第一個(gè)字節(jié)由7位從地址和R/ ̄W讀/寫(xiě)位組成。不論總線(xiàn)上傳送的是地址還是數(shù)據(jù)信息,每個(gè)字節(jié)傳輸完畢,接收設(shè)備都會(huì)發(fā)送響應(yīng)位(ACK)。地址類(lèi)信息傳輸之后是數(shù)據(jù)信息,直到接收到停止信息。

7 位尋址模式數(shù)據(jù)格式

輸入圖片說(shuō)明

② 10位尋址模式

如下圖所示為10位地址方式下的I2C數(shù)據(jù)傳輸格式。第一個(gè)字節(jié)由二進(jìn)制位11110、從地址的最高兩位及R/ ̄W讀/寫(xiě)控制位組成。第一個(gè)字節(jié)傳輸完畢后是ACK響應(yīng)位。第二個(gè)字節(jié)就是10位從地址的低8位,后面是響應(yīng)位和數(shù)據(jù)。

10 位尋址模式數(shù)據(jù)格式

輸入圖片說(shuō)明

③ 二次發(fā)送從地址模式(重復(fù)產(chǎn)生起始條件)

主機(jī)可以在不停止數(shù)據(jù)傳輸?shù)那闆r下,通過(guò)產(chǎn)生重復(fù)的起始條件,改變SDA上數(shù)據(jù)流的方向,這稱(chēng)為RESTART。再次發(fā)送起始信號(hào)后,需重新發(fā)送從地址和R/ ̄W讀/寫(xiě)控制位。重新產(chǎn)生起始條件數(shù)據(jù)傳輸格式如圖所示。

輸入圖片說(shuō)明

7.2.GD32 I2C 外設(shè)原理簡(jiǎn)介

因篇幅有限,本文無(wú)法詳細(xì)介紹GD32所有系列I2C外設(shè)接口,下面以GD32F30x為列,著重介紹下GD32F30x的I2C外設(shè)簡(jiǎn)介和結(jié)構(gòu)框圖,后介紹下各個(gè)系列的差異。

GD32 I2C 主要特性

GD32F30X系列I2C 接口模塊實(shí)現(xiàn)了 I2C 協(xié)議的標(biāo)速模式,快速模式以及快速+ 模式,具備CRC 計(jì)算和校驗(yàn)功能、支持 SMBus(系統(tǒng)管理總線(xiàn)) 和 PMBus(電源管理總線(xiàn)),此外還支持多主機(jī) I2C 總線(xiàn)架構(gòu)。 I2C 接口模塊也支持 DMA 模式,可有效減輕 CPU 的負(fù)擔(dān)。

GD32 MCU I2C模塊主要特性描述如下:

? 并行總線(xiàn)至 I2C 總線(xiàn)協(xié)議的轉(zhuǎn)換及接口;

? 同一接口既可實(shí)現(xiàn)主機(jī)功能又可實(shí)現(xiàn)從機(jī)功能;

? 主從機(jī)之間的雙向數(shù)據(jù)傳輸;

? 支持 7 位和 10 位的地址模式和廣播尋址;

? 支持 I2C 多主機(jī)模式;

? 支持標(biāo)速(最高 100 KHz),快速(最高 400 KHz) 和快速+ 模式(最高 1MHz);

? 從機(jī)模式下可配置的 SCL 主動(dòng)拉低;

? 支持 DMA 模式;

? 兼容 SMBus 2.0 和 PMBus;

? 兩個(gè)中斷:字節(jié)成功發(fā)送中斷和錯(cuò)誤事件中斷;

? 可選擇的 PEC(報(bào)文錯(cuò)誤校驗(yàn)) 生成和校驗(yàn);

I2C 結(jié)構(gòu)框圖介紹

I2C內(nèi)部結(jié)構(gòu)框圖如下圖所示,該結(jié)構(gòu)框圖可分為五個(gè)部分:

1、用于產(chǎn)生I2C通信時(shí)序;

2、用于收發(fā)I2C數(shù)據(jù),當(dāng)有數(shù)據(jù)需要發(fā)送時(shí),會(huì)首先將數(shù)據(jù)填充到數(shù)據(jù)寄存器,然后數(shù)據(jù)被自動(dòng)移位到移位寄存器,通過(guò)SDA引腳發(fā)送出去,當(dāng)有數(shù)據(jù)需要接受時(shí),首先會(huì)根據(jù)SCL選擇的時(shí)鐘邊沿在移位寄存器中鎖存SDA數(shù)據(jù),當(dāng)數(shù)據(jù)接受到后,數(shù)據(jù)被移到數(shù)據(jù)緩沖寄存器,并置位接受緩沖區(qū)非空標(biāo)志;

3、用于收發(fā)數(shù)據(jù)CRC計(jì)算;

4、用于I2C模塊控制及相關(guān)標(biāo)志位查詢(xún);

5、系統(tǒng)通過(guò)APB總線(xiàn)對(duì)I2C數(shù)據(jù)寄存器及控制寄存器進(jìn)行操作。

輸入圖片說(shuō)明

各系列 I2C 功能差異

GD32各系列MCU有關(guān)IIC功能差異如各系列I2C功能差異表所示。

輸入圖片說(shuō)明

7.3.硬件連接說(shuō)明

如AT24C02C EEPROM IIC接口參考電路圖所示,AT24C02C為IIC接口的EEPROM,該電路圖為其典型參考電路,其中5腳為I2C SDA引腳,6腳為I2C SCL引腳,I2C總線(xiàn)需要通過(guò)4.7K歐姆電阻上拉。

輸入圖片說(shuō)明

7.4.軟件配置說(shuō)明

本小節(jié)講解I2C_Example下的I2C0主機(jī)歷程,本例程講解IIC作為主機(jī)情況下對(duì)從機(jī)的讀寫(xiě),并引入超時(shí)恢復(fù)機(jī)制。

IIC 初始化配置

IIC初始化配置代碼如代碼清單I2C初始化配置所示,首先進(jìn)行GPIO初始化,然后對(duì)IIC外設(shè)進(jìn)行初始化。注意本例程僅講解IIC0的外設(shè)引腳及模塊初始化,若其他IIC模塊可參考修改。

void I2C_init(uint32_t I2Cx) { GPIO_Configuration_I2C(I2Cx); i2c_clock_config(I2Cx, 400000, I2C_DTCY_2); /* I2C address configure */ i2c_mode_addr_config(I2Cx, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0); /* enable acknowledge */ i2c_ack_config(I2Cx, I2C_ACK_DISABLE); /* enable I2Cx */ i2c_enable(I2Cx); }

時(shí)鐘及 GPIO 引腳配置

時(shí)鐘及GPIO引腳配置如代碼清單I2C時(shí)鐘及GPIO引腳配置所示,在例程中PB6、PB7引腳需要配置為復(fù)用開(kāi)漏模式。

void GPIO_Configuration_I2C(uint32_t I2Cx) { uint32_t GPIO_SDA; uint32_t GPIO_SCL; uint32_t GPIO_Pin_SDA,GPIO_Pin_SCL; rcu_periph_reset_enable(RCU_I2C0RST); rcu_periph_reset_disable(RCU_I2C0RST); #if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X || GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X /* enable GPIOB clock */ rcu_periph_clock_enable(RCU_GPIOB); /* enable I2C0 clock */ rcu_periph_clock_enable(RCU_I2C0); #if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X rcu_periph_clock_enable(RCU_AF); #elif defined GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X #endif GPIO_SCL=GPIOB; GPIO_Pin_SCL=GPIO_PIN_6; GPIO_SDA=GPIOB; GPIO_Pin_SDA=GPIO_PIN_7; #endif /* Reset I2C1 IP */ // I2C_DeInit(I2Cx); #if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X /* I2C0 GPIO ports */ /* connect PB6 to I2C0_SCL */ gpio_init(GPIO_SCL, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SCL); /* connect PB7 to I2C0_SDA */ gpio_init(GPIO_SDA, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SDA); #elif defined GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X #if defined GD32F1X0 || GD32F3X0 || GD32E23X /* I2C GPIO ports */ /* connect I2C_SCL_GPIO_PIN to I2C_SCL */ gpio_af_set(GPIO_SCL, GPIO_AF_1, GPIO_Pin_SCL); /* connect I2C_SDA_GPIO_PIN to I2C_SDA */ gpio_af_set(GPIO_SDA, GPIO_AF_1, GPIO_Pin_SDA); #elif defined GD32F4XX gpio_af_set(GPIO_SCL, GPIO_AF_4, GPIO_Pin_SCL); gpio_af_set(GPIO_SDA, GPIO_AF_4, GPIO_Pin_SDA); #endif gpio_mode_set(GPIO_SCL, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_Pin_SCL); gpio_output_options_set(GPIO_SCL, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SCL); gpio_mode_set(GPIO_SDA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_Pin_SDA); gpio_output_options_set(GPIO_SDA, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SDA); #endif }

I2C 多字節(jié)寫(xiě)操作

I2C多字節(jié)寫(xiě)操作如代碼清單IIC寫(xiě)多字節(jié)操作所示,該函數(shù)接口實(shí)現(xiàn)IIC外設(shè)對(duì)IIC從機(jī)的多字節(jié)寫(xiě)操作。

/*! \brief I2Cx Write NBytes \param[in] i2c_periph : I2Cx(x=0,1) \param[in] addr : slave address \param[in] start_Addr : reg \param[in] number_Bytes: number to Write \param[in] ADDR_Length : number of the addr */ I2C_Status I2Cx_Write_NBytes(uint32_t I2Cx,uint8_t driver_Addr, uint16_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer,uint8_t ADDR_Length) { uint32_t I2C_Timeout = I2C_SHORT_TIMEOUT; i2c_ack_config(I2Cx,I2C_ACK_ENABLE); while(i2c_flag_get(I2Cx, I2C_FLAG_I2CBSY)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_start_on_bus(I2Cx); I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_SBSEND)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_master_addressing(I2Cx, driver_Addr, I2C_TRANSMITTER); I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_ADDSEND)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_flag_clear(I2Cx,I2C_FLAG_ADDSEND); I2C_Timeout = I2C_SHORT_TIMEOUT; while(SET != i2c_flag_get( I2Cx , I2C_FLAG_TBE )) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_enable(I2Cx); if(ADDR_Length)//á?×??úμ??· { i2c_data_transmit(I2Cx, (uint8_t)((start_Addr & 0xFF00) >> 8)); I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_BTC)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_data_transmit(I2Cx, (uint8_t)(start_Addr & 0x00FF)); } else { i2c_data_transmit(I2Cx, start_Addr); } I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_BTC)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } while(number_Bytes) { i2c_data_transmit(I2Cx, *write_Buffer); I2C_Timeout = I2C_SHORT_TIMEOUT; //while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))//5 // while(!i2c_flag_get(I2Cx, I2C_BTC))// while(!i2c_flag_get(I2Cx, I2C_FLAG_TBE)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } /* point to the next location where the byte read will be saved */ write_Buffer++; /* decrement the read bytes counter */ number_Bytes--; } // while(!i2c_flag_get(I2C1, I2C_BTC)) // { // if((I2C_Timeout--) == 0) // { // Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); // return I2C_FAIL; // } // } /* send a stop condition to I2C bus */ i2c_stop_on_bus(I2Cx); I2C_Timeout = I2C_SHORT_TIMEOUT; while (I2C_CTL0(I2Cx) & 0x0200) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_ack_config(I2Cx,I2C_ACK_ENABLE); return I2C_OK; }

IIC 多字節(jié)讀操作

IIC多字節(jié)讀操作如代碼清單IIC多字節(jié)讀操作所示,該函數(shù)接口可實(shí)現(xiàn)對(duì)IIC從機(jī)的多字節(jié)讀功能。

I2C_Status I2Cx_Read_NBytes(uint32_t I2Cx,uint8_t driver_Addr, uint16_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer,uint8_t ADDR_Length) { uint32_t I2C_Timeout = I2C_SHORT_TIMEOUT; i2c_ack_config(I2Cx,I2C_ACK_ENABLE); while(i2c_flag_get(I2Cx, I2C_FLAG_I2CBSY)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } if(number_Bytes==2) { i2c_ackpos_config(I2Cx,I2C_ACKPOS_NEXT); } i2c_start_on_bus(I2Cx); I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_SBSEND)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_master_addressing(I2Cx, driver_Addr, I2C_TRANSMITTER); I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_ADDSEND)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } /* clear the ADDSEND bit */ i2c_flag_clear(I2Cx,I2C_FLAG_ADDSEND); I2C_Timeout = I2C_SHORT_TIMEOUT; while(SET != i2c_flag_get( I2Cx , I2C_FLAG_TBE )) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_enable(I2Cx); if(ADDR_Length)//á?×??úμ??· { i2c_data_transmit(I2Cx, (uint8_t)((start_Addr & 0xFF00) >> 8)); I2C_Timeout = I2C_SHORT_TIMEOUT; //while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) while(!i2c_flag_get(I2Cx, I2C_FLAG_BTC)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_data_transmit(I2Cx, (uint8_t)(start_Addr & 0x00FF)); } else { i2c_data_transmit(I2Cx, start_Addr); } I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_BTC)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_start_on_bus(I2Cx); I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_SBSEND)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_master_addressing(I2Cx, driver_Addr, I2C_RECEIVER); I2C_Timeout = I2C_SHORT_TIMEOUT; if(number_Bytes<3) { i2c_ack_config(I2Cx,I2C_ACK_DISABLE); } while(!i2c_flag_get(I2Cx, I2C_FLAG_ADDSEND)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } /* clear the ADDSEND bit */ i2c_flag_clear(I2Cx,I2C_FLAG_ADDSEND); if(number_Bytes==1) { i2c_stop_on_bus(I2Cx); } while(number_Bytes) { if(3 == number_Bytes){ /* wait until BTC bit is set */ I2C_Timeout = I2C_LONG_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_BTC)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } /* disable acknowledge */ /* disable acknowledge */ i2c_ack_config(I2Cx,I2C_ACK_DISABLE); } if(2 == number_Bytes){ /* wait until BTC bit is set */ I2C_Timeout = I2C_LONG_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_BTC)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } /* send a stop condition to I2C bus */ i2c_stop_on_bus(I2Cx); I2C_Timeout = I2C_SHORT_TIMEOUT; while (I2C_CTL0(I2Cx) & 0x0200) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } } /* wait until the RBNE bit is set and clear it */ if(i2c_flag_get(I2Cx, I2C_FLAG_RBNE)){ /* read a byte from the EEPROM */ *read_Buffer = i2c_data_receive(I2Cx); /* point to the next location where the byte read will be saved */ read_Buffer++; /* decrement the read bytes counter */ number_Bytes--; } } while(I2C_CTL0(I2Cx)&0x0200) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } /* enable acknowledge */ i2c_ack_config(I2Cx,I2C_ACK_ENABLE); i2c_ackpos_config(I2Cx,I2C_ACKPOS_CURRENT); return I2C_OK; }

IIC 超時(shí)恢復(fù)機(jī)制

IIC超時(shí)恢復(fù)機(jī)制實(shí)現(xiàn)如代碼清單IIC超時(shí)恢復(fù)機(jī)制所示。

uint32_t I2C_Timeout; void Delay_I2C(uint32_t i) { while(i--); } void Resume_IIC(uint32_t Timeout,uint32_t I2Cx ) { uint32_t GPIO_SDA; uint32_t GPIO_SCL; uint32_t GPIO_Pin_SDA,GPIO_Pin_SCL; #if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X || GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X /* enable GPIOB clock */ rcu_periph_clock_enable(RCU_GPIOB); /* enable I2C0 clock */ rcu_periph_clock_enable(RCU_I2C0); #if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X rcu_periph_clock_enable(RCU_AF); #elif defined GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X #endif #endif GPIO_SCL=GPIOB; GPIO_Pin_SCL=GPIO_PIN_6; GPIO_SDA=GPIOB; GPIO_Pin_SDA=GPIO_PIN_7; do{ #if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X /* I2C0 GPIO ports */ /* connect PB6 to I2C0_SCL */ gpio_init(GPIO_SCL, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SCL); /* connect PB7 to I2C0_SDA */ gpio_init(GPIO_SDA, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SDA); #elif defined GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X #if defined GD32F1X0 || GD32F3X0 || GD32E23X /* I2C GPIO ports */ /* connect I2C_SCL_GPIO_PIN to I2C_SCL */ gpio_af_set(GPIO_SCL, GPIO_AF_1, GPIO_Pin_SCL); /* connect I2C_SDA_GPIO_PIN to I2C_SDA */ gpio_af_set(GPIO_SDA, GPIO_AF_1, GPIO_Pin_SDA); #elif defined GD32F4XX gpio_af_set(GPIO_SCL, GPIO_AF_4, GPIO_Pin_SCL); gpio_af_set(GPIO_SDA, GPIO_AF_4, GPIO_Pin_SDA); #endif gpio_mode_set(GPIO_SCL, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_Pin_SCL); gpio_output_options_set(GPIO_SCL, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SCL); gpio_mode_set(GPIO_SDA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_Pin_SDA); gpio_output_options_set(GPIO_SDA, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SDA); #endif gpio_bit_reset(GPIO_SCL, GPIO_Pin_SCL); Delay_I2C(20); gpio_bit_reset(GPIO_SDA, GPIO_Pin_SDA); Delay_I2C(20); gpio_bit_set(GPIO_SCL, GPIO_Pin_SCL); Delay_I2C(20); gpio_bit_set(GPIO_SDA, GPIO_Pin_SDA); Delay_I2C(20); if(Timeout-- == 0) return; }while((!gpio_input_bit_get(GPIO_SDA, GPIO_Pin_SDA))&(!gpio_input_bit_get(GPIO_SCL, GPIO_Pin_SCL))); I2C_init(I2Cx); }

主函數(shù)說(shuō)明

本例程主函數(shù)如代碼清單I2C例程主函數(shù)所示。

int main(void) { I2C_init(I2C0); I2Cx_Write_NBytes(I2C0,0xA0, 0,8, Write_Buf,0); I2Cx_Read_NBytes(I2C0,0xA0, 0,8, Read_Buf,0); while (1) { }

7.5.I2C 使用注意事項(xiàng)

1、I2C總線(xiàn)需要上拉;

2、I2C引腳需要配置為復(fù)用開(kāi)漏模式;

3、若采用查詢(xún)方式進(jìn)行I2C數(shù)據(jù)傳輸,有可能會(huì)由于總線(xiàn)干擾,導(dǎo)致I2C卡死,可以在查詢(xún)方式上增加超時(shí)機(jī)制,如果超時(shí)重配IIC恢復(fù)總線(xiàn)通信(注意重配IIC時(shí),建議先將I2C模塊Deinit,然后 在調(diào)用Init函數(shù)進(jìn)行初始化)。

4、若采用軟件模擬IIC的方式,在移植過(guò)程中出現(xiàn)問(wèn)題,可能是由于代碼執(zhí)行效率的問(wèn)題,可以排查軟件延遲時(shí)間和其他芯片上的軟件延遲時(shí)間是否相同,可以通過(guò)調(diào)整軟件延遲時(shí)間進(jìn)行測(cè)試;或者有可能是由于初始化配置IO端口的時(shí)候可能會(huì)引入干擾,可以先配置IO口輸出高,然后再配置為推挽或開(kāi)漏模式。

教程GD32 MCU方案商聚沃科技原創(chuàng)發(fā)布,了解更多GD32 MCU教程,關(guān)注聚沃科技官網(wǎng)

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 單片機(jī)
    +關(guān)注

    關(guān)注

    6056

    文章

    44799

    瀏覽量

    643605
  • mcu
    mcu
    +關(guān)注

    關(guān)注

    146

    文章

    17638

    瀏覽量

    357096
  • 嵌入式
    +關(guān)注

    關(guān)注

    5120

    文章

    19407

    瀏覽量

    312305
  • I2C
    I2C
    +關(guān)注

    關(guān)注

    28

    文章

    1509

    瀏覽量

    126212
  • GD32
    +關(guān)注

    關(guān)注

    7

    文章

    417

    瀏覽量

    24924
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    GD32 MCU 入門(mén)教程GD32 MCU 常見(jiàn)外設(shè)介紹(12)FMC 模塊介紹

    閃存控制器(FMC),提供了片上閃存需要的所有功能。FMC 也提供了頁(yè)擦除,整片擦除,以及32 位整字或 16 位半字編程閃存等操作。 GD32 MCU 支持不同類(lèi)型編程的具體說(shuō)明如下表 GD32
    的頭像 發(fā)表于 08-21 09:56 ?1671次閱讀
    <b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>入門(mén)教程</b>】<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>常見(jiàn)外設(shè)</b><b class='flag-5'>介紹</b>(12)FMC <b class='flag-5'>模塊</b><b class='flag-5'>介紹</b>

    GD32 MCU移植

    gd32是一款國(guó)產(chǎn)單片機(jī)。該芯片在很多方面和STM32有異曲同工之處。資料不是很多! GD32外設(shè)方面、和STM32沒(méi)有多大區(qū)別。 只是需要注意資源的引腳分配。雖然和STM32使用方式一樣、但是也存在
    發(fā)表于 03-23 13:40

    GD32MCU介紹

    其實(shí)兆芯的MCU為了兼容ST,外設(shè)的寄存器設(shè)計(jì)與ST保持一致了。比如GD32VF103或者GD32E103系列的USBFS這個(gè)外設(shè),基本等同
    發(fā)表于 11-01 06:03

    GD32 MCU原理及固件庫(kù)開(kāi)發(fā)指南》+讀后感

    ,包括ADC和DAC。 第7介紹GD32 MCU的基礎(chǔ)通信外設(shè),包括USART、I2C和SPI
    發(fā)表于 06-06 21:52

    兆易創(chuàng)新GD32 MCU選型手冊(cè),適用于GD32全系列MCU

    兆易創(chuàng)新GD32MCU選型手冊(cè),適用于GD32全系列MCUGD32MCU選型手冊(cè),適用于GD32全系列MCU
    發(fā)表于 10-19 17:26 ?51次下載

    你了解GD32 MCU的命名規(guī)則嗎

    下面為大家介紹GD32 MCU的通用命名規(guī)則,以GD32F303ZGT6為例,其中,GD32代表GD32
    的頭像 發(fā)表于 01-13 09:38 ?4249次閱讀
    你了解<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b>的命名規(guī)則嗎

    GD32 MCU的選項(xiàng)字節(jié)是什么?

    GD32 MCU的選項(xiàng)字節(jié)是什么,有什么功能呢?選項(xiàng)字節(jié)被誤篡改如何回復(fù)?
    的頭像 發(fā)表于 01-17 09:42 ?1656次閱讀
    <b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b>的選項(xiàng)字節(jié)是什么?

    不同型號(hào)的GD32 MCU如何區(qū)分?

    大家是否碰到過(guò)以下應(yīng)用場(chǎng)景:同一套軟件代碼希望跑在不同型號(hào)的GD32 MCU中,但有些地方需要根據(jù)MCU型號(hào)進(jìn)行調(diào)整?或者上位機(jī)或其他MCUGD3
    的頭像 發(fā)表于 01-27 09:32 ?1252次閱讀
    不同型號(hào)的<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b>如何區(qū)分?

    GD32 MCU 入門(mén)教程】一、GD32 MCU 開(kāi)發(fā)環(huán)境搭建(1)使用Keil開(kāi)發(fā)GD32

    GD32系列為通用型MCU,所以開(kāi)發(fā)環(huán)境也可以使用通用型的IDE,目前使用較多的是KEIL、IAR、 GCC和Embedded Builder,客戶(hù)可以根據(jù)個(gè)人喜好來(lái)選擇相應(yīng)的開(kāi)發(fā)環(huán)境。
    的頭像 發(fā)表于 08-08 15:01 ?2191次閱讀
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>入門(mén)教程</b>】一、<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> 開(kāi)發(fā)環(huán)境搭建(1)使用Keil開(kāi)發(fā)<b class='flag-5'>GD32</b>

    GD32 MCU 入門(mén)教程】一、GD32 MCU 開(kāi)發(fā)環(huán)境搭建(2)使用 IAR 開(kāi)發(fā) GD32

    GD32系列為通用型MCU,所以開(kāi)發(fā)環(huán)境也可以使用通用型的IDE,目前使用較多的是KEIL、IAR、 GCC和Embedded Builder,客戶(hù)可以根據(jù)個(gè)人喜好來(lái)選擇相應(yīng)的開(kāi)發(fā)環(huán)境。
    的頭像 發(fā)表于 08-08 15:40 ?1077次閱讀
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>入門(mén)教程</b>】一、<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> 開(kāi)發(fā)環(huán)境搭建(<b class='flag-5'>2</b>)使用 IAR 開(kāi)發(fā) <b class='flag-5'>GD32</b>

    GD32 MCU 入門(mén)教程】一、GD32 MCU 開(kāi)發(fā)環(huán)境搭建(3)使用 Embedded Builder 開(kāi)發(fā) GD32

    GD32系列為通用型MCU,所以開(kāi)發(fā)環(huán)境也可以使用通用型的IDE,目前使用較多的是KEIL、IAR、 GCC和Embedded Builder,客戶(hù)可以根據(jù)個(gè)人喜好來(lái)選擇相應(yīng)的開(kāi)發(fā)環(huán)境。
    的頭像 發(fā)表于 08-08 16:03 ?1596次閱讀
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>入門(mén)教程</b>】一、<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> 開(kāi)發(fā)環(huán)境搭建(3)使用 Embedded Builder 開(kāi)發(fā) <b class='flag-5'>GD32</b>

    GD32 MCU 入門(mén)教程】二、GD32 MCU 燒錄說(shuō)明(1)ISP 燒錄

    ISP:In System Programing,在系統(tǒng)編程,通過(guò)MCU片內(nèi)的引導(dǎo)程序進(jìn)行Flash編程。 GD32片內(nèi)有一個(gè)只讀信息塊,用于存放引導(dǎo)裝載程序,引導(dǎo)程序在MCU出廠(chǎng)前就會(huì)提前燒錄好
    的頭像 發(fā)表于 08-08 16:20 ?1700次閱讀
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>入門(mén)教程</b>】二、<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> 燒錄說(shuō)明(1)ISP 燒錄

    GD32 MCU 入門(mén)教程GD32 MCU 常見(jiàn)外設(shè)介紹(14)RTC 模塊介紹

    GD32 MCU內(nèi)部提供了一個(gè)RTC(實(shí)時(shí)時(shí)鐘)模塊,通過(guò)RTC可以實(shí)現(xiàn)日歷時(shí)鐘、鬧鐘等功能。RTC也可以用于深度睡眠或待機(jī)模式的低功耗喚醒。不同系列的GD32
    的頭像 發(fā)表于 08-23 09:18 ?791次閱讀
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>入門(mén)教程</b>】<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>常見(jiàn)外設(shè)</b><b class='flag-5'>介紹</b>(14)RTC <b class='flag-5'>模塊</b><b class='flag-5'>介紹</b>

    GD32 MCU 入門(mén)教程GD32 MCU FPU 使用方法

    GD32 MCU FPU 使用方法
    的頭像 發(fā)表于 08-25 09:24 ?1039次閱讀
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>入門(mén)教程</b>】<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> FPU 使用方法

    GD32 MCU入門(mén)教程GD32 MCU GPIO 結(jié)構(gòu)與使用注意事項(xiàng)

    本文是專(zhuān)門(mén)為基于GD32 MCU開(kāi)發(fā)的工程設(shè)計(jì)人員提供,主要介紹了GPIO的功能配置、內(nèi)部結(jié)構(gòu)以及在不同場(chǎng)景使用時(shí)的注意事項(xiàng),旨在幫助GD32 MC
    的頭像 發(fā)表于 09-07 10:34 ?1262次閱讀
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b><b class='flag-5'>入門(mén)教程</b>】<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> GPIO 結(jié)構(gòu)與使用注意事項(xiàng)
    主站蜘蛛池模板: 亚洲va中文va欧美va爽爽 | abc119影院成人免费看 | 日本一本高清视频 | 亚洲 美腿 欧美 偷拍 | 色窝视频 | 天天插天天干天天射 | 亚洲成人aaa | 欧美日韩一区二区三区视频在线观看 | xxxxxxxxxxx性bbbb| 日日爽夜夜爽 | 日本三级视频在线观看 | 91极品女神私人尤物在线播放 | 日日躁夜夜躁狠狠天天 | 久久成人国产精品免费 | 久久福利国产 | 特黄特色三级在线观看 | 亚洲影视久久 | 色婷婷综合网 | 午夜精品视频在线观看 | h小视频在线观看网 | 嗯好舒服好爽好快好大 | 一级毛片女人喷潮 | 国产片91人成在线观看 | 好紧好爽水真多18 | 天天做天天添婷婷我也去 | 婷婷开心六月久久综合丁香 | 色香淫欲 | 一级做a爰片久久毛片图片 一级做a爰片久久毛片鸭王 | 一日本道加勒比高清一二三 | 亚洲欧美日韩在线精品2021 | 生活片毛片 | 亚洲欧洲色天使日韩精品 | 加勒比一区二区三区 | 日本在线播放一区 | 欧美日韩一区二区三区视频在线观看 | 青青热久久国产久精品秒播 | 91成人免费在线视频 | 亚洲欧美在线一区二区 | 美女国产在线观看免费观看 | 免费一级片视频 | bt天堂网在线资源www |