最近在研究IIC通讯,做IIC读写AT24C256的程序,但是
单片机用1M晶振可以正常运行,换成12M就出错,这应该就是时序的问题了,哪位大侠能帮我看看12M频率下应该把时序调整成扫描样呢??[C]
纯文本查看 复制代码
#ifndef AT24CXX_H_#define AT24CXX_H_#include
#include #define Wait_1us _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_()#define Wait_2us {Wait_1us;Wait_1us;}#define Sla_Wr 0xa0 /*0000 0 0 0 0*/#define Sla_Rd 0xa1 /*0000 0 0 0 1*/#define AT24C01 0x01#define AT24C01A 0x02#define AT24C02 0x03#define AT24C04 0x04#define AT24C08 0x05#define AT24C16 0x06#define AT24C32 0x07#define AT24C64 0x08#define AT24C128 0x09#define AT24C256 0x0a#define AT24C512 0x0b#define Mem_Size AT24C04 // 01/01A/02/04/08/16/32/64/128/256/512#define Chip_1 0x00 //本器件的器件地址,可以第一8个不同地址的芯片使之能用同一段程序进行读写void Start_I2c(void);void End_I2c(void);unsigned char Scan_I2c();void Send_I2c(unsigned char cData);void Send_Ack(void);void Send_Not_Ack(void);void Write_Mem(unsigned char cMem_Size,cChips_Address,cData_Size,unsigned int cStart_Address);void Read_Mem(unsigned char cMem_Size,cChips_Address,cData_Size,unsigned int cStart_Address);#endif[C] 纯文本查看 复制代码
#ifndef AT24CXXX_C_#define AT24CXXX_C_#include "at24cxx.h"***it bSda =P0^0;***it bScl =P0^1; bit bScan_Err;unsigned char idata cShare_Buf[8]={'P',1,2,3,4,5,6,7}; //I2c read and write buffervoid Start_I2c(void){ // unsigned char /*idata*/ i; bSda = 1;// Wait_1us; bScl = 1;// for(i=0;i<32;i++); //wait 7us Wait_1us; bSda = 0;// for(i=0;i<32;i++); //wait 7us Wait_1us; bScl = 0; Wait_1us;}void End_I2c(void){// unsigned char /*idata*/ i; bSda=0; Wait_1us; bScl=1;// for(i=0;i<16;i++); //wait 7us Wait_1us; bSda = 1; Wait_1us;}unsigned char Scan_I2c(){ unsigned char /*idata*/ i,j;//IIC data bSda = 1; j = 0; for(i=0;i<8;i++) { bScl = 1; j <<= 1; Wait_1us; j |= bSda; //Scan 0 Scan 1 bScl=0; Wait_1us; } return j;}void Send_I2c(unsigned char cData){ unsigned char /*idata*/ i; for(i=0;i<8;i++) { bSda=(bit)(cData&0x80); Wait_1us; bScl=1; cData<<=1; Wait_1us; bScl=0; Wait_1us; } bSda=1; Wait_1us; bScl=1; //检测ACK for(i=0;(bSda==1)&&(bScan_Err==0);i++) { if(i==90) bScan_Err=1; //如果101us没有响应就错误 } bScl=0; Wait_1us;}void Send_Ack(void){//unsigned char /*idata*/ i; bSda=0; Wait_1us; bScl=1;// for(i=0;i<2;i++); //wait 8us Wait_1us; bScl=0; Wait_1us;}void Send_Not_Ack(void){// unsigned char /*idata*/ i; bSda = 1; Wait_1us; bScl = 1;// for(i=0;i<2;i++); //wait 8us Wait_1us; bScl=0; Wait_1us;} void Write_Mem(unsigned char cMem_Size,cChips_Address,cData_Size,unsigned int cStart_Address){ unsigned char /*idata*/ i,cAddress[2]; //0-L;1-H bScan_Err=0; cAddress[0]=cStart_Address; cStart_Address>>=8; cAddress[1]=cStart_Address; i=Sla_Wr; i|=cChips_Address; if(cMem_Size==AT24C256) i&=0xf7; Start_I2c(); Wait_1us; Send_I2c(i); //SLA:1010 xxx0 Wait_1us; if(cMem_Size==AT24C256) //1-16用1个字节地址,32-512用2个字节地址,匹配地址AT24C32、64 Send_I2c(cAddress[1]); //先发送高字节地址 Send_I2c(cAddress[0]); //如果是双字节地址则为低地址否则为高地址 for(i=0;(bScan_Err==0)&&(i!=cData_Size);i++) Send_I2c(cShare_Buf); //写一个字节数据 End_I2c(); }void Read_Mem(unsigned char cMem_Size,cChips_Address,cData_Size,unsigned int cStart_Address){ unsigned char /*idata*/ i,cAddress[2]; bScan_Err=0; cAddress[0]=cStart_Address; //将16位地址分解为高低字节 cStart_Address>>=8; cAddress[1]=cStart_Address; i = Sla_Wr; i |= cChips_Address; if(cMem_Size==AT24C256) i&=0xf7; Start_I2c(); Send_I2c(i);//SLA:1010 xxx0 if(cMem_Size==AT24C256) //1-16用1个字节地址,32-512用2个字节地址,匹配地址AT24C32、64 Send_I2c(cAddress[1]); //先发送高字节地址 Send_I2c(cAddress[0]); //address and write i|=0x01; //Read Start_I2c(); Send_I2c(i); //address and read for(i=0;(bScan_Err==0)&&(i!=cData_Size);i++) { cShare_Buf=Scan_I2c(); //读入第一个字节 if(i==(cData_Size-1)) Send_Not_Ack(); else Send_Ack(); } End_I2c();}#endif