📄 cantest.c
字号:
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
//-----------------------------------------------------------------------------|
// 初始化 :MCU 时钟,端口方向 ,USART1 波特率 ,CAN控制器 ,看门狗 ,TCC1 |
// CAN控制器 0# ,4# 信箱中断接收 ,1#、2#、3# 信箱发送数据 |
// 定时器 TCC1 做CAN数据一秒内达到判断,1秒内无数据报警 |
//-----------------------------------------------------------------------------|
unsigned char can_data[4][8]=
{
1,2,3,4,5,6,7,8,
11,12,13,14,15,16,17,18,
};
void mcu_init(void)
{
unsigned int i=0;
//-------------------prot init-------------------
//DDRC = 0xff; //端口设置:PC设置为推挽1输出
// PORTC = 0xfe;
DDRA = 0x00; //端口设置:PA设置为输入
//---------------- MCU interrupt ----------------
SREG = 0x00; //关全局中断; 0x80开全局中断
//-----------------usart 1 INITIAL---------------
UBRR1 =25; //USART1 波特率设置9600 X 16M-"103",
//38400bpsX16M=25;
UCSR1B=(1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1); //使能接收 & 使能发送 & 使能接收中断
UCSR1C=(1<<UCSZ10)|(1<<UCSZ11); //0x06 8位数据,1位停止位,无校验 */
//----------------CAN_REG INITIAL----------------
CANGCON |= (1<<SWRES);
for(i=0;i<=50000;i++){}
for(i=0;i<=50000;i++){}
for(i=0;i<=50000;i++){}
for(i=0;i<=50000;i++){}
for(i=0;i<=50000;i++){}
for(i=0;i<=50000;i++){}
//CAN控制器软复位
CANBT1 = 0X06;
//设置波特率分频因子16MHz,16TQ,250k,=4=3+1,3
CANBT2 = 0x0c; //同步段为1“0x0n”传播段=7=6+1
CANBT3 = 0x37;
//相位缓冲PH2=4=3+1,PH1=4=3+1
// CANTCON = 0xff;
CANTCON = 0B00000010;
//--------------can_MOB INITIAL-------------------
//MOB0=RX[CMD] 接收上位机发来的指令 //格式:3,0,0,177,239,33
CANPAGE = 0x00; //MOB0,自动增量,初值为0
CANSTMOB = 0;
CANCDMOB = 0x08; //2.0b 0x10 8个byte
/* //can2B,DLC=8
CANIDT4 = 0x08; // 00001 0xx
CANIDT3 = 0x79; // 01111 001 33
CANIDT2 = 0x8f; // 10001 111 239
CANIDT1 = 0x65;
*/
// CANIDT4 = 0x20+0B00001000; // 00100 000
//CANIDT4 = 0x20;
// CANIDT3 = 0x23; // 00100 011 101
CANIDT2 = 0x2b; // 00101 011 100
CANIDT1 = 0xdd; // 01100 101 177
// CANIDM4 =0xff; // 11111 100
// CANIDM3 =0xff; // 11111 111
CANIDM2 = 0x00; // 11111 111
CANIDM1 = 0x00;
//MOB1=TX[STA1] 向上位机报告状态组1 6,0,0,178,239,33
CANPAGE = 0x10;
CANSTMOB = (1<<TXOK);
// CANCDMOB = 0;
CANCDMOB = 0x08;
CANIDT4 = 0x08; // 00001 000
CANIDT3 = 0x79; // 01111 001 33
CANIDT2 = 0x97; // 10010 111 239
CANIDT1 = 0xc5;
// 11000 101 178
//MOB2=TX[STA2] 向上位机报告状态组2 6,0,0,179,239,33
CANPAGE = 0x20;
CANCDMOB = 0;
CANSTMOB = (1<<TXOK);
CANCDMOB = 0x08;
CANIDT4 = 0x08; // 00001 000
CANIDT3 = 0x79; // 01111 001 33
CANIDT2 = 0x9f; // 10011 111 239
CANIDT1 = 0xc5; // 11000 101 179
CANCDMOB = 0x08;
//MOB3=RX[2#servo] 7,0,0,100,101,100
CANPAGE = 0x30; //MOB3,自动增量,初值为0
CANSTMOB = 0;
CANCDMOB = 0x08;
//can2B,DLC=8
CANIDT4 = 0x20; // 00100 000
CANIDT3 = 0x2b; // 00101 011 100
CANIDT2 = 0x22; // 00100 011 101
CANIDT1 = 0xe3; // 11100 011 100
CANIDM4 = 0xfc; // 11111 100
CANIDM3 = 0xff; // 11111 111
CANIDM2 = 0xff; // 11111 111
CANIDM1 = 0x07; //CANIDM4-1数据校验屏蔽寄存器 00000 111
//MOB4=TX[2#servo] 7,0,0,101,100,100
CANPAGE = 0x40;
CANCDMOB = 0;
CANSTMOB = (1<<TXOK);
CANCDMOB = 0x08;
CANIDT4 = 0x20; // 00100 000
CANIDT3 = 0x23; // 00100 011 101
CANIDT2 = 0x2b; // 00101 011 100
CANIDT1 = 0xe3; // 11100 011 100
CANCDMOB = 0x08;
CANGIE |= ((1<<ENIT) + (1<<ENRX)); //开全局中断 和 接收中断
CANIE2 |= 0x09; //开MOB3 & MOB0信箱接收中断(接收邮箱)
CANPAGE = 0x00;
CANCDMOB |= 0x80; //MOB0接收使能
CANPAGE = 0x30;
CANCDMOB |= 0x80; //MOB3接收使能
CANGCON |= 0x02; //enable //CAN控制器启动
/*
CANGIE |= ((1<<ENIT) + (1<<ENRX));
//开全局中断 和 接收中断
CANIE2 |= 0x09; //开MOB3 & MOB0信箱接收中断(接收邮箱)
CANPAGE = 0x00;
CANCDMOB |= 0x80; //MOB0接收使能
CANPAGE = 0x30;
CANCDMOB |= 0x80;
//MOB3接收使能
CANGCON |= 0x02; //enable //CAN控制器启动
*/
/*
//-------------TCC1定时器初始化-----------------
TCCR1A = 0x00; //设置工作模式和分频因子
TCCR1B = 0x04; // T=CLK/1024 0x04=1s 0x05=4s
TCCR1C = 0x00;
TIMSK1 = 0x01; // 允许溢出中断
TCNT1 = 0x0000; //初始化计数器值,在程序中更改相应数值可以更改中断时间
*/
//-------------------ADC初始化------------------
ADCSRA = 0x8c; //使能ADC单元,单次,允许中断,16分频(1MHzADC时钟)
ADMUX = 0x40; //AVcc参考电源,右对齐,未指定输入源
// __watchdog_reset(); //喂狗
SREG = 0x80; //开全局中断
}
//CAN数据帧发送
void MOB_send (unsigned char n)
{
CANGIE &= ~(1<<ENRX);
unsigned int i;
CANPAGE = (n<<4); //MOB_n, auto increment, index 0
if (CANSTMOB & (1<<TXOK))
{
// CANCDMOB= 0x18;
CANSTMOB &= ~(1<<TXOK);
for(i = 0; i < 8; i++) CANMSG = can_data[n][i];
CANCDMOB = 0x58; //帧发送
CANGIE |=(1<<ENRX);
}
}
int main(void)
{
unsigned int pp=0;
mcu_init();
//MOB_send(1);
//MOB_send(4);
while(1)
{
pp = 60000;
while(pp){pp--;}
pp = 60000;
while(pp){pp--;}
pp = 60000;
while(pp){pp--;}
pp = 60000;
while(pp){pp--;}
//MOB_send(4);
}
}
//-----------------------------------------------------------------------------
//中断函数 接收CAN数据帧 并 存入数据单元组
//**********************************************************
SIGNAL(SIG_CAN_INTERRUPT1)
{
volatile unsigned char i = 1, num_i,jj;
CANGIE &= ~(1<<ENRX); //关接收中断****
num_i = CANSIT2;
//-----------------------------------------------------
if (num_i & (1<<SIT0))
{
i=0;
TCNT1 = 0x0000; //重启定时监视器
CANPAGE = i<<4;
for(jj = 0; jj < 8; jj++)
{
can_data[i][jj]=CANMSG; //取得8个字节的数据
}
TCNT1 = 0x0000; //重启定时监视器
}
//------------------------------------------------------
if (num_i & (1<<SIT3))
{
i=3;
CANPAGE = i<<4;
for(jj = 0; jj < 8; jj++)
{
can_data[i][num_i]=CANMSG; //取得8个字节的数据
}
TCNT1 = 0x0000; //重启定时监视器
}
//------------------------------------------------------
CANPAGE = 0x00;
CANSTMOB &= ~(1<<RXOK); //清中断标志****
CANCDMOB = 0x98; //接收使能
CANPAGE = 0x30;
CANSTMOB &= ~(1<<RXOK); //清中断标志****
CANCDMOB |= 0x98; //接收使能
CANGIE |= (1<<ENRX); //开中断
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -