[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] |