历史上的今天
返回首页

历史上的今天

今天是:2025年01月31日(星期五)

2019年01月31日 | 基于stm32单片机的模拟IIC时序

2019-01-31 来源:eefocus

我下面要说的是基于stm32单片机的模拟IIC时序,以及是一些要注意的事项;结合自己所做的MMA7455加速度传感器,我把模拟IIC的源代码贴了出来,大家可以参考一下。


1.因为在IIC协议中,当总线空闲的时候,SDA和SCL都为高电平,所以硬件电路中SDA和SCL引脚都要接上拉电阻。


2.注意开始信号,停止信号,响应信号,非响应信号的时序,特别是要留意高低电平时间的延时:


3.应答信号分为主机应答和从机应答:

    主机应答是在主机从从机中读取数据时每次读取完一个字节的数据后主机给从机的一个应答信号,表示主机已收到数据了。

    从机应答是指主机给从机发送数据时从机给主机的应答,给一个应答就代表从机已经收到了数据,为主机接下来的工作做个判断。主机在核查从机的应答信号的时候,必须先将SDA总线拉高,释放总线。

    非应答信号是主机给从机的,当读取完一字节数据以后,主机不再去读取数据就给从机一个非应答信号,接着一个停止信号,直接给停止信号也是可以结束此次读操作,但是会对后面的操作带来影响。


主机发送一个字节的数据,从高位开始发送。SCL位高电平的时候,数据必须保持稳定,所以可以在SCL为低电平时组织数据;同理读取数据也是类似的。

4.SCL是单向的,由master控制。SDA是双向的,master可以控制,slaver也可以控制。

主机给从机写入数据时,SDA在SCL低电平的时候变化,SDA在SCL高电平的时候保持不变,也就是说在SCL上升沿时写入数据。

主机从从机读取数据时,SDA在SCL高电平的时候变化,SDA在SCL低电平的时候保持不变,也就是说在SCL下升沿时读出数据。

需要注意的是:写入数据时就是要先改变SDA的值再去制造一个SCL的上升沿,读取数据时就是要先改变SDA的值再去制造一个SCL的下降沿,先后顺序必须把握好。

下面是我在用MMA7455加速度传感器时,写的IIC时序;程序已验证过可使用,大家可以参考一下


#define mma7455addree  0x3a          //每个设备有还会有自己的设备地址

#define sdah GPIO_SetBits(GPIOA,GPIO_Pin_0)

#define sclh GPIO_SetBits(GPIOA,GPIO_Pin_1)


#define sdal GPIO_ResetBits(GPIOA,GPIO_Pin_0)

#define scll GPIO_ResetBits(GPIOA,GPIO_Pin_1)



void sdain()

{

    GPIO_InitTypeDef i2csdain;

    i2csdain.GPIO_Pin = GPIO_Pin_0;

    i2csdain.GPIO_Mode = GPIO_Mode_IN_FLOATING;        //设置为浮空输入

    GPIO_Init(GPIOA, &i2csdain);

}



void sdaout()

{

    GPIO_InitTypeDef i2csdaout;    

    i2csdaout.GPIO_Pin = GPIO_Pin_0;

    i2csdaout.GPIO_Mode = GPIO_Mode_Out_PP;

    i2csdaout.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &i2csdaout);

}



void sclout()

{

    GPIO_InitTypeDef i2csclout;

    SystemInit();

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    i2csclout.GPIO_Pin = GPIO_Pin_1;

    i2csclout.GPIO_Mode = GPIO_Mode_Out_PP;

    i2csclout.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &i2csclout);

}



void i2cst()                     //启动信号的函数

{

    sdaout();


    sclh;

    sdah;

    Delay_us(10);


    sdal;

    Delay_us(5);

    scll;

}


void i2ced()               //停止信号的函数

{

    sdaout();


    sdal;

    sclh;

    Delay_us(10);


    sdah;

    Delay_us(5);

}



void i2cack()             //等待信号,当发送器发送一个数据之后,需要等待从接收端发过来的应答信号,主机等待从机应答

{

    unsigned  char i;

    sdain();


    sclh;

    Delay_us(5);

    while((GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 1) && (i < 250))  i++;    //检测到SDA为低,也就是从机产生了应答信号或者从机没有应答信号,导致超时,都会跳出该函数。

    scll;

    Delay_us(10);

}



void i2cwrda(unsigned char da)                      //写入一个字节的函数

{

    unsigned char i, temp, temp1;

    sdaout();

    scll;

    temp1 = da;


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

    {

        scll;

        temp = temp1;

        temp = temp & 0x80; 

        if(temp == 0x80)

        {

            sdah;

        }

        else

        {

            sdal;

        }

        Delay_us(15);

        sclh;

        Delay_us(15);

        temp1 = temp1 << 1;


    }


}



unsigned char i2creda()                             //读取一个字节的函数

{

    unsigned char i, j;

    sdain();

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

    {

        sclh;

        Delay_us(5);

        j = (j << 1) | GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);

        scll;

        Delay_us(5);

    }

    return j;

}



void mma7455Write(unsigned char addr, unsigned char dat)    //往 mma7455的addr地址写入addr数据

{


    i2cst();

    i2cwrda(0x3a);

    i2cack();

    i2cwrda(addr);

    i2cack();

    i2cwrda(dat);

    i2cack();

    i2ced();



}



unsigned char mma7455Read(unsigned char addr)        //读取mma7455的addr地址的数据

{

    unsigned char num1;

    i2cst();

    i2cwrda(0x3a);

    i2cack();

    i2cwrda(addr);

    i2cack();


    i2cst();

    i2cwrda(0x3b);

    i2cack();

    num1 = i2creda();

    i2ced();

    return (num1);

}


 

其实多机通信可以用一个简单的办法解决,只要在只要在上面mma7455Write,mma7455Read函数中用if语句根据不同的标志位选择相应的设备地址,要读取地址即可。大家可以去试一下!

推荐阅读

史海拾趣

AURORA公司的发展小趣事

AURORA公司一直致力于提升自动驾驶技术的安全性和可靠性。通过不断研发和创新,AURORA在自动驾驶算法、传感器融合、数据处理等方面取得了显著进展。公司的技术团队不断攻克技术难题,推动自动驾驶技术向更高等级迈进。同时,AURORA还积极与高校和研究机构合作,共同推动自动驾驶技术的研发和应用。

ELMOS公司的发展小趣事

ELMOS公司自创立以来,就专注于汽车电子领域的发展。多年来,公司不断积累在模拟混合信号集成电路设计方面的专业知识,形成了深厚的技术底蕴。这种长期的技术积累使得ELMOS在汽车和工业物理接口领域拥有广泛的产品线,特别是在供电和DC/DC方面积累了丰富的经验。这种技术积累不仅为ELMOS赢得了市场的认可,也为公司的持续发展奠定了坚实的基础。

Anachip公司的发展小趣事

随着国内市场的饱和,Anachip公司开始将目光投向海外市场。公司通过参加国际电子展会、建立海外销售渠道等方式,逐步打开了国际市场。在海外市场,Anachip的产品以其高性能和可靠性赢得了客户的青睐。随着国际化拓展的深入,公司的业绩也实现了快速增长。

Bytes公司的发展小趣事

在发展过程中,Bytes公司注重与其他企业和机构的合作。公司与多家知名企业建立了战略合作关系,共同开发新产品、拓展新市场。同时,公司还积极参与行业组织和协会的活动,推动行业标准的制定和实施。通过合作与共赢的方式,Bytes公司实现了资源共享、优势互补,进一步提升了自身的竞争力和影响力。

安碁科技(AKER)公司的发展小趣事

随着市场需求的不断增长,安碁科技开始寻求扩大产能和全球化布局。1999年,公司正式量产电压控制振荡器(VCXO),并购置了更大的厂房以扩大产能。随后,安碁科技陆续在美国和中国大陆设立子公司和办事处,进一步拓展国际市场。这一系列的举措,不仅提高了公司的产能和效率,也使其能够更好地服务全球客户,实现业务的快速增长。

Gazelle Microcircuits Inc公司的发展小趣事
+12V电压是电脑主板中非常重要的电压之一,它主要用于给硬盘驱动器、光驱、风扇等大功率设备供电。这些设备通常需要较高的电压来驱动其内部的电机或机械结构。

问答坊 | AI 解惑

请问一下,现在哪种单片机的加密性能好一点?

请问一下,现在哪种单片机或者arm的加密性能好一点呢?最好不能轻易让别人破解的。大家来探讨一下,谢谢。…

查看全部问答>

求一段linux下c语音的源码,可以读出pci设备的各种属性

求一段linux下c语音的源码,可以读出pci设备的各种属性,急需!!…

查看全部问答>

求助!串口发送文件问题?

我在写bootloader,在串口这遇到点麻烦,各位大牛给点意见 我将bootloader分为两个阶段,现在第一阶段差不多完成了,就差实现从串口烧录第二阶段到flash的功能 思路是这样的,在kermit下send boot_sencond.bin,我想问下,在发送完后,boot_sencon ...…

查看全部问答>

请问嵌入式有没有什莫组织?供技术交流。开展活动得?

请问嵌入式有没有什莫组织?供技术交流。开展活动得?…

查看全部问答>

设计过光端机的或做过光纤传输系统的高手请进

想请教一下关于光端机的细节问题!QQ:552112190…

查看全部问答>

请问我的问题算什么开发啊?初学,请指教

我的问题是:我有个硬件可以读取一些数据,硬件上有个按钮,按这按钮后读取后的数据通过硬件上的SIM卡,将数据发送到数据接收端(比如用短信猫接收信息). 现在我需要完成开发涉及的操作是:读取后的数据通过硬件上的SIM卡,将数据发送到数据接收端. 请问 ...…

查看全部问答>

【急问】拉丁文(西班牙语)是否支持7bit编码方式?

请问:拉丁文(西班牙语)是否支持7bit编码方式? 在给客户做一个短信终端,客户要求已7bit编码方式实现拉丁文的短信内容 多谢!…

查看全部问答>

新建嵌入式交流群6239452 欢迎加入!

新建嵌入式交流群6239452 欢迎加入!…

查看全部问答>

ISE10.1中V4器件太少,是啥原因?

我的ISE是10.1版本的,器件中Virtex4中只有XC4VLX15、XC4VLX25、XC4VSX25、XC4VFX12这几个器件,缺少很多其它的,不知道是怎么回事,请大家帮下忙,应该怎么弄才会出现其它的?我要用到Virtex4中XC4VFX20…

查看全部问答>

发一本公司用的机电一体化教材

首先祝大家新年快乐!希望在新的一年大家都能够一帆风顺,心想事成! 然后弱弱地发一本某公司的内部资料。。。之前发在了百度,后来才发现上面有公司名字,不知道这会不会引起不必要的纠纷啊?  …

查看全部问答>