📄 communication._c
字号:
/*******************************************************************/
#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 + -