📄 can.c
字号:
#include <avr/io.h>
#include <avr/iocan32.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define uchar unsigned char
#define uint unsigned int
volatile uchar close_flag,open_flag,ad_flag,adc_ready,usart1_flag=0,rx_counter,adc0_counter;
volatile uchar adc0_buffer[]={};
volatile uchar can_rx_data[]={};
volatile uchar can_tx_data[]={};
volatile uchar rx_buffer[]={};
uchar address;
uint rx_ID[4]={192,168,0,1};
uint tx_ID[4]={0,0,0,0};
void USART_Transmit(uchar);
void read_address(void) //读取本机地址
{
uchar read_add;
DDRC = 0X00; //C口输入上拉
PORTC = 0XFF;
read_add = PINC;
address=read_add;
}
void can_baudrate(void) //设置波特率250K
{
uchar i;
int n;
uchar PH[8] = {20,16,15,12,10,8,25,18};
uchar CTSYNC,CBRP,CSJW,CPRS,CPHS2,CPHS1,CSMP;
//20,16,15,12,10,8,18
n = 48 ; // 12M/250K;
for(i=0;i<8;i++)
{
if( n%PH[i] == 0 )
{
break;
}
}
CPHS2 = PH[i]/3;
CPHS1 = PH[i]/3;
CTSYNC = 1;
CSJW = 0;
CSMP = 1;
CBRP = n/PH[i];
CPRS = PH[i]- CPHS2 - CPHS1 - CTSYNC;
CANBT1 = (CBRP-1)<<1;
CANBT2 = ((CSJW)<<5) | ((CPRS-1)<<1);
CANBT3 = ((CPHS2-1)<<4) | ((CPHS1-1)<<1) | CSMP;
}
void init_CAN(void)
{
CANGCON |= (1<<SWRES); //CAN控制器软复位
can_baudrate();
CANTCON = 0x00;
//--------------can_MOB INITIAL-------------------
//MOB0=RX[CMD] 接收设置 主机格式:192.168.0.0 从机192.168.0.1
CANPAGE = 0x00; //MOB0 接收,自动增量,初值为0
CANSTMOB = 0;
CANCDMOB = 0x18; //can2B,DLC=8
CANIDT4 = rx_ID[3]<<3; // 接收ID设置
CANIDT3 = rx_ID[2];
CANIDT2 = rx_ID[1];
CANIDT1 = rx_ID[0];
CANIDM4 = 0xff; //校验寄存器设置
CANIDM3 = 0xff;
CANIDM2 = 0xff;
CANIDM1 = 0xff;
//MOB4=TX[CMD] 发送设置 主机格式:192.168.0.1 从机192.168.0.0
CANPAGE = 0x40; //MOB4 发送,自动增量,初值为0
CANSTMOB = (1<<TXOK);
CANCDMOB = 0x18; //can2B,DLC=8
CANIDT4 = tx_ID[3]<<3; //发送ID设置
CANIDT3 = tx_ID[2];
CANIDT2 = tx_ID[1];
CANIDT1 = tx_ID[0];
CANGIE |= ((1<<ENIT) + (1<<ENRX)); //开全局中断 和 接收中断
CANIE2 |= (1<<IEMOB0); // MOB0信箱接收中断(接收邮箱)
CANPAGE = 0x00;
CANCDMOB |=(1<<CONMOB1); // CONMOB1,CONMOB0=10是接收使能
CANGCON |= (1<<ENASTB); //CAN控制器启动
}
// FET控制 CC 00 01 00 00 00 00 FF
// 开头 地址 指令 数据 结尾
// 开路电压DD 00 01 00 00 00 00 FF
// 开头 地址 指令 数据 结尾
void can_rx_deal(void) //接收数据处理
{
if(can_rx_data[0]==0Xcc) //FET控制
{
//if(can_rx_data[1]==0xb0)
{
switch(can_rx_data[1])
{
case 0xb0: close_flag=1; //通道关闭
break;
case 0xb8: open_flag=1; //通道开启
break;
case 0xa0: ad_flag=1; //AD采集启动
break;
default:
break;
}
}
}
else if(can_rx_data[0]==0XDD) //太阳能方阵开路电压采集
{
if(can_rx_data[1]==address)
{
switch(can_rx_data[2])
{
case 0x02: //电压采集需向上传送
break;
default:
break;
}
}
}
}
ISR(CANIT_vect) //CAN接收中断处理函数
{
uchar i , num_i;
CANGIE &= ~(1<<ENRX); //关接收中断****
num_i = CANSIT2;
//-----------------------------------------------------
if (num_i & (1<<SIT0))
{
i=0;
CANPAGE = i<<4;
for(num_i = 0; num_i < 8; num_i++)
{
can_rx_data[num_i]=CANMSG; //取得8个字节的数据
}
}
can_rx_deal() ; //处理接收指令
CANPAGE = 0x00;
CANSTMOB &= ~(1<<RXOK); //清中断标志****
CANCDMOB = 0x98; //接收使能 2.0B DLC=8
CANGIE |= (1<<ENRX); //开中断
}
void can_send_data(void) //发送前数据整理
{
can_tx_data[0]=0xDD;
can_tx_data[1]=0x00; //地址
can_tx_data[2]=0x02;
can_tx_data[3]=0x01; //ad高位
can_tx_data[4]=0x03; //ad低位
can_tx_data[5]=0x00;
can_tx_data[6]=0x00;
can_tx_data[7]=0xff;
}
void MOB_send (void) //CAN发送函数
{
CANGIE &= ~(1<<ENRX); //关接收中断
uint i,n=4;
CANPAGE = (n<<4); //MOB_n, auto increment, index 0
if (CANSTMOB & (1<<TXOK))
{
// CANCDMOB= 0x18;
CANSTMOB &= ~(1<<TXOK);
can_send_data(); //发送前整理
for(i = 0; i < 8; i++)
{
CANMSG = can_tx_data[i];
}
CANCDMOB = 0x58; //帧发送 DLC=8
CANGIE |=(1<<ENRX); //开接收中断
}
}
//---------------------串口测试相关函数------------------------------
void USART_Transmit(uchar data)
{
while(!(UCSR1A&_BV(UDRE1)));
UDR1=data;
}
ISR(USART1_RX_vect)
{
uchar status,data;
status=UCSR1A;
data=UDR1;
if((status&(_BV(FE1)|_BV(UPE1)|_BV(DOR1)))==0)
{
rx_buffer[rx_counter]=data;
rx_counter++;
switch(rx_counter)
{
case 1:
if(data!=0XBB)
rx_counter=0;
break;
case 5:
if(data==0XFF)
{
rx_counter=0;
usart1_flag=1;
}
break;
}
}
}
void USART_init(void)
{
UCSR1A= 0X00 ;
UCSR1B= _BV(RXCIE1)|_BV(RXEN1)|_BV(TXEN1)|_BV(TXCIE1); //发送允许,接收允许 发送中断使能,接收中断使能
UCSR1C= _BV(UCSZ11)|_BV(UCSZ10); //异步通信模式;通信参数 8位数据位1位停止位,无校验
UBRR1H= 0x00;
UBRR1L= 0x4D;
}
/**********************AD采集相关函数*****************************/
void adc_init(void) //初始化函数
{
DDRF=0X00;
PORTF=0X00; //输入禁止上拉
ADCSRA=0x00; //暂时关闭AD
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -