zoukankan      html  css  js  c++  java
  • STM32标准IIC驱动

        IIC(Inter-Integrated Circuit)总线是一种由 PHILIPS 公司开发的两线式串行总线,用于连接

    微控制器及其外围设备。也是目前很流行的通讯总线,使用IIC总线做产品能够很大程度上降低PCB的布线难度,以及布线数量,所以很多公司都优先选择IIC做产品,

    它是由数据线 SDA 和时钟 SCL 构成的串行总线,可发送和接收数据。

    在 CPU 与被控 IC 之间、IC 与 IC 之间进行双向传送,高速 IIC 总线一般可达 400kbps 以上。
    I2C 总线在传送数据过程中共有三种类型信号,  它们分别是:开始信号、结束信号和应答
    信号。
        开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变,开始传送数据。
        结束信号:SCL 为高电平时,SDA 由低电平向高电平跳变,结束传送数据。
        应答信号:接收数据的 IC 在接收到 8bit 数据后,向发送数据的 IC 发出特定的低电平脉冲,
    表示已收到数据。 CPU 向受控单元发出一个信号后,等待受控单元发出一个应答信号, CPU 接
    收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为
    受控单元出现故障。

    这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要

    对于高级CPU而言,IIC总线需要SDA线经常性的切换输入输出,鉴于此,做一个标准的可以切换输入输出的IIC驱动很有必要


    IIC总线在使用过程中主要需要的包括起始,停止,等待ACK 发送NACK 发送ACK


    IIC的时序图如下

    总结一下,就是

    起始信号:SCL为1 SDA为1 持续4us SDA变为0,SCL保持1持续最少4.7US

    停止信号:SCL为0 SDA为0次序4us SDA为1 SCL随意(最好也是1相当于释放总线)最少4.7us

    应答型号:SCL拉低 SDA拉低至少4us SCL拉高 SDA保持低至少4.7us(SCL是为了让总线检测)SCL拉低

    非应答 :   SCL拉低 SDA拉高至少4us SCL拉高 SDA保持高至少4.7us(SCL是为了让总线检测)SCL拉低

    注意一点就是这些时间在不同器件上甚至PCB不同的情况下都是需要调整的,不要一驱动处处用,这样是不能达到最好的驱动效果的


    代码如下

    #ifndef __IIC_H_
    #define __IIC_H_
    #include "ioremap.h"
    
    
    
    //IO方向设置
    #define SDA_IN()  {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=8<<12;}
    #define SDA_OUT() {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=3<<12;}
    
    
    //IO操作函数	 
    #define IIC_SCL    PBout(10) //SCL
    #define IIC_SDA    PBout(11) //SDA	 
    #define READ_SDA   PBin(11)  //输入SDA 
    
    
    //IIC所有操作函数
    void IIcInit(void);                //初始化IIC的IO口		
    
    void IIcStart(void);				//发送IIC开始信号
    
    void IIcStop(void);	  			//发送IIC停止信号
    
    void IIcSendByte(u8 txd);			//IIC发送一个字节
    
    u8 IIcReadByte(unsigned char ack);//IIC读取一个字节
    
    u8 IIcWaitAck(void); 				//IIC等待ACK信号
    
    void IIcAck(void);					//IIC发送ACK信号
    
    void IIcNAck(void);				//IIC不发送ACK信号
    
    void IIcWriteOneByte(u8 daddr,u8 addr,u8 data);//iic写一个字节数据
    
    u8 IIcReadOneByte(u8 daddr,u8 addr);	  //iic读一个字节数据
    
    #endif
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #include "iic.h"
    #include "delay.h"
    
    
    //初始化IIC
    void IIcInit(void)
    {					     
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	
        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_11); 	//PB10,PB11 输出高
    }
    
    
    //产生IIC起始信号
    void IIcStart(void)
    {
        SDA_OUT();     //sda线输出
        IIC_SDA=1;	  	  
        IIC_SCL=1;
        DelayUs(4);
        IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
        DelayUs(4);
        IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
    }
    
    //产生IIC停止信号
    void IIcStop(void)
    {
        SDA_OUT();//sda线输出
        IIC_SCL=0;
        IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
        DelayUs(4);
        IIC_SCL=1; 
        IIC_SDA=1;//发送I2C总线结束信号
        DelayUs(4);							   	
    }
    
    //等待应答信号到来
    //返回值:1,接收应答失败
    //        0,接收应答成功
    u8 IIcWaitAck(void)
    {
        u8 ucErrTime=0;
        SDA_IN();      //SDA设置为输入  
        IIC_SDA=1;DelayUs(1);	   
        IIC_SCL=1;DelayUs(1);	 
        while(READ_SDA)
        {
            ucErrTime++;
            if(ucErrTime>250)
            {
                IIcStop();
                return 1;
            }
        }
        IIC_SCL=0;//时钟输出0 	   
        return 0;  
    } 
    
    //产生ACK应答
    void IIcAck(void)
    {
        IIC_SCL=0;
        SDA_OUT();
        IIC_SDA=0;
        DelayUs(2);
        IIC_SCL=1;
        DelayUs(2);
        IIC_SCL=0;
    }
    
    //不产生ACK应答		    
    void IIcNAck(void)
    {
        IIC_SCL=0;
        SDA_OUT();
        IIC_SDA=1;
        DelayUs(2);
        IIC_SCL=1;
        DelayUs(2);
        IIC_SCL=0;
    }	
    
    //IIC发送一个字节
    //返回从机有无应答
    //1,有应答
    //0,无应答			  
    void IIcSendByte(u8 txd)
    {                        
        u8 t;   
        SDA_OUT(); 	    
        IIC_SCL=0;//拉低时钟开始数据传输
        for(t=0;t<8;t++)
        {              
            //IIC_SDA=(txd&0x80)>>7;
            if((txd&0x80)>>7)
                IIC_SDA=1;
            else
                IIC_SDA=0;
            txd<<=1; 	  
            DelayUs(2);   //对TEA5767这三个延时都是必须的
            IIC_SCL=1;
            DelayUs(2); 
            IIC_SCL=0;	
            DelayUs(2);
        }	 
    } 	
    
    
    //读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
    u8 IIcReadByte(unsigned char ack)
    {
        unsigned char i,receive=0;
        SDA_IN();//SDA设置为输入
        for(i=0;i<8;i++ )
        {
            IIC_SCL=0; 
            DelayUs(2);
            IIC_SCL=1;
            receive<<=1;
            if(READ_SDA)receive++;   
            DelayUs(1); 
        }					 
        if (!ack)
            IIcNAck();//发送nACK
        else
            IIcAck(); //发送ACK   
        return receive;
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    



  • 相关阅读:
    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结v2
    JS设置cookie、读取cookie、删除cookie
    Atitit 图像处理30大经典算法attilax总结
    Atitit数据库层次架构表与知识点 attilax 总结
    Atitit 游戏的通常流程 attilax 总结 基于cocos2d api
    Atitti css transition Animation differ区别
    Atitit 图像清晰度 模糊度 检测 识别 评价算法 源码实现attilax总结
    Atitit 全屏模式的cs桌面客户端软件gui h5解决方案 Kiosk模式
    Atitit 混合叠加俩张图片的处理 图像处理解决方案 javafx blend
    Atitit  rgb yuv  hsv HSL 模式和 HSV(HSB) 图像色彩空间的区别
  • 原文地址:https://www.cnblogs.com/dengxiaojun/p/4279447.html
Copyright © 2011-2022 走看看