历史上的今天
返回首页

历史上的今天

今天是:2025年04月23日(星期三)

正在发生

2019年04月23日 | stm32与AT24C02的I2C通信总结(模拟时序)

2019-04-23 来源:eefocus

从51的时候就学习了I2C通信协议,但51的功能就那些,内部没有集成I2C模块,所以只能通过模拟I2C通信的时序来和EEPROM进行通信,stm32内部集成了I2C通信的片上外设,但由于内部I2C外设复杂和不稳定行,所以用的人不是很多,而基本上使用I2C的通信都是通过模拟时序的方式来实现的


首先I2C是同步半双工的通信方式,需要两条线即可,SCL时钟线,同步时钟由主机产生,SDA数据线用来发送接收数据,任何时候只能一台主机发送数据。


在编程的时候碰到了很多问题,其中一项就是等待从机的应答程序


开始的时候编写如下


void iic_wait_ack()   错误                                                   void iic_wait_ack()          正确的程序            


{                                                                                  {


 SCL=1;                                                                        iic_sda_in();


iic_sda_in();                                                                 SCL=1;


delay_us(2);                                                                delay_us(2);


SDA=1;                                                                       SDA=1;


while(SDAIN);                                                            while(SDAIN);


SCL=0;                                                                       SCL=0;


}                                                                                   }


程序运行的时候总是死在红色部分的程序,后来用debug单步调试,慢慢的发现了规律,以下为个人观点,不敢保证一定正确:


                    1.SDAIN只会在SCL为低电平的时候拉低


                    2.且在SCL保持高电平的时候,SDAIN比保持低电平


                    3.在SCL变为高电平之后,SDAIN才会拉高


 stm32与AT24C02的I2C通信总结(模拟时序)

上图为I2C通信的时序图


其中起始信号:在SCL为高电平时,SDA电平由高变低,且高电平SDA高电平持续时间要大于4.7us,在SCL由高电平变低时,SDA的低电平持续时间要大于4us


终止信号:在SCL为高电平期间,SDA电平由低变高,且高电平持续时间大于4.7us,低电平持续时间大于4us


起始信号和终止信号无论何时都是由主设备产生的


数据帧:在SCL为高电平期间,SDA的电平保持稳定


主向从写数据

stm32与AT24C02的I2C通信总结(模拟时序)

期间地址为八位:其中高四位为固定位,bit3—bit1为可变位,最低位为操作位 为0时为写操作,为1时是读操作


地址发送完成之后,等待从器件的应答信号,切记此时要将SDA配置为上拉输入模式

stm32与AT24C02的I2C通信总结(模拟时序)

应答信号即为,SCL保持高电平时 SDA一直为低电平。


然后再发送要写入数据的地址,收到应答再写入数据,最后是停止信号


 


首先先配置IO口,PB10为SCL,PB.11为SDA


 


#include


void gpio_init()


{


 RCC->APB2ENR|=1<<2;


 GPIOA->CRH&=0xfffff00f;


 GPIOA->CRH|=0x000008b0;


 GPIOA->ODR|=3<<9;


 


 RCC->APB2ENR|=1<<3;


 GPIOB->CRH&=0xfffff0ff;


 GPIOB->CRH|=0x00000300;


 GPIOB->ODR|=1<<10;


}


 


void iic_sda_out()//此时为主器件发送数据


{


 RCC->APB2ENR|=1<<3;


 GPIOB->CRH&=0xffff0fff;


 GPIOB->CRH|=0x00003000;


 GPIOB->ODR|=1<<11;


}


 


void iic_sda_in()//此时为主器件接收数据或等待从器件发送应答信号


{


 RCC->APB2ENR|=1<<3;


 GPIOB->CRH&=0xffff0fff;


 GPIOB->CRH|=0x00008000;


 GPIOB->ODR|=1<<11;


}


 


然后是为头文件iic.h,如下


#define iic_write 0xa0


#define iic_read 0xa1


void iic_start(void);//起始信号


void iic_end(void);//终止信号


void iic_senddata(u8 data);//主器件发送一个字节数据


void iic_master_ack(void);//主机应答信号


void iic_master_nack(void);//主机非应答信号


void iic_wait_ack(void);//等待从机应答信号


void iic_master_write(u8 type,u8 address,u8 data);


u8 iic_master_read(u8 address);


u8 iic_readdata(void);


 


iic.c文件如下


#include


#include"gpio.h"


#include"delay.h"


#include"iic.h"


#include"sys.h"


void iic_start()


{


 iic_sda_out();


 SDA=0;


 SCL=1;


 SDA=1;


 delay_us(5);


 SDA=0;


 delay_us(5);


}


 


void iic_end(void)


{


 iic_sda_out();


 SCL=0;


 SDA=0;


 delay_us(2);


 SCL=1;


 delay_us(5);


 SDA=1;


 delay_us(5);


 SDA=0;


}


 


void iic_senddata(u8 data)


{


 int i;


 iic_sda_out();


 for(i=7;i>=0;i--)


    {


     SCL=0;


SDA=(data>>i);


SCL=1;


delay_us(5);


SCL=0;


}


}


 


 


void iic_master_ack()


{


 iic_sda_out();


 SCL=0;


 SDA=0;


 SCL=1;


 delay_us(5);


 SCL=0;


 SDA=1;


}


 


void iic_master_nack()


{


 iic_sda_out();


 SCL=0;


 SDA=1;


 SCL=1;


 delay_us(5);


 SCL=0;


}


 


void iic_wait_ack()


{


 iic_sda_in();


 SDA=1;


 delay_us(1);


 SCL=1;


 delay_us(1);


 while(SDAIN);


 SCL=0;


 


}


 


void iic_master_write(u8 type,u8 address,u8 data)


{


 iic_start();


 iic_senddata(type);


 iic_wait_ack();


 iic_senddata(address);


 iic_wait_ack();


 iic_senddata(data);


 iic_wait_ack();


 iic_end();


 delay_ms(10);


}


 


u8 iic_master_read(u8 address)


{


 u8 dcb;


 iic_start();


 iic_senddata(0xa0);


 iic_wait_ack();


 iic_senddata(address);


 iic_wait_ack();


 iic_start();


 iic_senddata(0xa1);


 iic_wait_ack();


 dcb=iic_readdata();


 iic_master_nack();


 iic_end();


 return dcb;


}


 


u8 iic_readdata()


{


  int k;


  u8 receive;


  iic_sda_in();


   for(k=7;k>=0;k--)


   {


    SCL=0;


delay_us(2);


SCL=1;


receive<<=1;


if(SDAIN==1)


receive|=1<<0;


else


receive&=~(1<<0);


   }


   return receive;


}


 


主程序


 


#include


#include"delay.h"


#include"usart1.h"


#include"sys.h"


#include"gpio.h"


#include"iic.h"


int main()


{


 u8 temp;


 Stm32_Clock_Init(9);


 delay_init(72);


 gpio_init();


 usart1_init();


 iic_master_write(iic_write,0x00,0xdf);


 temp=iic_master_read(0x00);


 USART1->DR=temp;


 while(1);


}

推荐阅读

史海拾趣

Eureka Microelectronics Inc公司的发展小趣事

Eureka一直重视研发实力的提升和技术创新。公司拥有一支专业的研发团队,致力于新技术的研发和应用。近年来,Eureka在人工智能、物联网等领域取得了多项技术突破,推出了一系列具有竞争力的新产品。这些技术的突破和应用,不仅提升了Eureka的产品性能和质量,也推动了公司在行业内的领先地位。

Dresden Elektronik公司的发展小趣事

随着公司的发展壮大,Dresden Elektronik公司越来越意识到合作的重要性。他们积极与产业链上下游的企业开展合作,共同推动整个行业的发展。同时,公司也注重与科研机构、高校等的合作,引进先进的技术和人才,为公司的发展注入新的活力。这种合作共赢的理念使公司在激烈的市场竞争中保持了稳健的发展态势。

谷峰(GOFORD)公司的发展小趣事

在电子产品日益追求轻薄化、高效能的大背景下,GStek不断加大研发投入,致力于技术创新和产品研发。公司拥有一支由行业资深专家和年轻技术骨干组成的研发团队,他们紧密跟踪国际前沿技术动态,结合市场需求,不断推出具有自主知识产权的新产品。这些新产品不仅性能优异,而且成本效益显著,深受市场欢迎。通过持续的技术创新和产品升级,GStek在电源管理领域树立了良好的品牌形象。

CUI公司的发展小趣事

随着电子行业的发展,CUI技术逐渐融入到整个电子产业链的各个环节中。一些企业通过整合上下游资源,形成了从CUI材料研发、生产到电子产品制造的完整产业链。这种产业链整合不仅提高了企业的运营效率,还降低了生产成本,为企业赢得了更多的市场份额。

CONTEC公司的发展小趣事

在互联网+的浪潮下,CONTEC公司积极拥抱变革。2010年,公司开始布局“互联网+”领域,通过建立河北省医疗检查监测仪器工程技术研究中心,探索将互联网技术应用于医疗设备。这一举措不仅拓宽了公司的业务范围,还提高了产品的智能化和便捷性。

Flamar公司的发展小趣事

Flamar公司自成立以来,始终将技术创新视为企业发展的核心驱动力。在电子元件领域,公司研发团队成功开发出一种新型高性能磁耦合传送臂,这一创新产品凭借其高效、稳定的传输性能,在半导体设备制造中迅速获得市场认可。通过不断的技术迭代和优化,Flamar公司的磁耦合传送臂逐渐成为行业内的标杆产品,帮助公司在激烈的市场竞争中脱颖而出。

问答坊 | AI 解惑

我想问下为什么要在单片机的i/o0上加上啦电阻

为啥要在i/op.0上的管脚加上拉电阻??…

查看全部问答>

急问:MP3电路原理图!请教高手,帮我分析下这个MP3原理图中各个组成部分的原理、处理器的功能。

http://blog.ednchina.com/Upload/Blog/2007/3/30/826adf84-7829-4de7-8065-2149d80d0c85.jpg 请高手帮我分析下这个MP3原理图中各个组成部分的原理、处理器的功能。 谢谢!…

查看全部问答>

弱弱的问一个问题,Windows中的WinInet API在Window Mobile中能用吗?

例如HttpSendRequest、InternetReadFile之类的函数。 如果不可以,是否手机就不能通过http协议请求某个服务器的数据?…

查看全部问答>

u盘+数据读写

ClassGUID={36FC9E60-C465-11CF-8056-444553540000}这个是mass stor的guid么?我自己做了个u盘,平时可以从u盘读设备的纪录信息,但是我要设置设备的一些信息或开启某些功能就想用VC写个程序来控制。不知道大家有什么好方法。u盘我已经留出了几个没 ...…

查看全部问答>

LED散热陶瓷新发展 金属化技术取得突破

陶瓷材料因本身具有优良的绝缘、耐热及稳定等先天特性,所以被大量运用在电气设备的绝缘上,又因陶瓷金属化技术的成熟,近几年更被应用于led陶瓷散热基板与载板的线路铺设。陶瓷材料金属化技术主要分为「DBC(Direct Bonded Copper) 」及「DPC(Di ...…

查看全部问答>

2812的flash怎么写不进去了

我的2812芯片flash写入了一次之后,就没办法写了怎么回事的?CCS连接之后点on-chip flash programmer,对话框全是灰色的,只有一个onlock按钮可以点,但是点了之后弹出unlock failed,CCS提示解锁失败,设备锁定。 但是上次烧写的时候我并没有改动 ...…

查看全部问答>

ORI与SBR的区别

大家好,本人初学avr,在看到汇编指令中ORI与SBR都是寄存器与立即数与的操作,不明白这两条指令的区别在哪里?多谢指导…

查看全部问答>

TI LM3S811学习心得

记录学习LM3S的点点滴滴 (声明:该学习心得是本人通过学习周立功的相关资料后的个人理解后的笔记,由于本人水平有限,也许会有错误或是偏差,若想要保证准确无误,建议自己去下相关资料学习,本心得只供参考,若有错误之处,敬请指出,万分感谢 ...…

查看全部问答>

新手求助!关于uCOS移植到S3C44B0X问题 不甚感激

本人刚开始学uCOS系统,现在有一块S3C44B0X的板子,想把uCOS移植进去,于是在网上找了一些基于S3C44B0X的uCOS源码,但是不知道如何运用编译器把源码处理,自然也就不知道怎么把内核系统烧进板子,现在不知道如何下手,而且在网上找的资料都没有运用 ...…

查看全部问答>

串口调试出现乱码,那位大哥大姐能帮帮我,万分感谢!

我用Verilog HDL编写了一个rs232串口驱动程序。在用串口调试助手进行调试时,当我发送2,4,6,8,A,C,E时,接受没有出现一个乱码,但当我发送1,3,5,7,9,B,D,F时出现乱码,在每300中出现4——5个乱码,有时只出现一个。请问这是什么原因,还是 ...…

查看全部问答>