打印

关于I2C的问题

[复制链接]
3075|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
scardashu|  楼主 | 2010-8-15 10:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
linqing171| | 2010-8-15 12:35 | 只看该作者
什么单片机?
看代码似乎是一个主机要发送地址+写信号吧。
你说的状态寄存器是 I21CONSET 么?
这个寄存器每一位是什么功能?

使用特权

评论回复
板凳
scardashu|  楼主 | 2010-8-18 13:15 | 只看该作者
用的ARM,LPC2378芯片,状态寄存器是I2CSTAT

使用特权

评论回复
地板
scardashu|  楼主 | 2010-8-23 07:30 | 只看该作者
请问你有I2C程序吗?调好可以用的

使用特权

评论回复
5
hruid| | 2010-8-23 22:08 | 只看该作者
给你一个,调试好的。可用于lpc2114和LPC2294
----------------------------------
*********************************************************************************************************
** 文件名称 :        I2CINT.c
** 功能说明 :        LPC2000硬件I2C中断方式软件包。
** 使用说明 :  主程序要配置好I2C总线接口(I2C引脚功能和I2C中断,并已使能I2C主模式)
*********************************************************************************************************
---------------------------------------------------------------------------------------------------------
*/
#include  "config.h"
#include  "I2CINT.H"

/* 定义用于和I2C中断传递信息的全局变量 */
volatile uint8         I2C_sla;                        /* I2C器件从地址                                         */
volatile uint32        I2C_suba;                        /* I2C器件内部子地址                                 */
volatile uint8         I2C_suba_num;                /* I2C子地址字节数                                        */
volatile uint8         *I2C_buf;                /* 数据缓冲区指针                                          */
volatile uint32 I2C_num;                        /* 要读取/写入的数据个数                         */
volatile uint8         I2C_end;                        /* I2C总线结束标志:结束总线是置1         */
volatile uint8         I2C_suba_en;                /*         子地址控制。
                                                                                0--子地址已经处理或者不需要子地址
                                                                                1--读取操作
                                                                                2--写操作
                                                                        */







//////////////////////////////////////////
void I2cInit(uint32 Fi2c)
{
        if (Fi2c > 400000)
                Fi2c = 400000;
               
           //PINSEL0 = (PINSEL0 & 0xFFFFFF0F) | 0x50;                         /* 设置I2C控制口有效                                 */
        PINSEL0 = (PINSEL0 & (~0xF0)) | 0x50;         // 不影响其它管脚连接
        I2SCLH = (Fpclk/Fi2c + 1) / 2;                                                /* 设定I2C时钟                                                 */
        I2SCLL = (Fpclk/Fi2c)/2;
        I2CONCLR = 0x2C;
        I2CONSET = 0x40;                                                                        /* 使能主I2C                                                 */
       
        /* 设置I2C中断允许 */
        VICIntSelect = 0x00000000;                                                        /* 设置所有通道为IRQ中断                         */
        VICVectCntl4 = (0x20 | 0x09);                                                /* I2C通道分配到IRQ slot0,最高优先级 */
        VICVectAddr4 = (int32)IRQ_I2C;                                                /* 设置I2C中断向量                                         */
        VICIntEnable = (1 << 9);                                                        /* 使能I2C中断                                                 */
}










/**********************************************************************************************************
** 函数名称:ISendByte()
** 函数功能:向无子地址器件发送1字节数据。
** 入口参数:sla                器件地址
**           dat                要发送的数据
** 出口参数:返回值为0时表示出错,为1时表示操作正确。
** 说明:        使用前要初始化好I2C引脚功能和I2C中断,并已使能I2C主模式
*********************************************************************************************************
*/
uint8  ISendByte(uint8 sla, uint8 dat)
{  /* 参数设置 */
   I2C_sla     = sla;                // 写操作的器件地址
   I2C_buf     = &dat;                // 待发送的数据
   I2C_num     = 1;                        // 发送1字节数据
   I2C_suba_en = 0;                         // 无子地址
   I2C_end     = 0;
   
   I2CONCLR = 0x2C;
   I2CONSET = 0x60;             // 设置为主机,并启动总线
   
   while(0==I2C_end);
   if(1==I2C_end) return(1);
     else return(0);
}

/*
*********************************************************************************************************
** 函数名称:IRcvByte()
** 函数功能:向无子地址器件读取1字节数据。
** 入口参数:sla                器件地址
**           dat                接收数据的变量指针
** 出口参数:返回值为0时表示操作出错,为1时表示操作正确。
** 说明:使用前要初始化好I2C引脚功能和I2C中断,并已使能I2C主模式
*********************************************************************************************************
*/
uint8  IRcvByte(uint8 sla, uint8 *dat)
{  /* 参数设置 */
   I2C_sla     = sla+1;                // 读操作的器件地址
   I2C_buf     = dat;
   I2C_num     = 1;
   I2C_suba_en = 0;                        // 无子地址
   I2C_end     = 0;
   
   I2CONCLR = 0x2C;
   I2CONSET = 0x60;         // 设置为主机,并启动总线
   
   while(0==I2C_end);
   if(1==I2C_end) return(1);
     else return(0);
}


/*
*********************************************************************************************************
** 函数名称 :I2C_ReadNByte()
** 函数功能 :从有子地址器件任意地址开始读取N字节数据
** 入口参数 :        sla                        器件从地址
**                                suba_type        子地址结构        1-单字节地址        2-8+X结构        2-双字节地址
**                                suba                器件子地址
**                                s                        数据接收缓冲区指针
**                                num                        读取的个数
** 出口参数 :        TRUE                操作成功
**                                FALSE                操作失败
*********************************************************************************************************
*/
uint8 I2C_ReadNByte (uint8 sla, uint32 suba_type, uint32 suba, uint8 *s, uint32 num)
{
        if (num > 0)        /* 判断num个数的合法性 */
        {        /* 参数设置 */
                if (suba_type == 1)
                {        /* 子地址为单字节 */
                        I2C_sla             = sla + 1;                                                        /* 读器件的从地址,R=1         */
                        I2C_suba            = suba;                                                                /* 器件子地址                         */
                        I2C_suba_num        = 1;                                                                /* 器件子地址为1字节         */
                }
                if (suba_type == 2)
                {        /* 子地址为2字节 */
                        I2C_sla             = sla + 1;                                                        /* 读器件的从地址,R=1         */
                        I2C_suba                    = suba;                                                                /* 器件子地址                         */
                        I2C_suba_num        = 2;                                                                /* 器件子地址为2字节         */
                }
                if (suba_type == 3)
                {        /* 子地址结构为8+X*/
                        I2C_sla                        = sla + ((suba >> 7 )& 0x0e) + 1;        /* 读器件的从地址,R=1        */
                        I2C_suba                = suba & 0x0ff;                                                /* 器件子地址                         */
                        I2C_suba_num        = 1;                                                                /* 器件子地址为8+x                 */
                }
                I2C_buf     = s;                                                                                /* 数据接收缓冲区指针         */
                I2C_num     = num;                                                                                /* 要读取的个数                 */
                I2C_suba_en = 1;                                                                                /* 有子地址读                         */
                I2C_end     = 0;
               
                /* 清除STA,SI,AA标志位 */
                I2CONCLR =         (1 << 2)|        /* AA                 */
                                        (1 << 3)|        /* SI                 */
                                        (1 << 5);        /* STA                 */
               
                /* 置位STA,启动I2C总线 */
                I2CONSET =         (1 << 5)|        /* STA                 */
                                        (1 << 6);        /* I2CEN         */
               
                /* 等待I2C操作完成 */
                while (I2C_end == 0)
                {        }
                if (I2C_end == 1)
                        return (TRUE);
                else
                        return (FALSE);                       
        }
        return (FALSE);
}

/*
*********************************************************************************************************
** 函数名称 :I2C_WriteNByte()
** 函数功能 :向有子地址器件写入N字节数据
** 入口参数 :        sla                        器件从地址
**                                suba_type        子地址结构        1-单字节地址        3-8+X结构        2-双字节地址
**                                  suba                器件内部物理地址
**                                  *s                        将要写入的数据的指针
**                                  num                        将要写入的数据的个数
** 出口参数 :        TRUE                操作成功
**                                  FALSE                操作失败
*********************************************************************************************************
*/
uint8 I2C_WriteNByte(uint8 sla, uint8 suba_type, uint32 suba, uint8 *s, uint32 num)
{
        if (num > 0)/* 如果读取的个数为0,则返回错误 */
        {        /* 设置参数 */       
                if (suba_type == 1)
                {        /* 子地址为单字节 */
                        I2C_sla             = sla;                                                                /* 读器件的从地址                 */
                        I2C_suba            = suba;                                                                /* 器件子地址                         */
                        I2C_suba_num        = 1;                                                                /* 器件子地址为1字节         */
                }
                if (suba_type == 2)
                {        /* 子地址为2字节 */
                        I2C_sla             = sla;                                                                /* 读器件的从地址                 */
                        I2C_suba                    = suba;                                                                /* 器件子地址                         */
                        I2C_suba_num        = 2;                                                                /* 器件子地址为2字节         */
                }
                if (suba_type == 3)
                {        /* 子地址结构为8+X */
                        I2C_sla                        = sla + ((suba >> 7 )& 0x0e);                /* 读器件的从地址                */
                        I2C_suba                = suba & 0x0ff;                                                /* 器件子地址                        */
                        I2C_suba_num        = 1;                                                                /* 器件子地址为8+X                 */
                }

                I2C_buf     = s;                                                                                /* 数据                                 */
                I2C_num     = num;                                                                                /* 数据个数                         */
                I2C_suba_en = 2;                                                                                /* 有子地址,写操作         */
                I2C_end     = 0;
               
                /* 清除STA,SI,AA标志位 */
                I2CONCLR =         (1 << 2)|        /* AA         */
                                        (1 << 3)|        /* SI         */
                                        (1 << 5);        /* STA         */
               
                /* 置位STA,启动I2C总线 */
                I2CONSET =         (1 << 5)|        /* STA         */
                                        (1 << 6);        /* I2CEN*/
               
                /* 等待I2C操作完成 */
                while (I2C_end == 0)
                {        }
                if (I2C_end == 1)
                        return (TRUE);
                else
                        return (FALSE);       
        }
        return (FALSE);
}

/*
*********************************************************************************************************
** 函数名称 :__irq IRQ_I2C()
** 函数名次 :硬件I2C中断服务程序。
** 入口参数 :无
** 出口参数 :无
** 说明     :注意处理子地址为2字节的情况。
*********************************************************************************************************
*/
void __irq IRQ_I2C(void)
{        /* 读取I2C状态寄存器I2DAT */
        /* 按照全局变量的设置进行操作及设置软件标志 */
        /* 清除中断逻辑,中断返回 */
       
        switch (I2STAT & 0xF8)
        {        /* 根据状态码进行相应的处理 */
                case 0x08:        /* 已发送起始条件 */                                /* 主发送和主接收都有                 */
                        /* 装入SLA+W或者SLA+R */
                         if(I2C_suba_en == 1)/* SLA+R */                                /* 指定子地址读                         */
                         {        I2DAT = I2C_sla & 0xFE;                                 /* 先写入地址                                 */
                         }
            else        /* SLA+W */
            {          I2DAT = I2C_sla;                                        /* 否则直接发送从机地址         */
            }
            /* 清零SI位 */
            I2CONCLR =        (1 << 3)|                                                /* SI                                                 */
                                    (1 << 5);                                                /* STA                                                 */
            break;
            
               case 0x10:        /*已发送重复起始条件 */                         /* 主发送和主接收都有                 */
                       /* 装入SLA+W或者SLA+R */
                       I2DAT = I2C_sla;                                                        /* 重起总线后,重发从地址         */
                       I2CONCLR = 0x28;                                                        /* 清零SI,STA */
                       break;

                case 0x18:
               case 0x28:        /* 已发送I2DAT中的数据,已接收ACK */
                       if (I2C_suba_en == 0)
                       {
                               if (I2C_num > 0)
                               {        I2DAT = *I2C_buf++;
                                       I2CONCLR = 0x28;                                        /* 清零SI,STA                                 */
                                       I2C_num--;
                               }
                               else        /* 没有数据发送了 */
                               {                /* 停止总线 */
                                         I2CONSET = (1 << 4);                                /* STO                                                 */
                                       I2CONCLR = 0x28;                                        /* 清零SI,STA                                 */
                                         I2C_end = 1;                                                /* 总线已经停止                         */
                               }
                       }
                      
            if(I2C_suba_en == 1)        /* 若是指定地址读,则重新启动总线                                 */
            {
                    if (I2C_suba_num == 2)
                    {        I2DAT = ((I2C_suba >> 8) & 0xff);
                                       I2CONCLR = 0x28;                                        /* 清零SI,STA                                 */
                                       I2C_suba_num--;
                                       break;       
                               }
                              
                               if(I2C_suba_num == 1)
                               {        I2DAT = (I2C_suba & 0xff);
                                       I2CONCLR = 0x28;                                        /* 清零SI,STA                                 */
                                       I2C_suba_num--;
                                       break;       
                               }
                              
                    if (I2C_suba_num == 0)
                    {        I2CONSET = 0x20;
                               I2CONCLR = 0x08;
                               I2C_suba_en = 0;                                     /* 子地址己处理                         */
                               break;
                       }
            }
            
            if (I2C_suba_en == 2)/* 指定子地址写,子地址尚未指定,则发送子地址                 */
                       {
                                if (I2C_suba_num > 0)
                    {        if (I2C_suba_num == 2)
                            {        I2DAT = ((I2C_suba >> 8) & 0xff);
                                    I2CONCLR = 0x28;
                                    I2C_suba_num--;
                                    break;
                            }
                            if (I2C_suba_num == 1)
                            {        I2DAT    = (I2C_suba & 0xff);
                                       I2CONCLR = 0x28;
                                       I2C_suba_num--;
                                       I2C_suba_en  = 0;
                                       break;
                               }
                       }
             }
                       break;
                         
       case 0x40:        /* 已发送SLA+R,已接收ACK */
                       if (I2C_num <= 1)        /* 如果是最后一个字节 */                       
                       {        I2CONCLR = 1 << 2;                                      /* 下次发送非应答信号                 */
                       }
                       else
                       {         I2CONSET = 1 << 2;                                                /* 下次发送应答信号                 */
                       }
                       I2CONCLR = 0x28;                                                        /* 清零SI,STA                                 */
                       break;

               case 0x20:        /* 已发送SLA+W,已接收非应答              */
               case 0x30:        /* 已发送I2DAT中的数据,已接收非应答     */
               case 0x38:        /* 在SLA+R/W或数据字节中丢失仲裁         */
                   case 0x48:        /* 已发送SLA+R,已接收非应答              */
                 I2CONCLR = 0x28;
            I2C_end = 0xFF;
                       break;                                  
       
                case 0x50:        /* 已接收数据字节,已返回ACK */
                        *I2C_buf++ = I2DAT;
                        I2C_num--;
                        if (I2C_num == 1)/* 接收最后一个字节 */
                        {          I2CONCLR = 0x2C;                                                /* STA,SI,AA = 0                         */
                        }
                        else
                        {          I2CONSET = 0x04;                                                /* AA=1                                         */
                                  I2CONCLR = 0x28;
                        }
                        break;
               
                case 0x58:        /* 已接收数据字节,已返回非应答 */
                        *I2C_buf++ = I2DAT;                                             /* 读取最后一字节数据                 */
            I2CONSET = 0x10;                                                /* 结束总线                                 */
            I2CONCLR = 0x28;
            I2C_end = 1;
            break;
            
              default:
                      break;
        }
   VICVectAddr = 0x00;                                                      /* 中断处理结束                         */
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

7

帖子

1

粉丝