当前位置:文档之家› can总线通信程序

can总线通信程序

CAN总线通信程序// CAN <==> UART的协议转换器// 说明:// 1,单片机使用P89C61X2BA// --晶振11.0592MHZ// --CAN总线中断使用单片机的中断0,外部有上拉电阻,波特率可以设定// 2,CAN总线发送采用查询方式,接收采用中断方式// 3,看门狗复位时间1.2S// 4,SJA1000晶振8MHZ,Peil模式// 5,串口中断接收,查询发送,波特率可设置// 6,×××当串口收到数据后,每8个数一组打包,通过CAN总线发送出去//// -----10.16日,重新修改程序完成以下功能-----// ----此功能已经改为,每收到一帧数据,启动一次CAN传输,传输字节数等于串口收到的数据// ----串行帧的帧间界定通过当前波特率下传输5个字节为时间间隔,具体为当顺序接收到的任意两个数据,它们之间的时间间隔大于5个字节传送时间,认为这两个数据分属于两个不同的帧// 7,当CAN总线每接收一帧信息后,通过串口发送出去// 改为可以识别CAN的报文字节长度,即串口只发送CAN报文长度个字节// 8,看门狗芯片MAX1232CPA,硬件溢出时间1.2S////-------------------------------------------------------#include#include#include#include "CANCOM.h"unsigned char UART_TX_Data[8] = {0,1,2,3,4,5,6,7};unsigned char CAN_TX_Data[8] = {0,1,2,3,4,5,6,7};unsigned char xdata UART_RX_Data[255]; //串口接收到的串行帧unsigned char xdata CAN_TX_Data[255]; //待发送的数据缓冲区unsigned char code ACR_ID[4] = {0,0,0,0}; //CAN初始设置验收滤波值unsigned char code AMR_ID[4] = {0xff,0xff,0xff,0xff};unsigned char CAN_TX_ID[4] = {0,0,0,0}; //待发送的目标的ID unsigned char CAN_RX_ID[4] = {0,0,0,0}; //接收到的信息来自何ID unsigned char CAN_RX_Data[8] = {7,6,5,4,3,2,1,0}; //接受到的数据缓冲unsigned char code CAN_BTR0[10] ={0xdf,0xcf,0xc7,0xc3,0x43,0xc1,0xc1,0 xc0,0xc0,0x80};unsigned char code CAN_BTR1[10] = {0x7f,0x7f,0x7f,0x7f,0x2f,0x7f,0x4d,0 x3e,0x3a,0x23};// 5K 10K 20K 40K 50K 80K 100K 200K 250K 500Kunsigned char code UART_BTR[4] = {0xe8,0xf4,0xfa};// 1.2K,2.4K,4.8Kunsigned char CAN_flag; //CAN发送标志位unsigned char UART_flag; //unsigned char CAN_ERROR_flag = NOT; //unsigned char CAN_DataLength = 8; //CAN信息的报文长度unsigned char UART_DataLength = 0; //串口接收时的当前指示unsigned char UART_Length = 0; //串口接收区的长度指示//sbit AAA = P1^4;void main(void){EA = 0;System_init(); //系统初始化Timer_init(); //定时器初始化Interrupt_init(); //中断UART_ini();CAN_init();Delay(1);W_WDT();EA = 1;//Delay(1);//UART_Length = 8;//CAN_Transmit(0);//UART_Transmit();while (1){W_WDT();if (CAN_flag == YES){CAN_flag = NOT;CAN_Transmit(0);LED1 = !LED1;}else{CAN_flag = NOT;}/*if (UART_flag == YES){UART_flag = NOT;//Delay(50);UART_Transmit();//Clear_Buffer(CAN_RX_Data,8); //LED3 = !LED3;}else{UART_flag = NOT;}*/if ((CAN_ERROR_flag == YES)){CAN_ERROR_flag = NOT;CAN_init();}else{CAN_ERROR_flag = NOT;}}}//---------------------------// 功能:系统设置// --外部数据存储区访问使能// --LED指示灯关(1=on,0=off)// --流程控制标志置为无效NOT// --清空串口,CAN的相关数据缓冲区//---------------------------void System_init(void){CKCON = 0x00; //Fosc devide 12AUXR = 0x00;//0x02; //EXM enableLED1 = 0; //LED0-3 off 指示灯,共阴接法,1时亮 LED2 = 0;LED3 = 0;LED4 = 0;WDT = 1; //WDT iniCAN_DataLength = 8;UART_DataLength = 0;UART_Length = 0;CAN_flag = NOT;CAN_ERROR_flag = NOT;//UART_flag = NOT;Clear_Buffer(UART_RX_Data,255); Clear_Buffer(CAN_TX_Data,255);Clear_Buffer(CAN_TX_ID,4);Clear_Buffer(CAN_RX_ID,4);Clear_Buffer(CAN_RX_Data,8);/*CAN_flag = YES;UART_flag = YES;*/}//-----------------------------//// 软件延时(非精确)// ----内置清看门狗定时器子函数// 防止多次调用延时过长导致// 看门狗复位////-----------------------------void Delay(unsigned char time){unsigned char i;unsigned int j;for (i = 0;i < time;i++){W_WDT();for (j=0;j<30000;j++){}}}//---------------------------------// 串行口初始化设置// 方式1,8数据位,一个停止位,无奇偶校验// 串口中断允许//------------------------------------void UART_ini(void){SCON = 0x50; //方式1,波特率可变,8bits,接受允许PCON&= 0x7F; //SMOD = 0TMOD |= 0x20; //timer1 mode 2TL1 = UART_BTR[2]; //| f//| 波特率=----------------------TH1 = UART_BTR[2]; //| 32*2^smod*12*(256-TL1) TCON |= 0x40; //startTI = 0;}//-----------------------------------------------//// 看门狗“喂狗”程序,WDT的一个下降沿触发一次////-----------------------------------------------void W_WDT(void) //triggle WDT{unsigned char i;WDT = 1;for (i=0;i<10;i++){}WDT = 0;}//---------------------------------------------------//// 中断初始化//// ----外部中断0有效,下降沿触发,用于SJA1000产生CAN事件中断// ----定时器中断,用于判定串口接收的顺序两个字节是否分属两帧// ----串口中断,RX使用中断,TX未使用// ----中断优先级暂时未设定////---------------------------------------------------void Interrupt_init(void){//IP = 0x00;IT0 = 0x01; //外部0中断沿触发ET0 = 1; //定时器0中断使能EX0 = 1; //外部中断使能ES = 1; //串行中断使能}//---------------------------------------------------//// 定时中断程序//// 一旦中断,说明一帧的接收已经结束,开始启动CAN发送程序// 把串口接收到的数据准备好给CAN总线发送// RX_buffer ===> CAN_TX_buffer////---------------------------------------------------void Timer0_ISR(void) interrupt 1 using 2{static unsigned char i;//unsigned char counter;//TH0 = temp_TH0;//TL0 = temp_TL0;/*counter += 1;if (counter == 20) //到1S了么?{//UART_flag = YES;}if (counter == 40) //到2S了么?{//CAN_flag = YES;counter = 0;}*///AAA = !AAA;TR0 = 0; //定时器关,开始次CAN信息传送for (i=0;i{CAN_TX_Data[i] = UART_RX_Data[i];}UART_Length = UART_DataLength;UART_DataLength = 0;CAN_flag = YES;}//--------------------------------------------------------------- //// 串口中断服务程序//// ----只有接收使用// ----每收一个数重新初始化定时器////----------------------------------------------------------------void RX_INT(void) interrupt 4 using 3{static unsigned char n;if (RI==1){do{RI = 0;}while (RI != 0);//UART_RX_Data[UART_DataLength++] = SBUF;n = SBUF;UART_Send_Byte(n);TH0 = temp_TH0;TL0 = temp_TL0;TR0 = 1; //启动数据间隔定时,判断是否分属两帧}else{//TX}}//--------------------------------------------------------------- //// 串口发送单字节程序////---------------------------------------------------------------- void UART_Send_Byte(unsigned char Data){SBUF = Data;while (TI == 0) //等待发送完毕{}TI = 0;}//--------------------------------------------------------------- //// 初始化定时器程序//// ----定时器0方式1,定时器1方式2留给串口////---------------------------------------------------------------- void Timer_init(void){TMOD |= 0x01; //使用定时器0-方式1TH0 = temp_TH0;TL0 = temp_TL0;//TR0 = 1; //这里不打开定时器}void CAN_init(void){EA = 0;MOD_CAN1 |= 0x08; //单滤波方式do{MOD_CAN1 |= 0x01; //request to reset mode }while ((MOD_CAN1&0x01) != 0x01);CDR_CAN1 = 0xc8; //选择PeliCAN模式,使用输入比较器,clk_out关闭 IER_CAN1 = 0x01; //允许发送中断,其他中断禁能ACR0_CAN1 = ACR_ID[0];ACR1_CAN1 = ACR_ID[1];ACR2_CAN1 = ACR_ID[2];ACR3_CAN1 = ACR_ID[3];AMR0_CAN1 = AMR_ID[0];AMR1_CAN1 = AMR_ID[1];AMR2_CAN1 = AMR_ID[2];AMR3_CAN1 = AMR_ID[3];//ECC_CAN1 = 0;//TXERR_CAN1 = 0;//RBSA_CAN1 = 0;BTR0_CAN1 = CAN_BTR0[0];BTR1_CAN1 = CAN_BTR1[0];OCR_CAN1 = 0xaa; //normal outputW_WDT();do{MOD_CAN1 &= 0xfe;}while ((MOD_CAN1&0x01) != 0x00);EA = 1;}//-----------------------------------//// 串口发送一帧接受到的CAN数据//// ----长度1-8,根据接收到的CAN信息来确定////-----------------------------------void UART_Transmit(void) //using 0unsigned char i;LED3 = !LED3;for (i=0;i{UART_Send_Byte(CAN_RX_Data[i]);}}//-----------------------------------//// CAN发送接受到的一帧串口数据//// ----最大长度255,根据接收到的串口信息的// 个数来确定// ----按每依次8个数据作为一个CAN帧的报文部分// 不足8个或超过8的倍数的部分按实际个数作// 为CAN报文// ----FarmeType = 1为扩展帧,FarmeType = 0为// 标准帧//-----------------------------------void CAN_Transmit(bit FarmeType){unsigned char i;unsigned char m;unsigned char can_status;unsigned char xdata *pointer;if (FarmeType == 0) //标准帧{for (m=0;m<(UART_Length/8);m++)W_WDT();do //发送缓冲区空么?{can_status = SR_CAN1;}while ((can_status&0x04) != 0x04);TXFrameInfo1 = 0x00 + 0x08;pointer = &TXID1;for (i=0;i<2;i++){*(pointer++) = CAN_TX_ID[i];}pointer = &TXID3;for (i=0;i<8;i++){*(pointer++) = CAN_TX_Data[i+8*m];}CMR_CAN1 = Request_TX;W_WDT();}if ((UART_Length%8) != 0){W_WDT();do //发送缓冲区空么?{can_status = SR_CAN1;}while ((can_status&0x04) != 0x04);TXFrameInfo1 = 0x00 + UART_Length%8;pointer = &TXID1;for (i=0;i<2;i++){*(pointer++) = CAN_TX_ID[i];}pointer = &TXID3;for (i=0;i<(UART_Length%8);i++){*(pointer++) = CAN_TX_Data[i+8*(UART_Length/8)]; }CMR_CAN1 = Request_TX;W_WDT();}else{}}else //扩展帧{for (m=0;m<(UART_Length/8);m++){W_WDT();do //发送缓冲区空么?{can_status = SR_CAN1;}while ((can_status&0x04) != 0x04);TXFrameInfo1 = 0x80 + 0x08;pointer = &TXID1;for (i=0;i<4;i++){*(pointer++) = CAN_TX_ID[i];}pointer = &TXDATA1;for (i=0;i<8;i++){*(pointer++) = CAN_TX_Data[i+8*m];}CMR_CAN1 = Request_TX;W_WDT();}if ((UART_Length%8) != 0){W_WDT();do //发送缓冲区空么?{can_status = SR_CAN1;}while ((can_status&0x04) != 0x04);TXFrameInfo1 = 0x80 + UART_Length%8;pointer = &TXID1;for (i=0;i<4;i++){*(pointer++) = CAN_TX_ID[i];}pointer = &TXDATA1;for (i=0;i<(UART_Length%8);i++){*(pointer++) = CAN_TX_Data[i+8*(UART_Length/8)]; }CMR_CAN1 = Request_TX;W_WDT();}else{}}UART_Length = 0;}//-----------------------------------//// CAN接收中断服务程序//// ----判断是否是RX中断,如果是// 把接受到的CAN信息通过串行口发送出去// ----其他的中断说明CAN总线出现错误或脱离////-----------------------------------void CAN_ISR(void) interrupt 0 using 1{unsigned char can_int;EA = 0;can_int = IR_CAN1;if ((can_int&0x01) == 0x01) //接收中断{CAN_Receive();CMR_CAN1 |= ReleaseRXBuf;}else{CAN_ERROR_flag = YES; //其他中断,暂时未用 }//UART_flag = YES;//CAN_flag = YES;UART_Transmit();EA = 1;}//-----------------------------------//// CAN接收数据函数//// ----根据接受到的帧信息,按不同的长度存储// 报文数据////-----------------------------------void CAN_Receive(void) using 1{unsigned char i;unsigned char xdata *pointer;unsigned char Info;Info = RXFrameInfo1;if ((Info&0x80) == 0) //standard Frame {//CAN_RX_ID[0] = RXID1;//CAN_RX_ID[1] = RXID2;CAN_DataLength = Info&0x0f;pointer = &RXID3;for (i=0;i{CAN_RX_Data[i] = *(pointer++);}for (;i<8;i++){CAN_RX_Data[i] = 0x00;}}else //Ex Frame{//CAN_RX_ID[0] = RXID1;//CAN_RX_ID[1] = RXID2;//CAN_RX_ID[2] = RXID3;//CAN_RX_ID[3] = RXID4;CAN_DataLength = Info&0x0f;pointer = &RXDATA1;for (i=0;i{CAN_RX_Data[i] = *(pointer++);//pointer += 1;}for (;i<8;i++){CAN_RX_Data[i] = 0x00;}}}//-----------------------------------//// 清0缓冲区//// ----pointer,指向待清0 的缓冲区首地址// ----length 清0 的长度//-----------------------------------void Clear_Buffer(unsigned char *pointer,unsigned char length) {unsigned char i;for (i=0;i{*(pointer++) = 0x00;}}另外头文件为:#ifndef _CANCOM_H#define _CANCOM_H#define CS1_SJA1000 0x7f00 //SJA1000 Pin /CS ----> P2.7,low le vel active#define MOD_CAN1 XBYTE[CS1_SJA1000+0] //Peli#define CMR_CAN1 XBYTE[CS1_SJA1000+1] //command#define SR_CAN1 XBYTE[CS1_SJA1000+2] //state#define IR_CAN1 XBYTE[CS1_SJA1000+3] //interrupt#define IER_CAN1 XBYTE[CS1_SJA1000+4] //interrupt enable //Peli#define BTR0_CAN1 XBYTE[CS1_SJA1000+6] //bus timing0#define BTR1_CAN1 XBYTE[CS1_SJA1000+7] //bus timing1#define OCR_CAN1 XBYTE[CS1_SJA1000+8]#define TEST_CAN1 XBYTE[CS1_SJA1000+9]#define ECC_CAN1 XBYTE[CS1_SJA1000+12] //error catch#define EWLR_CAN1 XBYTE[CS1_SJA1000+13] //error warning limit#define RXERR_CAN1 XBYTE[CS1_SJA1000+14] //#define TXERR_CAN1 XBYTE[CS1_SJA1000+15]#define ACR0_CAN1 XBYTE[CS1_SJA1000+16]#define ACR1_CAN1 XBYTE[CS1_SJA1000+17]#define ACR2_CAN1 XBYTE[CS1_SJA1000+18]#define ACR3_CAN1 XBYTE[CS1_SJA1000+19]#define AMR0_CAN1 XBYTE[CS1_SJA1000+20]#define AMR1_CAN1 XBYTE[CS1_SJA1000+21]#define AMR2_CAN1 XBYTE[CS1_SJA1000+22]#define AMR3_CAN1 XBYTE[CS1_SJA1000+23]#define RBSA_CAN1 XBYTE[CS1_SJA1000+30] //beginning of receive #define CDR_CAN1 XBYTE[CS1_SJA1000+31] //clock devide #define TXFrameInfo1 XBYTE[CS1_SJA1000+16]#define TXID1 XBYTE[CS1_SJA1000+17]#define TXID2 XBYTE[CS1_SJA1000+18]#define TXID3 XBYTE[CS1_SJA1000+19]#define TXID4 XBYTE[CS1_SJA1000+20]#define TXDATA1 XBYTE[CS1_SJA1000+21]#define TXDATA2 XBYTE[CS1_SJA1000+22]#define TXDATA3 XBYTE[CS1_SJA1000+23]#define TXDATA4 XBYTE[CS1_SJA1000+24]#define TXDATA5 XBYTE[CS1_SJA1000+25]#define TXDATA6 XBYTE[CS1_SJA1000+26]#define TXDATA7 XBYTE[CS1_SJA1000+27]#define TXDATA8 XBYTE[CS1_SJA1000+28]#define RXFrameInfo1 XBYTE[CS1_SJA1000+16]#define RXID1 XBYTE[CS1_SJA1000+17]#define RXID2 XBYTE[CS1_SJA1000+18]#define RXID3 XBYTE[CS1_SJA1000+19]#define RXID4 XBYTE[CS1_SJA1000+20]#define RXDATA1 XBYTE[CS1_SJA1000+21]#define RXDATA2 XBYTE[CS1_SJA1000+22]#define RXDATA3 XBYTE[CS1_SJA1000+23]#define RXDATA4 XBYTE[CS1_SJA1000+24]#define RXDATA5 XBYTE[CS1_SJA1000+25]#define RXDATA6 XBYTE[CS1_SJA1000+26]#define RXDATA7 XBYTE[CS1_SJA1000+27]#define RXDATA8 XBYTE[CS1_SJA1000+28]#define GoToRESET 0x01#define ReleaseRXBuf 0x04#define Request_TX 0x01#define NOT 0#define YES 1//4800bps 5bits 1.04mS#define TIME_MS 1#define temp_TH0 (0 - 922*TIME_MS)/256#define temp_TL0 (0 - 922*TIME_MS)%256sbit LED1 = P1^2;sbit LED2 = P1^3;sbit LED3 = P1^5;sbit LED4 = P1^4;sbit WDT = P3^4;void System_init(void);void Delay(unsigned char time);void W_WDT(void);void Interrupt_init(void);void CAN_init(void);//void CAN_Transmit(unsigned char Farmeinfo);void CAN_Transmit(bit FarmeType);void CAN_Receive(void);void Timer_init(void);void UART_ini(void);void UART_Send_Byte(unsigned char Data);void UART_Transmit(void);void Clear_Buffer(unsigned char *pointer,unsigned char length);#endif。

相关主题