zoukankan      html  css  js  c++  java
  • 【Hardware】STM32软件模拟IIC

     ###Date:2018.3.15

    转载自:   http://blog.csdn.net/pain_love/article/details/54947671

            IIC总线

    一、与IIC有关的知识

    (1)IIC属于半双工通信方式

    (2)IIC的协议

        1.空闲状态:IIC的SCL和SDA两条线均处于高电平状态,此时即释放总线

        2.起始信号(Start):SCL为高电平期间,SDA产生一个下降沿信号

        3.停止信号(End):SCL为高电平期间,SDA产生一个上升沿信号

        4.应答信号ACK: 发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。

        5.数据有效性:I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。即:数据在SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。

        6.数据传输:在I2C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。

    (3)24C02

        1.写数据流程

    第一步,首先是 I2C 的起始信号,接着跟上首字节,也就是我们前边讲的 I2C 的器件地
    址,并且在读写方向上选择“写”操作。
    第二步,发送数据的存储地址。24C02 一共256 个字节的存储空间,地址从0x00~0xFF,
    我们想把数据存储在哪个位置,此刻写的就是哪个地址。
    第三步,发送要存储的数据第一个字节、第二个字节„„注意在写数据的过程中,
    EEPROM 每个字节都会回应一个“应答位 0”,来告诉我们写 EEPROM 数据成功,如果没有
    回应答位,说明写入不成功。字

        2.读数据流程:

    第一步,首先是 I2C 的起始信号,接着跟上首字节,也就是我们前边讲的 I2C 的器件地
    址,并且在读写方向上选择“写”操作。这个地方可能有同学会诧异,我们明明是读数据为
    何方向也要选“写”呢?刚才说过了, 24C02 一共有 256 个地址,我们选择写操作,是为了
    把所要读的数据的存储地址先写进去,告诉 EEPROM 我们要读取哪个地址的数据。这就如
    同我们打电话,先拨总机号码( EEPROM 器件地址),而后还要继续拨分机号码(数据地址),
    而拨分机号码这个动作,主机仍然是发送方,方向依然是“写”。
    第二步,发送要读取的数据的地址,注意是地址而非存在 EEPROM 中的数据,通知
    EEPROM 我要哪个分机的信息。
    第三步,重新发送 I2C 起始信号和器件地址,并且在方向位选择“读”操作。
    这三步当中,每一个字节实际上都是在“写”,所以每一个字节EEPROM 都会回应一个
    “应答位0”。
    第四步,读取从器件发回的数据,读一个字节,如果还想继续读下一个字节,就发送一
    个“应答位 ACK(0)”,如果不想读了,告诉EEPROM,我不想要数据了,别再发数据了,那
    就发送一个“非应答位 NAK(1)”

    3.24C02地址

       24C02的 7 位地址中,其中高 4 位是固定的 0b1010,而低 3 位的地址取决于具体电路的设计,由芯片上的 A2、 A1、 A0 这 3 个引脚的实际电平决定,高为1,低为0.最低位是数据方向位(R/W)0表示接下来要发送数据(写),1表示接下来是请求数据(读)。

    二、用到的知识

    1.    GPIO、串口

    2.    IIC、24C02

    三、功能

    先在24c02的一个地址中写入一个字符,然后在读取该位置的字符并通过串口显示出来。

    [cpp] view plain copy
    1. #include "iic.h"  
    2.   
    3. #define iicsda PBout(7)  
    4. #define iicscl PBout(6)  
    5. #define iicsdain PBin(7)  
    6.   
    7. void SDAOUT(void)//sda×÷ΪÍÆÍìÊä³ö  
    8. {  
    9.   GPIO_InitTypeDef GPIO_InitTypeStruct;  
    10.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);  
    11.       
    12.     GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_Out_PP;  
    13.     GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_7;  
    14.     GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;  
    15.     GPIO_Init(GPIOB,&GPIO_InitTypeStruct);  
    16. }  
    17.   
    18. void SDAIN(void)//SDA×÷Ϊ¸¡¿ÕÊäÈë  
    19. {  
    20.   GPIO_InitTypeDef GPIO_InitTypeStruct;  
    21.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);  
    22.       
    23.     GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;  
    24.     GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_7;  
    25.     GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;  
    26.     GPIO_Init(GPIOB,&GPIO_InitTypeStruct);  
    27. }  
    28.   
    29. void Myiic_INIT()//IIC³õʼ»¯  
    30. {  
    31.     GPIO_InitTypeDef GPIO_InitTypeStruct;  
    32.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);  
    33.       
    34.     GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_Out_PP;  
    35.     GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;  
    36.     GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;  
    37.     GPIO_Init(GPIOB,&GPIO_InitTypeStruct);  
    38.       
    39.     GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);  
    40. }  
    41.   
    42. void Myiic_Start(void)//ÆðʼÐźŠ 
    43. {  
    44.   SDAOUT();  
    45.     iicsda=1;  
    46.     iicscl=1;  
    47.     delay_us(4);  
    48.   iicsda=0;  
    49.     delay_us(4);  
    50.     iicscl=0;  
    51. }  
    52.   
    53. void Myiic_Stop(void)//Í£Ö¹ÐźŠ 
    54. {  
    55.   SDAOUT();  
    56.     iicscl=0;  
    57.     iicsda=0;  
    58.     delay_us(4);  
    59.     iicscl=1;  
    60.     iicsda=1;  
    61.     delay_us(4);  
    62. }  
    63.   
    64. u8 Myiic_Wait_Ack(void)//µÈ´ýACK  
    65. {  
    66.   u8 time=0;  
    67.     SDAIN();  
    68.     iicsda=1;  
    69.     delay_us(1);  
    70.     iicscl=1;  
    71.     delay_us(1);  
    72.     while(iicsdain)  
    73.     {  
    74.       time++;  
    75.         if(time>250)  
    76.         {  
    77.             Myiic_Stop();  
    78.             return 1;  
    79.         }  
    80.     }  
    81.     iicscl=0;  
    82.     return 0;  
    83. }  
    84.   
    85. void Myiic_ACK(void)//²úÉúACKÓ¦´ð  
    86. {  
    87.   iicscl=0;  
    88.     SDAOUT();  
    89.     iicsda=0;  
    90.   delay_us(2);  
    91.     iicscl=1;  
    92.     delay_us(2);  
    93.     iicscl=0;  
    94. }  
    95.   
    96. void Myiic_NACK(void)//²»²úÉúÓ¦´ðλ  
    97. {  
    98.   iicscl=0;  
    99.     SDAOUT();  
    100.     iicsda=1;  
    101.   delay_us(2);  
    102.     iicscl=1;  
    103.     delay_us(2);  
    104.     iicscl=0;  
    105. }  
    106.   
    107. void Myiic_Sendbyte(u8 w)//·¢ËÍÒ»¸ö×Ö½Ú  
    108. {  
    109.     u8 i;  
    110.   SDAOUT();  
    111.     iicscl=0;  
    112.     for(i=0;i<8;i++)  
    113.     {  
    114.       iicsda=(w&0x80)>>7;  
    115.         w<<=1;  
    116.         delay_us(2);  
    117.         iicscl=1;  
    118.         delay_us(2);  
    119.         iicscl=0;  
    120.         delay_us(2);  
    121.     }  
    122. }  
    123.   
    124. u8 Myiic_Readbyte(unsigned char ack)//¶ÁÈ¡Ò»¸ö×Ö½Ú  
    125. {  
    126.   unsigned char i=0,r=0;  
    127.     SDAIN();  
    128.     for(i=0;i<8;i++)  
    129.     {  
    130.       iicscl=0;  
    131.         delay_us(2);  
    132.         iicscl=1;  
    133.         r<<=1;  
    134.         if(iicsdain)  
    135.             r++;  
    136.         delay_us(1);  
    137.     }  
    138.     if(!ack)  
    139.         Myiic_NACK();  
    140.     else  
    141.         Myiic_ACK();  
    142.     return r;  
    143. }  
    本文为博主原创文章,未经博主允许不得转载。若允许转载,请注明来源https://www.cnblogs.com/SoaringLee/,否则保留追究法律责任的权利!另外,本人提供付费咨询服务并长期承接各类毕设以及外包项目。联系QQ:2963033731。加Q备注:CSDN外包
  • 相关阅读:
    String.PadLeft()
    数据生成树 新增
    SQL允许你用EXECUTE执行一个变量中定义的SQL语句,并且允许你在被执行的SQL语句中,再次嵌套入一个变量定义的语句,并且再次在其中用EXECUTE执行它
    获取SqlConnection的统计信息
    页面缓存 OutputCache
    将小写金额转换成大写
    判断是否枚举中的匹配项
    js获取系统时间的几种方法<一> 《网摘学习》
    将指定文件夹(路径)下的所有内容copy到目标文件夹(路径)下的方法
    50个优美的句子<摘自网上>
  • 原文地址:https://www.cnblogs.com/SoaringLee/p/10532537.html
Copyright © 2011-2022 走看看