zoukankan      html  css  js  c++  java
  • I2C裸机驱动程序设计

    ① I2C(Inter-Integrated Circuit)总线是由飞利浦公司开发的两线式串行总线,用于连接微控制器及其外围设备

    ② I2C总线有两根双向信号线

    (1)SDA:Serial Data Line(数据线)

    (2)SCL:Serial CLock Line(时钟线)

    ③ I2C总线寻址

    (1)I2C总线协议规定,从设备采用7位的地址。

      * D7~D0:从设备地址

      * D0位:数据的传送方向。“0”表示主设备向从设备写数据;“1”表示主设备由从设备读数据

      注:主设备发送地址时,总线上的每个从设备都将这7位地址与自己的地址进行比较,如果相同,则认为是自己正被主设备寻址,根据R/W位将自己确定为发送器或者接收器

    (2)从设备的地址由固定部分和用户自定义部分组成。

      * 固定部分:D7-D4 共4位。这是由从设备的生产厂商生产时就已确定的值。

      * 用户自定义部分:D3-D1 共3位。这3位通常对应设备的3个引脚(A0~A2)。把3个引脚接到不同的电平上,就可以形成一个3位的数值。

    ④ I2C总线时序

    (1)空闲状态:I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。

    (2)起始状态:在时钟线SCL保持高电平期间,数据线SDA上的电平被拉低(即负跳变),定义为I2C总线总线的启动信号,它标志着一次数据传输的开始

    (3)结束状态:在时钟线SCL保持高电平时,数据线SDA被释放,使得SDA返回高电平(即正跳变),称为I2C总线的停止信号

    (4)数据传送:I2C总线上的所有数据(地址和数据)都是以8位一个字节为单位传送的

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

      注:I2C接口会在SCL为高电平期间对SDA状态进行采样,所以SDA高低位的变换应该在SCL是低电平期间完成。所以SDA的高电平脉冲要要比SCL略宽。

    ⑤ 基于S3C2440的I2C裸机代码:

    #include "GlobalDefine.h"
    #include "Error.h"
    #include "Common.h"
    #include "I2c.h"
    
    #include "ModManager.h"
    #include "../Protocol/inc/I2cProtocol.h"
    
    #define INTPND (*(volatile unsigned long*)0x4a000010)
    #define SRCPND (*(volatile unsigned long*)0x4a000000)
    #define INTMSK (*(volatile unsigned long*)0x4a000008)
    #define GPECON (*(volatile unsigned long*)0x56000040)
    #define GPEUP  (*(volatile unsigned long*)0x56000048)
    
    #define IICCON    (*(volatile unsigned char*)0x54000000)
    #define IICSTAT   (*(volatile unsigned char*)0x54000004)
    #define IICDS     (*(volatile unsigned char*)0x5400000C)
    
    #define SLAVE_WRITE_ADDR 0xa0
    #define SLAVE_READ_ADDR 0xa1
    
    static void I2cDelay(int i)
    {
       int j = 0;
       while (i--)    
       {
           for (j = 0; j < 100; j++)
           {    
               ;
           }  
       }    
    }
    
    static void I2cInit()
    {
        //1 Interrupt Initialize
        INTPND |= (1 << 27);
        SRCPND |= (1 << 27);  
        INTMSK &= ~(1 << 27);
         
        IICCON |= (1 << 5); 
        
        //2 Set I2C-Bus transmit clock
        IICCON &= ~(1 << 6);
        IICCON &= ~(0xf << 0);
        IICCON |= (0x5 << 0);
        
        //3. Set IIC-bus data output enable
        IICSTAT |= (1 << 4);
        
        //4. Set GPIO pin function
        GPECON |= (0x2 << 28)|(0x2 << 30);
        GPEUP |= (0x3 << 14);
        
        //5. Set IIC-bus acknowledge enable
        IICCON |= (1 << 7);
    }
    
    static void I2cWriteByte(unsigned char data, unsigned char addr)
    {    
        //1. Set to Master-Transmit mode
        IICSTAT |= (3 << 6);
        
        //2. Write slave device address
        IICDS = SLAVE_WRITE_ADDR;
        IICCON &= ~(1 << 4);
        
        //3. Write 0xF0 to IICSTAT.(Generate START signal) 
        IICSTAT = 0xF0;
        
        // Wait Ack
        while ((IICCON & (1 << 4)) == 0 )
            I2cDelay(100);
        
        //4. Write address in chip to IICDS
        IICDS = addr;
        IICCON &= ~(1 << 4);
        
        // Wait Ack
        while ((IICCON & (1 << 4)) == 0 )
            I2cDelay(100);
        
        //5. Write data to IICDS
        IICDS = data;
        IICCON &= ~(1 << 4);   
        
        // Wait Ack
        while ((IICCON & (1 << 4)) == 0 )
            I2cDelay(100);
        
        //6. Write 0xD0 to IICSTAT(Generate STOP signal)
        IICSTAT = 0xD0;
        
        //7. Clear Interrupt
        IICCON &= ~(1 << 4);    
        
        I2cDelay(100);
    }
    
    static void I2cReadBytes(unsigned char addr, int length, unsigned char *buf)
    {
        int j = 0;
        unsigned char unusedata;
        
        //1. Set to Master-Transmit mode
        IICSTAT |= (3 << 6);
        
        //2. Write slave device write address
        IICDS = SLAVE_WRITE_ADDR;
        IICCON &= ~(1 << 4);
        
        //3. Write 0xF0 to IICSTAT
        IICSTAT = 0xF0;
        
        //Wait ACK
        while ((IICCON & (1 << 4)) == 0 )
            I2cDelay(100);
        
        //4. Write address in the eeprom
        IICDS = addr;
        IICCON &= ~(1 << 4);
        
        // Wait ACK
        while ((IICCON & (1 << 4)) == 0 )
            I2cDelay(100);
                 
        //5. Set to Master-Receive mode
        IICSTAT &= ~(3 << 6);
        IICSTAT |= (2 << 6);
        
        //6. Write slave device read address
        IICDS = SLAVE_READ_ADDR;
        IICCON &= ~(1 << 4);
        
        //7. Write 0xB0 to IICSTAT for starting to receive
        IICSTAT = 0xb0;
        while ((IICCON & (1 << 4)) == 0 )
            I2cDelay(100);
        
        //8. Write address in chip
        IICDS = addr;
        IICCON &= ~(1 << 4);
        
        while((IICCON & (1 << 4)) == 0)
        {
            I2cDelay(100);
        }
      
        for(j = 0; j < length; j++)
        {
            if(j == (length - 1))
            {
               IICCON &= ~(1 << 7);         
            }
       
            buf[j] = IICDS;
            
            // Clear Interrupt
            IICCON &= ~(1 << 4);
        
            // Wait for Interrupt
            while ((IICCON & (1 << 4)) == 0 )
                I2cDelay(100);
        }
        
        //9. Write 0x90 to IICSTAT(Generate STOP signal)
        IICSTAT = 0x90;
        
        //10. Clear Interrupt
        IICCON &= ~(1 << 4);
    }
    
    I2cModeOps i2cModeOps = {
        .I2cInit = I2cInit,
        .I2cWriteByte = I2cWriteByte,
        .I2cReadBytes = I2cReadBytes,
    };
    
    MODULE_INSTALL(I2c, MOD_I2C, 0, &i2cModeOps);
  • 相关阅读:
    HDU 5115 Dire Wolf (区间DP)
    HDU 4283 You Are the One(区间DP(最优出栈顺序))
    ZOJ 3469 Food Delivery(区间DP好题)
    LightOJ 1422 Halloween Costumes(区间DP)
    POJ 1651 Multiplication Puzzle(区间DP)
    NYOJ 石子合并(一)(区间DP)
    POJ 2955 Brackets(括号匹配一)
    POJ 1141 Brackets Sequence(括号匹配二)
    ZOJ 3537 Cake(凸包+区间DP)
    Graham求凸包模板
  • 原文地址:https://www.cnblogs.com/wulei0630/p/9582203.html
Copyright © 2011-2022 走看看