天天看點

I2C專題(二)—— STM32驅動AT24C02

前言:

為了友善檢視部落格,特意申請了一個公衆号,附上二維碼,有興趣的朋友可以關注,和我一起讨論學習,一起享受技術,一起成長。

I2C專題(二)—— STM32驅動AT24C02

github:my github

注:部落格所涉及的關于 stm32 的代碼,均在倉庫【stm32f013_study】下,包括底層驅動和應用測試代碼。

本文設計的檔案包含:

(1)drvsfi2c.c:軟體模拟 i2c 驅動實作

(2)app_at24cxx.c:AT24C02 測試實作

(3)頭檔案:

drvsfi2c.h : 軟體模拟I2C;

app_at24cxx.h:AT24C02 應用測試;

1. 概述

MiniSTM32 開發闆闆載的 EEPROM 晶片型号為 24C02。該晶片的總容量是 256個位元組,該晶片通過 I2C 總線與外部連接配接。這裡直接采用原子闆上的 AT24C02 ,主要是軟體程式設計方面的學習。

2. 硬體連接配接

I2C專題(二)—— STM32驅動AT24C02

A2、A1、A0 三個引腳直接接地。供電: (VCC = 2.7V to 5.5V)

器件位址設定:

I2C專題(二)—— STM32驅動AT24C02

對于AT24C02:Addr—>0xA0(寫)/ 0xA1(讀)。

單位元組寫入:

I2C專題(二)—— STM32驅動AT24C02
//--------------------------------------------------------------------------------------------------------------------------
//	函 數 名: ee_at24cxx_write_byte
//	功能說明: eeprom寫一個位元組資料
//	形    參: 	write_addr:寫入位址
//              write_byte:寫入資料
//	返 回 值: 無
//	日    期: 2020-03-22
//  備    注: eeprom小于16K bits
//	作    者: by 霁風AI
//--------------------------------------------------------------------------------------------------------------------------
bool ee_at24cxx_write_byte(uint16_t write_addr, uint8_t write_byte)
{
    I2c_Start();

    I2c_SendOneByte(AT24CXX_ADDR | ((write_addr / 256) << 1));    //發送裝置位址+資料位址高3位(<16K:1010 + p2p1p0 + r/w)
    if (I2c_WaitAck(I2C_WAIT_TIME) == I2C_NACK)
    {
        return false;
    }
    I2c_SendOneByte(write_addr % 256);	//裝置位址低8位
    if (I2c_WaitAck(I2C_WAIT_TIME) == I2C_NACK)
    {
        return false;
    }

    I2c_SendOneByte(write_byte);    //寫入的資料
    if (I2c_WaitAck(I2C_WAIT_TIME) == I2C_NACK)
    {
        return false;
    }

    I2c_Stop();
	
	delay_ms(5  );	//寫完一個位元組需要延時重新開啟總線

    return true;
}
           

按頁寫入:

I2C專題(二)—— STM32驅動AT24C02

從目前位址讀出資料;

I2C專題(二)—— STM32驅動AT24C02
//--------------------------------------------------------------------------------------------------------------------------
//	函 數 名: ee_at24cxx_read_byte
//	功能說明: eeprom讀一個位元組資料
//	形    參: 	write_addr:讀出位址
//              write_byte:讀出資料
//	返 回 值: 無
//	日    期: 2020-03-22
//  備    注: eeprom小于16K bits(先确定讀資料位址,再進行讀資料)
//	作    者: by 霁風AI
//--------------------------------------------------------------------------------------------------------------------------
bool ee_at24cxx_read_byte(uint16_t read_addr)
{
    uint8_t ret = 0;

    I2c_Start();

    I2c_SendOneByte(AT24CXX_ADDR | ((read_addr / 256) << 1));    //發送位址高3位(<16K:1010 + p2p1p0 + r/w)
    if (I2c_WaitAck(I2C_WAIT_TIME) == I2C_NACK)
    {
        return false;
    }
    I2c_SendOneByte(read_addr % 256);
    if (I2c_WaitAck(I2C_WAIT_TIME) == I2C_NACK)
    {
        return false;
    }

	 I2c_Start();
	
    I2c_SendOneByte(AT24CXX_ADDR | 0x01);  //裝置位址 + 讀操作
    if (I2c_WaitAck(I2C_WAIT_TIME) == I2C_NACK)
    {
        return false;
    }

    ret = I2c_RecvOneByte(I2C_NACK);

    I2c_Stop();
	
	return ret;
}
           

随機讀取:

I2C專題(二)—— STM32驅動AT24C02

順序讀出:

I2C專題(二)—— STM32驅動AT24C02

3. 例程分析

(一)I2C 部分實作代碼

包括 IIC 的初始化(IO 口)、 IIC 開始、 IIC 結束、 ACK、 IIC 讀寫等功能,在其他函數裡面,隻需要調用相關的 IIC 函數就可以和外部 IIC 器件通信了,這裡并不局限于 24C02,該段代碼可以用在任何 IIC 裝置上。

IIC_SCL 和 IIC_SDA 分别連在 STM32 的 PC12 和 PC11。

I2C 部分的代碼請參看---->STM32 驅動溫濕度傳感器 HTU21D

(二)AT24C02 操作

1. 初始化

//--------------------------------------------------------------------------------------------------------------------------
//	函 數 名: ee_at24cxx_init
//	功能說明: eeprom初始化
//	形    參: 無
//	返 回 值: 無
//	日    期: 2020-03-22
//  備    注: 調用I2c_Init
//	作    者: by 霁風AI
//--------------------------------------------------------------------------------------------------------------------------
void ee_at24cxx_init(void)
{
    I2c_Init();
}
           

2. 在 AT24CXX 指定位址讀出一個資料

//--------------------------------------------------------------------------------------------------------------------------
//	函 數 名: ee_at24cxx_read_byte
//	功能說明: eeprom讀一個位元組資料
//	形    參: 	write_addr:讀出位址
//              write_byte:讀出資料
//	返 回 值: 無
//	日    期: 2020-03-22
//  備    注: eeprom小于16K bits(先确定讀資料位址,再進行讀資料)
//	作    者: by 霁風AI
//--------------------------------------------------------------------------------------------------------------------------
bool ee_at24cxx_read_byte(uint16_t read_addr)
{
    uint8_t ret = 0;

    I2c_Start();

    I2c_SendOneByte(AT24CXX_ADDR | ((read_addr / 256) << 1));    //發送位址高3位(<16K:1010 + p2p1p0 + r/w)
    if (I2c_WaitAck(I2C_WAIT_TIME) == I2C_NACK)
    {
        return false;
    }
    I2c_SendOneByte(read_addr % 256);
    if (I2c_WaitAck(I2C_WAIT_TIME) == I2C_NACK)
    {
        return false;
    }

	 I2c_Start();
	
    I2c_SendOneByte(AT24CXX_ADDR | 0x01);  //裝置位址 + 讀操作
    if (I2c_WaitAck(I2C_WAIT_TIME) == I2C_NACK)
    {
        return false;
    }

    ret = I2c_RecvOneByte(I2C_NACK);

    I2c_Stop();
	
	return ret;
}
           

3. 在 AT24CXX 指定位址寫入一個資料

//--------------------------------------------------------------------------------------------------------------------------
//	函 數 名: ee_at24cxx_write_byte
//	功能說明: eeprom寫一個位元組資料
//	形    參: 	write_addr:寫入位址
//              write_byte:寫入資料
//	返 回 值: 無
//	日    期: 2020-03-22
//  備    注: eeprom小于16K bits
//	作    者: by 霁風AI
//--------------------------------------------------------------------------------------------------------------------------
bool ee_at24cxx_write_byte(uint16_t write_addr, uint8_t write_byte)
{
    I2c_Start();

    I2c_SendOneByte(AT24CXX_ADDR | ((write_addr / 256) << 1));    //發送裝置位址+資料位址高3位(<16K:1010 + p2p1p0 + r/w)
    if (I2c_WaitAck(I2C_WAIT_TIME) == I2C_NACK)
    {
        return false;
    }
    I2c_SendOneByte(write_addr % 256);	//裝置位址低8位
    if (I2c_WaitAck(I2C_WAIT_TIME) == I2C_NACK)
    {
        return false;
    }

    I2c_SendOneByte(write_byte);    //寫入的資料
    if (I2c_WaitAck(I2C_WAIT_TIME) == I2C_NACK)
    {
        return false;
    }

    I2c_Stop();
	
	delay_ms(5  );	//寫完一個位元組需要延時重新開啟總線

    return true;
}
           

4. AT24CXX 裡面的指定位址開始讀出指定個數的資料

//--------------------------------------------------------------------------------------------------------------------------
//	函 數 名: ee_at24cxx_read_some_bytes
//	功能說明: eeprom讀出一些位元組資料
//	形    參: 	read_addr:讀出裝置位址
//				pbdata:讀出資料位址
//              read_length:讀出資料長度
//	返 回 值: 無
//	日    期: 2020-03-22
//  備    注: eeprom小于16K bits,循環調用ee_at24cxx_read_byte
//	作    者: by 霁風AI
//--------------------------------------------------------------------------------------------------------------------------
uint16_t ee_at24cxx_read_some_bytes(uint16_t read_addr, uint8_t *pbdata, uint16_t read_length)
{
    uint16_t temp = read_length;

    while (temp--)
    {
        *pbdata++ = ee_at24cxx_read_byte(read_addr);	
		read_addr++;	//讀出位址遞增
    }

    return read_length;
}
           

5. AT24CXX 裡面的指定位址開始寫入指定個數的資料

//--------------------------------------------------------------------------------------------------------------------------
//	函 數 名: ee_at24cxx_write_some_bytes
//	功能說明: eeprom寫一些位元組資料
//	形    參: 	write_addr:寫入裝置位址
//				pbdata:寫入資料位址
//              write_length:寫入資料長度
//	返 回 值: 無
//	日    期: 2020-03-22
//  備    注: eeprom小于16K bits,循環調用ee_at24cxx_write_byte
//	作    者: by 霁風AI
//--------------------------------------------------------------------------------------------------------------------------
void ee_at24cxx_write_some_bytes(uint16_t write_addr, uint8_t *pbdata, uint16_t write_length)
{
    for (uint16_t i = 0; i < write_length; i++)
    {
        ee_at24cxx_write_byte(write_addr, pbdata[i]);
		write_addr++;	//寫入位址遞增
    }
}
           

6. AT24CXX 讀寫測試

//--------------------------------------------------------------------------------------------------------------------------
//	函 數 名: ee_at24cxx_test
//	功能說明: eeprom測試
//	形    參: 無
//	返 回 值: 無
//	日    期: 2020-03-22
//  備    注: eeprom小于16K bits
//	作    者: by 霁風AI
//--------------------------------------------------------------------------------------------------------------------------
#define AT_TEST_ADDR 	0x10
void ee_at24cxx_test(void)
{
    uint8_t test_val = 0x55;
    uint8_t ret = 0;
	uint8_t write_buf[10] = {0xcc, 0xaa, 0x66, 0x5a, 0x77, 0x89, 0x33, 0xbb, 0xac, 0xe9};
	uint8_t read_buf[10] = {0};

    ee_at24cxx_write_byte(0x00, test_val);
	
	Sys_delay_ms(10);

    ret = ee_at24cxx_read_byte(0x00);

    printf("ee at24cxx test val :0x%02x \r\n", ret);
	
	ee_at24cxx_write_some_bytes(AT_TEST_ADDR, write_buf, sizeof(write_buf));
	Sys_delay_ms(50);
	ee_at24cxx_read_some_bytes(AT_TEST_ADDR, read_buf, sizeof(write_buf));
	
	for (uint16_t i = 0; i < sizeof(write_buf); i++)
	{
		printf("ee test some byte ---> 0x%02x \r\n", read_buf[i]);
	}
	
	printf("\r\n");
}
           

測試結果:

I2C專題(二)—— STM32驅動AT24C02

參考:

  1. 原子 STM32 開發庫函數版本
  2. STM32 驅動溫濕度傳感器 HTU21D

繼續閱讀