Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >STM32快速读写AT24C16 代码 模拟I2C

STM32快速读写AT24C16 代码 模拟I2C

作者头像
知否知否应是绿肥红瘦
发布于 2025-02-19 13:12:07
发布于 2025-02-19 13:12:07
22900
代码可运行
举报
文章被收录于专栏:Linux知识Linux知识
运行总次数:0
代码可运行

本帖只适用AT24C16及以下的芯片,AT24C32及以上的芯片读写方式不一样,故不适用!!!

如果你的代码可以正常读写24C01/02,直接拿来读取24C16是可以的,但是只能读取256字节。

AT24C16与AT24C01/02/04/08 不同,它引脚的A2,A1,A0是无效的,也就是它没有自己独立的地址,总线上只能挂一个AT24C16设备。

AT24C16总共2048字节,分为128页,每页16字节,地址范围是0~2047。

128页只需要7位地址,分为高3位和低4位,高3位在设备地址中,低4位在字节地址中。

设备地址:1010+页地址高3位+读写方向(1:读  0:写)

字节地址:页地址高4位+4位页内偏移地址

例如读写地址:1864 ,首先计算该地址是多少页的多少个字节,1864/16=116(0x74)页,1864%16=8(0x08),即116页的第8个字节

其中页地址0x74=0 1 1 1 0 1 0 0,最高位忽略,分为D6、D5、D4(高3位)和D3~D0(低4位)两个部分 。

可以计算出 设备地址和字节地址:

设备地址:1010+111+0/1  (AT24C16设备地址高4位固定为1010)

字节地址:0100+1000(高4位是页地址低4位,低4位是页内偏移地址,即0x08)

最后,根据标准I2C读写时序来对这个地址进行读写即可!

模拟I2C.c

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include "myiic.h"
#include "delay.h"

#if SoftDelay
__asm void delay_us(u32 usec)  
{                    
 ALIGN
	PUSH.W {r1}		//2时钟周期
	MOV r1,#18		//1时钟周期
	MUL r0,r1		//1时钟周期
	SUB r0,#3		//1时钟周期
loop
	SUBS r0,#1			//1时钟周期
	BNE loop			//如果跳转则为3个周期,不跳则只有1个周期
	POP {r1}			//2时钟周期
	BX lr				//3个时钟周期
						//总共所用周期为(usec*4)-4,此处减4主要用于抵消调用此函数的消耗时钟周期(传参1时钟,BLX跳转3时钟)
  //本函数内总共所用周期为usec*(freq/4)-2 +9,调用此函数的消耗5个时钟周期(传参2时钟,BLX跳转3时钟)
} 
#endif

//初始化IIC
void IIC_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(IIC_CLOCK, ENABLE );		   
	GPIO_InitStructure.GPIO_Pin = SCL_PIN|SDA_PIN;    //引脚
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(SCL_PORT, &GPIO_InitStructure);
 
	IIC_SCL=1;
	IIC_SDA=1;//拉高SDA和SCL

}
//产生IIC起始信号
void IIC_Start(void)
{
	SDA_OUT();     //sda线输出
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}	  
//产生IIC停止信号
void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL=0;
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL=1; 
	IIC_SDA=1;//发送I2C总线结束信号
	delay_us(4);							   	
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us(1);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;//时钟输出0 	   
	return 0;  
} 
//产生ACK应答
void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}
//不产生ACK应答		    
void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}					 				     
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	SDA_OUT(); 	    
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1; 	  
		delay_us(2);   //对TEA5767这三个延时都是必须的
		IIC_SCL=1;
		delay_us(2); 
		IIC_SCL=0;	
		delay_us(2);
    }	 
} 	    
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
        IIC_SCL=0; 
        delay_us(2);
		IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
		delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}

i2c.h

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#ifndef __MYIIC_H
#define __MYIIC_H
#include "stm32f10x.h"
//位段定义 方便后面直接操作IO口   Reg:寄存器地址  Bit:该寄存器的第多少位
#define BITBAND_REG(Reg,Bit) (*((uint32_t volatile*)(0x42000000u + (((uint32_t)&(Reg) - (uint32_t)0x40000000u)<<5) + (((uint32_t)(Bit))<<2))))
#define SoftDelay 0  //是否使用软件延时


//IO口定义 移植需要修改
#define SCL_PORT GPIOC
#define SDA_PORT GPIOC
#define SCL_PIN  GPIO_Pin_12
#define SDA_PIN  GPIO_Pin_11
//I2C 时钟 移植需要修改
#define IIC_CLOCK RCC_APB2Periph_GPIOC

//IO方向设置  移植需要修改
#define SDA_IN()  {SDA_PORT->CRH&=0XFFFF0FFF;SDA_PORT->CRH|=8<<12;} // SDA配置为输入
#define SDA_OUT() {SDA_PORT->CRH&=0XFFFF0FFF;SDA_PORT->CRH|=3<<12;} // SDA配置为输出

//IO操作函数	移植需要修改
#define IIC_SCL    BITBAND_REG(SCL_PORT->ODR,12) //SCL输出=?
#define IIC_SDA    BITBAND_REG(SDA_PORT->ODR,11)  //SDA输出=?	 
#define READ_SDA   (SDA_PORT->IDR&(1<<11))  //读SDA脚 

//IIC所有操作函数
void IIC_Init(void);         //初始化IIC的IO口
void IIC_Start(void);				//发送IIC开始信号
void IIC_Stop(void);	  			//发送IIC停止信号
void IIC_Send_Byte(u8 txd);			//IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); 				//IIC等待ACK信号
void IIC_Ack(void);					//IIC发送ACK信号
void IIC_NAck(void);				//IIC不发送ACK信号

void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);
#endif

AT24C16.c

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include "24cxx.h"
#include "delay.h"
#include "stdio.h"

//初始化IIC接口
void AT24CXX_Init(void)
{
    IIC_Init();
}

#if EE_TYPE<=AT24C08  //24C01/02/08
//在AT24CXX指定地址读出一个数据
//ReadAddr:开始读数的地址
//返回值  :读到的数据
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{
    u8 temp=0;
    IIC_Start();
    if(EE_TYPE>AT24C16)
    {
        IIC_Send_Byte(0XA0);	   //发送写命令
        IIC_Wait_Ack();
        IIC_Send_Byte(ReadAddr>>8);//发送高地址
        IIC_Wait_Ack();
    } else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));   //发送器件地址0XA0,写数据

    IIC_Wait_Ack();
    IIC_Send_Byte(ReadAddr%256);   //发送低地址
    IIC_Wait_Ack();
    IIC_Start();
    IIC_Send_Byte(0XA1);//进入接收模式
    IIC_Wait_Ack();
    temp=IIC_Read_Byte(0);
    IIC_Stop();//产生一个停止条件
    return temp;
}
//在AT24CXX指定地址写入一个数据
//WriteAddr  :写入数据的目的地址
//DataToWrite:要写入的数据
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{
    IIC_Start();
    if(EE_TYPE>AT24C16)
    {
        IIC_Send_Byte(0XA0);//发送设备地址
        IIC_Wait_Ack();
        IIC_Send_Byte(WriteAddr>>8);//发送字节高地址
    } else
    {
        IIC_Send_Byte(0XA0+((WriteAddr/256)<<1));   //发送器件地址0XA0,写数据
    }
    IIC_Wait_Ack();
    IIC_Send_Byte(WriteAddr%256);   //发送字节低地址
    IIC_Wait_Ack();
    IIC_Send_Byte(DataToWrite);     //发送要写入的数据
    IIC_Wait_Ack();
    IIC_Stop();//产生一个停止条件
    delay_ms(10);
}
#else  //24C16
/*****************************************************************
*函数名: AT24CXX_ReadOneByte(u16 ReadAddr)
*功能:AT24CXX 读指定地址的一个字节   AT24C16使用
*调用:底层I2C读写函数
*被调用:外部调用
*形参:
			ReadAddr:要读取的地址
*返回值:返回读取的数据
*其他:每次读就启动一次I2C时序
*****************************************************************/
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{
    unsigned char Page=0,WordAddress=0,DeviceAddress=0xA0;
    u8 temp=0;
    Page=ReadAddr/AT24CXX_Page_Size;
    WordAddress=(ReadAddr%AT24CXX_Page_Size) & 0x0F;
    DeviceAddress |= (((Page<<1) & 0xE0)>>4);//High 3 bits
    WordAddress |= (Page & 0x0F)<<4;//Low 4 bits
    IIC_Start();
    IIC_Send_Byte(DeviceAddress&0xFE);//发送设备地址+写方向
    IIC_Wait_Ack();
    IIC_Send_Byte(WordAddress);//发送字节地址
    IIC_Wait_Ack();
    IIC_Start();                //起始信号
    IIC_Send_Byte(DeviceAddress|0x01);//发送设备地址+读方向
    IIC_Wait_Ack();
    temp=IIC_Read_Byte(0);
    IIC_Stop();//产生一个停止条件
    return temp;
}
/*****************************************************************
*函数名: AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
*功能:AT24CXX 向指定地址写入一个字节   AT24C16使用
*调用:
*被调用:外部调用
*形参:
			WriteAddr:要写入的地址
			DataToWrite:写入的数据
*返回值:无
*其他:每次写就启动一次I2C时序
*****************************************************************/
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{
    unsigned char Page=0,WordAddress=0,DeviceAddress=0xA0;
    Page=WriteAddr/AT24CXX_Page_Size;
    WordAddress=(WriteAddr%AT24CXX_Page_Size) & 0x0F;
    DeviceAddress |= (((Page<<1) & 0xE0)>>4);//High 3 bits
    WordAddress |= (Page & 0x0F)<<4;//Low 4 bits
#if DEBUG	> 0
    printf("Page:%x\r\n",Page);
    printf("WordAddress:%x\r\n",WordAddress);
    printf("DeviveAddress:%x\r\n",DeviceAddress);
#endif
    IIC_Start();
    IIC_Send_Byte(DeviceAddress);//发送设备地址
    IIC_Wait_Ack();
    IIC_Send_Byte(WordAddress);//发送字节地址
    IIC_Wait_Ack();
    IIC_Send_Byte(DataToWrite);     //发送要写入的数据
    IIC_Wait_Ack();
    IIC_Stop();//产生一个停止条件
    delay_ms(10);
}
#endif



/*---------------读写方式选择-----------------*/
#if  QuickWR == 0
//在AT24CXX里面的指定地址开始读出指定个数的数据
//ReadAddr :开始读出的地址 对24c02为0~255
//pBuffer  :数据数组首地址
//NumToRead:要读出数据的个数
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
{
    while(NumToRead)
    {
        *pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);
        NumToRead--;
    }
}
//在AT24CXX里面的指定地址开始写入指定个数的数据
//WriteAddr :开始写入的地址 对24c02为0~255
//pBuffer   :数据数组首地址
//NumToWrite:要写入数据的个数
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{
    while(NumToWrite--)
    {
        AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
        WriteAddr++;
        pBuffer++;
    }
}
#else  //快速读写方式
/*****************************************************************
*函数名: AT24CXX_Write_Bytes(u8 *pBuffer,u16 WriteAddress,u8 Len)
*功能: 页写函数 最多写入一页(16字节)
*调用: 底层I2C写函数
*被调用:外部调用
*形参:
      *pBuffer:指向写入缓存区
			WriteAddr:要写入的地址
			Len:写入数据长度
*返回值:无
*其他:启动一次I2C时序最多写入一页(16Bytes)数据,明显快于按字节写入
*****************************************************************/
void AT24CXX_Write_Bytes(u8 *pBuffer,u16 WriteAddress,u8 Len)
{
    unsigned char Page=0,WordAddress=0,DeviceAddress=0xA0;
    u8 i=0;
    Page=WriteAddress/AT24CXX_Page_Size;
    WordAddress=(WriteAddress%AT24CXX_Page_Size) & 0x0F;
    DeviceAddress |= (((Page<<1) & 0xE0)>>4);//High 3 bits
    WordAddress |= (Page & 0x0F)<<4;//Low 4 bits
    IIC_Start();
    IIC_Send_Byte(DeviceAddress);//发送设备地址
    IIC_Wait_Ack();
    IIC_Send_Byte(WordAddress);//发送字节地址
    IIC_Wait_Ack();
    for(i=0; i<Len; i++)
    {
        IIC_Send_Byte(*pBuffer++);//发送字节地址
        IIC_Wait_Ack();
    }
    IIC_Stop();//产生一个停止条件
    delay_ms(10);
}
/*****************************************************************
*函数名: AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
*功能:AT24CXX 快速写入不定量字节
*调用:
*被调用:外部调用
*形参:
			WriteAddr:要写入的首地址
			*pBuffer:指向写入缓存区
			NumToWrite:写入的字节数
*返回值:无
*其他:快速模式 不用每次写一个字节就启动一次I2C时序
*****************************************************************/
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{
    unsigned char NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;
    Addr=WriteAddr%AT24CXX_Page_Size;//地址正好是16字节对齐
    count=AT24CXX_Page_Size-Addr;//不对齐字节数
    NumOfPage=NumToWrite/AT24CXX_Page_Size;//需要写入多少页
    NumOfSingle=NumToWrite%AT24CXX_Page_Size;//剩余需写入的字节数
    if(0==Addr)//如果地址对齐
    {
        if(NumToWrite<=AT24CXX_Page_Size)//写入字节<=1页
        {
            AT24CXX_Write_Bytes(pBuffer,WriteAddr,NumToWrite);
        }
        else
        {
            while(NumOfPage--)//按页写入
            {
                AT24CXX_Write_Bytes(pBuffer,WriteAddr,AT24CXX_Page_Size);
                pBuffer+=AT24CXX_Page_Size;
                WriteAddr+=AT24CXX_Page_Size;
            }
            if(NumOfSingle != 0)//如果还剩下字节
            {
                AT24CXX_Write_Bytes(pBuffer,WriteAddr,NumOfSingle);//把剩下的字节写入
            }
        }
    }
    else//地址不对齐
    {
        if(NumToWrite<=count)// 要写入的字节数<=count
        {
            AT24CXX_Write_Bytes(pBuffer,WriteAddr,NumToWrite);//写入实际字节数
        }
        else//要写入字节数大于count
        {
            AT24CXX_Write_Bytes(pBuffer,WriteAddr,count);//现将count个字节写入 写入后 地址刚好对齐
            NumToWrite-=count;//计算剩余字节数
            pBuffer+=count;//写入内容偏移count
            WriteAddr+=count;//写入地址偏移count

            NumOfPage=NumToWrite/AT24CXX_Page_Size;//需要写入多少页
            NumOfSingle=NumToWrite%AT24CXX_Page_Size;//剩余需写入的字节数

            while(NumOfPage--)//先按页写入
            {
                AT24CXX_Write_Bytes(pBuffer,WriteAddr,AT24CXX_Page_Size);
                pBuffer+=AT24CXX_Page_Size;
                WriteAddr+=AT24CXX_Page_Size;
            }
            if(NumOfSingle != 0)//还剩余字节
            {
                AT24CXX_Write_Bytes(pBuffer,WriteAddr,NumOfSingle);//把剩下的字节写入
            }
        }
    }
}

void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
{
    unsigned char Page=0,WordAddress=0,DeviceAddress=0x50;
    Page=ReadAddr/AT24CXX_Page_Size;
    WordAddress=(ReadAddr%AT24CXX_Page_Size) & 0x0F;
    DeviceAddress |= (((Page<<1) & 0xE0)>>4);//High 3 bits
    WordAddress |= (Page & 0x0F)<<4;//Low 4 bits
    while(NumToRead)
    {
        *pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);
        NumToRead--;
    }
}

#endif  //快速读写方式

//检查AT24CXX是否正常
//这里用了24XX的最后一个地址(255)来存储标志字.
//如果用其他24C系列,这个地址要修改
//返回1:检测失败
//返回0:检测成功
u8 AT24CXX_Check(void)
{
    u8 temp;
    temp=AT24CXX_ReadOneByte(255);//避免每次开机都写AT24CXX
    if(temp==0X55)return 0;
    else//排除第一次初始化的情况
    {
        AT24CXX_WriteOneByte(255,0X55);
        temp=AT24CXX_ReadOneByte(255);
        if(temp==0X55)return 0;
    }
    return 1;
}

AT24C16.h

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#ifndef __24CXX_H
#define __24CXX_H
#include "myiic.h"
//Mini STM32开发板
//24CXX驱动函数(适合24C01~24C16,24C32~256未经过测试!有待验证!)
//正点原子@ALIENTEK
//2010/6/10
//V1.2
#define AT24C01		127
#define AT24C02		255
#define AT24C04		511
#define AT24C08		1023
#define AT24C16		2047
#define AT24C32		4095
#define AT24C64	    8191
#define AT24C128	16383
#define AT24C256	32767


/*----------------EEPROM相关配置--------------------*/
#define EE_TYPE AT24C16  //EEPROM类型
#define AT24CXX_Page_Size 16 //AT24C16每页有16个字节
#define DEBUG   0  //串口调试开关
#define QuickWR 0 //快速读写开关


u8 AT24CXX_ReadOneByte(u16 ReadAddr);							//指定地址读取一个字节
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite);		//指定地址写入一个字节
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite);	//从指定地址开始写入指定长度的数据
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead);   	//从指定地址开始读出指定长度的数据

u8 AT24CXX_Check(void);  //检查器件
void AT24CXX_Init(void); //初始化IIC
#endif

main.c

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "24cxx.h" 
#include "myiic.h"
#include "stdio.h"
//要写入到24c16的字符串数组
const u8 TEXT_Buffer[]={"C++ is the best language!"};//要写入的内容
#define SIZE sizeof(TEXT_Buffer)	//写入内容的大小
#define ADDRESS 2020	//读写地址
 int main(void)
 { 
	u8 datatemp[SIZE];
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
	delay_init();	    	 //延时函数初始化	  
	uart_init(9600);	 	//串口初始化为9600
	LED_Init();		  		//初始化与LED连接的硬件接口		 	
	AT24CXX_Init();			//IIC初始化 	
 	while(AT24CXX_Check())//检测不到24c16
	{		
		delay_ms(500);
		LED0=!LED0;//DS0闪烁
	}	  
	while(1)
	{			
			   		
			AT24CXX_Write(ADDRESS,(u8*)TEXT_Buffer,SIZE);
			printf("Write:%s\r\n",TEXT_Buffer); //显示写入内容		
		    delay_ms(1000);		
			AT24CXX_Read(ADDRESS,datatemp,SIZE);
			printf("Read:%s\r\n",datatemp);//显示读取内容 						
	}
}

 演示结果:

注意:上面的代码可以支持24C01/02 ,将AT24CXX.h中的宏定义EE_TYPE 改为AT24C01/02即可

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-02-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
基于STM32F10X的BMP280程序
基于STM32F10X的BMP280完整程序示例,采用IIC通信方式,可以实现温度、气压和高度的测试。
用户4006703
2025/06/05
820
基于STM32设计的姿态感应刹车灯
由于自行车本身没有带指示灯,比如刹车指示灯等,所以自行车的安全性并不是很好,如果人们在骑自行车时紧急刹车,后车无法及时判断前方自行车的行为,容易造成交通事故。
DS小龙哥
2025/05/27
960
基于STM32设计的姿态感应刹车灯
三大通信协议(二):IIC通信协议
主设备和从设备进行数据传输时遵循以下协议格式。 数据通过一条SDA数据线在主设备和从设备之间传输0和1的串行数据。串行数据序列的结构可以分为,开始条件,地址位,读写位,应答位,数据位,停止条件,具体如下所示;
全栈程序员站长
2022/08/22
2K0
三大通信协议(二):IIC通信协议
从IIC实测波形入手,搞懂IIC通信
玩单片机的朋友都知道IIC通信这个工具,但好多人只是会用,内部的原理不求甚解,或是想要了解其原理,但却对抽象的时序描述一头雾水。本文将从实测的IIC波形入手,带你看到真实的IIC样子,进而去理解IIC的通信原理。
xxpcb
2020/08/04
4.7K0
STM32控制max30102读取血氧心率数据(keil5工程)
MAX30102是一款由Maxim Integrated推出的低功耗、高精度的心率和血氧饱和度检测传感器模块,适用于可穿戴设备如智能手环、智能手表等健康管理类电子产品。
DS小龙哥
2024/05/24
1.1K0
STM32控制max30102读取血氧心率数据(keil5工程)
IIC通信协议详解
IIC:两线式串行总线,它是由数据线SDA和时钟线SCL构成的串行总线,可发送和接收数据。
全栈程序员站长
2022/06/29
3K0
IIC通信协议详解
(31)STM32——I2C实验笔记
目录 学习目标 运行结果 内容 代码 总结  ---- 学习目标         本节介绍的是I2C实验,使用的是AT24C02来实现存储操作,这部分内容与C51的I2C的实验基本上是一模一样,而且在51中讲解的特别详细与通俗,所以本节内容不会过多介绍,介绍部分可以去看51的笔记。 运行结果         就是一个简单的存储实验,和在51上的基本一样。  内容         关于I2C实验,51的笔记讲的非常详细了,基本上是一模一样,在此就不再赘述了,我们直接来到代码部分。(十一)51
小点点
2022/12/12
3630
(31)STM32——I2C实验笔记
EEPROM-AT24C02存储器芯片数据读写
在嵌入式系统设计中,数据的存储与读取是至关重要的一环。随着技术的不断发展,对存储设备的性能、容量和可靠性要求也越来越高。EEPROM(电可擦除可编程只读存储器)作为一种非易失性存储介质,以其数据存储可靠、功耗低、读取速度快等特点,广泛应用于各种嵌入式系统中。本项目在利用STC90C51单片机和EEPROM-AT24C02存储器芯片实现高效的数据读写存储功能,以满足现代嵌入式系统对数据存储的需求。
DS小龙哥
2025/05/27
1230
EEPROM-AT24C02存储器芯片数据读写
STM32F103驱动GT911
// SCL——-PB10 // SDA——-PB11 // INT——–PB1 // RST——–PB2
全栈程序员站长
2022/09/07
1.8K1
STM32F103驱动GT911
STM32通信模拟 I2C
I²C(Inter-Integrated Circuit),常读作“I方C”,它是一种多主从架构串行通信总线。在1980年由飞利浦公司设计,用于让主板、嵌入式系统或手机连接低速周边设备。如今在嵌入式领域是非常常见通信协议,常用于MPU/MCU与外部设备连接通信、数据传输。
韦东山
2022/05/09
1.1K0
STM32通信模拟 I2C
激光测距芯片VL53L0X的使用与代码
采用940nm垂直腔面发射激光器(Vertical-Cavity Surface-Emitting Laser,简称VCSEL)发射出激光,激光碰到障碍物后反射回来被VL53L0X接收到,测量激光在空气中的传播时间,进而得到距离。VCSEL相关知识
全栈程序员站长
2022/09/05
2.1K0
激光测距芯片VL53L0X的使用与代码
IIC通信协议,搞懂这篇就够了
I2C(IIC)属于两线式串行总线,由飞利浦公司开发用于微控制器(MCU)和外围设备(从设备)进行通信的一种总线,属于一主多从(一个主设备(Master),多个从设备(Slave))的总线结构,总线上的每个设备都有一个特定的设备地址,以区分同一I2C总线上的其他设备。
混说Linux
2022/07/14
9K0
IIC通信协议,搞懂这篇就够了
STM32+MPU6050设计便携式Mini桌面时钟(自动调整时间显示方向)
完整项目源码下载地址: https://download.csdn.net/download/xiaolong1126626497/18657534
DS小龙哥
2022/01/17
1.1K0
STM32+MPU6050设计便携式Mini桌面时钟(自动调整时间显示方向)
IIC通信协议技术说明
IIC Bus 最早是Philips半导体开发的两线时串行总线,经常用于微控制器和外设之间的连接。IIC通信方式为半双工,只有一根SDA线,同一时间只可以单向通信,485为半双工,SPI和UART为全双工。
全栈程序员站长
2022/09/07
4720
IIC通信协议技术说明
STM32 BMP280模块 获取气压温度高度传感器数据
BMP280是博世最新推出的数字气压传感器,具有卓越的性能和低廉的价格,相对精度为±0.12 hPa(相当于±1米),传感器功耗仅有2.7μA,包括压力和温度测量功能。
CoderEnd
2023/05/07
9680
STM32 BMP280模块 获取气压温度高度传感器数据
STM32入门开发: 介绍IIC总线、读写AT24C02(EEPROM)(采用模拟时序)
IIC总线: STM32本身支持IIC硬件时序的,本文采用的是模拟时序,下篇文章就介绍配置STM32的IIC硬件时序读写AT24C02和AT24C08。
DS小龙哥
2022/01/12
2.1K0
STM32入门开发: 介绍IIC总线、读写AT24C02(EEPROM)(采用模拟时序)
STM32+BH1750光敏传感器获取光照强度
代码说明:使用IIC模拟时序驱动,方便移植到其他平台,采集的光照度比较灵敏. 合成的光照度返回值范围是 0~255。 0表示全黑 255表示很亮。
DS小龙哥
2022/01/17
1.6K0
STM32+BH1750光敏传感器获取光照强度
MPU9250传感器
MPU9250 内部包括 3 轴陀螺仪、3 轴加速度计和 3 轴磁力计,这3个功能输出都是 16 位的数字量; 可以通过常用的数据总线( IIC) 接口和单片机进行数据交互,传输速率 400 kHz /s。陀螺仪的角速度测量范围±2000(° /s),具有良好的动态响应特性。加速度计的测量范围最大为±16g( g 为重力加速度),静态测量精度高。磁力计采用高灵度霍尔型传感器进行数据采集,磁感应强度测量范围为±4800μT,可用于对偏航角的辅助测量。 MPU9250 自带的数字运动处理器DMP硬件加速引擎,可以整合九轴传感器数据,向应用端输出完整的 9 轴融合演算数据。 有了 DMP,我们可以使用运动处理库非常方便的实现姿态解算,降低了运动处理运算对操作系统的负荷,同时大大降低了开发难度。
全栈程序员站长
2022/07/23
1.9K0
MPU9250传感器
(40)STM32——OV2640摄像头实验
目录 学习目标 运行结果 内容 OV2640 特点 时序 帧输出时序 配置 DCMI 特点 信号 DMA 寄存器 配置 硬件连接 代码 总结  ---- 学习目标         今天我们要学习的是OV2640摄像头实验,采用的是DCMI接口,进行传输。个人觉得难度较大,加上没有相应的串口线,导致部分实验无法进行,所以就先讲解理论知识,等串口线到了再把电脑端的实验补上。 运行结果 https://live.csdn.net/v/embed/242011 摄像头实验 内容 OV2640        
小点点
2022/12/12
3.3K0
(40)STM32——OV2640摄像头实验
at24c02模块怎么用_AI8C模块参数
一、STM32专栏目录 二、Linux专栏目录 三、Android专栏目录
全栈程序员站长
2022/11/17
4840
at24c02模块怎么用_AI8C模块参数
相关推荐
基于STM32F10X的BMP280程序
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档