AT24C02是一種失去電源供給后依舊能保持?jǐn)?shù)據(jù)的儲存器,常用來儲存一些配置信息,在系統(tǒng)重新上電之后也可以加載。它的容量是2k bit的EEPROM存儲器,采用I2C通信方式。
AT24C02支持兩種寫操作:字節(jié)寫操作和頁寫操作。本實驗中我們采用的是字節(jié)寫操作,就是一個地址一個數(shù)據(jù)這樣進行數(shù)據(jù)寫入。頁寫模式就是連續(xù)寫入數(shù)據(jù),只需寫入一個地址,連續(xù)寫入數(shù)據(jù)的時候,地址會自動后移,但有頁限制,超出一頁的時候,超出數(shù)據(jù)會覆蓋原先寫入的數(shù)據(jù)。
AT24C02支持三種讀操作:當(dāng)前地址讀操作,隨機地址讀操作和順序讀操作模式。
當(dāng)前地址讀模式是基于上一次讀/寫操作的最后位置繼續(xù)讀出數(shù)據(jù)。隨機地址讀模式是指定地址讀出數(shù)據(jù)。順序讀操作模式就是連續(xù)讀出數(shù)據(jù),會自動翻頁。
注意到我們采用的STM32F1系列里,SCL時鐘線為PB6,SDA數(shù)據(jù)線為PB7。本次實驗中,時鐘線我們就正常的設(shè)置為推挽輸入,數(shù)據(jù)線則設(shè)置為開漏模式(因為我們引入了外部上拉電阻,提供穩(wěn)定的空閑高電平,而且我們的數(shù)據(jù)線既要作為輸出,又要作為輸入,用開漏輸出模式,能很好地實現(xiàn)輸入輸出共用,避免頻繁IO模式切換帶來的麻煩)。編寫代碼時,注意完成發(fā)送的時候,主機要釋放SDA。
在開漏模式下,MCU讀取IDR狀態(tài)寄存器,來獲取引腳高低電平。
接下來編寫我們的實驗代碼:
首先編寫我們的函數(shù)頭文件iic.c:
#include "./BSP/IIC/iic.h"
#include "./SYSTEM/delay/delay.h"
void iic_init(void){
GPIO_InitTypeDef gpio_init_struct = {0};
IIC_SCL_GPIO_CLK_ENABLE();
IIC_SDA_GPIO_CLK_ENABLE();
//SCL設(shè)置
gpio_init_strcut.Pin = IIC_SCL_GPIO_PIN;
gpio_init_strcut.Mode = GPIO_MODE_OUTPUT_PP;
gpio_init_strcut.Pull = GPIO_PULLUP;
gpio_init_strcut.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(IIC_GPIO_PORT, &gpio_init_strcut); //IIC_GPIO_PORT就是GPIOB
//SCL設(shè)置
gpio_init_strcut.Pin = IIC_SDA_GPIO_PIN;
gpio_init_strcut.Mode = GPIO_MODE_OUTPUT_OD;
HAL_GPIO_Init(IIC_GPIO_PORT, &gpio_init_strcut);
}
static void iic_delay(void){
delay_ms(2);
}
void iic_start(void){
//SCL為高電平時,SDA從高電平向低電平跳變,制造起始信號
IIC_SDA(1);
IIC_SCL(1);
delay_ms();
IIC_SDA(0);
delay_ms();
IIC_SCL(0);
delay_ms();//鉗住總線,準(zhǔn)備發(fā)送或者接受數(shù)據(jù)
}
void iic_stop(void){
//SCL為高電平的適合,SDA從低電平向高電平跳變,制造停止信號
IIC_SDA(0);
delay_ms();
IIC_SCL(1);
delay_ms();
IIC_SDA(1);
delay_ms();
}
uint8_t iic_wait_ack(void){ //主機檢測應(yīng)答信號
IIC_SDA(1); //主機釋放SDA線
delay_ms();
IIC_SCL(1); //從機返回ACK
delay_ms();
if(IIC_READ_SDA){ //SDA高電平表示讀取到高電平,從機未作出應(yīng)答,由于上拉電阻有高電平阻塞效果,表示讀取到非應(yīng)答信號
iic_stop();
return 1;
}
IIC_SCL(0);
delay_ms();
return 0;
}
void iic_ack(void){ //從機發(fā)送低電平應(yīng)答信號,將主機發(fā)送的高電平信號導(dǎo)入至此,使主機的數(shù)據(jù)線檢測函數(shù)得到的是低電平,繼續(xù)要求數(shù)據(jù)
IIC_SCL(0);
delay_ms();
IIC_SDA(0);
delay_ms();
IIC_SCL(1);
delay_ms();
}
void iic_nack(void){ //從機發(fā)送非應(yīng)答信號,不再要求數(shù)據(jù)
IIC_SCL(0);
delay_ms();
IIC_SDA(1);
delay_ms();
IIC_SCL(1);
delay_ms();
}
void iic_send_byte(uint8_t data){
for(uint8_t t = 0; t < 8; t++){
//高位先發(fā)
IIC_SDA((data & 0x80) >> 7);
IIC_SCL(1);
delay_ms();
IIC_SCL(0);
data <<= 1; //左移一位,進行下一次發(fā)送
}
IIC_SDA(1); //完成后,釋放數(shù)據(jù)線,進行應(yīng)答檢測
}
uint8_t iic_read_byte(uint8_t ack){
uint8_t receive = 0;
for(uint8_t i = 0; t < 8; t++){
//高位先被輸入,左移以騰空右邊的位置給下一低位數(shù)據(jù)
receive <<= 1;
IIC_SCL(1);
delay_ms();
if(IIC_READ_SDA) receive++;
IIC_SCL(0);
delay_ms();
}
if(!ack) iic_nack();
else iic_ack();
return receive;
}
接下來編寫函數(shù)頭文件iic.h:
#ifndef __IIC_H
#define __IIC_H
void iic_init(void);
static void iic_delay(void);
void iic_start(void);
void iic_stop(void);
uint8_t iic_wait_ack(void);
void iic_ack(void);
void iic_nack(void);
void iic_send_byte(uint8_t data);
uint8_t iic_read_byte(uint8_t ack);
#endif
接下來再編寫存儲器的函數(shù)文件24cxx.c:
#include "./BSP/IIC/iic.h"
#include "./BSP/24CXX/24cxx.h"
#include "./SYSTEM/delay/delay.h"
void at24c02_init(void){
iic_init();
}
void at24c02_write_byte(uint8_t addr, uint8_t data){
iic_start();
iic_send_byte(0xA0); //發(fā)送通訊地址(寫地址操作)
iic_wait_ack();
iic_send_byte(addr);
iic_wait_ack();
iic_send_byte(data);
iic_wait_ack();
iic_stop();
delay_ms(10);
}
uint8_t at24c02_read_byte(uint8_t addr){
uint8_t rec = 0;
iic_start();
iic_send_byte(0xA0); //發(fā)送通訊地址(寫地址操作)
iic_wait_ack();
iic_send_byte(addr);
iic_wait_ack();
iic_start();
iic_send_byte(0xA1); //發(fā)送通訊地址(寫地址操作)
iic_wait_ack();
iic_send_byte(addr);
iic_wait_ack();
rec = iic_read_byte(0);
iic_stop();
return rec;
}
接下來編寫存儲器函數(shù)文件的頭文件:24cxx.h:文章來源:http://www.zghlxwxcb.cn/news/detail-484343.html
#ifndef __24CXX_H
#define __24CXX_H
void at24c02_init(void);
void at24c02_write_byte(uint8_t addr, uint8_t data);
uint8_t at24c02_read_byte(uint8_t addr);
#endif
到這里我們的示例代碼便編寫完成了。文章來源地址http://www.zghlxwxcb.cn/news/detail-484343.html
到了這里,關(guān)于STM32-I2C通信在AT24C02的應(yīng)用的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!