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

📄 od2101.c

📁 OD2101是可以实现I2C与RS232或RS485透传
💻 C
字号:
//#include "reg52.h"
#include <STC12C2052AD.h>
#include "intrins.h"

#ifndef uchar
#define uchar unsigned char
#endif

#ifndef uint
#define uint unsigned int
#endif


#define WR             0x00
#define RD             0x00
#define UARTBUF        0x01
#define I2CBUF         0x02
#define CTRL		   0x03	
#define OD2101         0x5e			//A0 H  A1 H  A2 H

#define ACKCNT         150

sbit VI2C_SDA=P1^1;
sbit VI2C_SCL=P1^2;
sbit IRQ=P3^2;
sbit LED=P1^0;              //用来监测IRQ脚的电平
bit  data ack;	             //*应答标志位*/


bit data  IRQ_VALUE=0;


uchar data in_dat,in_dat1,PC_COMMAND;
uchar data RAM_buff[8];

enum{UART_9600,UART_300,UART_600,UART_900,
		UART_1200,UART_1800,UART_2400,UART_3600,
		UART_4800,UART_7200,UART_14400,UART_19200,
		UART_28800,UART_38400,UART_57600,UART_115200};

bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no);



//50ms延时
void delay5ms(void)
{
 unsigned char TempCyc = 250;
 while(TempCyc--);
}

//串行口初始化
void init_serialcomm(void)
{
    SCON  = 0x50;       //SCON: serail mode 1, 8-bit UART, enable ucvr 
    //TMOD |= 0x20;       //TMOD: timer 1, mode 2, 8-bit reload 
	TMOD=0x21;    //time1 work mode 2 auto replace time0 work mode 1 16 bit
    PCON |= 0x80;       //SMOD=1; 
   	//baud_setup(eeprom_read(sector1));

    TH1   = 0xFA;       //   fosc=11.0592MHz 
    IE   |= 0x90;       //Enable Serial Interrupt 
    TR1   = 1;          // timer 1 run 
   // TI=1; 
}

//串行数据发送,查询模式
//向串口发送一个字符 
void serial_out(unsigned char ch)  
{
    SBUF=ch;
    while(TI==0);
    TI=0;
}

void send_string_com(unsigned char *str,unsigned int strlen)
{
    unsigned int i=0;
    do 
    {
        serial_out(*(str + i));
        i++;
    } while(i < strlen);
}






void DelayNs(unsigned int i)
{
	for(;i>0;i--) ;
}

/************************************************************************/
//1:定义如下函数
unsigned char TestSCL()
{
uint i ;
for( i = 0 ; i < 0xffff ; i++ ) {
if ( VI2C_SCL == 1 ) return 1 ;
}
return 0 ;
}
//2:在每一个SCL=1;这句话后加入此函数就可以用了。   如下所示:
  //SCL=1;
//TestSCL();
/************************************************************************/


/*******************************************************************
                     起动总线函数               
函数原型: void  Start_I2c();  
功能:       启动I2C总线,即发送I2C起始条件.
  
********************************************************************/
void Start_I2c()
{
  VI2C_SDA=1;   /*发送起始条件的数据信号*/ 

  _nop_();
  
  VI2C_SCL=1;  TestSCL();
  _nop_();    /*起始条件建立时间大于4.7us,延时*/
  _nop_();
  _nop_();
  _nop_();
  _nop_();   
  
  VI2C_SDA=0;   /*发送起始信号*/
  _nop_();    /* 起始条件锁定时间大于4μs*/
  _nop_();
  _nop_();
  _nop_();
  _nop_();   
  
  VI2C_SCL=0;   /*钳住I2C总线,准备发送或接收数据 */
  _nop_();
  _nop_();
}

/*******************************************************************
                      结束总线函数               
函数原型: void  Stop_I2c();  
功能:       结束I2C总线,即发送I2C结束条件.
  
********************************************************************/
void Stop_I2c()
{
  VI2C_SDA=0;  /*发送结束条件的数据信号*/
  _nop_();   /*发送结束条件的时钟信号*/
  VI2C_SCL=1;  /*结束条件建立时间大于4μs*/TestSCL();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
 
  VI2C_SDA=1;  /*发送I2C总线结束信号*/
  _nop_();
  _nop_();
  _nop_();
  _nop_();
}




/*******************************************************************
                 字节数据传送函数               
函数原型: void  SendByte(uchar c);
功能:  将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
     此状态位进行操作.(不应答或非应答都使ack=0 假)     
     发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
********************************************************************/
void  SendByte(uchar c)
{
 uchar data BitCnt,i;
 
 for(BitCnt=0;BitCnt<8;BitCnt++)  /*要传送的数据长度为8位*/
    {
     if((c<<BitCnt)&0x80)VI2C_SDA=1;   /*判断发送位*/
       else  VI2C_SDA=0;                
     _nop_();

     VI2C_SCL=1;               /*置时钟线为高,通知被控器开始接收数据位*/TestSCL();
      _nop_(); 
      _nop_();               /*保证时钟高电平周期大于4μs*/
      _nop_();
      _nop_();
      _nop_();   

	 
      
     VI2C_SCL=0; 
    }
    
    _nop_();
    _nop_();
	
    VI2C_SDA=1;               /*8位发送完后释放数据线,准备接收应答位*/
    _nop_();
    _nop_(); 
    
    VI2C_SCL=1;   TestSCL();
    _nop_();
    _nop_(); 
    _nop_(); 


	while((VI2C_SDA==1)&&(i<ACKCNT)){i++;}
    if(i>ACKCNT) ack=0;      
      else ack=1;        /*判断是否接收到应答信号*/
    VI2C_SCL=0;
    _nop_();
    _nop_();

	DelayNs(50);   //cfy
}






/*******************************************************************
                 字节数据传送函数               
函数原型: uchar  RcvByte();
功能:  用来接收从器件传来的数据,并判断总线错误(不发应答信号),
     发完后请用应答函数。  
********************************************************************/	
uchar  RcvByte()
{
  uchar data retc;
  uchar data BitCnt;
  
  retc=0; 
  VI2C_SDA=1;             /*置数据线为输入方式*/
  for(BitCnt=0;BitCnt<8;BitCnt++)
      {
        _nop_();           
        VI2C_SCL=0;       /*置时钟线为低,准备接收数据位*/
        _nop_();
        _nop_();         /*时钟低电平周期大于4.7μs*/
        _nop_();
        _nop_();
        _nop_();
	

        VI2C_SCL=1;       /*置时钟线为高使数据线上数据有效*/ TestSCL();
        _nop_();
        _nop_();
		
        retc=retc<<1;
        if(VI2C_SDA==1)retc=retc+1; /*读数据位,接收的数据位放入retc中 */
        _nop_();
        _nop_(); 
      }
  VI2C_SCL=0;    
  _nop_();
  _nop_();
  	//serial_out(retc);   //test
  return(retc);
}




/********************************************************************
                     应答子函数
原型:  void Ack_I2c(bit a);
 
功能:主控器进行应答信号,(可以是应答或非应答信号)
********************************************************************/
void Ack_I2c(bit a)
{
  
  if(a==0)VI2C_SDA=0;     /*在此发出应答或非应答信号 */
        else VI2C_SDA=1;
  _nop_();
  _nop_();
  _nop_();      
  VI2C_SCL=1; TestSCL();
    _nop_();
    _nop_();              /*时钟低电平周期大于4μs*/
    _nop_();
    _nop_();
    _nop_(); 
 
 VI2C_SCL=0;                /*清时钟线,钳住I2C总线以便继续接收*/
    _nop_();
    _nop_();    
}






/*******************************************************************
                    向无子地址器件发送字节数据函数               
函数原型: bit  ISendByte(uchar sla,ucahr c);  
功能:     从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.
           如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/






/*******************************************************************
                    向有子地址器件发送多字节数据函数               
函数原型: bit  ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);  
功能:     从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
          地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
           如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/
bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no)
{
   uchar data i;

   Start_I2c();               /*启动总线*/
   SendByte(sla);            /*发送器件地址*/
    if(ack==0) 	return(0);
		 

   SendByte(suba);            /*发送器件子地址*/
     if(ack==0) 		return(0);
	 

   for(i=0;i<no;i++)
    {   
     SendByte(*s);               /*发送数据*/
    if(ack==0)return(0);
     s++;
    } 
 Stop_I2c();                 /*结束总线*/ 
 
  return(1);
}






/*******************************************************************
                    向无子地址器件读字节数据函数               
函数原型: bit  IRcvByte(uchar sla,ucahr *c);  
功能:     从启动总线到发送地址,读数据,结束总线的全过程,从器件地
          址sla,返回值在c.
           如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/




/*******************************************************************
                    向有子地址器件读取多字节数据函数               
函数原型: bit  ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);  
功能:     从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
          地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
           如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/
bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no)
{
   uchar data i;

   Start_I2c();               /*启动总线*/
   SendByte(sla);            /*发送器件地址*/
     if(ack==0)return(0);
   SendByte(suba);            /*发送器件子地址*/
     if(ack==0)return(0);

   Start_I2c();
   SendByte(sla+1);
      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();                    /*结束总线*/ 
   //i=*s;
  return(1);
}

//===============================================

//串行中断接收
void receive() interrupt 4
{
	if(RI)
	{
		RI = 0;
		ES = 0;
		PC_COMMAND = SBUF;
		//delay5ms();

		//serial_out(PC_COMMAND);
	
		ISendStr(OD2101, WR, &PC_COMMAND, 1);
		delay5ms();

		//RX_BUFFER[RX_index] = PC_COMMAND;		//保存数据到数组里面
		//RX_index++;
	 
	}
		
	ES = 1;	
	
}

void int_0() interrupt 0 //P3.2                                 
{   
	//unsigned char i;
    EX0=0; 

	delay5ms();
	delay5ms();
	delay5ms();
	IRQ_VALUE=0;


	IT0=1;   
    EX0=1;
	EA=1;
} 


void main()
{
	uchar i;
 

	P1M0 = 0xff; //设置STC的 IO 为标准51 IO模式
	P1M1 = 0xff;
	P3M0 = 0xff;
	P3M1 = 0xff;	
	
	P1=0xff;
	P3=0xff;

//	IRQ = 1 ;         /*将IRQ管脚设置成输入状态*/ 

	EA=1;	
	EX0=1;
    IT0=1;      
    
    init_serialcomm();   
       
     LED=1;    
                                                               
  if(IRcvStr( OD2101 , CTRL , &in_dat , 1 )) //;     /*读取OD2101控制寄存器*/    
   			
      
   in_dat = ( in_dat & 0xf0 ) | UART_4800 ;      /*设置OD2101UART波特率为9600*/      
   if(ISendStr( OD2101 , CTRL, &in_dat , 1))// ;     /*发送控制字节*/                      
   			
                                                                           
   ISendStr( OD2101 , WR , "message from OD2101\n", 19);        /*发送"good"字节到OD2101*/           
   send_string_com("message from TEST CPU\n",21);
   			
   			//serial_out(0x55);   //test     
   IRQ_VALUE=1;                                                    
   while(1)                                                                  
   {       
   		 
  		
   		if( !IRQ_VALUE)                                           /*判断是否有接收中断产生*/          
        {                                                                  
                    			
         	IRQ_VALUE=1;
			LED=0;  //test                                    
            if (IRcvStr(OD2101,UARTBUF,&in_dat,1)) //;/*UART接收缓存接收字节*/  
			{
				//serial_out(in_dat);   //test	
                for( i = 0 ; i <in_dat  ; i++ )            /*将接收缓冲区的数据读出*/    //  in_dat
                {                                                             
            		if(IRcvStr( OD2101 , RD , &in_dat1 , 1 )) /*读取一个字节数据*/    
                              /*将读取出的数据进行大小写转换*/          
                	{	
									//serial_out(in_dat1);   //test
					//				DelayNs(100); //test
                              	/*	if( (in_dat1>='A')&&(in_dat1<='Z') )                           
                              		{                                                         
                                  		in_dat1 += 'a'-'A' ;                                         
                              		}                                                        
                              		else if( (in_dat1>='a')&&(in_dat1<='z') )                           
                              		{                                                           
                                  		in_dat1 -= 'a'-'A' ;                                         
                              		}                                 */      
                    
					
     					//ISendStr(OD2101, WR, &in_dat1, 1);/*将转换后的数据发送给I2C总线*/  
						serial_out(in_dat1);	//serial_out(in_dat);send_string_com(&in_dat1,1);//test
					}
  								     
				}
                                                                    
             } 
  					    
						       
           //          }                                                               
          }else LED=1;    //test                                                                 
      }        

}

⌨️ 快捷键说明

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