⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 51单片机
💻 C
字号:
//--------------------------------------------------------------------------------
#include <c8051f340.h> 
#include <stdio.h>
typedef  unsigned int   uint ;     
typedef  unsigned char  uchar;             
#define  SYSCLK         12000000              // 12M内部时钟
#define  BAUDRATE        9600                 // Baud rate of UART in bps
sbit SDA = P1^0;
sbit SCL = P1^1;
uchar  buffer[16];    //数据存储器

bit  Ack(void); /*应答位*/
bit  NAck(void);     //无应答位
void delay();        //长延时
void UART0_Init (void);   //UART Init
void Start(void); /*起始条件*/
void Stop(void); /*停止条件*/
void Send(uchar Data); /*发送数据子程序,Data为要求发送的数据*/
uchar Read(void); /*读一个字节的数据,并返回该字节值*/
void OSCILLATOR_Init (void);   //内部振荡器初始化
void PORT_Init (void);         //I/O初始化
void wait(int n);              //精确延时
int  I2cReadWriteZL(int mode,unsigned char ChipAddress,unsigned char *Data,int NbData);
void outputchar(uint order);
void selectout(uint dat);



void main (void)
{  
   uchar  i;   
   uchar  deviceAddr=0x1C;
   uchar  dat[2]={0x14,0xC0};
   uchar  ucBuffer[3]={0xFF};


   PCA0MD &= ~0x40;                    // WDTE = 0 (clear watchdog timer
                                       // enable)

   PORT_Init();                        // Initialize Port I/O
   OSCILLATOR_Init ();                 // Initialize Oscillator
  
   UART0_Init();                       //Initialize  UART0

   delay();
   delay();
 

   
 
}




void PORT_Init (void)
{

   P1MDOUT &= 0x00;                    // Enable UTX as push-pull output
   P0MDOUT |= 0x10;  
   XBR1    = 0x40;                     // Enable crossbar and enable
   XBR0     = 0x01;                    // Enable UART on P0.4(TX) and P0.5(RX)                     
                                       // weak pull-ups
}


void OSCILLATOR_Init (void)
{
   OSCICN |= 0x03;                     // Configure internal oscillator for
                                       // its maximum frequency
   RSTSRC  = 0x04;                     // Enable missing clock detector
}

void Start(void) /*起始条件*/

{
SDA=1;

SCL=1;

wait(50);

SDA=0;

wait(50);

}


void Stop(void) /*起始条件*/

{

SDA=0;

SCL=1;

wait(50);

SDA=1;

wait(50);


}




void UART0_Init (void)
{
   SCON0 = 0x10;                       // SCON0: 8-bit variable bit rate
                                       //        level of STOP bit is ignored
                                       //        RX enabled
                                       //        ninth bits are zeros
                                       //        clear RI0 and TI0 bits
   if (SYSCLK/BAUDRATE/2/256 < 1) {
      TH1 = -(SYSCLK/BAUDRATE/2);
      CKCON &= ~0x0B;                  // T1M = 1; SCA1:0 = xx
      CKCON |=  0x08;
   } else if (SYSCLK/BAUDRATE/2/256 < 4) {
      TH1 = -(SYSCLK/BAUDRATE/2/4);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 01                  
      CKCON |=  0x01;
   } else if (SYSCLK/BAUDRATE/2/256 < 12) {
      TH1 = -(SYSCLK/BAUDRATE/2/12);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 00
   } else {
      TH1 = -(SYSCLK/BAUDRATE/2/48);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 10
      CKCON |=  0x02;
   }

   TL1 = TH1;                          // Init Timer1
   TMOD &= ~0xf0;                      // TMOD: timer 1 in 8-bit autoreload
   TMOD |=  0x20;                       
   TR1 = 1;                            // START Timer1
   TI0 = 1;                            // Indicate TX0 ready
}
/*------长延时-----*/
void delay(void)
{  
int  i,j;
for(i=255;i>0;i--)
for(j=255;j>0;j--)
;
}


void wait(int n)               //延长n个系统时钟
{
for(;n>0;n--)
;
}


void SEND_0(void) /*发送0比特*/
{
  SCL=0;           //获取总线控制权
  SDA=0;           //发送数据
  SCL=1;
  wait(50);        //延时  确保从机读取数据  具体时间视系统时钟而定
  SCL=0;
  wait(20);         //延时
}


void SEND_1(void)               /*发送比特1*/
{
  SCL=0;
  SDA=1;
  SCL=1;
  wait(50);
  SCL=0;
  wait(20);
}


void Send(uchar Data)           /*发送数据子程序,Data为要求发送的数据*/

{

 char i;
  for(i=0;i<8;i++)
  {
  if((Data<<i)&0x80)
    SEND_1();        
  else
    SEND_0();
  }
}

uchar Read(void)                 /*读一个字节的数据,并返回该字节值*/

{
  bit F0;
  char b=0,i;
  for(i=0;i<8;i++)
  {
    SDA=1;     /*释放总线*/
    SCL=1;     /*接受数据*/
    wait(10);  //等待数据建立
    F0=SDA;    //读取数据
    if(F0==1)   //判断存储
    {
       b=b<<1;
       b=b|0x01;
    }
    else
       b=b<<1;
	   wait(20);
       SCL=0;
	   wait(10);
   }
  return b;

}



bit Ack(void) /*应答位*/

{
  uchar w=40;    //等待时间值
  bit F0=1;      //标志位
  SDA=1;
  SCL=1;
  wait(10);
  while(--w&&F0)  //读取应答位
  F0=SDA;         
  wait(20);
  SCL=0;
  return F0;
} 


/*无应答数据位发送子程序*/

bit NAck(void) 

{

bit s=0;

SCL=0;

wait(5);

SCL=1;

SDA=1;

wait(20);

s=SDA;

wait(40);

SCL=0;
return !s;
}


/*------底层I2C读写子程序-----
函数为单主机主控发送接受子程序,该程序使用时总线上不可有其他主机。。。。
函数参数设置为   wr_mode--读写模式    char_slv_addr--从机地址    *dat--数据首地址     len----数据长度  
数据地址的第一个字节一般为寄存器的地址
写数据时--在上层函数中需要把被写寄存器地址写入*dat的第一个字节   写入数据从第二个字节开始  写入字节数不多于16个
读数据时--需要读取的寄存器地址存放在第一个字节中,读取的数据存放在第一个字节中,读取的数据会覆盖原寄存器的地址
读模式专用于10313和10039器件,其格式为
--发送开始标志
--发送从机地址(写形式)
--应答位
--发送寄存器地址
--应答位
--发送开始标志
--发送从机地址(读模式)
------------------
--应答位
--读取寄存器数据
----------------
--无应答位
--结束标志。
----------------------------------------------------------------------------------------------------------------*/
int I2cReadWriteZL(int wr_mode, char slv_addr, char *dat, int len)
{
    uchar i;
	if (wr_mode == 1)      //判断读写功能
	{
    Start();               //开始标志
    Send(slv_addr);        //发送从机地址
    for(i=0;i<len;i++)
    {
    if(Ack())              //读取应答位
	return 1;
    Send(*dat);            //发送数据
    ++dat;
    }
    NAck();
    Stop();                 //结束标志  
    if(i==len)    //成功
        return 0;
    } 
	
	
	else                          //数据读取
	{
      Start();                    //开始标志位
      Send(slv_addr);             //从机地址
      Ack();
      Send(*dat);                  //数据发送--寄存器地址
      Ack();
      Start();                     //开始标志
      Send(slv_addr+1);            //从机地址
      for(i=0;i<len;i++)
      {
      if (Ack())                    //应答位
	  return 1;
      *dat=Read();                  //数据读取
      ++dat;
      }
      NAck();
      Stop();                        //结束标志
      if(i==len)     //成功
            return 0;
	
	}
	
	return 1;         //失败
}


/*------输出字符形式数据---
数据以ASCII的形式输出  
------------------------------*/
void outputchar(uint order)
{
selectout(order/16);

selectout(order%16);
}


/*获得的数据判断--以确定输出字符
---------------------------------*/
void selectout(uint dat)
{
switch(dat)
{
case 0:printf("%c",'0');
break;
case 1:printf("%c",'1');
break;
case 2:printf("%c",'2');
break;
case 3:printf("%c",'3');
break;
case 4:printf("%c",'4');
break;
case 5:printf("%c",'5');
break;
case 6:printf("%c",'6');
break;
case 7:printf("%c",'7');
break;
case 8:printf("%c",'8');
break;
case 9:printf("%c",'9');
break;
case 10:printf("%c",'A');
break;
case 11:printf("%c",'B');
break;
case 12:printf("%c",'C');
break;
case 13:printf("%c",'D');
break;
case 14:printf("%c",'E');
break;
case 15:printf("%c",'F');
break;
default:printf("error");
}
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -