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

📄 communication._c

📁 基于PIC单片机
💻 _C
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************/
#include "allhead.h"

uchar tx_buff[12];              //存放要发向转换器的数
uchar  errorflag  = 0;                                     //485出错
uchar fl=0;             //服了(fule),自动搜索用!
extern uchar can_cuo_flag[32];                  //转换器故障 用
//TWI 相关全局变量
uchar i2c_rd_buff[32];   //i2c读出的数最初存放的地方
uchar i2c_wt_buff[35];   //写
uchar fhz;               //读写完返回值0或1
uchar autoc[5];

uchar nnn=0;
extern uchar canuse[4];
extern uchar zhongbuff[33][10];
extern uchar detuse[33][4];
extern uchar det_link[33];
extern uchar keyc;
extern uchar jiemian;
extern uchar denglu;
extern uchar gal3data;
//延时1us;晶振为8M时1us延时函数
void delay_1us(void)
{
  asm("nop");
}
//延时n us
void delay_nus(unsigned int n)
{
  unsigned int i;
  for(i=0;i<n;i++)
    delay_1us();
} 
//延时1ms;
void delay_1ms(void)
{
  unsigned int i;
  for(i=1;i<(unsigned int)(xtal*143-2);i++)
  ;
}
//延时n ms
void delay_nms(unsigned int n)
{
  unsigned int j;
  wdr();
  for(j=0;j<n;j++)
    delay_1ms();
}
//复位MCP
void reset_MCP(void)
{  
  //unsigned char 
  PORTB&=~(1<<CS_CAN);			 //	CS  Low -> MCP enable
  SPDR=RESET_MCP;			    //	send Reset command
  while(!(SPSR & (1<<SPIF)))
  ; 	                       //	wait
  PORTB|=(1<<CS_CAN);		  //	CS  High -> MCP disable
  delay_1ms();		         //	waiting
}
//写函数
void write_MCP(unsigned char adress, unsigned char value)
{
  PORTB&=~(1<<CS_CAN);				//	CS  Low -> MCP enable
  SPDR=0x02;					//	sende Write command
  while(!(SPSR & (1<<SPIF)));	//	warten bis das Byte gesendet wurde
  SPDR=adress;					//	Addresse senden
  while(!(SPSR & (1<<SPIF)));	//	warten bis das Byte gesendet wurde
  SPDR=value;					//	Wert senden
  while(!(SPSR & (1<<SPIF)));	//	warten bis das Byte gesendet wurde
  PORTB|=(1<<CS_CAN);					//	CS  High -> MCP disable
}
//读函数
unsigned char read_MCP(unsigned char adress)
{
	unsigned char spidata;
	PORTB&=~(1<<CS_CAN);				//	CS  Low -> MCP enable
	SPDR=0x03;					//	sende Read command
	while(!(SPSR&(1<<SPIF)));	//	wait
	SPDR=adress;					//	adress send
	while(!(SPSR&(1<<SPIF)));	//	wait
	SPDR=0xAA;					//	不懂
	while(!(SPSR&(1<<SPIF)));	//	wait
	spidata = SPDR;				//	Data return
	PORTB|=(1<<CS_CAN);				//	CS  High -> MCP disable
	return (spidata);
}
//位调整函数
void bit_modify(unsigned char adress,unsigned char cc, unsigned char value)
{  
    PORTB&=~(1<<CS_CAN);		   //	CS  Low -> MCP enable
    SPDR=0x05;					   //	bit modify Write command
	while(!(SPSR & (1<<SPIF)));	   //	
	SPDR=adress;				   //	sende Write command
	while(!(SPSR & (1<<SPIF)));	   //	
	SPDR=cc;					   //	sende Write command
	while(!(SPSR & (1<<SPIF)));	   //	warten bis das Byte gesendet wurde
	SPDR=value;					  //	sende Write command
	while(!(SPSR & (1<<SPIF)));	 //	
    PORTB|=(1<<CS_CAN);					//	CS  High -> MCP disable
}
 //发送缓冲器0
void send_box_0(void)   //此处好像应该加发送缓冲器空标志查询!!!!!
{
	write_MCP (TXB0CTRL, 0x0B);			//	sende Telegramm mit h鯿hster Priori
	//0x0B--缓冲区等待报文发送,最高的报文发送优先级
	PORTB&=~(1<<CS_CAN);				//	CS  Low -> MCP enable
	SPDR=(RTS | 0x01);			//	sende Mailbox Nummer 0
	while(!(SPSR & (1<<SPIF)));	//	warten bis das Byte gesendet wurde
	PORTB|=(1<<CS_CAN);					//	CS  High -> MCP disable
}
//数据请求数据帧函数
void remotesend(uchar id_addr)
{
    NOP();
    write_MCP(TXB0SIDH,id_addr);//接收方的地址,
   // write_MCP(TXB0SIDL,0x48);   //扩展帧格式 且4就表示是发送请求命令
	write_MCP(TXB0SIDL,0xc8);   //扩展帧格式 且4就表示是发送请求命令
    write_MCP(TXB0EID8,0x00);   //标识发送方地址主控制器为0x00
    write_MCP(TXB0EID0,0x00);   //   
    write_MCP(TXB0DLC, 0x08);    //发送8个字节
    write_MCP(TXB0D0,  0x00);  //
    write_MCP(TXB0D1,  0x00);  //
    write_MCP(TXB0D2,  0x00);  //
    write_MCP(TXB0D3,  0x00);  //
    write_MCP(TXB0D4,  0x00);  //
    write_MCP(TXB0D5,  0x00);  //
    write_MCP(TXB0D6,  0x00);  //
    write_MCP(TXB0D7,  0x00);
	send_box_0();
	NOP();
}
//装载报文 TXB0
void fill_msg_box_0(void)
{  
   tx_buff[9]=8;   
   write_MCP(TXB0SIDH,tx_buff[1]);         //接收方的地址
   write_MCP(TXB0SIDL,tx_buff[7]);         //扩展帧格式   
   write_MCP(TXB0EID8,tx_buff[8]);         //标识发送方地址
   write_MCP(TXB0EID0,tx_buff[2]);         //485节点地址
   write_MCP(TXB0DLC, tx_buff[9]);         //发送8个字节
   write_MCP(TXB0D0,  tx_buff[2]);         //485NA节点地址
   write_MCP(TXB0D1,  tx_buff[0]);         //命令字节
   write_MCP(TXB0D2,  tx_buff[3]);         //高报点高字节
   write_MCP(TXB0D3,  tx_buff[4]);         //高报点低字节
   write_MCP(TXB0D4,  tx_buff[5]);         //低报点高字节
   write_MCP(TXB0D5,  tx_buff[6]);         //低报点低字节
   write_MCP(TXB0D6, tx_buff[10]);         //校验
   write_MCP(TXB0D7, tx_buff[11]);
} 
//485收发函数
void Usart_Transmit_Data(uchar data,uchar i) 
{  
   int aaa=0;
   cs_485_send();           
   for(aaa=1000;aaa>0;aaa--);//等待PB3引脚稳定 1000
   while(!(UCSR0A&(1<<UDRE0)))
   ;
   if(i==1)
      UCSR0B|=(1<<TXB80);  //发送地址
   else
   {
      UCSR0B&=~(1<<TXB80); //发送数据
   }
   UDR0=data;
   while(!(UCSR0A&(1<<TXC0)))
   ;
   UCSR0A|=1<<TXC0;
   cs_485_receive();
} 
//发送多个字节函数
void usart_transmits(unsigned char n, unsigned char *p)
{
    uchar *pr;int bbb=0;
    cs_485_send(); 
    for(bbb=1000;bbb>0;bbb--);//等待PB3引脚稳定 
    for(pr=p;pr<(p+n);pr++)
    {
        while(!(UCSR0A&(1<<UDRE0)))
	    ;
	    UDR0= *pr;
    }
    while(!(UCSR0A&(1<<TXC0))) 
    ;
    UCSR0A|=1<<TXC0;
    cs_485_receive(); 
}
//8位数据单字节接收函数Usart_Receive_Data()
uchar Usart_Receive_Data(void)
{
     int flag5=0;uchar j=0;int tcounter=0;
     while(!(UCSR0A&(1<<RXC0)))
     {
	    flag5++; 
		//wdr();
	    if(flag5>5000)
	    {
		    wdr();
		    flag5=0; 
	        tcounter++;
	    }  	 
		if(tcounter>2)       //原来是3
	    {  
	         tcounter=0;
	         errorflag=1;    //最多等待50s还没有数据传上来说明节点断开
	         break;          //errorflag 为未接受到数据 标识
	    }		 
     }	 
     j=UCSR0B;
     return UDR0;  
}   
//8位数据单字节接收函数Usart2_Receive_Data() 调零专用
uchar Usart2_Receive_Data(void)
{
     int flag5=0;uchar j=0;int tcounter=0;
     while(!(UCSR0A&(1<<RXC0)))
     {
	    flag5++; 
	    if(flag5>5000)
	    {
		    wdr();
		    flag5=0; 
	        tcounter++;
	    }  	 
		if(tcounter>500)        //
	    {  
		     wdr();
	         tcounter=0;
	         errorflag=1;    //最多等待50s还没有数据传上来说明节点断开
	         break;          //errorflag 为未接受到数据 标识
	    }		 
     }	 
     j=UCSR0B;
     return UDR0;  
}   
//发送一个字节
void usart_transmit_char(uchar c)            
{ 
  uchar a=0;
  //delay_nus(6);     //很重要,有待思考
  delay_nus(9);
  a=PIND;
  while((a&0x20)==0x20)
  {
    a=PIND;
	wdr();
  }
  while(!(UCSR1A&(1<<UDRE1)))
  {
     wdr();
  }
  //;
  UDR1=c;
  while(!(UCSR1A&(1<<TXC1))) 	  
  ;
  UCSR1A|=1<<TXC1;
  delay_nus(1);
}
/**********************************************************************
                       TWI相关的函数开始
 **********************************************************************/
 //一个字节的高低位的翻转函数
uchar byte_revert(uchar data)
{
     unsigned char a, b, c;
     a = data;
     if( ( b = a | 0x81 ) != a
     && ( c = a^0x81 ) != b )
           a = c;
     if( ( b = a | 0x42 ) != a
     && ( c = a^0x42 ) != b )
           a = c;
     if( ( b = a | 0x24 ) != a
     && ( c = a^0x24 ) != b )
           a = c;
     if( ( b = a | 0x18 ) != a
     && ( c = a^0x18 ) != b )
           a = c;
     return a;
}
/****************************************************************************
Call this function to set up the TWI master to its initial standby state.
Remember to enable interrupts from the main application after initializing the TWI.
****************************************************************************/
void TWI_Master_Initialise(void)
{
    TWBR = TWI_TWBR;     // Set bit rate register (Baudrate)4k. Defined in header file.
    // TWSR = TWI_TWPS;         // Not used. Driver presumes prescaler to be 00.
    TWDR = 0xFF;                // Default content = SDA released.
    TWCR = (1<<TWEN)|           // Enable TWI-interface and release TWI pins.
           (0<<TWIE)|(0<<TWINT)|                      // Disable Interupt.
           (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // No Signal requests.
           (0<<TWWC);                                 //
}       
/***************************  TWI相关函数结束*****************************/
//写数据到TWDR
void i2c_wt_8bit(unsigned char data)
{
    TWDR=data;
	TWCR=(1<<TWINT)|(1<<TWEN)|(0<<TWEA)|
	     (0<<TWSTA)|(0<<TWSTO)|(0<<TWWC); 
}	
//device_addr为器件地址,addrhi,addrlo为全地址,num 要连续读的个数
//返回1:失败,0:成功 一次最多写32个字节
uchar I2cRead(uchar device_wt,uchar device_rd, uchar addrhi,uchar addrlo,uchar num)
{
    uchar j=0;
	Start()	;          //I2C开始
	Wait()  ;          //等待TWIINT标志为1
	if(TestAck()!=TWI_START )
	{
		TWI_Master_Initialise(); 
		return 1;     //出错
	}	
	i2c_wt_8bit(device_wt);  //写I2C从器件地址及写方式	
	Wait();                 //等
	if(TestAck()!=TWI_MTX_ADR_ACK )  //ACK
	{
		TWI_Master_Initialise(); 
		return 1;    //出错
	}	
	i2c_wt_8bit(addrhi); //高地址
	Wait();                 //等
	if(TestAck()!=TWI_MTX_DATA_ACK  )  //ACK
	{
	    TWI_Master_Initialise(); 
	    return 1;    //出错  	
	}	
	i2c_wt_8bit(addrlo); //低地址
	Wait();                 //等
	if(TestAck()!=TWI_MTX_DATA_ACK  )  //ACK
	{  
	    TWI_Master_Initialise(); 
	    return 1;    //出错  
	}	
	Start()	;          //I2C从新开始
	Wait()  ;          //等待TWIINT标志为1	
	if(TestAck()!=TWI_REP_START  )  //ACK
	{   
	    TWI_Master_Initialise(); 
	    return 1;    //出错  	
	}	
	i2c_wt_8bit(device_rd);  //写I2C从器件地址及读方式	
	Wait();                 //等
	if(TestAck()!=TWI_MRX_ADR_ACK )  //ACK
	{
	    TWI_Master_Initialise(); 
	    return 1;    //出错	
	}	
	TWCR = (1<<TWEN)|                          // TWI Interface enabled
           (0<<TWIE)|(1<<TWINT)|               // Enable TWI Interupt and clear the flag to read next byte
           (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|    // Send ACK after reception
           (0<<TWWC); 
	delay_nus(25);  //最低值!25 
    for(j=1;j<num;j++)   //读取num-1个
	{
	    if(TestAck()!= TWI_MRX_DATA_ACK  )  //ACK
		{
		    TWI_Master_Initialise(); 
	        return 1;    //出错	
		}	
		i2c_rd_buff[j-1]=TWDR;  //读取数
		TWCR = (1<<TWEN)|                          // TWI Interface enabled
               (0<<TWIE)|(1<<TWINT)|               // Enable TWI Interupt and clear the flag to read next byte
               (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|    // Send ACK after reception
               (0<<TWWC); 	
		delay_nus(25);   //最低值! 25
	}	
	if(TestAck()!= TWI_MRX_DATA_ACK  )  //ACK
	{
	    TWI_Master_Initialise(); 
	    return 1;    //出错	
	}	
    i2c_rd_buff[num-1]=TWDR;  //读取数
	TWCR = (1<<TWEN)|                          // TWI Interface enabled
           (0<<TWIE)|(1<<TWINT)|               // Enable TWI Interupt and clear the flag to read next byte
           (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|    // Send NACK after reception
           (0<<TWWC); 
	delay_nus(25);	 //最低值!   25
	if(TestAck()!= TWI_MRX_DATA_NACK   )  //NACK
	{
	    TWI_Master_Initialise(); 
	    return 1;    //出错		
	}	   
	Stop();   //I2C停止
	return 0;   //整个过程正常时返回0	   
}
//num ,msg写的数组 num包括前面的三个字节的地址
//返回1:失败,0:成功
uchar I2cWrite(uchar *msg,uchar num)
{
    uchar i=0;  //一般用途 
    i2c_wt_buff[0]=msg[0] ;  //器件
	i2c_wt_buff[1]=msg[1] ;  // 地址高字节
	i2c_wt_buff[2]=msg[2] ;  // 地址低字节
	for(i=3;i<num;i++)
	    i2c_wt_buff[i]=msg[i];   //转移字节
	Start()	;          //I2C开始
	Wait()  ;          //等待TWIINT标志为1
	if(TestAck()!=TWI_START )
	{  
	    TWI_Master_Initialise(); 
	    return 1;    //出错  
	}	
	i2c_wt_8bit(i2c_wt_buff[0])	;   //从器件地址和写方式
	Wait();                 //等
	if(TestAck()!=TWI_MTX_ADR_ACK )  //ACK
	{  
	    TWI_Master_Initialise(); 
	    return 1;    //出错  
	}	
	i2c_wt_8bit(i2c_wt_buff[1])	;       //写地址高	
	Wait();                 //等
	if(TestAck()!=TWI_MTX_DATA_ACK  )  //ACK
	{  
	    TWI_Master_Initialise(); 
	    return 1;    //出错  
	}	
	i2c_wt_8bit(i2c_wt_buff[2])	;       //写地址低	
	Wait();                 //等
	if(TestAck()!=TWI_MTX_DATA_ACK  )  //ACK
	{  
	    TWI_Master_Initialise(); 
	    return 1;    //出错  
	}	
	for(i=3;i<num;i++)   //写真正的数据
	{
	    i2c_wt_8bit(i2c_wt_buff[i])	;       //写地址高	
		Wait();                 //等
		if(TestAck()!=TWI_MTX_DATA_ACK  )  //ACK
		{  
	    TWI_Master_Initialise(); 
	    return 1;    //出错  
	    }	
		delay_nus(25);                 //没必要
	}	
	Stop();   //I2C停止
	return 0;   //整个过程正常时返回0
	
}
//时钟的读写
uchar clock_wt(uchar *msg,uchar num)
{
    uchar i=0;
    for(i=0;i<num;i++)
	    i2c_wt_buff[i]=msg[i];   //转移字节
    Start()	;          //I2C开始
	Wait()  ;          //等待TWIINT标志为1
	if(TestAck()!=TWI_START )
	{  
	    Stop();   //I2C停止
	    return 1;     //出错
	}	
	i2c_wt_8bit(i2c_wt_buff[0])	;   //从器件地址和写方式
	//delay_nms(8);
	Wait();                 //等
	if(TestAck()!=TWI_MTX_ADR_ACK )  //ACK
	    return 1;    //出错	
	for(i=1;i<num;i++)   //写真正的数据
	{
	    i2c_wt_8bit(i2c_wt_buff[i])	;       //写地址高	

⌨️ 快捷键说明

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