1. 主控芯片(STC89C52RC),CAN控制器(SJA1000T),CAN收发器(PCA82C250)似乎PCA82C251更好些
2. 下载对应的芯片手册,以及SJA1000独立的CAN控制器应用指南.pdf。
部分电路图:
其中需要注意的是复位单元设计,最好使用软件复位,我选择的是P2.6复位,另外SJA1000T的/INT端口需要添加上拉电阻,不然会恒为低。其他好像没啥需要特别注意的,只要按照电路图正确连接即可。下来就是编写测试代码。
过程主要参考应用指南,首先设置串口工作模式,8n1,然后设置使用定时器1,并设置工作方式2和波特率,启动定时器1,设置接收中断。然后设置外部中断优先级和中断方式(下降沿中断门),然后使能全局和外部中断,接着主要是复位SJA1000芯片,给引脚RST一个负脉冲。复位后默认是进入复位模式,但是最好还是确认芯片进入复位模式,然后输出提示信息,接着设置时钟分配寄存器,主要是设置PeliCAN模式,接收RX0还是RX1中断,设置CLKOUT输出,设置验收码寄存器和验收屏蔽寄存器,这两个结合起来来过滤数据包,判断是否需要被本节点接收,下一步配置总线定时器寄存器,设置发送频率和输出模式,确认进入自接收模式,发送数据,使用while循环等待中断到来,编译并下载到STC89C52芯片上,测试结果如下图所示:
设计源码:
/*------------------------------------------------------------------------------ HELLO.C Copyright 1995-2005 Keil Software, Inc. ------------------------------------------------------------------------------*/ #include <REG52.H> /* special function register declarations */ /* for the intended 8051 derivative */ #include <stdio.h> /* prototype declarations for I/O functions */ #include "sja1000_reg.h" /* sja1000T的寄存器定义文件*/ #include <absacc.h> /* 主要是用于寻址外部存储器*/ sbit SJARst = P2 ^ 6; //复位控制 /*------------------------------------------------ The main C function. Program execution starts here after stack initialization. ------------------------------------------------*/ void main (void) { /*------------------------------------------------ Setup the serial port for 9600 baud at 11.0592MHz. ------------------------------------------------*/ #ifndef MONITOR51 SCON = 0x50; /* SCON: mode 1, 8-bit UART, enable rcvr */ TMOD |= 0x20; /* TMOD: timer 1, mode 2, 8-bit reload */ TH1 = 0xFD; /* TH1: reload value for 9600 baud @ 11.0595MHZ */ TR1 = 1; /* TR1: timer 1 run */ TI = 1; /* TI: set TI to send first char of UART */ #endif PX0=1; //外部中断0高优先级 IT0=1; //设置INT0为下降沿中断 EX0=1; //使能INT0中断 /*------------------------------------------------ Note that an embedded program never exits (because there is no operating system to return to). It must loop and execute forever. ------------------------------------------------*/ printf ("Hello World\n"); /* Print "Hello World" */ SJA_Init();//主要是使芯片复位 /* Enter the reset Mode */ REG_MODE = 0x01; while((REG_MODE&0x01)!= 0x01); //确定进入复位模式 printf("1.Enter the Reset Mode,REG_MODE=0x%.4x\n",REG_MODE); REG_CDR = 0xc8;//设置时钟分频寄存器。CDR.7 = 1,PeliCAN模式;CDR.6(RX0激活,关闭RX1) fCLKOUT = fOSC/2, CDR.3(Close the CLKOUT) REG_RBSA = 0x00;//RX缓冲器起始地址 /*Configure acceptance code and mask register*/ REG_ACR0 = 0xff;//验收码寄存器 REG_ACR1 = 0xff; REG_ACR2 = 0xff; REG_ACR3 = 0xff; REG_AMR0 = 0xff;//验收屏蔽寄存器,接收任何标识符的数据包 REG_AMR1 = 0xff; REG_AMR2 = 0xff; REG_AMR3 = 0xff; /*configure bus timing registers*/ REG_BTR0 = 0x00; REG_BTR1 = 0x14; //100k REG_IR_ABLE = 0x01;//Peli模式中断使能,接收中断使能,发送中断禁止 REG_OCR = 0x1a;//设置输出模式:正常输出,从TX0口输出;TX1悬空 REG_MODE = 0x0c; //进入自接收模式.CDR.3(选择单个验收滤波器),CDR.2 (此模式可以检测所有节点) while(REG_MODE != 0x0c);//确定进入自接收模式下 printf("2.Enter the self-test Mode\n",REG_MODE); SJA1000_TxData();//发送数据 printf("\n\n"); //SJA1000_Rx_Display();//接收数据展示 EA = 1;//使能全局中断 while(1); } void SJA1000_TxData(void) { while(REG_SR & 0x10);//当SJA1000不处于接收状态时才可继续执行,SR.4==0x1,正在接收,等待 while(!(REG_SR & 0x08)); //SR.3=0,发送请求未处理完,等待直到SR.3=1 while(!(REG_SR & 0x04)); //SR.2=0,发送缓冲器被锁。等待直到SR.2=1 REG_TxBuffer0 = 0x08;//帧信息,标准帧,数据帧,8字节 REG_TxBuffer1 = 0xFF;//标识符1 REG_TxBuffer2 = 0xFF;//标识符2 REG_TxBuffer3 = 0x11;//发送数据位:1 REG_TxBuffer4 = 0x22;//发送数据位:2 REG_TxBuffer5 = 0x33; REG_TxBuffer6 = 0x44; REG_TxBuffer7 = 0x55; REG_TxBuffer8 = 0x66; REG_TxBuffer9 = 0x77; REG_TxBuffer10 = 0x88;//here Over SJA1000_Tx_Display(); REG_CMD = 0x10;//自接收 while(!(REG_SR & 0x08));//检测发送完毕 } /************************************************************ 函数:ex0_int 说明:中断服务程序 入口:无 返回:无 ***********************************************************/ void handle_int(void) interrupt 0 using 1 { if(REG_IR & 0x01) //产生了接收中断 { #pragma disable printf( " Received message.\n"); printf( " RBSR3 = %x \n", REG_RxBuffer3 ); printf( " RBSR4 = %x \n", REG_RxBuffer4 ); printf( " RBSR5 = %x \n", REG_RxBuffer5 ); printf( " RBSR6 = %x \n", REG_RxBuffer6 ); printf( " RBSR7 = %x \n", REG_RxBuffer7 ); printf( " RBSR8 = %x \n", REG_RxBuffer8 ); printf( " RBSR9 = %x \n", REG_RxBuffer9 ); printf( " RBSR10 = %x \n",REG_RxBuffer10); } } void SJA1000_Tx_Display(void) { printf( " TBSR3 = 0x%.4x \n", REG_TxBuffer3 ); printf( " TBSR4 = 0x%.4x \n", REG_TxBuffer4 ); printf( " TBSR5 = 0x%.4x \n", REG_TxBuffer5 ); printf( " TBSR6 = 0x%.4x \n", REG_TxBuffer6 ); printf( " TBSR7 = 0x%.4x \n", REG_TxBuffer7 ); printf( " TBSR8 = 0x%.4x \n", REG_TxBuffer8 ); printf( " TBSR9 = 0x%.4x \n", REG_TxBuffer9 ); printf( " TBSR10 = 0x%.4x \n",REG_TxBuffer10); } void SJA_Init(void) { //SJA1000复位 unsigned char i; for(i = 0;i < 125;i++); SJARst = 0; for(i = 0;i < 125;i++);//给RST引脚一个低脉冲 SJARst = 1; for(i = 0;i < 125;i++); }
sja1000_reg.h定义:
/* SJA1000的寄存器有关控制 */ #ifndef SJA1000_H #define SJA1000_H /*指定SJA1000的起始地址为0x7800*/ #define SJA_REG_BaseADD 0x7800 #define REG_MODE XBYTE[SJA_REG_BaseADD + 0x00] #define REG_CMD XBYTE[SJA_REG_BaseADD + 0x01] #define REG_SR XBYTE[SJA_REG_BaseADD + 0x02] #define REG_IR XBYTE[SJA_REG_BaseADD + 0x03] #define REG_IR_ABLE XBYTE[SJA_REG_BaseADD + 0x04] #define REG_BTR0 XBYTE[SJA_REG_BaseADD + 0x06] //05保留 #define REG_BTR1 XBYTE[SJA_REG_BaseADD + 0x07] #define REG_OCR XBYTE[SJA_REG_BaseADD + 0x08] #define REG_TEST XBYTE[SJA_REG_BaseADD + 0x09] #define REG_ALC XBYTE[SJA_REG_BaseADD + 0x0b] //0a保留 #define REG_ECC XBYTE[SJA_REG_BaseADD + 0x0c] #define REG_EMLR XBYTE[SJA_REG_BaseADD + 0x0d] #define REG_RXERR XBYTE[SJA_REG_BaseADD + 0x0e] #define REG_TXERR XBYTE[SJA_REG_BaseADD + 0x0f] #define REG_ACR0 XBYTE[SJA_REG_BaseADD + 0x10] #define REG_ACR1 XBYTE[SJA_REG_BaseADD + 0x11] #define REG_ACR2 XBYTE[SJA_REG_BaseADD + 0x12] #define REG_ACR3 XBYTE[SJA_REG_BaseADD + 0x13] #define REG_AMR0 XBYTE[SJA_REG_BaseADD + 0x14] #define REG_AMR1 XBYTE[SJA_REG_BaseADD + 0x15] #define REG_AMR2 XBYTE[SJA_REG_BaseADD + 0x16] #define REG_AMR3 XBYTE[SJA_REG_BaseADD + 0x17] /*接收缓冲区*/ #define REG_RxBuffer0 XBYTE[SJA_REG_BaseADD + 0x10] #define REG_RxBuffer1 XBYTE[SJA_REG_BaseADD + 0x11] #define REG_RxBuffer2 XBYTE[SJA_REG_BaseADD + 0x12] #define REG_RxBuffer3 XBYTE[SJA_REG_BaseADD + 0x13] #define REG_RxBuffer4 XBYTE[SJA_REG_BaseADD + 0x14] #define REG_RxBuffer5 XBYTE[SJA_REG_BaseADD + 0x15] #define REG_RxBuffer6 XBYTE[SJA_REG_BaseADD + 0x16] #define REG_RxBuffer7 XBYTE[SJA_REG_BaseADD + 0x17] #define REG_RxBuffer8 XBYTE[SJA_REG_BaseADD + 0x18] #define REG_RxBuffer9 XBYTE[SJA_REG_BaseADD + 0x19] #define REG_RxBuffer10 XBYTE[SJA_REG_BaseADD + 0x1a] #define REG_RxBuffer11 XBYTE[SJA_REG_BaseADD + 0x1b] #define REG_RxBuffer12 XBYTE[SJA_REG_BaseADD + 0x1c] /*发送缓冲区*/ #define REG_TxBuffer0 XBYTE[SJA_REG_BaseADD + 0x10] #define REG_TxBuffer1 XBYTE[SJA_REG_BaseADD + 0x11] #define REG_TxBuffer2 XBYTE[SJA_REG_BaseADD + 0x12] #define REG_TxBuffer3 XBYTE[SJA_REG_BaseADD + 0x13] #define REG_TxBuffer4 XBYTE[SJA_REG_BaseADD + 0x14] #define REG_TxBuffer5 XBYTE[SJA_REG_BaseADD + 0x15] #define REG_TxBuffer6 XBYTE[SJA_REG_BaseADD + 0x16] #define REG_TxBuffer7 XBYTE[SJA_REG_BaseADD + 0x17] #define REG_TxBuffer8 XBYTE[SJA_REG_BaseADD + 0x18] #define REG_TxBuffer9 XBYTE[SJA_REG_BaseADD + 0x19] #define REG_TxBuffer10 XBYTE[SJA_REG_BaseADD + 0x1a] #define REG_TxBuffer11 XBYTE[SJA_REG_BaseADD + 0x1b] #define REG_TxBuffer12 XBYTE[SJA_REG_BaseADD + 0x1c] #define REG_RBSA XBYTE[SJA_REG_BaseADD + 0x1e] #define REG_CDR XBYTE[SJA_REG_BaseADD + 0x1f] #define REG_Receive_Counter XBYTE[SJA_REG_BaseADD + 0x1d] void SJA_Init(void); void SJA1000_TxData(void); void handle0_int(void); void SJA1000_Tx_Display(void); #endif
原文:http://blog.csdn.net/jefbai/article/details/19697501