在线情况
楼主
  • 头像
  • 级别
    • 积分5
    • 经验365
    • 文章3
    • 注册2007-01-15
    msp430f5418读写FM24C04的问题请教
    [P]各位大侠:[/P][P]    帮忙看看。今用msp430f5418控制一片fm24c04的读写,wp:p55 scl:p54 sda:p37 10M晶振[/P][P]    源程序如下:[/P][P]//此代码适用于 FM24C04/FM24C04A
    //采用MSP430F5418.  
    //WP P5.5 SDA P3.7 SCL P5.4
    //工作频率10MHz
    //'自由读' AND '字节写'.
    //=============================
    #include "xms430f5438.h"
    #include "intrinsics.h"
    #include "math.h"
    #define   mcu_xtal   10   //可定义为你所用的晶振频率Mhz
    #define   Delay_us(x)   __delay_cycles (x * mcu_xtal)
    #define   Delay_ms(x)   __delay_cycles ((unsigned long)x * mcu_xtal*1000)
    #define   Delay_s(x)    __delay_cycles ((unsigned long)x * mcu_xtal*1000000)//定义管脚
    #define WE BIT5
    #define SCL BIT4
    #define SDA BIT7
    //定义函数
    void I2C_Initial(void);
    void I2C_Set_sda_high(void);
    void I2C_Set_sda_low (void);
    void I2C_Set_sck_high(void);
    void I2C_Set_sck_low (void);
    int  I2C_GetACK(void);
    void I2C_SetACK(void);
    void I2C_SetNAk(void);
    void I2C_START(void);
    void I2C_STOP(void);
    void I2C_TxByte(unsigned char);
    int  I2C_RxByte(void);
    int WriteSingleByte(char nAddr,char nValue);
    int PageWrite(char nAddr,char pBuf[],char num);
    int ReadRandom(char nAddr, char *nValue);
    int ReadSeq(char nAddr, char *nValue, int nLen);
    void Init_CLK(void);
    void UCS_init(void)
    {
      P5SEL |= BIT2+BIT3;//选择XT2,10Mhz
      UCSCTL6 &= ~XT2OFF;// 使能XT2
      UCSCTL3 |= SELREF_2;// FLL参考REFO,因为XT1不能用
      UCSCTL4 |= SELA_2;  // ACLK=REFO,SMCLK=DCO,MCLK=DCO
      //循环直到XT1,XT2,DCO稳定
      do
      {
        UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);//清XT2,XT1,DCO错误标志
        SFRIFG1 &= ~OFIFG;//清错误标志
      }while (SFRIFG1&OFIFG);//测试振荡器错误标志
      UCSCTL6=XT2DRIVE0+XT1OFF_L;//XT2运行范围为8 MHz to 16 MHz,关闭XT1
      UCSCTL4=SELM__XT2CLK+SELS__XT2CLK+SELA__XT2CLK;  //ACLK,SMCLK,MCLK选择XT2
      UCSCTL5|=DIVA__32;  //ACLK=XT2/32 0.3125MHz
      UCSCTL5|=DIVM__1;  //MCLK=XT2
      UCSCTL5|=DIVS__8;  //SMCLK=XT2/8 1.25MHz
    }
    void I2C_Initial( void )
    {
        P3SEL &=~BIT7;              //SDA口为普通IO口
        P5SEL &=~(BIT4+BIT5);       //SCL和WP口为普通IO口
        P3REN |=BIT7;               //SDA口为漏极开路
        P3DIR |= BIT7;  //将SDK管脚设置为输出管脚
        P5DIR |= (BIT4+BIT5); //将SCL和WP管脚设置为输出管脚
        P5OUT &=~BIT5;              //WP为低,写使能
        I2C_Set_sck_low();          //SCK为低
        Delay_us(10);
        I2C_Set_sda_low ();         //SDA为低
        I2C_STOP();                 //停止IIC
        Delay_ms(10);
    }
    void I2C_Set_sda_high( void )
    {
        P3OUT |= SDA;  //SDA管脚输出为高电平
        _NOP();
        _NOP();
    }
    void I2C_Set_sda_low ( void )
    {
        P3OUT &= ~(SDA);  //SDA管脚输出为低电平
        _NOP();
        _NOP();
        return;
    }
    void I2C_Set_sck_high( void )
    {
        P5OUT |= SCL;  //SCL管脚输出为高电平
        _NOP();
        _NOP();
        return;
    }
    void I2C_Set_sck_low ( void )
    {
        P5OUT &= ~(SCL);  //SCL管脚输出为低电平
        _NOP();
        _NOP();
        return;
    }
    int  I2C_GetACK(void)
    {
        int nTemp = 0;
        P3DIR |= SDA;  //将SDA设置为输出方向
        _NOP();
        _NOP();
        I2C_Set_sda_high();         //SDA管脚输出为高电平
        I2C_Set_sck_low();         //SCL管脚输出为低电平
        Delay_us(10);
        P3DIR &= ~(SDA);  //将SDA设置为输入方向
        P3OUT|=SDA;//上拉电阻输入
        I2C_Set_sck_high();         //SCL管脚输出为高电平
        Delay_us(10);
        nTemp = (int)(P3IN & SDA); //获得数据
        I2C_Set_sck_low();
        P3DIR |= SDA;  //将SDA设置为输出方向
        return (nTemp & SDA);
    }
    void I2C_SetACK(void)
    {  
        P3DIR |= SDA;  //将SDA设置为输出方向
        I2C_Set_sda_high();
        I2C_Set_sck_high();
        I2C_Set_sck_low();
        return;
    }
    void I2C_START(void)
    {
        P3DIR |= SDA;  //将SDA设置为输出方向
        I2C_Set_sda_low();
        Delay_us(10);
        I2C_Set_sck_low();
        Delay_us(10);
        return;
    }
    void I2C_STOP(void)
    {
        P3DIR |= SDA;  //将SDA设置为输出方向
        I2C_Set_sck_high();
        Delay_us(10);
        I2C_Set_sda_high();
        Delay_ms(10);  //延迟一点时间
        return;
    }
    void I2C_TxByte(unsigned char nValue)
    {
        int i;
        P3DIR |= SDA;  //将SDA设置为输出方向
        for(i = 0;i < 8;i++)
        {
         if(nValue & 0x80)
             I2C_Set_sda_high();
         else
             I2C_Set_sda_low();
           Delay_us(10);
         I2C_Set_sck_high();
         nValue <<= 1;
           Delay_us(10);
         I2C_Set_sck_low();
           Delay_us(10);
        }
       
        return;
    }
    /////////////////////////////////////////////
    // 接收是从 LSB 到 MSB 的顺序
    int  I2C_RxByte(void)
    {
        int nTemp = 0;
        int i;
        I2C_Set_sda_high();
        P3DIR &= ~(SDA);   //将SDA管脚设置为输入方向
        P3OUT|=SDA;//上拉电阻输入
        Delay_us(10);
        for(i = 0;i < 8;i++)
        {
         I2C_Set_sck_high();
         if(P3IN & SDA)
         {
             nTemp |= (0x01 << i);
         }
           Delay_us(10);
         I2C_Set_sck_low();
           Delay_us(10);
        }
        return nTemp;
    }
    int WriteSingleByte(char nAddr,char nValue)
    {
     int nTemp = 0xa0;//写命令
     // 启动数据总线
     I2C_START();
     // 发送控制字节
     I2C_TxByte(nTemp);
     // 等待 ACK
     nTemp = I2C_GetACK();
     if(nTemp & BIT7) return 0;
     // 发送地址字节
     I2C_TxByte(nAddr);
     // 等待 ACK
     nTemp = I2C_GetACK();
     if(nTemp & BIT7) return 0;
     // 发送数据字节
     I2C_TxByte(nValue);
     // 等待 ACK
     nTemp = I2C_GetACK();
     if(nTemp & BIT7) return 0;
     // 停止总线
     I2C_STOP();    
        return (nTemp & SDA);
    }
    int PageWrite(char nAddr,char pBuf[],char num)
    {
     int i;
     int nTemp = 0xa0;//写命令
     // 启动数据总线
     I2C_START();
     // 发送控制字节
     I2C_TxByte(nTemp);
     // 等待 ACK
     nTemp = I2C_GetACK();
     if(nTemp & BIT7) return 0;
     // 发送地址字节
     I2C_TxByte(nAddr);
     // 等待 ACK
     nTemp = I2C_GetACK();
     if(nTemp & BIT7) return 0;
     // 发送数据字节
     for(i = 0; i < num;i++)
     {
      I2C_TxByte(pBuf[0]);
      // 等待 ACK
      nTemp = I2C_GetACK();
      if(nTemp & BIT7) return 0;
     }
     // 停止总线
     I2C_STOP();    
        return (nTemp & SDA);
    }
    int ReadRandom(char nAddr, char *nValue)
    {
     //写命令
     int nTemp = 0xa0;
     // 启动数据总线
     I2C_START();
     // 发送控制字节
     I2C_TxByte(nTemp);
     // 等待 ACK
     nTemp = I2C_GetACK();
     if(nTemp & BIT7) return 0;
     // 发送地址字节
     I2C_TxByte(nAddr);
     // 等待 ACK
     nTemp = I2C_GetACK();
     if(nTemp & BIT7) return 0;
     // 启动数据总线
     I2C_START();
     // 发送控制字节
     nTemp = 0xa1;
     I2C_TxByte(nTemp);
     // 等待 ACK
     nTemp = I2C_GetACK();
     if(nTemp & BIT7) return 0;
     //读取数据
           *nValue = I2C_RxByte();
     // 停止总线
     I2C_STOP();
     //成功返回
     return 1;
    }
    int ReadSeq(char nAddr, char nValue[], int nLen)
    {
     int i;
     //写命令
     int nTemp = 0xa0;
     // 启动数据总线
     I2C_START();
     // 发送控制字节
     I2C_TxByte(nTemp);
     // 等待 ACK
     nTemp = I2C_GetACK();
     if(nTemp & BIT7) return 0;[/P][P] // 发送地址字节
     I2C_TxByte(nAddr);
     // 等待 ACK
     nTemp = I2C_GetACK();
     if(nTemp & BIT7) return 0;[/P][P] // 启动数据总线
     I2C_START();
     // 发送控制字节
     nTemp = 0xa1;
     I2C_TxByte(nTemp);
     // 等待 ACK
     nTemp = I2C_GetACK();
     if(nTemp & BIT7) return 0;[/P][P] //读取数据
     for(i = 0; i < nLen; i++)
     {
      //读一个字节数据
      nValue[i] = I2C_RxByte();
                   if(i<(nLen-1))
                   {
                       nTemp = I2C_GetACK();
                       if(nTemp & BIT7) return 0;
                   }
      else//发送ACK
      I2C_SetACK();
     }    [/P][P] // 停止总线
     I2C_STOP();
     //成功返回
     return 1;
    }
    void main(void)
    {
      unsigned char k;
      char pTime[4]={0,1,2,3};
      WDTCTL = WDTPW + WDTHOLD;
     //初始化时钟
           UCS_init();
           //初始化I2C
           I2C_Initial();
           while(1)
           {
               pTime[0]=0xaa;
               pTime[1]=0x55;
               PageWrite(0x00,pTime,1);
               pTime[0]=0;
               pTime[1]=0;
               k=ReadSeq(0x00,pTime,1);
           }
    }[/P][P]不能对FM24C04操作,请帮忙看看。[/P]
    微控网感谢您的参与
    在线情况
    2
    • 头像
    • 级别
      • 积分5
      • 经验365
      • 文章3
      • 注册2007-01-15
      用了斑竹DC的程序一次就成功了,帖子见[URL=http://www.microcontrol.cn/bbs/a/a.asp?B=112&ID=6652&RID=6657#F6657]http://www.microcontrol.cn/bbs/a/a.asp?B=112&ID=6652&RID=6657#F6657[/URL] 。我的程序回去再看看,不足之处再与大家分享。
      微控网感谢您的参与
      在线情况
      3
      • 头像
      • 级别
      • 门派
      • 职务总版主
      • 声望+9
      • 财富5
      • 积分3065
      • 经验390701
      • 文章6744
      • 注册2006-03-07
      [P]哥们,我都有点怕大家动不动都将问题代码贴出来...。说实在话,这样找问题成功率比较低。
      一来,看代码基本上看不出啥动东西来,还要花较大的精力。所以这种求助成功性不大。
      二来,真正要解决还是要实物实际调试。否则...你懂的。
      最好的办法如你那样参考一下别人的代码这样更有效。[/P]
      [COLOR=#0000ff]欢迎发贴分享设计心得、开源DIY...[/COLOR]
      在线情况
      4
      • 头像
      • 级别
        • 积分2
        • 经验77
        • 文章2
        • 注册2012-05-23
        DC老大说的好
        微控网感谢您的参与
        Powered by LeadBBS 9.2 .
        Page created in 0.9072 seconds with 5 queries.