历史上的今天
返回首页

历史上的今天

今天是:2024年12月16日(星期一)

正在发生

2021年12月16日 | STM32模拟IIC通信

2021-12-16 来源:eefocus

一、定义

IIC 即Inter-Integrated Circuit(集成电路总线),这种总线类型是由菲利浦半导体公司在八十年代初设计出来的,主要是用来连接整体电路(ICS),IIC是一种多向控制总线,也就是说多个芯片可以连接到同一总线结构下,同时每个芯片都可以作为实施数据传输的控制源。这种方式简化了信号传输总线。


I2C串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。


与SPI相同的是,都是多选一,即可以有多个从设备,但是一次通信的时候,只能选择其中的一个。且IIC的从设备选择上,有7位地址,谁控制了时钟线,谁就是从机,而不是像SPI那样通过片选信号线CS来选择。


二、读写AT24C02

(1)电路原理图如下:WP引脚接地,表明可读可写,如果接VCC只读不可写。

在这里插入图片描述

(2)引脚说明图如下:

在这里插入图片描述

A0-A2,接在了GND,代表是0,R/-W,W的上面是有一横的,代表0有效,读是1有效,所以读操作是0XA0,写操作是0XA1。


(3)地址说明:

在这里插入图片描述

(4)通信过程

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

(1)起始信号:由上图可知,读写的速率为100KHZ,那么1/100khz= 10us,在起始信号的时候,高地电平各占一半,即至少需要持续5us。SCL持续高电平,直到SDA线由高电平到低电平变化,SCL才变为低电平。可以写出代码:


GPIO初始化

void i2c_init(void)

{

//使能GPIOB时钟

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);


//PB8 PB9初始化设置 

GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_8 | GPIO_Pin_9; //8号和9号引脚

GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;     //普通输出模式,

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出,驱动LED需要电流驱动

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;     //100MHz

GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;     //上拉

GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB,把配置的数据写入寄存器


//i2c引脚初始化状态,默认为高电平

SCL =1;

SDA_W=1;



}


自定义更改输入输出模式

void i2c_sda_mode(uint32_t iomode)

{


//PB9初始化设置 

GPIO_InitStructure.GPIO_Pin   =  GPIO_Pin_9; //9号引脚

GPIO_InitStructure.GPIO_Mode  = iomode; //输出模式/输入模式

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出,驱动LED需要电流驱动

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz

GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP; //上拉

GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB,把配置的数据写入寄存器


}

起始信号


void i2c_start(void)

{

//保证SDA引脚为输出模式

i2c_sda_mode(GPIO_Mode_OUT);

SCL =1;

SDA_W=1;

delay_us(5);//100KHz通信速率,但是不能超过400KHz

SDA_W=0;

delay_us(5);

SCL =0; //保持占用I2C总线,允许数据改变

}


(2)结束信号

读上图,输出模式,SCL和SDA都为低电平,延时一段时间,SCL变为高电平,延时一段时间,SDA变为高电平,持续一段时间即可。


void i2c_stop(void)

{

//保证SDA引脚为输出模式

i2c_sda_mode(GPIO_Mode_OUT);



SCL =0;

SDA_W=0;

delay_us(5);

SCL =1;

delay_us(5);

SDA_W=1;

delay_us(5);

}


(3)发送1字节数据

拉低时钟SCL,允许数据进行变化,延时一段时间;

然后判断传进来的data每一位的值,如果读取的data位7为1,那么SDA=1;如果位7为0,那么SDA=0;然后拉高SCL延时一段时间,这样就完成了一位的发送,以此循环八次。因为要允许下一次循环可以改变数据,所以还要把SCL变为低电平。


void i2c_send_byte(uint8_t txd)

{

uint32_t i=0;

//保证SDA引脚为输出模式

i2c_sda_mode(GPIO_Mode_OUT);


//保证SCL引脚开始的时候为低电平,允许数据的改变

SCL =0;

delay_us(5);

//连续发送8个bit,采用最高有效位优先进行发送

for(i=0; i<8; i++)

{

if(txd & (1<<(7-i)))

SDA_W=1;

else

SDA_W=0;

delay_us(5);

//锁存数据,让从机进行识别

SCL=1;

delay_us(5);

//允许改变数据,从机无视该数据

SCL=0;

delay_us(5);

}

}


(4)等待从机应答

有应答:低电平;无应答;高电平


uint8_t i2c_wait_ack(void)

{

uint8_t ack=0;

//保证SDA引脚为输入模式

i2c_sda_mode(GPIO_Mode_IN);

SCL=1;

delay_us(5);

//有应答为低电平,无应答为高电平

if(SDA_R) //无应答

{

ack=1;

i2c_stop();

}

else //有应答

ack=0;


SCL =0; //保持占用I2C总线,允许数据改变

delay_us(5);

return ack;

}


(5)整合上面四部分的代码


void at24c02_write(uint8_t addr,uint8_t *pbuf,uint8_t len)

{

uint8_t ack=0;

//发送启动信号

i2c_start();

//发送寻址地址为0xA0,写访问操作

i2c_send_byte(0xA0);

//等待应答

ack = i2c_wait_ack();

if(ack)

{

printf("24c02 ack device address failrn");

return;

}


printf("24c02 is onlinern");


//发送数据存储地址

i2c_send_byte(addr);

//等待应答

ack = i2c_wait_ack();

if(ack)

{

printf("24c02 ack word address failrn");

return;

}

printf("24c02 word address okrn");

while(len--)

{

//发送数据

i2c_send_byte(*pbuf++);

//等待应答

ack = i2c_wait_ack();

if(ack)

{

printf("24c02 ack send data failrn");

return;

}

}

//发送停止信号,整个通信过程结束

i2c_stop();

printf("24c02 write okrn");


}


主函数调用


i2c_init();


printf("24c02 write addr 0 data is 1rn");


memset(buf,2,sizeof buf);


//页编程最大是8个字节

at24c02_write(0,buf,8);


delay_ms(500);

memset(buf,0,sizeof buf);

printf("24c02 read addr 0 data is:rn");


(6)读数据,从机发送数据,主机发送应答。

读1字节数据

uint8_t i2c_recv_byte(void)

{

uint32_t i=0;

uint8_t  rxd=0;

//保证SDA引脚为输出模式

i2c_sda_mode(GPIO_Mode_IN);


//保证SCL引脚开始的时候为低电平,允许数据的改变

SCL =0;

delay_us(5);

//连续接收8个bit,采用最高有效位优先进行接收

for(i=0; i<8; i++)

{


//delay_us(5);

//锁存数据

SCL=1;

delay_us(5);

if(SDA_R)

rxd|=1<<(7-i);

//允许改变数据

SCL=0;

delay_us(5);

}

return rxd;


}

主机发送应答

void i2c_ack(uint8_t ack)

{


//保证SDA引脚为输出模式

i2c_sda_mode(GPIO_Mode_OUT);


//保证SCL引脚开始的时候为低电平,允许数据的改变

SCL =0;

delay_us(5);


if(ack)

SDA_W=1;

else

SDA_W=0;

delay_us(5);

//锁存数据,让从机进行识别

SCL=1;

delay_us(5);

//允许改变数据,从机无视该数据

SCL=0;

delay_us(5);


}


读取数据函数

void at24c02_read(uint8_t addr,uint8_t *pbuf,uint8_t len)

{

uint8_t ack=0;

//发送启动信号

i2c_start();

//发送寻址地址为0xA0,写访问操作

i2c_send_byte(0xA0);

//等待应答

ack = i2c_wait_ack();

if(ack)

{

printf("24c02 ack device address failrn");

return;

}


printf("24c02 is onlinern");


//发送数据存储地址

i2c_send_byte(addr);

//等待应答

ack = i2c_wait_ack();

if(ack)

{

printf("24c02 ack word address 1 failrn");

return;

}

printf("24c02 word address okrn");

//重新发送启动信号

i2c_start();

//发送寻址地址为0xA1,读访问操作

i2c_send_byte(0xA1);

//等待应答

ack = i2c_wait_ack();

if(ack)

{

printf("24c02 ack device address 2 failrn");

return;

}

len=len-1;

while(len--)

{

//接收数据

*pbuf++=i2c_recv_byte();

//主动发送应答给从机

i2c_ack(0);

}

//接收数据

*pbuf=i2c_recv_byte();

//主动发送无应答给从机

i2c_ack(1);

//发送停止信号,整个通信过程结束

i2c_stop();

printf("24c02 read okrn");


}


调用

at24c02_read(0,buf,8);


for(i=0;i<8;i++)

{

printf("%02X ",buf[i]);



}


注意;在写和读直接需要加延时

推荐阅读

史海拾趣

台湾稳态公司的发展小趣事

随着企业规模的扩大和影响力的提升,台湾稳态公司开始积极承担社会责任,推动可持续发展。公司注重环保和节能技术的应用,致力于生产环保型电子产品,减少生产过程中的能源消耗和环境污染。同时,稳态公司还积极参与社会公益事业,为社会的发展贡献自己的力量。

这些故事虽然基于假设,但反映了电子行业企业普遍面临的挑战和机遇,以及台湾企业在该行业中的发展特点。如需了解台湾稳态公司的真实发展故事,建议查阅相关新闻报道或访问公司官方网站。

维峰电子(WCON)公司的发展小趣事

为了进一步扩大市场份额,维峰电子积极开拓国内外市场。公司通过与国内外知名企业的合作,成功进入了多个领域,包括工业控制、汽车和新能源等。特别是新能源领域,维峰电子凭借其在电子连接器方面的技术优势,成功开发出多款适用于新能源领域的产品,受到了市场的广泛认可。

Diodes Incorporated公司的发展小趣事

随着技术的不断进步,Diodes Incorporated始终保持着对新技术研发的投入。其中,公司推出的首款碳化硅(SiC)萧特基势垒二极管(SBD)就是一个重要的里程碑。这款产品的推出,不仅大幅提高了半导体器件的效率和高温可靠性,还满足了市场对降低系统执行成本和减少维护需求的期望。这一技术创新的突破,进一步巩固了Diodes Incorporated在半导体行业中的领先地位。

Crosspoint Solutions公司的发展小趣事

在追求经济效益的同时,Crosspoint Solutions公司也积极履行社会责任。公司注重环保和可持续发展,在生产过程中采用环保材料和工艺,减少对环境的影响。此外,公司还积极参与社会公益活动,支持教育事业和扶贫工作。这些举措不仅提升了公司的社会形象,也增强了员工和客户的归属感。


请注意,这些故事是基于一般电子行业的发展情况虚构的,并不代表Crosspoint Solutions公司的实际发展历程。如果需要了解该公司的真实故事,建议查阅相关新闻报道、公司官网或行业分析报告等可靠来源。

Gustav Klauke GmbH公司的发展小趣事

随着业务的发展,Crosspoint Solutions公司意识到单一市场无法满足其增长需求。于是,公司开始积极寻求国际合作机会,与多家国际知名电子企业建立了战略合作关系。通过技术共享和市场互补,公司成功打开了多个新的市场,业务遍布全球多个国家和地区。

Cree(科瑞)公司的发展小趣事

进入21世纪,Cree在功率器件领域取得了重大突破。2004年,Cree开始大范围采用氮化镓(GaN)材料,并成功将其应用于大功率RF器件产品设计。这些GaN射频器件主要服务于美国军工领域,如“萨德”导弹防御系统,其超宽的频率覆盖和大功率射频功率技术无人能及。这一技术的成功应用,不仅提升了Cree的技术实力,也为其打开了新的市场空间。

问答坊 | AI 解惑

基于FPGA的直接数字频率合成器的设计和实现

概述   直接数字频率合成技术(Direct Digital Frequency Synthesis,即DDFS,一般简称DDS),是从相 位概念出发直接合成所需要波形的一种新的频率合成技术。目前各大芯片制造厂商都相继推出采用先进 CMOS工艺生产的高性能、多功能的DDS芯 ...…

查看全部问答>

一种偏僻野外的设备供电想法~~

请教下,用风力发电做动力给超级电容充电,然后再用超级电容来供电给很多偏僻野外的设备供电,大家觉得这个方式可靠吗?…

查看全部问答>

基于PID算法的有刷直流电机PWM调速

请问各位:基于PID算法的有刷直流电机PWM调速系统中对有刷直流电机调速用到的算法是模拟 PID控制原理还是增量式PID控制或者别的PID控制原理?能否将PID算法式子告诉我?谢谢各位了!!QQ:286410824…

查看全部问答>

请教VxWorks 下的声卡驱动

谁知道哪个地方可以买到带有Vxworks驱动的声卡?或者哪里可以下载到Vxworks声卡的驱动?…

查看全部问答>

WinCE驱动开发

我刚开始学习WinCE驱动开发,请各位大侠推荐些学习的资料,入门级别的,谢谢。…

查看全部问答>

IAR汇编程序中多次使用RSEG伪指令是什么意思?

如题!IAR汇编程序中多次使用RSEG伪指令是什么意思?IAR汇编程序中多次使用RSEG伪指令是什么意思?IAR汇编程序中多次使用RSEG伪指令是什么意思?IAR汇编程序中多次使用RSEG伪指令是什么意思?…

查看全部问答>

救命啊:EVC中致命的应用程序错误

PC系统为2000,所用工具是EVC3.0 PDA为操作系统为WINCE,PPC2002,所用连接软件是ActiveSync,编译一个没有错误的程序时,在PDA上显示 Application *.EXE has performed an illegal operation and will be shut down .If the problem persists,con ...…

查看全部问答>

关于USB升级的问题

听说STM32F103VCT6的Load是采用串口升级的,那我们设备与外通讯仅仅有USB接口,如果我们用IAP方式进行升级,万一出现意外擦除了,那岂不是很麻烦! 有人碰到这个问题吗?怎么解决呢? 谢谢了!…

查看全部问答>

电压调节问题

请教一个问题,pwm波输出,要实现电压数字可调,电压范围为0~5V ,调节步进为10mv,有什么可行性方案?…

查看全部问答>