1.概述
MiniSTM32 開(kāi)發(fā)板板載的 EEPROM 芯片型號(hào)為 24C02。該芯片的總?cè)萘渴?256個(gè)字節(jié),該芯片通過(guò) IIC 總線與外部連接。這里直接采用原子板上的 AT24C02 ,主要是軟件編程方面的學(xué)習(xí)。
2.硬件連接
A2、A1、A0 三個(gè)引腳直接接地。供電: (VCC = 2.7V to 5.5V)
器件地址設(shè)置:
對(duì)于AT24C02:Addr—>0xA0(寫(xiě))/ 0xA1(讀)。
單字節(jié)寫(xiě)入:
按頁(yè)寫(xiě)入:
從當(dāng)前地址讀出數(shù)據(jù);
隨機(jī)讀?。?/p>
順序讀出:
3.例程分析
(一)IIC 部分實(shí)現(xiàn)代碼
包括 IIC 的初始化(IO 口)、 IIC 開(kāi)始、 IIC 結(jié)束、 ACK、 IIC 讀寫(xiě)等功能,在其他函數(shù)里面,只需要調(diào)用相關(guān)的 IIC 函數(shù)就可以和外部 IIC 器件通信了,這里并不局限于 24C02,該段代碼可以用在任何 IIC 設(shè)備上。
IIC_SCL 和 IIC_SDA 分別連在 STM32 的 PC12 和 PC11。
1.IIC 初始化
//IO操作函數(shù)
#define IIC_SCL PCout(12) //SCL
#define IIC_SDA PCout(11) //SDA
#define READ_SDA PCin(11) //輸入SDA
//初始化 IIC
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
IIC_SCL=1;
IIC_SDA=1;
}
2.產(chǎn)生 IIC 開(kāi)始信號(hào)
//產(chǎn)生 IIC 起始信號(hào)
void IIC_Start(void)
{
SDA_OUT(); //sda 線輸出
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;//鉗住 I2C 總線, 準(zhǔn)備發(fā)送或接收數(shù)據(jù)
}
3.產(chǎn)生停止IIC信號(hào)
//產(chǎn)生 IIC 停止信號(hào)
void IIC_Stop(void)
{
SDA_OUT();//sda 線輸出
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high , DATA change form low to high
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//發(fā)送 I2C 總線結(jié)束信號(hào)
delay_us(4);
}
4.等待應(yīng)答信號(hào)
//等待應(yīng)答信號(hào)到來(lái)
//返回值: 1,接收應(yīng)答失敗
// 0,接收應(yīng)答成功
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN(); //SDA 設(shè)置為輸入
IIC_SDA=1;
delay_us(1);
IIC_SCL=1;
delay_us(1);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//時(shí)鐘輸出 0
return 0;
}
5.應(yīng)答信號(hào)
//產(chǎn)生 ACK 應(yīng)答
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
6.不產(chǎn)生應(yīng)答
//不產(chǎn)生 ACK 應(yīng)答
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
7.IIC發(fā)送一個(gè)字節(jié)
//IIC 發(fā)送一個(gè)字節(jié)
//返回從機(jī)有無(wú)應(yīng)答
//1,有應(yīng)答
//0,無(wú)應(yīng)答
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低時(shí)鐘開(kāi)始數(shù)據(jù)傳輸
for(t=0;t<8;t++)
{
IIC_SDA=(txd&0x80)>>7;//高位開(kāi)始,一位一位的傳數(shù)據(jù)
txd<<=1;
delay_us(2); //對(duì) TEA5767 這三個(gè)延時(shí)都是必須的
IIC_SCL=1; //保持?jǐn)?shù)據(jù)的穩(wěn)定
delay_us(2);
IIC_SCL=0; //下一位數(shù)據(jù)傳輸開(kāi)始
delay_us(2);
}
}
8.IIC讀一個(gè)字節(jié)
//讀 1 個(gè)字節(jié), ack=1 時(shí),發(fā)送 ACK, ack=0,發(fā)送 nACK
u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA 設(shè)置為輸入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)
receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();//發(fā)送 nACK
else
IIC_Ack(); //發(fā)送 ACK
return receive;
}
(二)AT24C02 操作
直接通過(guò)寄存器操作設(shè)置 IO 口的模式為輸入還是輸出,代碼如下:
#define SDA_IN() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;}
#define SDA_OUT() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=3<<12;}
1.初始化 IIC 接口
//初始化 IIC 接口
void AT24CXX_Init(void)
{
IIC_Init();
}
2.在 AT24CXX 指定地址讀出一個(gè)數(shù)據(jù)
//在 AT24CXX 指定地址讀出一個(gè)數(shù)據(jù)
//ReadAddr:開(kāi)始讀數(shù)的地址,24C02大小為2Kbit;ADDR:0x00---0x7FF
//返回值 :讀到的數(shù)據(jù)
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{
u8 temp=0;
IIC_Start();
if(EE_TYPE>AT24C16)
/*宏定義有個(gè)選擇芯片類型的,如果這個(gè)定義大于AT24C16的話就發(fā)送兩個(gè)8bit地址,否則就發(fā)送一個(gè)8bit地址*/
{
IIC_Send_Byte(0XA0); //發(fā)送寫(xiě)命令,0XA0:器件的地址,7位地址+寫(xiě)(0)
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr>>8);//發(fā)送高地址
}else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1)); //發(fā)送器件地址 0XA0,寫(xiě)數(shù)據(jù)
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr%256); //發(fā)送低地址
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(0XA1); //進(jìn)入接收模式,7位地址+讀(1)
IIC_Wait_Ack();
temp=IIC_Read_Byte(0);
IIC_Stop();//產(chǎn)生一個(gè)停止條件
return temp;
}
3.在 AT24CXX 指定地址寫(xiě)入一個(gè)數(shù)據(jù)
//在 AT24CXX 指定地址寫(xiě)入一個(gè)數(shù)據(jù)
//WriteAddr :寫(xiě)入數(shù)據(jù)的目的地址
//DataToWrite:要寫(xiě)入的數(shù)據(jù)
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{
IIC_Start();
if(EE_TYPE>AT24C16)
{
IIC_Send_Byte(0XA0); //發(fā)送寫(xiě)命令
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr>>8);//發(fā)送高地址
}else IIC_Send_Byte(0XA0+((WriteAddr/256)<<1)); //發(fā)送器件地址 0XA0,寫(xiě)數(shù)據(jù)
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr%256); //發(fā)送低地址
IIC_Wait_Ack();
IIC_Send_Byte(DataToWrite); //發(fā)送字節(jié)
IIC_Wait_Ack();
IIC_Stop(); //產(chǎn)生一個(gè)停止條件
delay_ms(10); //對(duì)于 EEPROM 器件,每寫(xiě)一次要等待一段時(shí)間,否則寫(xiě)失??!
}
4.AT24CXX 里面的指定地址開(kāi)始寫(xiě)入長(zhǎng)度為 Len 的數(shù)據(jù)
//在 AT24CXX 里面的指定地址開(kāi)始寫(xiě)入長(zhǎng)度為 Len 的數(shù)據(jù)
//該函數(shù)用于寫(xiě)入 16bit 或者 32bit 的數(shù)據(jù).
//WriteAddr :開(kāi)始寫(xiě)入的地址
//DataToWrite:數(shù)據(jù)數(shù)組首地址
//Len :要寫(xiě)入數(shù)據(jù)的長(zhǎng)度 2,4
void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len)
{
u8 t;
for(t=0;t AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff); } 5.AT24CXX 里面的指定地址開(kāi)始讀出長(zhǎng)度為 Len 的數(shù)據(jù) //在 AT24CXX 里面的指定地址開(kāi)始讀出長(zhǎng)度為 Len 的數(shù)據(jù) //該函數(shù)用于讀出 16bit 或者 32bit 的數(shù)據(jù). //ReadAddr :開(kāi)始讀出的地址 //返回值 :數(shù)據(jù) //Len :要讀出數(shù)據(jù)的長(zhǎng)度 2,4 u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len) { u8 t; u32 temp=0; for(t=0;t { temp<<=8; temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1); } return temp; } 6.檢查 AT24CXX 是否正常 //檢查 AT24CXX 是否正常 //這里用了 24XX 的最后一個(gè)地址(255)來(lái)存儲(chǔ)標(biāo)志字. //如果用其他 24C 系列,這個(gè)地址要修改 //返回 1:檢測(cè)失敗 //返回 0:檢測(cè)成功 u8 AT24CXX_Check(void) { u8 temp; temp=AT24CXX_ReadOneByte(255);//避免每次開(kāi)機(jī)都寫(xiě) AT24CXX if(temp==0X55) return 0; else//排除第一次初始化的情況 { AT24CXX_WriteOneByte(255,0X55); temp=AT24CXX_ReadOneByte(255); if(temp==0X55) return 0; } return 1; } 7.AT24CXX 里面的指定地址開(kāi)始讀出指定個(gè)數(shù)的數(shù)據(jù) /在 AT24CXX 里面的指定地址開(kāi)始讀出指定個(gè)數(shù)的數(shù)據(jù) //ReadAddr :開(kāi)始讀出的地址 對(duì) 24c02 為 0~255 //pBuffer :數(shù)據(jù)數(shù)組首地址 //NumToRead:要讀出數(shù)據(jù)的個(gè)數(shù) void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead) { while(NumToRead) { *pBuffer++=AT24CXX_ReadOneByte(ReadAddr++); NumToRead--; } } 8.AT24CXX 里面的指定地址開(kāi)始寫(xiě)入指定個(gè)數(shù)的數(shù)據(jù) //在 AT24CXX 里面的指定地址開(kāi)始寫(xiě)入指定個(gè)數(shù)的數(shù)據(jù) //WriteAddr :開(kāi)始寫(xiě)入的地址 對(duì) 24c02 為 0~255 //pBuffer :數(shù)據(jù)數(shù)組首地址 //NumToWrite:要寫(xiě)入數(shù)據(jù)的個(gè)數(shù) void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite) { while(NumToWrite--) { AT24CXX_WriteOneByte(WriteAddr,*pBuffer); WriteAddr++; pBuffer++; } } 參考: 1.原子 STM32 開(kāi)發(fā)庫(kù)函數(shù)版本
上一篇:SPI專題(二)——STM32驅(qū)動(dòng)FLASH(W25Q64)
下一篇:STM32學(xué)習(xí)筆記一一ADC
推薦閱讀
史海拾趣
設(shè)計(jì)資源 培訓(xùn) 開(kāi)發(fā)板 精華推薦
- Microchip 升級(jí)數(shù)字信號(hào)控制器(DSC)產(chǎn)品線 推出PWM 分辨率和 ADC 速度業(yè)界領(lǐng)先的新器件
- 意法半導(dǎo)體STM32MP23x:突破成本限制的工業(yè)AI應(yīng)用核心
- 意法半導(dǎo)體推出用于匹配遠(yuǎn)距離無(wú)線微控制器STM32WL33的集成的匹配濾波芯片
- ESP32開(kāi)發(fā)板連接TFT顯示屏ST7789跳坑記
- 如何讓ESP32支持analogWrite函數(shù)
- LGVL配合FreeType為可變字體設(shè)置字重-ESP32篇
- 使用樹(shù)莓派進(jìn)行 ESP32 Jtag 調(diào)試
- ESP32怎么在SPIFFS里面存儲(chǔ)html,css,js文件,以及網(wǎng)頁(yè)和arduino的通訊
- ESP32 freeRTOS使用測(cè)試
- ARXML 規(guī)則下 ECU 總線通訊與 ADTF 測(cè)試方案
- 日產(chǎn)在歐洲推出第三代e-POWER技術(shù)
- 福特CEO更看好Waymo激光雷達(dá)方案:比特斯拉純視覺(jué)自動(dòng)駕駛路線可靠
- 智元機(jī)器人兩大核心產(chǎn)品啟動(dòng)規(guī)模化生產(chǎn)
- 固態(tài)電池2026量產(chǎn)豪賭,真相還是泡沫?
- 100億元!湖北“下注”人形機(jī)器人產(chǎn)業(yè)
- 海外磷酸鐵鋰電池產(chǎn)能從0到1
- 基于多傳感器數(shù)據(jù)的自動(dòng)駕駛仿真確定性驗(yàn)證
- 國(guó)芯科技發(fā)布全球首款48V安全氣囊芯片,引領(lǐng)智能汽車新紀(jì)元
- 亞馬遜全球部署100萬(wàn)臺(tái)機(jī)器人
- TI Sensor Menu 助力感應(yīng)全世界——下載有禮!
- Avnet&On semi 帶你看未來(lái),3個(gè)你必須知道的行業(yè)趨勢(shì)!
- 立即報(bào)名 | 2025 瑞薩電子工業(yè)以太網(wǎng)技術(shù)日 即將開(kāi)啟?。?月12日-4月18日)
- “感謝有你,感恩有禮”——感恩節(jié)搶樓&送謝禮活動(dòng)
- TI 中國(guó)大學(xué)計(jì)劃20周年——寫(xiě)祝福送好禮!
- “悅”讀deyisupport博文 樂(lè)享知識(shí)智贏好禮
- 家電新風(fēng)尚,PI開(kāi)啟您的家電新生活!下載產(chǎn)品資料答題贏好禮!
- 2019東芝PCIM在線展會(huì):會(huì)一會(huì) 電力領(lǐng)域中的高能晶體管們
- 一起分享,共同成長(zhǎng)!EEWORLD月月有獎(jiǎng)優(yōu)秀主題/回復(fù)第29期
- 榮耀X10 Max上手 “5G時(shí)代的第一款大屏手機(jī)”體驗(yàn)如何?
- 美封殺華為造成洗牌效應(yīng),愛(ài)立信5G超車華為
- 韓國(guó)5G用戶實(shí)際使用5G信號(hào)的時(shí)間僅為15%
- 富士康在印度iPhone組裝業(yè)務(wù)受清關(guān)延誤被迫暫停
- 華潤(rùn)微對(duì)外產(chǎn)品發(fā)布會(huì)將召開(kāi)!為國(guó)產(chǎn)SiC注入堅(jiān)實(shí)“芯力量
- 先裝360,特斯拉才敢上路?
- 外資股比放開(kāi),特斯拉將得到什么?
- ST25DV的NFC解決方案,可用于最新開(kāi)發(fā)的智能計(jì)量表
- 窺探日本制造技術(shù)創(chuàng)新史的興衰
- 如何有效地引導(dǎo)地方級(jí)中小企業(yè)網(wǎng)絡(luò)化、數(shù)字化轉(zhuǎn)型
- MSP430單片機(jī)開(kāi)發(fā)總結(jié)
- #以拆會(huì)友#怡成5D-1血糖儀源代碼
- 怎么讓一個(gè)結(jié)構(gòu)體首地址8字節(jié)對(duì)齊?
- 【CN0271】帶有整合冷端補(bǔ)償?shù)腒型熱電偶測(cè)量系統(tǒng)
- 2410的觸摸屏驅(qū)動(dòng)問(wèn)題求助
- 關(guān)于smp8634芯片問(wèn)題
- msp430串口發(fā)送中斷操作之簡(jiǎn)單三步
- 基于TMS320C6455的以太網(wǎng)通信程序的設(shè)計(jì)
- 情有獨(dú)鐘,迷情電子三五年(三)
- 在wince下(解決馬上給分):如何自畫(huà)對(duì)話框上的標(biāo)題欄?如何讓話框上有標(biāo)題欄而沒(méi)有邊框?