讨论一下mega162实现can通信!(附电路图及程序)
我参考LOVEMCU及其他人的资料,自己搭建了电路来实现162的can通信,实现了can的自发自收,因为我是用面包板实现的,电路不稳定,而且我搭建好两个一样的电路实现不了正常通信,希望大家看看,提点建议,谢谢!注意:测试版我没有使用6n137!
另外,我是让记时时间到发送,实验中如果不加CanTransmit();电路稳定,灯也闪烁正常,一加就不稳定了.
点击此处下载armok01163521.rar
点击此处下载armok01163522.rar
大家帮忙啊!先谢谢!
-----此内容被tauther435于2007-07-26,11:23:47编辑过 自己顶一下,怎么各位大虾都潜水啊!!
哈哈!qq:12933745,欢迎讨论! #ifndef can_h
#define can_h
#define startadd 0x7F00 //SJA1000的首地址
#define FALSE 0
#define TRUE 1
//#define unsigned char unsigned char
//#define unsigned int uint
#define CanID 0x88
#define MODE 0x00 //模式寄存器
#define CMR 0x01 //命令寄存器
#define SR 0x02 //状态寄存器
#define IR 0x03 //中断寄存器
#define IER 0x04 //中断使能寄存器
#define BTR0 0x06 //总线时序寄存器0
#define BTR1 0x07 //总线时序寄存器1
#define OCR 0x08 //输出控制寄存器
#define TEST 0x09
#define ALC 0x0B //仲裁丢失捕捉寄存器
#define ECC 0x0C //错误代码捕捉寄存器
#define EWLR 0x0D //错误报警限额寄存器
#define RXERR 0x0E //RX错误计数寄存器
#define TXERR 0x0F //TX错误计数寄存器
#define ACR0 0x10 //验收代码寄存器
#define ACR1 0x11
#define ACR2 0x12
#define ACR3 0x13
#define AMR0 0x14 //验收屏障寄存器
#define AMR1 0x15
#define AMR2 0x16
#define AMR3 0x17
///////////////////////////
#define TXEFF 0x10
#define TXID0 0x11
#define TXID1 0x12
#define TXID2 0x13
#define TXID3 0x14
#define RXEFF 0x10
#define RXID0 0x11
#define RXID1 0x12
#define RXID2 0x13
#define RXID3 0x14
#define TXDATA0 0x15
#define TXDATA1 0x16
#define TXDATA2 0x17
#define TXDATA3 0x18
#define TXDATA4 0x19
#define TXDATA5 0x1A
#define TXDATA6 0x1B
#define TXDATA7 0x1C
#define RXDATA0 0x15
#define RXDATA1 0x16
#define RXDATA2 0x17
#define RXDATA3 0x18
#define RXDATA4 0x19
#define RXDATA5 0x1A
#define RXDATA6 0x1B
#define RXDATA7 0x1C
//////////////////////////
#define RMC 0x1D
//RX报文计数器
#define RBSA 0x1E
//RX缓冲器起始地址寄存器
#define CDR 0x1F
//时钟分频寄存器
//////////////////////////////////////////////////////////////////////
unsigned char read_sja(unsigned char addr); //读SJA1000状态寄存器子程序
void write_sja(unsigned char addr,unsigned char val); //写SJA1000控制寄存器子程序
unsigned char SJATestInterface(unsigned char testvalue);
unsigned char SJAEntryResetMode(void);
unsigned char SJAQuitResetMode(void);
unsigned char SJATestRstMode(void);
unsigned char SJASetOutControl(unsigned char OutCtrl);
unsigned char SJASetClockDivision(unsigned char clockdiv);
unsigned char SJASetAccCode(unsigned char acr0, unsigned char acr1, unsigned char acr2, unsigned char acr3);
unsigned char SJASetAccMask(unsigned char amr0, unsigned char amr1, unsigned char amr2, unsigned char amr3);
unsigned char SJASetBaudRateStandard(unsigned char BaudRateSize);
unsigned char SJASetOtherReg(void);
unsigned char SJASetIER(unsigned char value);
void SJAWriteDataToTxBuf(unsigned char Num, unsigned char Data);
void Init_CAN(void);
void CanTransmit(void);
unsigned char CanReceive(void);
#endif #include "can.h"
#include "macros.h"
extern unsigned char TX_Buffer;
extern unsigned char RX_Buffer;
unsigned char read_sja(unsigned char addr) //读SJA1000状态寄存器子程序
{
unsigned char *sja_address = (unsigned char *)startadd;
sja_address = sja_address + addr;
return (*(sja_address));
}
void write_sja(unsigned char addr,unsigned char val) //写SJA1000控制寄存器子程序
{
unsigned char *sja_address = (unsigned char *)startadd;
sja_address = sja_address + addr;
*(sja_address) = val;
}
unsigned char SJATestInterface(unsigned char testvalue)
{
unsigned char Err_Cnt = 0x20;
unsigned char Err_Flag = TRUE;
while(--Err_Cnt)
{
write_sja(TEST, testvalue);
if(read_sja(TEST) == testvalue)
{
Err_Flag = FALSE;
break;
}
}
return Err_Flag;
}
unsigned char SJAEntryResetMode(void)
{
unsigned char Err_Cnt = 0x20;
unsigned char Err_Flag = TRUE;
while(--Err_Cnt)
{
write_sja(MODE, 0x09);
if((read_sja(MODE) & 0x01) == 0x01)
{
Err_Flag = FALSE;
break;
}
}
return Err_Flag;
}
unsigned char SJAQuitResetMode(void)
{
unsigned char Err_Cnt = 0x20;
unsigned char Err_Flag = TRUE;
while(--Err_Cnt)
{
write_sja(MODE, 0x00);
if(read_sja(MODE) == 0x00)
{
Err_Flag = FALSE;
break;
}
}
return Err_Flag;
}
unsigned char SJATestRstMode(void)
{
unsigned char SjaFlag;
if((read_sja(MODE) & 0x01) == 0x01)
{
SjaFlag = FALSE;
}
else
SjaFlag = TRUE;//工作模式下返回TRUE
return SjaFlag;
}
unsigned char SJASetOutControl(unsigned char OutCtrl)
{
unsigned char Err_Cnt = 0x20;
unsigned char Err_Flag = TRUE;
if(SJATestRstMode())
{
Err_Flag = TRUE;
}
else
{
while(--Err_Cnt)
{
write_sja(OCR, OutCtrl);
if(read_sja(OCR) == OutCtrl)
{
Err_Flag = FALSE;
break;
}
}
}
return Err_Flag;
}
unsigned char SJASetAccCode(unsigned char acr0, unsigned char acr1, unsigned char acr2, unsigned char acr3)
{
unsigned char Err_Cnt = 0x20;
unsigned char Err_Flag = TRUE;
if(SJATestRstMode())
{
Err_Flag = TRUE;
}
else
{
while(--Err_Cnt)
{
write_sja(ACR0, acr0);
if(read_sja(ACR0) != acr0)
{
continue;
}
Err_Cnt = 0x20;
write_sja(ACR1, acr1);
if(read_sja(ACR1) != acr1)
{
continue;
}
Err_Cnt = 0x20;
write_sja(ACR2, acr2);
if(read_sja(ACR2) != acr2)
{
continue;
}
Err_Cnt = 0x20;
write_sja(ACR3, acr3);
if(read_sja(ACR3) != acr3)
{
continue;
}
Err_Flag = FALSE;
break;
}
}
return Err_Flag;
}
unsigned char SJASetClockDivision(unsigned char clockdiv)
{
unsigned char Err_Cnt = 0x20;
unsigned char Err_Flag = TRUE;
if(SJATestRstMode())
{
Err_Flag = TRUE;
}
else
{
while(--Err_Cnt)
{
write_sja(CDR, clockdiv);
if(read_sja(CDR) == clockdiv)
{
Err_Flag = FALSE;
break;
}
}
}
return Err_Flag;
}
unsigned char SJASetAccMask(unsigned char amr0, unsigned char amr1, unsigned char amr2, unsigned char amr3)
{
unsigned char Err_Cnt = 0x20;
unsigned char Err_Flag = TRUE;
if(SJATestRstMode())
{
Err_Flag = TRUE;
}
else
{
while(--Err_Cnt)
{
write_sja(AMR0, amr0);
if(read_sja(AMR0) != amr0)
{
continue;
}
Err_Cnt = 0x20;
write_sja(AMR1, amr1);
if(read_sja(AMR1) != amr1)
{
continue;
}
Err_Cnt = 0x20;
write_sja(AMR2, amr2);
if(read_sja(AMR2) != amr2)
{
continue;
}
Err_Cnt = 0x20;
write_sja(AMR3, amr3);
if(read_sja(AMR3) != amr3)
{
continue;
}
Err_Flag = FALSE;
break;
}
}
return Err_Flag;
}
//16MHZ
unsigned char SJA_BTR_CODETAB[] = {
0x53, 0x2F, //20KBPS 0
0x87, 0xFF, //40KBPS 1
0x47, 0x2F, //50KBPS 2
0x83, 0xFF, //80KBPS 3
0x43, 0x2F, //100KBPS 4
0x03, 0x1C, //125KBPS 5
0x81, 0xFA, //200KBPS 6
0x01, 0x1C, //250KBPS 7
0x80, 0xFA, //400KBPS 8
0x00, 0x1C, //500KBPS 9
0x80, 0xB6, //666KBPS 10
0x00, 0x16, //800KBPS 11
0x00, 0x14 //1000KBPS12
};
unsigned char SJASetBaudRateStandard(unsigned char BaudRateSize)
{
unsigned char Err_Cnt = 0x20;
unsigned char Err_Flag = TRUE;
if(BaudRateSize > 12)
{
Err_Flag = TRUE;
}
else
{
while(--Err_Cnt)
{
write_sja(BTR0, SJA_BTR_CODETAB);
if(read_sja(BTR0) != SJA_BTR_CODETAB)
{
continue;
}
Err_Cnt = 0x20;
write_sja(BTR1, SJA_BTR_CODETAB);
if(read_sja(BTR1) != SJA_BTR_CODETAB)
{
continue;
}
Err_Flag = FALSE;
break;
}
}
return Err_Flag;
}
/*void SJAWriteDataToTxBuf(unsigned char Num, unsigned char Data)
{
switch(Num)
{
case 0:
TX_Buffer = Data;
break;
case 1:
TX_Buffer = Data;
break;
case 2:
TX_Buffer = Data;
break;
case 3:
TX_Buffer = Data;
break;
case 4:
TX_Buffer = Data;
break;
case 5:
TX_Buffer = Data;
break;
case 6:
TX_Buffer = Data;
break;
case 7:
TX_Buffer = Data;
break;
case 8:
TX_Buffer = Data;
break;
case 9:
TX_Buffer = Data;
break;
case 10:
TX_Buffer = Data;
break;
case 11:
TX_Buffer = Data;
break;
case 12:
TX_Buffer = Data;
break;
}
}*/
unsigned char SJASetOtherReg(void)
{
unsigned char Err_Cnt = 0x20;
unsigned char Err_Flag = TRUE;
if(SJATestRstMode())
{
Err_Flag = TRUE;
}
else
{
while(--Err_Cnt)
{
write_sja(RXERR,0x00);
if(read_sja(RXERR) != 0x00)
{
continue;
}
Err_Cnt = 0x20;
write_sja(TXERR,0x00);;
if(read_sja(TXERR) != 0x00)
{
continue;
}
Err_Cnt = 0x20;
write_sja(ECC,0x00);
if(read_sja(ECC) != 0x00)
{
continue;
}
Err_Cnt = 0x20;
write_sja(RBSA,0x00);;
if(read_sja(RBSA) != 0x00)
{
continue;
}
Err_Flag = FALSE;
break;
}
}
return Err_Flag;
}
unsigned char SJASetIER(unsigned char value)
{
unsigned char Err_Cnt = 0x20;
unsigned char Err_Flag = TRUE;
/*if(SJATestRstMode())
{
Err_Flag = TRUE;
}
else*/
//{
while(--Err_Cnt)
{
write_sja(IER, value);
if(read_sja(IER) == value)
{
Err_Flag = FALSE;
break;
}
}
//}
return Err_Flag;
}
/*************************************************
SJA1000初始化子函数
*************************************************/
void Init_CAN(void)
{
unsigned char temp;
unsigned int k ;
CLI();
do
{
temp = SJATestInterface(0x55);
}while(temp);//检查硬件连线
WDR();
for(k=0;k<6;k++); //延时约5us
do
{
temp = SJAEntryResetMode();
}while(temp);
WDR();
read_sja(IR);//clear IR
for(k=0;k<6;k++); //延时约5us
WDR();
if(!SJATestRstMode())
{
do
{
temp = SJASetClockDivision(0xC8);
}while(temp);
WDR();
for(k=0;k<6;k++); //延时约5us
do
{
temp = SJASetOutControl(0x1a);
}while(temp);
WDR();
for(k=0;k<6;k++); //延时约5us
do
{
temp = SJASetBaudRateStandard(2);
}while(temp);
WDR();
for(k=0;k<6;k++); //延时约5us
do
{
temp = SJASetAccCode(0x00, 0x00, 0x00, 0x00);
}while(temp);
WDR();
for(k=0;k<6;k++); //延时约5us
do
{
temp = SJASetAccMask(0xFF, 0xFF, 0xFF, 0xFF);
}while(temp);
WDR();
for(k=0;k<6;k++); //延时约5us
do
{
temp = SJASetOtherReg();
}while(temp);
WDR();
for(k=0;k<6;k++); //延时约5us
do
{
temp = SJAQuitResetMode();
}while(temp);
WDR();
for(k=0;k<6;k++); //延时约5us
do
{
temp = SJASetIER(0x01);
}while(temp);
}
write_sja(CMR,0x0c); //清除数据溢出和释放接收缓冲器;
for(k=0;k<6;k++); //延时约5us
WDR();
do
{
write_sja(MODE, 0x0C);
}while((read_sja(MODE) & 0x01));
/*WDR();
for(k=0;k<6;k++); //延时约5us
if(SJATestRstMode())
{
do
{
temp = SJASetIER(0x01);
}while(temp);
}*/
SEI();
}
/*************************************************
SJA1000发送子函数
*************************************************/
void CanTransmit(void)
{
unsigned char status;
CLI(); //关中断
//实际用时对SJAWriteDataToTxBuf();的调用在个检测模块中
/*SJAWriteDataToTxBuf(0, 0x88);
SJAWriteDataToTxBuf(1, 0x00);
SJAWriteDataToTxBuf(2, 0x00);
SJAWriteDataToTxBuf(3, 0x00);
SJAWriteDataToTxBuf(4, 0x00);
SJAWriteDataToTxBuf(5, 0x01);
SJAWriteDataToTxBuf(6, 0x02);
SJAWriteDataToTxBuf(7, 0x03);
SJAWriteDataToTxBuf(8, 0x04);
SJAWriteDataToTxBuf(9, 0x05);
SJAWriteDataToTxBuf(10, 0x06);
SJAWriteDataToTxBuf(11, 0x07);
SJAWriteDataToTxBuf(12, 0xaa);*/
TX_Buffer=0x88;
TX_Buffer=0x00;
TX_Buffer=0x00;
TX_Buffer=0x00;
TX_Buffer=0x00;
TX_Buffer=0x01;
TX_Buffer=0x02;
TX_Buffer=0x03;
TX_Buffer=0x04;
TX_Buffer=0x05;
TX_Buffer=0x06;
TX_Buffer=0x07;
TX_Buffer=0xaa;
while(!(read_sja(SR)&0x04));//wait until reg2^2==1 ,即判断发送缓冲器的状态
write_sja(TXEFF,TX_Buffer); //扩展帧,数据长度为8个字节
write_sja(TXID0,TX_Buffer);
write_sja(TXID1,TX_Buffer);
write_sja(TXID2,TX_Buffer);
write_sja(TXID3,TX_Buffer);
write_sja(TXDATA0,TX_Buffer);
write_sja(TXDATA1,TX_Buffer);
write_sja(TXDATA2,TX_Buffer);
write_sja(TXDATA3,TX_Buffer);
write_sja(TXDATA4,TX_Buffer);
write_sja(TXDATA5,TX_Buffer);
write_sja(TXDATA6,TX_Buffer);
write_sja(TXDATA7,TX_Buffer);
write_sja(CMR,0x10); //发送请求命令
while(!(read_sja(SR) & 0x08));//检测SR.3位,判断发送是否完成
//SEI(); //开中断
}
unsigned char CanReceive(void)
{
unsigned char result = FALSE;
unsigned char status,number,i,sff;
unsigned char prbuf;
status = read_sja(SR);
prbuf = RXEFF;
if((status&0xc3) != 0) //读取总线脱离、错误状态、接收溢出、有数据等位
{
if((status&0x80) == 0x80)
{
write_sja(MODE, 0x00);
return FALSE;
}
if((status&0x02) == 0x02)
{
write_sja(CMR, 0x0c);
return FALSE;
}
if((status&0x01) == 0x01)
{
if((read_sja(RXEFF) & 0x40) == 0x40)//如果RTR=1,为远程帧
{
write_sja(CMR, 0x04); //则释放FXFIFO
}
else //为0,则是数据帧
{
sff = read_sja(prbuf) & 0x80; //取第一个字节的最高位
number = (read_sja(prbuf) & 0x0f);//取第一个字节的低四位,即数据长度
if((sff & 0x80) == 0x80) //判断是标准帧还是扩展帧
number = number + 5; //扩展帧,则帧的总长度加5(13字节)
else
number = number + 3; //标准帧,则帧的总长度加3(11字节)
for(i = 0; i < number; i++) //读取数据
{
RX_Buffer=read_sja(prbuf);
prbuf++;
}
result = TRUE; //读取到正确的数据则返回TRUE
write_sja(CMR, 0x04); //最后释放FXFIFO
}
}
}
return result;
} //ICC-AVR application builder : 2007-7-21 15:11:59
// Target : M162
// Crystal: 16.000Mhz
#include <iom162v.h>
#include <macros.h>
#include "can.h"
unsigned char TX_Buffer;
unsigned char RX_Buffer;
unsigned char timer_ok;
unsigned char timer_count;
unsigned char RevFlag;
unsigned int count;
/**********************************************************
软延时
**********************************************************/
void delay_1ms(void)
{
unsigned int k;
for(k = 0; k < (16*142 - 2); k++) // 定时1ms公式:xtal*142-2
;
}
void Delay(unsigned int n)
{
unsigned int p;
for(p = 0; p < n; p++)
{
delay_1ms();
}
}
void port_init(void)
{
PORTA = 0x00;
DDRA= 0xFF;
PORTB = 0xF0;
DDRB= 0x00;
PORTC = 0x7F;
DDRC= 0xFF;
PORTD = 0x04;
DDRD= 0xFA;
PORTE = 0x07;
DDRE= 0x07;
}
//Watchdog initialisation
// prescale: 2048K cycles
void watchdog_init(void)
{
WDR(); //this prevents a timout on enabling
WDTCR= 0x0F; //WATCHDOG ENABLED - dont forget to issue WDRs
}
//TIMER1 initialisation - prescale:256
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 50Hz
// actual value: 50.000Hz (0.0%)
void timer1_init(void)
{
TCCR1B= 0x00; //stop
TCNT1H= 0xFB; //setup
TCNT1L= 0x1E;
//OCR1AH= 0x04;
//OCR1AL= 0xE2;
//OCR1BH= 0x04;
//OCR1BL= 0xE2;
TCCR1A= 0x00;
TCCR1B= 0x04; //start Timer
}
#pragma interrupt_handler timer1_ovf_isr:16
void timer1_ovf_isr(void)
{
//TIMER1 has overflowed
TCNT1H= 0xFB; //reload counter high value
TCNT1L= 0x1E; //reload counter low value
timer_ok = 1;
count++;
if(count == 30)
{
count = 0;
PORTD ^= (1<<PD4); //程序在运行
}
}
/*
//TIMER0 initialisation - prescale:256
// WGM: Normal
// desired value: 1000Hz
// actual value: 1008.065Hz (0.8%)
void timer0_init(void)
{
TCCR0= 0x00; //stop
TCNT0= 0xFE; //set count
OCR0= 0x3E; //set compare value
TCCR0= 0x04; //start timer
TIMSK = 0x02;
}
#pragma interrupt_handler timer0_ovf_isr:18
void timer0_ovf_isr(void)
{
TCNT0= 0xFE; //reload counter value
timer_ok = 1;
count++;
if(count == 1)
{
count = 0;
PORTD ^= (1<<PD4); //程序在运行
}
}*/
#pragma interrupt_handler int0_isr:2
void int0_isr(void)
{
unsigned char reg;
unsigned char CompCount;
unsigned char can_status;
CLI(); //关CPU中断
RevFlag = 1;
reg = read_sja(IER); //保存SJA1000的中断允许状态
write_sja(IER, 0x00); //重设中断允许状态为不允许任何中断
can_status = CanReceive(); //接收消息
if(can_status == 0x01)
{
for(CompCount = 5; CompCount < 13; CompCount++) //检查接收到的数据是否正确
{
if(RX_Buffer != TX_Buffer)
{
RevFlag = 0; //发现有不一致时,则清0标志位
}
}
}
else
Init_CAN(); //如果不是正确接收,则重新初始化
write_sja(IER, reg); //重新写回中断允许模式
SEI();
}
// **Section not found**
//call this routine to initialise all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
watchdog_init();
//timer1_init();
MCUCR = 0x82;
EMCUCR = 0x00;
//GIMSK= 0x00;
TIMSK = 0x80; //timer interrupt sources
//ETIMSK = 0x00;
//GICR = 0x40;
//PCMSK0 = 0x00;
//PCMSK1 = 0x00;
SEI(); //re-enable interrupts
//all peripherals are now initialised
}
void main(void)
{
init_devices();
WDR();
Init_CAN(); //CAN初始化
WDR();
//Delay(1000);
WDR();
timer1_init();
WDR();
while(1)
{
PORTD |= (1<<PD1);//初始化成功
WDR();
if(timer_ok == 1)
{
timer_ok = 0;
timer_count++;
if(timer_count == 90)
{
timer_count = 0;
//CLI();
TCCR1B = 0x00;
CanTransmit(); //发送数据
WDR();
//while(!(read_sja(SR) & 0x08));
PORTD ^= (1<<PD3);
TCCR1B = 0x04;
SEI();
}
}
WDR();
if(RevFlag == 1) //如果正确接收到数据
{
RevFlag = 0;
PORTD ^= (1<<PD5);
//write_sja(CMR, 0x04); //最后释放FXFIFO
}
}
} 各位仁兄,麻烦看看,不知道为什么,一发送就死掉!难道电路有问题? 点击此处打开armok01163530.doc 怎么没有人顶啊!哎 今天在电脑里加了一块双路pci can卡,直接接canh,canl,但是接收不到啊
哪位帮我看看,提提建议啊 我这里有USB 双路CAN卡分析仪,才398.00.
http://www.ucore.com.cn/ucore_CAN.htm#uSBCAN-S 谢谢楼上的
我已调试通过 162的CAN程序,第一次见到。。。 学习一下. 学习 MARK mark 楼主辛苦了,看看!
页:
[1]