搜索
bottom↓
回复: 3

LPC2368 I2C0读写FRAM,遇到问题,请各位大哥看看

[复制链接]

出0入0汤圆

发表于 2010-8-3 00:12:15 | 显示全部楼层 |阅读模式
/*---------------------------------------------------------------------------------------------------------  
** 文件名称 :   i2c0.c  
** 功能说明 :  LPC2000硬件I2C中断方式软件包。  
** 使用说明 :  主程序要配置好I2C总线接口(I2C引脚功能和I2C中断,并已使能I2C主模式) ,专用驱动,用于挂FM3130
*********************************************************************************************************  
---------------------------------------------------------------------------------------------------------*/  
#include "config.h"

//***********************************************************************************************
//本地函数申明 全部加 static
  
        /* 定义I2C0的驱动控制资源 */
        volatile static struct I2C_TCB_Source
        {                 
                uint8  IIC_FLAG;                                // I2C标志:0没有使用,1正在使用,2正常结束,3硬件异常结束,4超时结束
                uint8  OP_TYPE;                                // 操作类型:1表示同步读,2表同步写,3表示异步读,4表示异步写
                uint8  OP_State;                    // 操作状态

                uint8  *IOData;                                        // 数据缓冲区指针:存放读写数据   
                uint32 IOData_num;                    // 要读取/写入的数据个数
                uint32 IO_Index;                                // 读取或写入索引       
                uint8  Device_sla;                    // 器件从地址
                uint8  OffAddr[3];                       // 器件内部偏移地址
                uint32 OffAddr_num;                       // 器件内部偏移地址字节数
        }I2C0_TCB;

//***********************************************************************************************


/**********************************************************************************************************  
* 名称:
* 功能:查询结束没有,如果结束会将I2C标志清除,有时间超时控制:20-30MS
* 入口参数:无
* 出口参数:1正在使用,2正常结束,3硬件异常结束,4超时结束
**********************************************************************************************************/   
uint32 I2C0_IO_End(void)   
{  
        uint32 i;

        if(I2C0_TCB.IIC_FLAG > 1)
        {       
                I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC|I2CONCLR_I2ENC);                 // AA SI STA I2EN clr
                i = I2C0_TCB.IIC_FLAG;
                I2C0_TCB.IIC_FLAG = 0;
                return i;
        }
        else
        {
                return 1;
        }               
        
}   

  
/**********************************************************************************************************  
** 函数名称 :I2C0读写操作
** 函数功能 :向有子地址器件写入N字节数据  
** 入口参数 :  
        IO_type     : 1表示同步读,2表同步写,3表示异步读,4表示异步写
        sla         : 器件从地址  
        offaddr     : 器件内部物理地址
        offaddr_num : 器件内部物理地址字节数:1-单字节地址 2-双字节地址
        IO_dataP    : 将要写入或读出的数据的指针  
        IO_num      : 将要写入或读出的数据的个数,操作的数据最大数受I2C0_MAXBUF限制  
** 返回参数 :
        异步:0失败,1表示操作成功
        同步:0失败,2正常结束,3硬件异常结束,4超时结束
**********************************************************************************************************/   
uint32 I2C0_IO_Start(uint8 IO_type, uint8 sla, const uint8 *offaddr, uint32 offaddr_num,uint8 *IO_dataP, uint32 IO_num)   
{   
        uint32 i;
          
        if((offaddr_num == 0) || (offaddr_num > 2))
    {
                return (0);  
        }  

    if((IO_num == 0) || (IO_num > I2C0_MAXBUF))
    {
                return (0);  
        }  

        if(I2C0_TCB.IIC_FLAG != 0)
        {
                return 0;
        }
        I2C0_TCB.IIC_FLAG = 1;

        I2C0_TCB.OP_TYPE = IO_type;                                // 操作类型
        I2C0_TCB.OP_State = 0;                                    // 操作状态


        I2C0_TCB.IOData = IO_dataP;                                        // 数据缓冲区指针
        I2C0_TCB.IOData_num = IO_num;                    // 要读取/写入的数据个数
        I2C0_TCB.IO_Index = 0;                                                // 读取或写入索引

        I2C0_TCB.Device_sla = sla ;                     // 器件地址
        for(i=0;i<offaddr_num;i++)
        {          
                I2C0_TCB.OffAddr = offaddr;       // 器件内部偏移地址
        }
        I2C0_TCB.OffAddr_num = offaddr_num;               // 器件内部偏移地址字节数

        /* 清除标志 */
        I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC);         // AA  SI  STA  clr  
           
        /* 置位STA,启动I2C总线 */   
        I20CONSET =  (I2CONSET_STA|I2CONSET_I2EN);                                // STA  I2CEN   set   
   
        /* 等待I2C操作完成 */   
        OSTimeDly(10);//SET_10MS_SIG(IIC0_10MS_SIG,0);
       
        Uart0Write("wait I2C end\r\n",-1);
        if(I2C0_TCB.OP_TYPE <= 2)
        {
                // 同步
                i = I2C0_IO_End();
                while(1 == i)
                {
                        i = I2C0_IO_End();
                }
                return i;
        }
        else
        {
                // 异步   
                return 1;      
        }   
}

      
/**********************************************************************************************************  
** 函数名称 :__irq IRQ_I2C()  
** 函数名次 :硬件I2C中断服务程序。   
** 入口参数 :无  
** 出口参数 :无  
** 说明     :注意处理子地址为2字节的情况。   
**********************************************************************************************************/   
void IRQ_I2C0(void)   
{            
OS_ENTER_CRITICAL();  
    if((I2C0_TCB.OP_TYPE%2) == 0)                                /* 写入操作 */
        {   
                switch (I20STAT & 0xF8)  
                {   
                        case 0x08:  /* 已发送起始条件 */  
                        case 0x10:         /* 已发送重复起始条件 */
                                I20DAT = I2C0_TCB.Device_sla & 0xFE;                 // 发送SLA+W   
                                I2C0_TCB.OP_State = 1;
                                I2C0_TCB.IO_Index = 0;                                    
                                  
                            I20CONCLR = (I2CONCLR_SIC|I2CONCLR_STAC);        // 清零SI与STA位                                        
                            break;
                                         
                        case 0x18:        /* 已发送SLA+W,已接收ACK */
                        case 0x28:  /* 已发送I2DAT中的数据,已接收ACK */
                                  if(I2C0_TCB.OP_State == 1)
                                  {
                                                  //写入设备内部地址
                                                   I20DAT = I2C0_TCB.OffAddr[I2C0_TCB.IO_Index++];
                                                if( (I2C0_TCB.IO_Index >= I2C0_TCB.OffAddr_num) || (I2C0_TCB.IO_Index >= 2) )
                                                {
                                                        I2C0_TCB.IO_Index = 0;
                                                        I2C0_TCB.OP_State = 2;
                                                }
                                                I20CONCLR = (I2CONCLR_SIC);
                                  }
                                  else if(I2C0_TCB.OP_State == 2)
                                  {
                                                  //写入数据
                                                   I20DAT = I2C0_TCB.IOData[I2C0_TCB.IO_Index++];
                                                if( (I2C0_TCB.IO_Index >= I2C0_TCB.IOData_num) || (I2C0_TCB.IO_Index >= I2C0_MAXBUF) )
                                                {
                                                        I2C0_TCB.IO_Index = 0;
                                                        I2C0_TCB.OP_State = 3;
                                                }
                                                I20CONCLR = (I2CONCLR_SIC);
                                  }
                                  else if(I2C0_TCB.OP_State == 3)
                                  {
                                                  //写入成功完成
                                                I20CONSET = (I2CONSET_STO);                                                                // STO
                                                I2C0_TCB.IIC_FLAG = 2;                                                                        // 总线已经正常停止
                                                I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC);         // AA  SI  STA  clr                                                   
                                  }
                                  else
                                  {
                                                  //写入异常中断
                                                I20CONSET = (I2CONSET_STO);                                                                // STO
                                                I2C0_TCB.IIC_FLAG = 3;                                                                        // 总线已经正常停止
                                                I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC);         // AA  SI  STA  clr                                                   
                                  }
                                  break;   
                                           
                        case 0x20:  /* 已发送SLA+W,已接收非应答              */   
                        case 0x30:  /* 已发送I2DAT中的数据,已接收非应答     */   
                        case 0x38:  /* 在SLA+R/W或数据字节中丢失仲裁         */   
                                //写入异常中断
                                I20CONSET = (I2CONSET_STO);                                                                                // STO
                                I2C0_TCB.IIC_FLAG = 3;                                                                                        // 总线已经异常停止
                                I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC);                         // AA  SI  STA  clr
                            break;                     
          
                        default:   
                                //写入异常中断
                                I20CONSET = (I2CONSET_STO);                                                                                // STO                               
                                I2C0_TCB.IIC_FLAG = 3;                                                                                        // 总线已经异常停止
                                I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC);                         // AA  SI  STA  clr                                         
                                   break;   
                }
        }   
        else                                /* 读取操作 */
        {
                switch (I20STAT & 0xF8)  
                {   
//----------------------------------------------------------------------------
                        case 0x08:  /* 已发送起始条件 */  
                                /* 1.发送SLA+W,先写地址 */
                                I20DAT = I2C0_TCB.Device_sla & 0xFE;                // 发送SLA+W
                                I2C0_TCB.OP_State = 1;                  
                                I2C0_TCB.IO_Index = 0;                                    
                            I20CONCLR = (I2CONCLR_SIC|I2CONCLR_STAC);        // 清零SI与STA位                                        
                            break;
                                 
                        case 0x18:        /* 已发送SLA+W,已接收ACK */
                        case 0x28:  /* 已发送I2DAT中的数据,已接收ACK */
                                /* 2.写入设备内部地址 */
                                if(I2C0_TCB.OP_State == 1)
                                {
                                           I20DAT = I2C0_TCB.OffAddr[I2C0_TCB.IO_Index++];
                                        if( (I2C0_TCB.IO_Index >= I2C0_TCB.OffAddr_num) || (I2C0_TCB.IO_Index >= 2) )
                                        {
                                                I2C0_TCB.OP_State = 2;                
                                        }
                                        I20CONCLR = (I2CONCLR_SIC);
                                }
                                else //I2C0_TCB.OP_State = 2
                                {       
                                        //I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC);         // AA SI STA clr  
                                        /* 置位STA,重新启动总线 */   
                                        I20CONSET = (I2CONSET_STA);                                // STA  set  
                                        I20CONCLR = (I2CONCLR_SIC);                         // SI clr
                                }
                                break;  
//----------------------------------------------------------------------------                                 
                           case 0x10:         /* 已发送重复起始条件 */
                                /* 3.发送SLA+R */
                                I20DAT = I2C0_TCB.Device_sla | 0x01;                 // 发送SLA+R                   
                                I2C0_TCB.IO_Index = 0;                                    
                            I20CONCLR = (I2CONCLR_SIC|I2CONCLR_STAC);        // 清零SI与STA位
                                break;
                                                                      
                       case 0x40:        /* 已发送SLA+R,已接收ACK */
                                /* 4.设置应答信号 */
                                if(I2C0_TCB.IOData_num <= 1)
                                {
                                        I20CONCLR = I2CONCLR_AAC;                                 // 下次发送非应答信号
                                }
                                else
                                {
                                        I20CONSET = I2CONSET_AA;                                // 下次发送应答信号
                                }
                                I2C0_TCB.IO_Index = 0;                               
                                I20CONCLR = (I2CONCLR_SIC|I2CONCLR_STAC);        // 清零SI与STA位
                                break;

                        case 0x50:        /* 已接收数据字节,已返回ACK */
                                /* 5.读取数据 */
                                I2C0_TCB.IOData[I2C0_TCB.IO_Index++] = I20DAT ;
                                if( (I2C0_TCB.IO_Index >= (I2C0_TCB.IOData_num - 1)) || (I2C0_TCB.IO_Index >= (I2C0_MAXBUF - 1)) )
                                {
                                        I20CONCLR = I2CONCLR_AAC;                                 // 下次发送非应答信号
                                }
                                I20CONCLR = (I2CONCLR_SIC|I2CONCLR_STAC);        // 清零SI与STA位
                                break;

                        case 0x58: /* 已接收数据字节,已返回非应答 */  
                                /* 6.读取成功完成 */
                                I2C0_TCB.IOData[I2C0_TCB.IO_Index++] = I20DAT ;
                                I20CONSET = (I2CONSET_STO);                                                                // STO
                                if(I2C0_TCB.IO_Index == I2C0_TCB.IOData_num)
                                {
                                        I2C0_TCB.IIC_FLAG = 2;                                                                // 总线已经正常停止
                                }
                                else
                                {
                                        I2C0_TCB.IIC_FLAG = 3;                                                                // 总线已经正常停止
                                }
                                I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC);         // AA  SI  STA  clr       
                                break;

                        case 0x38:  /* 在SLA+R/W或数据字节中丢失仲裁         */  
                        case 0x48:  /* 已发送SLA+R,已接收非应答              */
                                /* 读取异常中断 */
                                I20CONSET = (I2CONSET_STO);                                                                // STO
                                I2C0_TCB.IIC_FLAG = 3;                                                                        // 总线已经异常停止
                                I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC);         // AA  SI  STA  clr
                            break;

                        default:   
                                /* 读取异常中断 */
                                I20CONSET = (I2CONSET_STO);                                                                // STO
                                I2C0_TCB.IIC_FLAG = 3;                                                                        // 总线已经异常停止
                                I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC);         // AA  SI  STA  clr                                        
                                   break;   
                }
        }  
        VICVectAddr = 0x00;
  OS_EXIT_CRITICAL();       
}

/*************************************************************************************************
** 函数名称:
** 功能描述:
** 输 入: 无
** 输 出: 无     
** 返回值: 无
** 全局变量:
** 调用模块:
**--------------------------------------------------------------------------------------------
** 修改记录: bobo 2010/03/30 建立
*************************************************************************************************/
uint32 I2C0_Init(void)
{       
        //init data
        I2C0_TCB.IIC_FLAG = 0;
        I2C0_TCB.OP_TYPE = 0;
        I2C0_TCB.OP_State = 0;
        I2C0_TCB.IOData_num = 0;
        I2C0_TCB.IO_Index = 0;
        I2C0_TCB.OffAddr_num = 0;
       
//        if(fi2c > 400000)
//        {
//                fi2c = 400000;
//        }

        //IIC0_COM0_PINSELr &= IIC0_COM0_PIN_DISvalue;
        //IIC0_COM0_PINSELr |= IIC0_COM0_PIN_ENvalue;

  PCONP |= (1 << 19);
  PINSEL1 &= ~0x03C00000;
        PINSEL1 |= 0x01400000;        /* set PIO0.27 and PIO0.28 to I2C0 SDA and SCK */

#define I2SCLH_SCLH                        0x00000080  /* I2C SCL Duty Cycle High Reg */
#define I2SCLL_SCLL                        0x00000080  /* I2C SCL Duty Cycle Low Reg */
               
        I20CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;
        I20SCLH = ((12000000*3) / 400000 + 1)/2;
        I20SCLL = ((12000000*3) / 400000)/2;

//  I20SCLL   = I2SCLL_SCLL;
//  I20SCLH   = I2SCLH_SCLH;

  SetVICIRQ(9, 5, (uint32)IRQ_I2C0);                        // 注册I2C0中断

        return (TRUE);
}


/*****************************************************************************
** Function name:                I2CEngine
**
** Descriptions:                The routine to complete a I2C transaction
**                                from start to stop. All the intermitten
**                                steps are handled in the interrupt handler.
**                                Before this routine is called, the read
**                                length, write length, I2C master buffer,
**                                and I2C command fields need to be filled.
**                                see i2cmst.c for more details.
**
** parameters:                        None
** Returned value:                true or false, return false only if the
**                                start condition can never be generated and
**                                timed out.
**
*****************************************************************************/
//DWORD I2CEngine( void )
//{
//    I2CMasterState = I2C_IDLE;
//    RdIndex = 0;
//    WrIndex = 0;
//    if ( I2CStart() != TRUE )
//    {
//                I2CStop();
//                return ( FALSE );
//    }
//
//    while ( 1 )
//    {
//                if ( I2CMasterState == DATA_NACK )
//                {
//                    I2CStop();
//                    break;
//                }
//    }   
//    return ( TRUE );      
//}


===============================================================================================================================
/****************************************Copyright (c)******************************************
*
*    http://www.aoretech.cn/main.asp  Copyright(C) 2010, YMHX ,All rights reserved.
*
*-------------------------------------文件信息--------------------------------------------
*   文件名:
*         功能描述:Header file for
*   创建 人: bobo
*
*   修改历史:
*   2010/01/13  v1.00 bobo

*         范围性质:全局性头文件,半全局头性文件,私有性头文件
************************************************************************************************/

#ifndef  __I2C0_H__
#define  __I2C0_H__

  /* 以下是变量和函数声明 */
//  uint32 I2C0_Init(uint32 fi2c);
  uint32 I2C0_IO_End(void);

  #define I2C0_MAXBUF   (512)
  #define I2C0_SYN_READ         (1)
  #define I2C0_SYN_WRITE         (2)
  #define I2C0_ASYN_READ         (3)
  #define I2C0_ASYN_WRITE         (4)

/* I2C Control Set Register */
#define I2CONSET_I2EN                0x00000040  
#define I2CONSET_AA                        0x00000004
#define I2CONSET_SI                        0x00000008
#define I2CONSET_STO                0x00000010
#define I2CONSET_STA                0x00000020

/* I2C Control clear Register */
#define I2CONCLR_AAC                0x00000004  
#define I2CONCLR_SIC                0x00000008
#define I2CONCLR_STAC                0x00000020
#define I2CONCLR_I2ENC                0x00000040

  uint32 I2C0_Init(void);
  uint32 I2C0_IO_Start(uint8 IO_type, uint8 sla, const uint8 *offaddr, uint32 offaddr_num,uint8 *IO_dataP, uint32 IO_num);

typedef        struct
{         
    unsigned char year  ;
                                unsigned char month ;
                                unsigned char day   ;
                                unsigned char hour  ;
                                unsigned char minute;
                                unsigned char second;
}        RTC_DT;

extern RTC_DT           rtc;       


#endif  /* __I2C0_H__ */



//************************************************************************************************
//                                                                                    END FILE
//************************************************************************************************

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2010-8-3 00:13:05 | 显示全部楼层
请兄弟帮忙看看,什么原因

出0入0汤圆

发表于 2010-8-3 08:48:13 | 显示全部楼层
估计是管脚配置有问题??

用示波器抓波形看了么?

出0入0汤圆

 楼主| 发表于 2010-8-3 12:33:56 | 显示全部楼层
兄弟,管脚配置什么地方有问题啊??
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-28 09:40

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表