1、根据board.h步骤配置IIC
1.1、打开RT-Thread Settings里的模拟IIC
去RT-Thread Settings里找到模拟iic,打开,然后保存,就配置好了;
1.2、打开"BSP_USING_I2Cx"宏定义
图中I2C1和I2C2都打开了,实际用的是I2C2;
1.3、根据实际的GPIO配置IIC的SCL和SDA引脚
根据硬件来连,PB8是SCL,PB9是SDA;
2、at24cxx软件包
2.1、安装软件包
打开RT-Thread Settings,搜索“at24cxx”,选择安装然后保存,就可以看到packages下面多了一个“at24cxx”的文件夹;
2.2、配置软件包
打开软件包的readme,可以看到注意事项如下,我打开at24cxx.h默认就是AT24C02,5ms;
- 请在at24cxx.h中修改EE_TYPE为自己使用的型号(默认为AT25C512) 。
- 请在at24cxx.h中修改EE_TWR为自己使用EEPROM的Write Cycle Time,具体值请查看芯片datasheet(默认为5ms) 。
- 从设备地址为7位地址 0x50, 而不是 0xA0 。
2.2.1、芯片型号 EE_TYPE
#ifndef EE_TYPE
#define EE_TYPE AT24C02
#endif
2.2.2、写周期时间 EE_TWR
#define EE_TWR 5
打开数据手册,就可以看到write cycle最大时间是5ms;
2.2.3、器件的IIC地址
IIC通讯中,主机在发送起始信号之后,会发送一个字节的数据,前7位是从机的地址,最后一位是R/W读写标志;
24C02是2K,A0/A1/A2均为0,根据数据手册的图这个字节也就是,1 0 1 0 0 0 0 R/W;
写:R/W=0,1 0 1 0 0 0 0 0,即0xA0;
读:R/W=1,1 0 1 0 0 0 0 1,即0xA1;
再看rtt中关于发送地址的代码,分析完就很清楚了:
写:addr1 = msg->addr << 1;
已知addr1=0xA0,所以msg->addr = addr1 >> 1 = 0xA0 >> 1 = 0x50;
2.3、测试
配置完软件包后,编译、烧录,打开终端,输入at24cxx可查看命令;
3、查看AT24C02在IIC通信中的流程
修改下DBG_LVL才能看到下面输出的信息;
at24cxx check
因为已经地址255写过一次了,所以修改为了0x58,这样在check的时候不会读一次数据就结束,而是有读数据,写数据,再读数据的过程。
根据log中的信息,可以看到AT24C02在IIC通信过程中具体的流程。
4、不用软件包,根据rtt模拟iic驱动写一下24C02读写字节的代码
4.1、头文件
#ifndef APPLICATIONS_AT24C02_IIC2_AT24C02_H_
#define APPLICATIONS_AT24C02_IIC2_AT24C02_H_
#include <rtthread.h>
#include "drv_soft_i2c.h"
#define AT24C02_I2C_BUS_NAME "i2c2" //挂载IIC2上,P89、PB9
#define AT24C02_I2C_ADDR 0x50 //AT24C02从机地址
#define AT24C02_SIZE 256 //AT24C02大小,共256字节
#define AT24C02_CHECK_VALUE 0x5a
//初始化AT24C02
rt_err_t at24c02_init();
#endif /* APPLICATIONS_AT24C02_IIC2_AT24C02_H_ */
4.2、源文件
#include "at24c02.h"
#define LOG_TAG "AT24C02"
#define LOG_LVL LOG_LVL_DBG
#include <ulog.h>
/* I2C总 线 设 备 句 柄 */
static struct rt_i2c_bus_device *i2c_bus = RT_NULL;
//读at24c02中addr地址的数据,并返回
static uint8_t at24c02_read_byte(uint8_t addr)
{
struct rt_i2c_msg msg;
uint8_t buffer[2];
uint8_t data;
msg.addr = AT24C02_I2C_ADDR;
msg.flags = RT_I2C_WR;
buffer[0] = addr;
msg.buf = buffer;
msg.len = 1;
//发送要读数据的地址
rt_i2c_transfer(i2c_bus, &msg, 1);
msg.flags = RT_I2C_RD;
msg.buf = &data;
//读数据
rt_i2c_transfer(i2c_bus, &msg, 1);
return data;
}
//写at24c02中addr地址的数据
static rt_err_t at24c02_write_byte(uint8_t addr,uint8_t data)
{
struct rt_i2c_msg msg;
uint8_t buffer[2];
buffer[0] = addr;
buffer[1] = data;
msg.addr = AT24C02_I2C_ADDR;
msg.flags = RT_I2C_WR;
msg.buf = buffer;
msg.len = 2;
//发送要写数据的地址、写的数据
if(rt_i2c_transfer(i2c_bus, &msg, 1) != 1){
return RT_ERROR;
}
return RT_EOK;
}
static rt_err_t at24c02_check(uint8_t check)
{
uint8_t temp;
temp = at24c02_read_byte(AT24C02_SIZE-1);
if(temp != check){
at24c02_write_byte(AT24C02_SIZE-1,check);
rt_thread_mdelay(5); //wait 5ms
temp = at24c02_read_byte(AT24C02_SIZE-1);
if(temp != check){
return RT_ERROR;
}
}
return RT_EOK;
}
//初始化AT24C02
rt_err_t at24c02_init()
{
//查找I2C总线设备,获取I2C总线设备句柄
i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(AT24C02_I2C_BUS_NAME);
if (i2c_bus == RT_NULL){
LOG_D("can't find device!\n");
return RT_ERROR;
}
//检查AT24C02
if(at24c02_check(AT24C02_CHECK_VALUE) != RT_EOK){
LOG_D("at24c02 check fail!\n");
return RT_ERROR;
}
LOG_D("at24c02 check ok!\n");
return RT_EOK;
}
4.3、main.c
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include "drv_common.h"
#include "at24c02.h"
#define LOG_TAG "main"
#define LOG_LVL LOG_LVL_DBG
#include <ulog.h>
int main(void)
{
//设置LED为推挽输出
rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
LOG_I("init at24c02...");
at24c02_init();
while (1)
{
rt_pin_write(LED0_PIN, PIN_HIGH); //设置高电平
rt_thread_mdelay(500);
rt_pin_write(LED0_PIN, PIN_LOW); //设置低电平
rt_thread_mdelay(500);
}
return RT_EOK;
}