| 最近在研究IIC通讯,做IIC读写AT24C256的程序,但是单片机用1M晶振可以正常运行,换成12M就出错,这应该就是时序的问题了,哪位大侠能帮我看看12M频率下应该把时序调整成扫描样呢??
 
[mw_shl_code=c,true]#ifndef AT24CXX_H_
#define AT24CXX_H_
#include <\SiLABS\c8051f340.h>
#include <intrins.h>
#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[/mw_shl_code]
 
[mw_shl_code=c,true]#ifndef AT24CXXX_C_
#define AT24CXXX_C_
#include "at24cxx.h"
sbit    bSda        =P0^0;
sbit    bScl        =P0^1;    
bit bScan_Err;
unsigned char idata cShare_Buf[8]={'P',1,2,3,4,5,6,7};    //I2c read and write buffer
void 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[/mw_shl_code]
 
 
  |