?
一、環境介紹
操作系統: win10
STM32編程方式: 寄存器開發 (方便程序移植到其他單片機)
IIC總線:STM32本身支持IIC硬件時序的,上篇文章已經介紹了采用IIC模擬時序讀寫AT24C02,這篇文章介紹STM32的硬件IIC配置方法,并讀寫AT24C08。
文章地址:https://xiaolong.blog.csdn.net/article/details/117586108
模擬時序更加方便移植到其他單片機,通用性更高,不分MCU;硬件時序效率更高,每個MCU配置方法不同,依賴硬件本身支持。
器件型號: 采用AT24C08 EEPROM存儲芯片
二、AT24C08存儲芯片介紹
2.1 芯片功能特性介紹
AT24C08 是串行CMOS類型的EEPROM存儲芯片,AT24C0x這個系列包含了AT24C01、AT24C02、AT24C04、AT24C08、AT24C16這些具體的芯片型號。
他們容量分別是:1K (128 x 8)、2K (256 x 8)、8K (1024 x 8)、16K (2048 x 8) ,其中的8表示8位(bit)
它們的管腳功能、封裝特點如下:


?


?


?
芯片功能描述:
AT24C08系列支持I2C,總線數據傳送協議I2C,總線協議規定任何將數據傳送到總線的器件作為發送器。任何從總線接收數據的器件為接收器;數據傳送是由產生串行時鐘和所有起始停止信號的主器件控制的。主器件和從器件都可以作為發送器或接收器,但由主器件控制傳送數據(發送或接收)的模式。
芯片特性介紹:
1. 低壓和標準電壓運行
–2.7(VCC=2.7伏至5.5伏)
–1.8(VCC=1.8伏至5.5伏)
3. 有用于硬件數據保護的寫保護引腳
4. 自定時寫入周期(5毫秒~10毫秒),因為內部有頁緩沖區,向AT24C0x寫入數據之后,還需要等待AT24C0x將緩沖區數據寫入到內部EEPROM區域.
5. 數據保存可達100年
6. 100萬次擦寫周期
7. 高數據傳送速率為400KHz、低速100KHZ和IIC總線兼容。 100 kHz(1.8V)和400 kHz(2.7V、5V)
8. 8字節頁寫緩沖區
這個緩沖區大小與芯片具體型號有關: 8字節頁(1K、2K)、16字節頁(4K、8K、16K)
2.2 芯片設備地址介紹

?


?
因為IIC協議規定,每次傳遞數據都是按8個字節傳輸的,AT24C08是1024字節,地址的選擇上與AT24C02有所區別;
IIC設備的標準地址位是7位。上面這個圖里AT24C08的1010是芯片內部固定值,A2 是硬件引腳、由硬件決定電平;P1、P0是空間存儲塊選擇,每個存儲塊大小是256字節,尋址范圍是0~255,AT24C08相當于是4塊AT24C02的構造;最后一位是讀/寫位(1是讀,0是寫),讀寫位不算在地址位里,但是根據IIC的時序順序,在操作設備前,都需要先發送7位地址,再發送1位讀寫位,才能啟動對芯片的操作,我們在寫模擬時序為了方便統一寫for循環,按字節發送,所以一般都是將7地址位與1位讀寫位拼在一起,組合成1個字節,方便按字節傳輸數據。
我現在使用的開發板上AT24C08的原理圖是這樣的:


?
那么這個AT24C08的標準設備地址分別是:
第一塊區域: 0x50(十六進制),對應的二進制就是: 1010000
第二塊區域: 0x51(十六進制),對應的二進制就是: 1010001
第三塊區域: 0x52(十六進制),對應的二進制就是: 1010010
第四塊區域: 0x53(十六進制),對應的二進制就是: 1010011
如果將讀寫位組合在一起,讀權限的設備地址:
第一塊區域: 0xA1(十六進制),對應的二進制就是: 10100001
第二塊區域: 0xA3(十六進制),對應的二進制就是: 10100011
第三塊區域: 0xA5(十六進制),對應的二進制就是: 10100101
第四塊區域: 0xA7(十六進制),對應的二進制就是: 10100111
如果將讀寫位組合在一起,寫權限的設備地址:
第一塊區域: 0xA0(十六進制),對應的二進制就是: 10100000
第二塊區域: 0xA2(十六進制),對應的二進制就是: 10100010
第三塊區域: 0xA4(十六進制),對應的二進制就是: 10100100
第四塊區域: 0xA6(十六進制),對應的二進制就是: 10100110
2.3 對AT24C08 按字節寫數據的指令流程(時序)


?
詳細解釋:
1. 先發送起始信號
2. 發送設備地址(寫權限)
3. 等待AT24C08應答、低電平有效
4. 發送存儲地址、AT24C08內部一共有256個字節空間,尋址是從0開始的,范圍是(0~255);發送這個存儲器地址就是告訴AT24C08接下來的數據改存儲到哪個地方。
5.等待AT24C08應答、低電平有效
6. 發送一個字節的數據,這個數據就是想存儲到AT24C08里保存的數據。
7.等待AT24C08應答、低電平有效
8. 發送停止信號
2.3 對AT24C08 按頁寫數據的指令流程(時序)


?
詳細解釋:
1. 先發送起始信號
2. 發送設備地址(寫權限)
3. 等待AT24C08應答、低電平有效
4. 發送存儲地址、AT24C08內部一共有256個字節空間,尋址是從0開始的,范圍是(0~255);發送這個存儲器地址就是告訴AT24C08接下來的數據改存儲到哪個地方。
5.等待AT24C08應答、低電平有效
6. 可以循環發送8個字節的數據,這些數據就是想存儲到AT24C08里保存的數據。
AT24C08的頁緩沖區是16個字節,所有這里的循環最多也只能發送16個字節,多發送的字節會將前面的覆蓋掉。
需要注意的地方: 這個頁緩沖區的尋址也是從0開始,比如: 0~15算第1頁,16~32算第2頁......依次類推。 如果現在寫數據的起始地址是3,那么這一頁只剩下13個字節可以寫;并不是說從哪里都可以循環寫16個字節。
詳細流程: 這里程序里一般使用for循環實現
(1). 發送字節1
(2). 等待AT24C08應答,低電平有效
(3). 發送字節2
(4).等待AT24C08應答,低電平有效
.........
最多8次.
7.等待AT24C08應答、低電平有效
8. 發送停止信號
2.4 從AT24C08任意地址讀任意字節數據(時序)


?
AT24C08支持當前地址讀、任意地址讀,最常用的還是任意地址讀,因為可以指定讀取數據的地址,比較靈活,上面這個指定時序圖就是任意地址讀。
詳細解釋:
1. 先發送起始信號
2. 發送設備地址(寫權限)
3. 等待AT24C08應答、低電平有效
4. 發送存儲地址、AT24C08內部一共有2048個字節空間,尋址是從0開始的,范圍是(0~1024);發送這個存儲器地址就是告訴AT24C08接下來應該返回那個地址的數據給單片機。
5.等待AT24C08應答、低電平有效
6. 重新發送起始信號(切換讀寫模式)
7.發送設備地址(讀權限)
8.等待AT24C08應答、低電平有效
9. 循環讀取數據: 接收AT24C08返回的數據.
讀數據沒有字節限制,可以第1個字節、也可以連續將整個芯片讀完。
10. 發送非應答(高電平有效)
11. 發送停止信號
三、IIC總線介紹
2.1 IIC總線簡介
I2C(Inter-Integrated Circuit)總線是由PHILIPS公司開發的兩線式串行總線,用于連接微控制器及其外圍設備,是微電子通信控制領域廣泛采用的一種總線標準。具有接口線少,控制方式簡單,器件封裝形式小,通信速率較高等優點。
I2C規程運用主/從雙向通訊。器件發送數據到總線上,則定義為發送器,器件接收數據則定義為接收器。主器件和從器件都可以工作于接收和發送狀態。
I2C 總線通過串行數據(SDA)線和串行時鐘(SCL)線在連接到總線的器件間傳遞信息。每個器件都有一個唯一的地址識別,而且都可以作為一個發送器或接收器(由器件的功能決定)。
I2C有四種工作模式:
1.主機發送
2.主機接收
3.從機發送
4.從機接收
I2C總線只用兩根線:串行數據SDA(Serial Data)、串行時鐘SCL(Serial Clock)。
總線必須由主機(通常為微控制器)控制,主機產生串行時鐘(SCL)控制總線的傳輸方向,并產生起始和停止條件。
SDA線上的數據狀態僅在SCL為低電平的期間才能改變。
2.2 IIC總線上的設備連接圖


?
I2C 總線在物理連接上非常簡單,分別由SDA(串行數據線)和SCL(串行時鐘線)及上拉電阻組成。通信原理是通過對SCL和SDA線高低電平時序的控制,來產生I2C總線協議所需要的信號進行數據的傳遞。在總線空閑狀態時,這兩根線一般被上面所接的上拉電阻拉高,保持著高電平。
其中上拉電阻范圍是4.7K~100K。
2.3I2C總線特征
I2C總線上的每一個設備都可以作為主設備或者從設備,而且每一個從設備都會對應一個唯一的地址(可以從I2C器件的數據手冊得知)。主從設備之間就通過這個地址來確定與哪個器件進行通信,在通常的應用中,我們把CPU帶I2C總線接口的模塊作為主設備,把掛接在總線上的其他設備都作為從設備。
1. 總線上能掛接的器件數量
I2C總線上可掛接的設備數量受總線的最大電容400pF 限制,如果所掛接的是相同型號的器件,則還受器件地址的限制。
一般I2C設備地址是7位地址(也有10位),地址分成兩部分:芯片固化地址(生產芯片時候哪些接地,哪些接電源,已經固定),可編程地址(引出IO口,由硬件設備決定)。
例如: 某一個器件是7 位地址,其中10101 xxx 高4位出廠時候固定了,低3位可以由設計者決定。
則一條I2C總線上只能掛該種器件最少8個。
如果7位地址都可以編程,那理論上就可以達到128個器件,但實際中不會掛載這么多。
2. 總線速度傳輸速度:
I2C總線數據傳輸速率在標準模式下可達100kbit/s,快速模式下可達400kbit/s,高速模式下可達3.4Mbit/s。一般通過I2C總線接口可編程時鐘來實現傳輸速率的調整。
3. 總線數據長度
I2C總線上的主設備與從設備之間以字節(8位)為單位進行雙向的數據傳輸。
2.4 I2C總線協議基本時序信號
空閑狀態:SCL和SDA都保持著高電平。
起始條件:總線在空閑狀態時,SCL和SDA都保持著高電平,當SCL為高電平期間而SDA由高到低的跳變,表示產生一個起始條件。在起始條件產生后,總線處于忙狀態,由本次數據傳輸的主從設備獨占,其他I2C器件無法訪問總線。
停止條件:當SCL為高而SDA由低到高的跳變,表示產生一個停止條件。
答應信號:每個字節傳輸完成后的下一個時鐘信號,在SCL高電平期間,SDA為低,則表示一個應答信號。
非答應信號:每個字節傳輸完成后的下一個時鐘信號,在SCL高電平期間,SDA為高,則表示一個應答信號。應答信號或非應答信號是由接收器發出的,發送器則是檢測這個信號(發送器,接收器可以從設備也可以主設備)。
注意:起始和結束信號總是由主設備產生。
2.5 起始信號與停止信號
起始信號就是: 時鐘線SCL處于高電平的時候,數據線SDA由高電平變為低電平的過程。SCL=1;SDA=1;SDA=0;
停止信號就是: 時鐘線SCL處于低電平的時候, 數據線SDA由低電平變為高電平的過程。SCL=1;SDA=0;SDA=1;


?
2.6 應答信號
數據位的第9位就時應答位。 讀取應答位的流程和讀取數據位是一樣的。示例: SCL=0;SCL=1;ACK=SDA; 這個ACK就是讀取的應答狀態。


?
2.7 數據位傳輸時序
通過時序圖了解到,SCL處于高電平的時候數據穩定,SCL處于低電平的時候數據不穩定。
那么對于寫一位數據(STM32--->AT24C08):SCL=0;SDA=data;SCL=1;
那么對于讀一位數據(STM32<-----AT24C08):?SCL=0;SCL=1;data=SDA;??


?
2.8 總線時序


?
四、IIC總線時序代碼、AT24C08讀寫代碼
在調試IIC模擬時序的時候,可以在淘寶上買一個24M的USB邏輯分析儀,時序出現問題,使用邏輯分析儀一分析就可以快速找到問題。


?
完整的工程源碼下載地址,下載即可編譯運行測試(包含了模擬IIC時序、STM32硬件IIC時序分別驅動AT24C02和AT24C08): https://download.csdn.net/download/xiaolong1126626497/19399945
4.1 iic.c 這是STM32的IIC硬件時序完整代碼
/*
函數功能: 初始化IIC總線
硬件連接:
SCL---PB6
SDA---PB7
*/
void IIC_Init(void)
{
/*1. 時鐘配置*/
RCC->APB2ENR|=1<<3; //PB
/*2. GPIO口模式配置*/
GPIOB->CRL&=0x00FFFFFF;
GPIOB->CRL|=0xFF000000; //復用開漏輸出
GPIOB->ODR|=0x3<<6;
/*3. GPIO口時鐘配置(順序不能錯)*/
RCC->APB1ENR|=1<<21; //I2C1時鐘
RCC->APB1RSTR|=1<<21; //開啟復位時鐘
RCC->APB1RSTR&=~(1<<21);//關閉復位時鐘
/*4. 配置IIC的核心寄存器*/
I2C1->CR2=0x24<<0; //配置主機頻率為36MHZ
I2C1->CCR|=0x2D<<0; //配置主機頻率是400KHZ
I2C1->CR1|=1<<0; //開啟IIC模塊
/*
CCR=主機時鐘頻率/2/IIC總線的頻率
45=36MHZ/2/400KHZ ---0x2D
*/
}
/*
函數功能: 發送起始信號
當時鐘線為高電平的時候,數據線由高電平變為低電平的過程
*/
void IIC_SendStart(void)
{
I2C1->CR1|=1<<8; //產生起始信號
while(!(I2C1->SR1&1<<0)){} //等待起始信號完成
I2C1->SR1=0; //清除狀態位
}
/*
函數功能: 停止信號
當時鐘線為高電平的時候,數據線由低電平變為高電平的過程
*/
void IIC_SendStop(void)
{
I2C1->CR1|=1<<9;
}
/*
函數功能: 發送地址數據
*/
void IIC_SendAddr(u8 addr)
{
u32 s1,s2;
I2C1->DR=addr; //發送數據
while(1)
{
s1=I2C1->SR1;
s2=I2C1->SR2;
if(s1&1<<1) //判斷地址有沒有發送成功
{
break;
}
}
}
/*
函數功能: 發送數據
*/
void IIC_SendOneByte(u8 addr)
{
u32 s1,s2;
I2C1->DR=addr; //發送數據
while(1)
{
s1=I2C1->SR1;
s2=I2C1->SR2;
if(s1&1<<2) //判斷數據有沒有發送成功
{
break;
}
}
}
/*
函數功能: 接收一個字節數據
*/
u8 IIC_RecvOneByte(void)
{
u8 data=0;
I2C1->CR1|=1<<10; //使能應答
while(!(I2C1->SR1&1<<6)){} //等待數據
data=I2C1->DR;
I2C1->CR1&=~(1<<10); //關閉應答使能
return data;
}

4.2 AT24C08.c 這是AT24C08完整的讀寫代碼
*
函數功能: 寫一個字節
函數參數:
u8 addr 數據的位置(0~1023)
u8 data 數據范圍(0~255)
*/
void AT24C08_WriteOneByte(u16 addr,u8 data)
{
u8 read_device_addr=AT24C08_READ_ADDR;
u8 write_device_addr=AT24C08_WRITE_ADDR;
if(addr<256*1) //第一個塊
{
write_device_addr|=0x0<<1;
read_device_addr|=0x0<<1;
}
else if(addr<256*2) //第二個塊
{
write_device_addr|=0x1<<1;
read_device_addr|=0x1<<1;
}
else if(addr<256*3) //第三個塊
{
write_device_addr|=0x2<<1;
read_device_addr|=0x2<<1;
}
else if(addr<256*4) //第四個塊
{
write_device_addr|=0x3<<1;
read_device_addr|=0x3<<1;
}
addr=addr%256; //得到地址范圍
IIC_SendStart();//起始信號
IIC_SendAddr(write_device_addr);//發送設備地址
IIC_SendOneByte(addr); //數據存放的地址
IIC_SendOneByte(data); //發送將要存放的數據
IIC_SendStop(); //停止信號
DelayMs(10); //等待寫
}
/*
函數功能: 讀一個字節
函數參數:
u8 addr 數據的位置(0~1023)
返回值: 讀到的數據
*/
u8 AT24C08_ReadOneByte(u16 addr)
{
u8 data=0;
u8 read_device_addr=AT24C08_READ_ADDR;
u8 write_device_addr=AT24C08_WRITE_ADDR;
if(addr<256*1) //第一個塊
{
write_device_addr|=0x0<<1;
read_device_addr|=0x0<<1;
}
else if(addr<256*2) //第二個塊
{
write_device_addr|=0x1<<1;
read_device_addr|=0x1<<1;
}
else if(addr<256*3) //第三個塊
{
write_device_addr|=0x2<<1;
read_device_addr|=0x2<<1;
}
else if(addr<256*4) //第四個塊
{
write_device_addr|=0x3<<1;
read_device_addr|=0x3<<1;
}
addr=addr%256; //得到地址范圍
IIC_SendStart();//起始信號
IIC_SendAddr(write_device_addr);//發送設備地址
IIC_SendOneByte(addr); //將要讀取數據的地址
IIC_SendStart();//起始信號
IIC_SendAddr(read_device_addr);//發送設備地址
data=IIC_RecvOneByte();//讀取數據
IIC_SendStop(); //停止信號
return data;
}
/*
函數功能: 從指定位置讀取指定長度的數據
函數參數:
u16 addr 數據的位置(0~1023)
u16 len 讀取的長度
u8 *buffer 存放讀取的數據
返回值: 讀到的數據
*/
void AT24C08_ReadByte(u16 addr,u16 len,u8 *buffer)
{
u16 i=0;
IIC_SendStart();//起始信號
IIC_SendAddr(AT24C08_WRITE_ADDR);//發送設備地址
IIC_SendOneByte(addr); //將要讀取數據的地址
IIC_SendStart();//起始信號
IIC_SendAddr(AT24C08_READ_ADDR);//發送設備地址
for(i=0;ilen) //判斷當前頁剩余的字節空間是否夠寫
{
page_byte=len; //表示一次性可以寫完
}
while(1)
{
AT24C08_PageWrite(addr,page_byte,buffer); //寫一頁
if(page_byte==len)break; //寫完了
buffer+=page_byte; //指針偏移
addr+=page_byte;//地址偏移
len-=page_byte;//得到剩余沒有寫完的長度
if(len>16)page_byte=16;
else page_byte=len; //一次可以寫完
}
};i++)>

4.3 main.c 這是AT24C08測試代碼
#include "stm32f10x.h"
#include "beep.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include
#include
#include "exti.h"
#include "timer.h"
#include "rtc.h"
#include "adc.h"
#include "ds18b20.h"
#include "ble.h"
#include "esp8266.h"
#include "wdg.h"
#include "oled.h"
#include "rfid_rc522.h"
#include "infrared.h"
#include "iic.h"
#include "at24c08.h"
u8 buff_tx[50]="1234567890";
u8 buff_rx[50];
u8 data=88;
u8 data2;
int main()
{
u8 key;
LED_Init();
KEY_Init();
BEEP_Init();
TIM1_Init(72,20000); //輔助串口1接收,超時時間為20ms
USART_X_Init(USART1,72,115200);
IIC_Init(); //IIC總線初始化
printf("usart1 ok\n");
while(1)
{
key=KEY_Scanf();
if(key)
{
//AT24C08_WriteByte(100,50,buff_tx);
//AT24C08_ReadByte(100,50,buff_rx);
//printf("buff_rx=%s\n",buff_rx);
//測試第0塊
// data=AT24C08_ReadOneByte(0);
// AT24C08_WriteOneByte(0,data+1);
// printf("data=%d\n",data);
//測試第1塊
// data=AT24C08_ReadOneByte(300);
// AT24C08_WriteOneByte(300,data+1);
// printf("data=%d\n",data);
//測試第2塊
// data=AT24C08_ReadOneByte(600);
// AT24C08_WriteOneByte(600,data+1);
// printf("data=%d\n",data);
//測試第3塊
data=AT24C08_ReadOneByte(900);
AT24C08_WriteOneByte(900,data+1);
printf("data=%d\n",data);
}
}
}
串口調試助手源碼下載地址:QT應用編程: 開發串口調試助手_DS小龍哥的博客-CSDN博客


?
審核編輯:湯梓紅
?
-
mcu
+關注
關注
146文章
17486瀏覽量
354655 -
STM32
+關注
關注
2277文章
10952瀏覽量
359253 -
硬件
+關注
關注
11文章
3421瀏覽量
66708 -
時序
+關注
關注
5文章
392瀏覽量
37533
發布評論請先 登錄
相關推薦
用verilog實現IIC。
請問讀寫AT24C256的時序是掃描樣嗎?
電可檫編程只讀存儲器AT24C08相關資料下載
IIC及AT24C02的讀寫
AT24C02/AT24C04/AT24C08/AT24C1
IIC及AT24C02的讀寫(單片機實驗)

STM32入門開發: 介紹IIC總線、讀寫AT24C02(EEPROM)(采用模擬時序)

評論