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

📄 pic16f946_i2c.txt

📁 PIC16F946 软件模拟I2C操作FM24C16铁电存储器C源程序.
💻 TXT
字号:
#include<pic.h> 

#define  SCL    RD5  //FM24C16-6
#define  SDA     RD4  //FM24C16-5
#define  WP      RD3  //写保护 

#define  LED RC3 

#define  SCL_DIR   TRISD5  //1
#define  SDA_DIR   TRISD4  //2 

#define  IIC_READ  0xA1     //定义读指令
#define  IIC_WRITE 0xA0     //定义写指令 

#define  OUTPUT  0
#define  INPUT  1 

bit ack;          //应答标志位 

unsigned char b[4];
unsigned char b1[4];
unsigned char c[1]; 

/*--------------------------------------------------------------------------------------------
功能:启动I2C总线,即发送I2C起始条件.  
名称:Start_I2c()
输入:无
输出:无
返回:无
备注:无
---------------------------------------------------------------------------------------------*/
void Start_I2c(void)
{
 SDA_DIR = OUTPUT;
 SCL_DIR = OUTPUT; 

 SDA = 1;        //发送起始条件的数据信号 
 SCL = 1;    
 SDA = 0;        //发送起始信号         
 SCL = 0;        //钳住I2C总线,准备发送或接收数据  

}
/*--------------------------------------------------------------------------------------------
功能:结束I2C总线,即发送I2C结束条件.   
名称:Stop_I2c()
输入:无
输出:无
返回:无
备注:无
---------------------------------------------------------------------------------------------*/
void Stop_I2c()
{
 SDA_DIR = OUTPUT;
 SCL_DIR = OUTPUT;
 
 SDA=0;      //发送结束条件的数据信号 
  SCL=1;       //发送结束条件的时钟信号 
  SDA=1;       //发送I2C总线结束信号 


} 


/*--------------------------------------------------------------------------------------------
功能:将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状态位进行操作.(不应答或非应答都使ack=0)     
     发送数据正常,ack=1; ack=0表示被控器无应答或损坏。  
名称:void  SendByte
输入:c:要发送的数据
输出:无
返回:无
备注:无
---------------------------------------------------------------------------------------------*/ 

void  SendByte(unsigned char c)
{
 unsigned char BitCnt; 

 SCL_DIR = OUTPUT;
 SDA_DIR = OUTPUT;  
 
 for(BitCnt=0;BitCnt<8;BitCnt++)  //要传送的数据长度为8位 
 {  
  if((c<<BitCnt)&0x80)   //判断发送位 
  { SDA=1; } 
         else { SDA=0; }                   
        SCL=1;                       //置时钟线为高,通知被控器开始接收数据位        
        SCL=0; 

    } 
         
    SDA=1;                          //8位发送完后释放数据线,准备接收应答位   
    
    SDA_DIR = INPUT;     //将SDA置为输入口,等待应答 
    
    SCL=1;  
    
    
    
    if(SDA==1) { ack=0; }   
       else { ack=1; }            //判断是否接收到应答信号,如果正确第九个sda为零
    SCL=0; 
} 

/*--------------------------------------------------------------------------------------------
功能:用来接收从器件传来的数据,并判断总线错误(不发应答信号),发完后请用应答函数应答从机。     
名称:RcvByte
输入:无
输出:无
返回:retc
备注:无
---------------------------------------------------------------------------------------------*/ 
unsigned char  RcvByte(void)
{
 unsigned char retc;
    unsigned char BitCnt;
  
   retc=0; 
   SDA=1;                        //置数据线为输入方式 

   SDA_DIR = INPUT;     //将SDA置为输入口,等待应答 
   for(BitCnt=0;BitCnt<8;BitCnt++)
    {
                  
        SCL=0;                       //置时钟线为低,准备接收数据位       
        SCL=1;                       //置时钟线为高使数据线上数据有效     
        retc=retc<<1;
        if(SDA==1)retc=retc+1;       //读数据位,接收的数据位放入retc中        
    }
  SCL=0;  
   return(retc);
} 

/*--------------------------------------------------------------------------------------------
功能:主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)
名称:void Ack_I2c
输入:无
输出:无
返回:无
备注:无
---------------------------------------------------------------------------------------------*/ 
void Ack_I2c(unsigned char a)
{
 SCL_DIR = OUTPUT;
 SDA_DIR = OUTPUT;   

    if(a==0)
    {
     SDA=0;               //在此发出应答或非应答信号 
    }
    else
    {  
     SDA=1;
    }
  
   SCL=1;  
   SCL=0;                    //清时钟线,钳住I2C总线以便继续接收
} 

/*--------------------------------------------------------------------------------------------
功能:向有子地址器件发送字节数据函数
     从启动总线到发送命令,地址,数据,结束总线的全过程,器件子地址sbua.如果返回1表示操作成功,否则操作有误。
名称:ISendByte
输入:
输出:
返回:
备注:
---------------------------------------------------------------------------------------------*/ 
unsigned char ISendByte(unsigned int suba,unsigned char c)
{
 unsigned char temp,tempw; 

 temp=(unsigned char)(suba>>8);  //temp =0 0 0 0 0 a10 a9 a8
 tempw=(IIC_WRITE|(temp<<1));   //tempw=1 0 1 0 a10 a9 a8 0
    Start_I2c();                  //启动总线
    SendByte(tempw);               //发送命令            
    if(ack==0)
    {   
     //LED=0; 
     return(0);
    } 
 SendByte((unsigned char)suba);  //发送地址 
    if(ack==0)
    {  
    //LED=0;    
      return(0);
    } 
    SendByte(c);                    //发送数据
    if(ack==0)
    {
     //LED=0;
      return(0);
    } 
    Stop_I2c();                     //结束总线
    return(1);
} 

/*--------------------------------------------------------------------------------------------
功能:向有子地址器件发送多字节数据函数
     从启动总线到发送命令,子地址,数据,结束总线的全过程如果返回1表示操作成功,否则操作有误。
名称:ISendStr输入:
输出:
返回:
备注:使用前必须已结束总线。
---------------------------------------------------------------------------------------------*/ 
unsigned char ISendStr(unsigned int suba,unsigned char *s,unsigned char no)
{
 unsigned char i;
 unsigned char temp,tempw; 

 temp=(unsigned char)(suba>>8);       //temp=0 0 0 0  0 a10 a9 a8
 tempw=(IIC_WRITE|(temp<<1));  //tempw=1 0 1 0 a10 a9 a8 0
    Start_I2c();                  //启动总线
    SendByte(tempw);              //发送命令
    if(ack==0)return(0);
    SendByte((unsigned char)suba);       //发送器件子地址
    if(ack==0)return(0);
    for(i=0;i<no;i++)
    {   
      SendByte(*s);              //发送数据
      if(ack==0)return(0);
      s++;
    } 
    Stop_I2c();                     //结束总线 
    return(1);
}
/*--------------------------------------------------------------------------------------------
功能:向有子地址器件读字节数据函数
     从启动总线到发送命令,地址,读数据,结束总线的全过程,器件子地址sbua ,返回值在c.
     如果返回1表示操作成功,否则操作有误。
名称:IRcvByte
输出:
返回:
备注:
---------------------------------------------------------------------------------------------*/
unsigned char IRcvByte(unsigned int sbua,unsigned char *c)
{
 unsigned char temp,tempw,tempr;
 
 temp=(unsigned char)(sbua>>8);     //temp=0 0 0 0  0 a10 a9 a8
 tempw=(IIC_WRITE|(temp<<1));       //tempw=1 0 1 0 a10 a9 a8 0
 tempr=(IIC_READ|(temp<<1));       //tempr=1 0 1 0 a10 a9 a8 1
    Start_I2c();                      //启动总线
 SendByte(tempw);                  //写命令
 if(ack==0)
 {  
  return(0);
 }
 SendByte((unsigned char)sbua);    //写地址
 if(ack==0)
 {
  return(0);
 } 
 Start_I2c();                      //重新启动总线
    SendByte(tempr);                  //读命令
    if(ack==0)
    {
     return(0);
    }
    *c=RcvByte();                     //读取数据
    
    Ack_I2c(1);                       //发送非就答位
    Stop_I2c();                       //结束总线 
    return(1);
}  

/*--------------------------------------------------------------------------------------------
功能:向有子地址器件读取多字节数据函数
     从启动总线到发送命令,子地址,读数据,结束总线的全过程,如果返回1表示操作成功,否则操作有误。
名称:IRcvStr
输出:
返回:
备注:
---------------------------------------------------------------------------------------------*/ 

unsigned char IRcvStr(unsigned int suba,unsigned char *s,unsigned char no)
{
    unsigned char i;
    unsigned char temp,tempw,tempr;
 
 temp=(unsigned char)(suba>>8);    //temp=0 0 0 0  0 a10 a9 a8
 tempw=(IIC_WRITE|(temp<<1));      //tempw=1 0 1 0 a10 a9 a8 0
 tempr=(IIC_READ|(temp<<1));       //tempr=1 0 1 0 a10 a9 a8 1
    Start_I2c();                      //启动总线
    SendByte(tempw);                  //写命令
    if(ack==0)return(0);
    SendByte((unsigned char)suba);    //写地址
    if(ack==0)return(0); 

    Start_I2c();             //重新启动总线
    SendByte(tempr);
    if(ack==0)return(0);
    for(i=0;i<no-1;i++)
    {   
      *s=RcvByte();               //发送数据
       Ack_I2c(0);                 //发送就答位
      s++;
    } 
    *s=RcvByte();
    Ack_I2c(1);                      //发送非应位
    Stop_I2c();                      //结束总线 
    return(1);
} 


void main(void)
{
 unsigned char a[4]={0xDc,0x55,0xaa,0xed};
 unsigned char d=0xDD;   
 
 OSCCON = 0b011001111;
 
 TRISD3=OUTPUT;
 TRISD4=INPUT;
 TRISD5=INPUT;
 
 TRISC3=OUTPUT;
 
 RD4=0;
 RD5=0;
  
 WP=0;   
 LED=1;
  
 ISendStr(0x400,a,4);   
 IRcvStr(0x400,b,4);
 
 if( b[0]==0xDC && b[1]==0x55 && b[2]==0xaa && b[3]==0xed )
 {
  LED=0;
 }
 /*
    ISendByte(0x301,d);
    IRcvByte(0x301,c);  
 
    if(c[0]==d)
    {
       LED=0;
    }  
    */
 //IRcvStr(0x400,b1,4); 
 while(1)
 {
  
 }
} 

本程序在MPLAB8.0版本中调成功 
 
 

⌨️ 快捷键说明

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