• 正文
    • 一模塊來(lái)源
    • 二規(guī)格參數(shù)
    • 三移植過(guò)程
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

【CW32模塊使用】AT24C02-EEPROM存儲(chǔ)器:CW32F030C8T6開發(fā)板實(shí)現(xiàn)播報(bào)語(yǔ)音

03/06 15:51
725
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

EEPROM (Electrically Erasable Programmable read only memory)是指帶電可擦可編程只讀存儲(chǔ)器。是一種掉電后數(shù)據(jù)不丟失的存儲(chǔ)芯片。EEPROM 可以在電腦上或?qū)S迷O(shè)備上擦除已有信息,重新編程。一般用在即插即用。AT24C02是一個(gè)2K位串行CMOS E2PROM, 內(nèi)部含有256個(gè)8位字節(jié),CATALYST公司的先進(jìn)CMOS技術(shù)實(shí)質(zhì)上減少了器件的功耗。AT24C02有一個(gè)16字節(jié)頁(yè)寫緩沖器。該器件通過(guò)IIC總線接口進(jìn)行操作,有一個(gè)專門的寫保護(hù)功能。

模塊來(lái)源

模塊實(shí)物展示:

 

規(guī)格參數(shù)

工作電壓:1.8V-5.5V

工作電流:最大3mA

通信接口:IIC

內(nèi)存:2048位

時(shí)鐘速度:5V時(shí)最大1000Khz,其余為400Khz

以上信息見(jiàn)廠家資料文件

移植過(guò)程

我們的目標(biāo)是將例程移植至CW32F030C8T6開發(fā)板上【能夠播報(bào)語(yǔ)音的功能】。首先要獲取資料,查看數(shù)據(jù)手冊(cè)應(yīng)如何實(shí)現(xiàn)讀取數(shù)據(jù),再移植至我們的工程。

3.1查看資料

上圖是AT24CXX的設(shè)備地址(第一行的為AT24C02,它的容量為2K),我們發(fā)現(xiàn)AT24CXX整個(gè)系列芯片的地址高四位都相同,都是1010,這四位是由生產(chǎn)商固化在芯片內(nèi)部,無(wú)法改變。

AT24C02地址的低三位(不包括讀寫位)對(duì)應(yīng)芯片的三個(gè)引腳,也就是說(shuō)這三位是可以人為設(shè)定的,23=8,所以一條I2C總線上可以掛載8個(gè)AT24C02。

AT24C02的地址為7位二進(jìn)制數(shù),下圖中最后一位是讀寫位(數(shù)據(jù)方向位),1 表示讀數(shù)據(jù),0 表示寫數(shù)據(jù)。

這樣,7位設(shè)備地址加1位讀寫位,構(gòu)成I2C的尋址數(shù)據(jù)。I2C 總線的尋址過(guò)程中,通常在起始條件后的第一個(gè)字節(jié)決定了主機(jī)選擇哪一個(gè)從機(jī),該字節(jié)的最后一位決定數(shù)據(jù)傳輸方向。

AT24C02讀寫:AT24C02的存儲(chǔ)空間為2K位(256字節(jié)),在對(duì)其進(jìn)行寫數(shù)據(jù)時(shí),最小寫入單位為字節(jié)(Byte),最大寫入單位為頁(yè)(Page),AT24C02頁(yè)大小為 16 Byte。

字節(jié)寫

在字節(jié)寫模式下,主器件發(fā)送起始信號(hào)和從器件地址信息(R/W 位置零)給從器件,在從器件送回應(yīng)答信號(hào)后,主器件發(fā)送 AT24WC01/02/04/08/16 的字節(jié)地址,主器件在收到從器件的應(yīng)答信號(hào)后,再發(fā)送數(shù)據(jù)到被尋址的存儲(chǔ)單元。AT24WC01/02/04/08/16 再次應(yīng)答,并在主器件產(chǎn)生停止信號(hào)后開始內(nèi)部數(shù)據(jù)的擦寫,在內(nèi)部擦寫過(guò)程中,AT24WC01/02/04/08/16 不再應(yīng)答主器件的任何請(qǐng)求。

頁(yè)寫

用頁(yè)寫,AT24WC01 可一次寫入 8 個(gè)字節(jié)數(shù)據(jù),AT24WC02/04/08/16 可以一次寫入 16 個(gè)字節(jié)的數(shù)據(jù),頁(yè)寫操作的啟動(dòng)和字節(jié)寫一樣,不同在于傳送了一字節(jié)數(shù)據(jù)后并不產(chǎn)生停止信號(hào),主器件被允許發(fā)送 P(AT24WC01 P=7;AT24WC02/04/08/16 P=15)個(gè)額外的字節(jié)。每發(fā)送一個(gè)字節(jié)數(shù)據(jù)后 AT24WC01/02/04/08/16 產(chǎn)生一個(gè)應(yīng)答位并將字節(jié)地址低位加 1,高位保持不變。

如果在發(fā)送停止信號(hào)之前主器件發(fā)送超過(guò)P+1個(gè)字節(jié),地址計(jì)數(shù)器將自動(dòng)翻轉(zhuǎn),先前寫入的數(shù)據(jù)被覆蓋。

接收到P+1字節(jié)數(shù)據(jù)和主器件發(fā)送的停止信號(hào)后,AT24CXXX啟動(dòng)內(nèi)部寫周期將數(shù)據(jù)寫到數(shù)據(jù)區(qū),所有接收的數(shù)據(jù)在一個(gè)寫周期內(nèi)寫入AT24WC01/02/04/08/16。

當(dāng)前地址讀

AT24WC01/02/04/08/16 的地址計(jì)數(shù)器內(nèi)容為最后操作字節(jié)的地址加 1。也就是說(shuō) 如果上次讀/寫的操作地址為 N,則立即讀的地址從地址 N+1 開始。如果 N=E(這里對(duì) 24WC01 E=127;對(duì) 24WC02 E=255;對(duì) 24WC04 E=511;對(duì) 24WC08 E=1023;對(duì) 24WC16 E=2047)則計(jì)數(shù)器將翻轉(zhuǎn)到 0 且繼續(xù)輸出數(shù)據(jù)。AT24WC01/02/04/08/16 接收到從器件地址信號(hào)后(R/W 位置 1),它首先發(fā)送一個(gè)應(yīng)答信號(hào),然后發(fā)送一個(gè) 8 位字節(jié)數(shù)據(jù)。主器件不需發(fā)送一個(gè)應(yīng)答信號(hào),但要產(chǎn)生一個(gè)停止信號(hào)。

選擇讀(隨機(jī)讀)

選擇性讀操作允許主器件對(duì)寄存器的任意字節(jié)進(jìn)行讀操作,主器件首先通過(guò)發(fā)送起始信號(hào)、從器件地址和它想讀取的字節(jié)數(shù)據(jù)的地址執(zhí)行一個(gè)偽寫操作。在 AT24WC01/02/04/08/16 應(yīng)答之后,主器件重新發(fā)送起始信號(hào)和從器件地址,此時(shí) R/W 位置 1,AT24WC01/02/04/08/16 響應(yīng)并發(fā)送應(yīng)答信號(hào),然后輸出所要求的一個(gè) 8 位字節(jié)數(shù)據(jù),主器件不發(fā)送應(yīng)答信號(hào)但產(chǎn)生一個(gè)停止信號(hào)。

連續(xù)讀

連續(xù)讀操作可通過(guò)立即讀或選擇性讀操作啟動(dòng)。在 AT24WC01/02/04/08/16 發(fā)送完一個(gè) 8 位字節(jié)數(shù)據(jù)后,主器件產(chǎn)生一個(gè)應(yīng)答信號(hào)來(lái)響應(yīng),告知 AT24WC01/02/04/08/16 主器件要求更多的數(shù)據(jù),對(duì)應(yīng)每個(gè)主機(jī)產(chǎn)生的應(yīng)答信號(hào) AT24WC01/02/04/08/16 將發(fā)送一個(gè) 8 位數(shù)據(jù)字節(jié)。當(dāng)主器件不發(fā)送應(yīng)答信號(hào)而發(fā)送停止位時(shí)結(jié)束此操作。

從 AT24WC01/02/04/08/16 輸出的數(shù)據(jù)按順序由 N 到 N+1 輸出。讀操作時(shí)地址計(jì)數(shù)器在 AT24WC01/02/04/08/16 整個(gè)地址內(nèi)增加,這樣整個(gè)寄存器區(qū)域在可在一個(gè)讀操作內(nèi)全部讀出。當(dāng)讀取的字節(jié)超過(guò) E(對(duì)于 24WC01 E=127;對(duì) 24WC02 E=255; 對(duì) 24WC04 E=511;對(duì) 24WC08 E=1023;對(duì) 24WC16 E=2047)計(jì)數(shù)器將翻轉(zhuǎn)到零并繼續(xù)輸出數(shù)據(jù)字節(jié)。

3.2引腳選擇

模塊接線圖

3.3移植至工程

移植步驟中的導(dǎo)入.c和.h文件與【CW32模塊使用】DHT11溫濕度傳感器相同,只是將.c和.h文件更改為bsp_at24c02.c與bsp_at24c02.h。這里不再過(guò)多講述,移植完成后面修改相關(guān)代碼。

在文件bsp_at24c02.c中,編寫如下代碼。

/* * Change Logs: * Date           Author       Notes * 2024-06-25     LCKFB-LP    first version */
#include "bsp_at24c02.h"#include "stdio.h"
// SLAVE ADDRESS+W為0xA0,SLAVE ADDRESS+R為0xA1#define AT24C02_ADDRESS_READ                0xA0#define AT24C02_ADDRESS_WRITE               0xA1

/****************************************************************** * 函 數(shù) 名 稱:AT24C02_GPIO_Init * 函 數(shù) 說(shuō) 明:AT24C02的引腳初始化 * 函 數(shù) 形 參:無(wú) * 函 數(shù) 返 回:無(wú) * 作       者:LC * 備       注:無(wú)******************************************************************/void AT24C02_GPIO_Init(void){    GPIO_InitTypeDef GPIO_InitStruct; // GPIO初始化結(jié)構(gòu)體
    RCC_AT24C02_GPIO_ENABLE();        // 使能GPIO時(shí)鐘
    GPIO_InitStruct.Pins = GPIO_SDA|GPIO_SCL;   // GPIO引腳    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 開漏輸出    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;    // 輸出速度高    GPIO_Init(PORT_AT24C02, &GPIO_InitStruct);  // 初始化}

/****************************************************************** * 函 數(shù) 名 稱:IIC_Start * 函 數(shù) 說(shuō) 明:IIC起始時(shí)序 * 函 數(shù) 形 參:無(wú) * 函 數(shù) 返 回:無(wú) * 作       者:LC * 備       注:無(wú)******************************************************************/void IIC_Start(void){        SDA_OUT();
        SDA(1);        delay_us(5);        SCL(1);        delay_us(5);
        SDA(0);        delay_us(5);        SCL(0);        delay_us(5);
}/****************************************************************** * 函 數(shù) 名 稱:IIC_Stop * 函 數(shù) 說(shuō) 明:IIC停止信號(hào) * 函 數(shù) 形 參:無(wú) * 函 數(shù) 返 回:無(wú) * 作       者:LC * 備       注:無(wú)******************************************************************/void IIC_Stop(void){        SDA_OUT();        SCL(0);        SDA(0);
        SCL(1);        delay_us(5);        SDA(1);        delay_us(5);
}
/****************************************************************** * 函 數(shù) 名 稱:IIC_Send_Ack * 函 數(shù) 說(shuō) 明:主機(jī)發(fā)送應(yīng)答或者非應(yīng)答信號(hào) * 函 數(shù) 形 參:0發(fā)送應(yīng)答  1發(fā)送非應(yīng)答 * 函 數(shù) 返 回:無(wú) * 作       者:LC * 備       注:無(wú)******************************************************************/void IIC_Send_Ack(unsigned char ack){        SDA_OUT();        SCL(0);        SDA(0);        delay_us(5);        if(!ack) SDA(0);        else     SDA(1);        SCL(1);        delay_us(5);        SCL(0);        SDA(1);}

/****************************************************************** * 函 數(shù) 名 稱:I2C_WaitAck * 函 數(shù) 說(shuō) 明:等待從機(jī)應(yīng)答 * 函 數(shù) 形 參:無(wú) * 函 數(shù) 返 回:0有應(yīng)答  1超時(shí)無(wú)應(yīng)答 * 作       者:LC * 備       注:無(wú)******************************************************************/unsigned char I2C_WaitAck(void){
        char ack = 0;        unsigned char ack_flag = 10;        SCL(0);        SDA(1);        SDA_IN();        delay_us(5);        SCL(1);    delay_us(5);
        while( (SDA_GET()==1) && ( ack_flag ) )        {                        ack_flag--;                        delay_us(5);        }
        if( ack_flag <= 0 )        {                        IIC_Stop();                        return 1;        }        else        {                        SCL(0);                        SDA_OUT();        }        return ack;}
/****************************************************************** * 函 數(shù) 名 稱:Send_Byte * 函 數(shù) 說(shuō) 明:寫入一個(gè)字節(jié) * 函 數(shù) 形 參:dat要寫人的數(shù)據(jù) * 函 數(shù) 返 回:無(wú) * 作       者:LC * 備       注:無(wú)******************************************************************/void Send_Byte(uint8_t dat){    int i = 0;    SDA_OUT();    SCL(0);//拉低時(shí)鐘開始數(shù)據(jù)傳輸
    for( i = 0; i < 8; i++ )    {        SDA( (dat & 0x80) >> 7 );        delay_us(1);        SCL(1);        delay_us(5);        SCL(0);        delay_us(5);        dat<<=1;    }}
/****************************************************************** * 函 數(shù) 名 稱:Read_Byte * 函 數(shù) 說(shuō) 明:IIC讀時(shí)序 * 函 數(shù) 形 參:無(wú) * 函 數(shù) 返 回:讀到的數(shù)據(jù) * 作       者:LC * 備       注:無(wú)******************************************************************/unsigned char Read_Byte(void){    unsigned char i,receive=0;    SDA_IN();//SDA設(shè)置為輸入    for(i=0;i<8;i++ )    {        SCL(0);        delay_us(5);        SCL(1);        delay_us(5);        receive<<=1;        if( SDA_GET() )        {            receive|=1;        }        delay_us(5);    }    SCL(0);    return receive;}




/****************************************************************** * 函 數(shù) 名 稱:AT24C02_WriteByte * 函 數(shù) 說(shuō) 明:AT24C02寫入一個(gè)字節(jié) * 函 數(shù) 形 參:WordAddress 要寫入字節(jié)的地址  Data 要寫入的數(shù)據(jù) * 函 數(shù) 返 回:無(wú) * 作       者:LC * 備       注:無(wú)******************************************************************/void AT24C02_WriteByte(unsigned char WordAddress,unsigned char Data){        IIC_Start();        Send_Byte(AT24C02_ADDRESS_READ);        I2C_WaitAck();        Send_Byte(WordAddress);        I2C_WaitAck();        Send_Byte(Data);        I2C_WaitAck();        IIC_Stop();}
/****************************************************************** * 函 數(shù) 名 稱:AT24C02_ReadByte * 函 數(shù) 說(shuō) 明:AT24C02讀取一個(gè)字節(jié) * 函 數(shù) 形 參:WordAddress 要讀出字節(jié)的地址 * 函 數(shù) 返 回:讀出的數(shù)據(jù) * 作       者:LC * 備       注:無(wú)******************************************************************/unsigned char AT24C02_ReadByte(unsigned char WordAddress){        unsigned char Data;        IIC_Start();        Send_Byte(AT24C02_ADDRESS_READ);        I2C_WaitAck();        Send_Byte(WordAddress);        I2C_WaitAck();        IIC_Start();        Send_Byte(AT24C02_ADDRESS_WRITE);        I2C_WaitAck();        Data=Read_Byte();        IIC_Send_Ack(1);        IIC_Stop();        return Data;}

在文件bsp_at24c02.h中,編寫如下代碼。

/*?*?Change?Logs: * Date           Author       Notes * 2024-06-25     LCKFB-LP    first version */
#ifndef _BSP_AT24C02_H_#define _BSP_AT24C02_H_
#include "board.h"

//端口移植#define RCC_AT24C02_GPIO_ENABLE()   __RCC_GPIOB_CLK_ENABLE()#define PORT_AT24C02                CW_GPIOB
#define GPIO_SDA                    GPIO_PIN_8#define GPIO_SCL                    GPIO_PIN_9
//設(shè)置SDA輸出模式#define SDA_OUT()   {                                GPIO_InitTypeDef GPIO_InitStruct;                                        GPIO_InitStruct.Pins = GPIO_SDA;                                         GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;                              GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;                                 GPIO_Init(PORT_AT24C02, &GPIO_InitStruct);                            }//設(shè)置SDA輸入模式#define SDA_IN()    {                                GPIO_InitTypeDef GPIO_InitStruct;                                        GPIO_InitStruct.Pins = GPIO_SDA;                                         GPIO_InitStruct.Mode = GPIO_MODE_INPUT;                                  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;                                 GPIO_Init(PORT_AT24C02, &GPIO_InitStruct);                           }//獲取SDA引腳的電平變化#define SDA_GET()       GPIO_ReadPin(PORT_AT24C02, GPIO_SDA)//SDA與SCL輸出#define SDA(x)          GPIO_WritePin(PORT_AT24C02, GPIO_SDA, (x?GPIO_Pin_SET:GPIO_Pin_RESET) )#define SCL(x)          GPIO_WritePin(PORT_AT24C02, GPIO_SCL, (x?GPIO_Pin_SET:GPIO_Pin_RESET) )
void AT24C02_GPIO_Init(void);void AT24C02_WriteByte(unsigned char WordAddress,unsigned char Data);unsigned char AT24C02_ReadByte(unsigned char WordAddress);#endif

移植驗(yàn)證
>>>

在自己工程中的main主函數(shù)中,編寫如下。

/* * Change Logs: * Date           Author       Notes * 2024-06-25     LCKFB-LP    first version */#include "board.h"#include "stdio.h"#include "bsp_uart.h"#include "bsp_at24c02.h"
int32_t main(void){    unsigned char dat1 = 0;    unsigned char dat2 = 0;
    board_init();    uart1_init(115200U);
    AT24C02_GPIO_Init();    printf("startrn");
    //向0地址寫入數(shù)據(jù)48    AT24C02_WriteByte(0,48);    delay_ms(5);
    //向8地址寫入數(shù)據(jù)48    AT24C02_WriteByte(8,66);    delay_ms(5);
    //從0地址讀取數(shù)據(jù)到dat1    dat1 = AT24C02_ReadByte(0);    delay_ms(5);    //從8地址讀取數(shù)據(jù)到dat2    dat2 = AT24C02_ReadByte(8);    delay_ms(5);
    delay_ms(50);
    //輸出dat查看數(shù)據(jù)是否正確    printf("dat1 = %drn",dat1);    delay_ms(1);    printf("dat2 = %drn",dat2);    delay_ms(1);
    while(1)    {
    }}

移植現(xiàn)象:

向0地址寫入數(shù)據(jù)48,再讀出查看是否是48。

向8地址寫入數(shù)據(jù)66,再讀出查看是否是66。

 

模塊移植成功案例代碼:

鏈接:https://pan.baidu.com/s/1vMkhtubSlSjCLW960FccxQ?pwd=LCKF

提取碼:LCKF

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計(jì)資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

以開放、共享、互助為理念,致力于構(gòu)建武漢芯源半導(dǎo)體CW32系列MCU生態(tài)社區(qū)。無(wú)論是嵌入式MCU小自還是想要攻破技術(shù)難題的工程師,亦或是需求解決方案的產(chǎn)品經(jīng)理都可在CW32生態(tài)社區(qū)汲取營(yíng)養(yǎng)、共同成長(zhǎng)。

B站