I2C专题(二)—— STM32驱动AT24C02

前言:

为了方便查看博客,特意申请了一个公众号,附上二维码,有兴趣的朋友可以关注,和我一起讨论学习,一起享受技术,一起成长。

I2C专题(二)—— STM32驱动AT24C02_第1张图片


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_第2张图片

A2、A1、A0 三个引脚直接接地。供电: (VCC = 2.7V to 5.5V)

器件地址设置:

I2C专题(二)—— STM32驱动AT24C02_第3张图片

对于AT24C02:Addr—>0xA0(写)/ 0xA1(读)。

单字节写入:

I2C专题(二)—— STM32驱动AT24C02_第4张图片

//--------------------------------------------------------------------------------------------------------------------------
//	函 数 名: 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_第5张图片

从当前地址读出数据;

I2C专题(二)—— STM32驱动AT24C02_第6张图片

//--------------------------------------------------------------------------------------------------------------------------
//	函 数 名: 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_第7张图片

顺序读出:

I2C专题(二)—— STM32驱动AT24C02_第8张图片

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_第9张图片

参考:

  1. 原子 STM32 开发库函数版本
  2. STM32 驱动温湿度传感器 HTU21D

你可能感兴趣的:(iic驱动,stm32开发,STM32学习笔记)