⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can.c

📁 8052控制SJA1000的CAN总线通信程序
💻 C
字号:
//------------------------------------------------------------
//		
//		CAN总线通信测试程序
//
//		主控制芯片	:	AT89C52,12MHZ晶振   
//		CAN控制芯片	:	SJA1000,16MHZ晶振   
//
//------------------------------------------------------------

//------------------------------------------------------------
//头文件
#include <reg52.h>
#include <absacc.h>
#include "CAN.h"

//------------------------------------------------------------
//常量定义
#define		TIMER0_1S	50
#define		T0_L		0xb0
#define		T0_H		0x3c
#define		YES			1				
#define		NOT			0

//------------------------------------------------------------
//变量定义
unsigned char Timer0_counter;
unsigned char CAN_TX_buffer[8] = {0x00,0xff,0x55,0xaa,0x00,0xff,0x55,0xaa};
unsigned char CAN_RX_buffer[10] = {0,0,0,0,0,0,0,0,0,0};

bit UART_transmit_flag;
bit CAN_ERROR_flag;

//------------------------------------------------------------
//函数预定义
void Interrupt_ini(void);
void CAN_ini(void);
void CAN_Transmit(void);
void Timer0_ini(void);
void UART_ini(void);
void UART_transmit(void) ;
void Delay(unsigned char m);

//------------------------------------------------------------
//		函数:		主函数
//		入口参数:	无	
//		返回值	:	无
//		函数说明:	定时器控制,每1S中向CAN总线发送一个报文
//					接收到报文后,把接收到的数通过RS232串口
//					发送到计算机
//
//------------------------------------------------------------
void main(void)
{
	Delay(100);								//延时,等待系统稳定	
	
	UART_transmit_flag = NOT;
	CAN_ERROR_flag = NOT;    

	EA = 0;
	Timer0_ini();
	UART_ini();
	CAN_ini();
	Interrupt_ini();
	EA = 1;

	for (;;)
	{
		if (Timer0_counter >= TIMER0_1S)	//到达1S,启动CAN发送
		{
			Timer0_counter = 0;
			CAN_Transmit();

		}

		if (UART_transmit_flag == YES)		//串口发送
		{
			UART_transmit_flag = NOT;
			UART_transmit();
		}

		if (CAN_ERROR_flag == YES)			//CAN总线错误或异常
		{
			CAN_ERROR_flag = NOT;
			CAN_ini();
		}
	}
}
//------------------------------------------------------------
//		函数:		外部中断0初始化函数
//		入口参数:	无
//		返回值	:	无
//		函数说明:  下降沿触发,用于得到CAN总线中断
//------------------------------------------------------------
void Interrupt_ini(void)
{	
	IT0 = 1;
	EX0 = 1;
}
//------------------------------------------------------------
//		函数:		CAN初始化函数
//		入口参数:	无
//		返回值	:	无
//		函数说明:	为了保证操作的准确性,需要在函数运行时禁止
//					中断
//------------------------------------------------------------

void CAN_ini(void)
{
	EA = 0;								//关全局中断
	Delay(1);
	
	do									//进入复位请求
	{
		CONTROL_REG = 0x01;
	}
	while(!((CONTROL_REG&0x01) == 0x01));


	CDR_REG = 0x08;						//Basic CAN模式,使用输入比较器,clk_out关闭
	ACR_REG = 0x11;
	AMR_REG = 0x00;
	BTR0_REG = 0x01;					//400kbps,sjw = 1,BTL cycle = 10,sam = 3
	BTR0_REG = 0xa5;
	OCR_REG = 0xaa;						//normal output
	CONTROL_REG |= 0x1a;				//溢出,出错,接收中断使能
	
	//退出复位状态
	do
	{
		CONTROL_REG &= ~0x01;
	}
	while((CONTROL_REG&0x01) == 0x01);	//退出复位模式
	
	EA = 1;
}

//------------------------------------------------------------
//		函数:		CAN接收中断函数
//		入口参数:	无
//		返回值	:	无
//		函数说明:  使用单片机的外部中断0
//------------------------------------------------------------
void CAN_INT(void) interrupt 0 using 1
{
	unsigned char interrupt_reg;
	unsigned char can_status;

	EA = 0;

	interrupt_reg = INTERRUPT_REG;
	if ((interrupt_reg&0x01) == 0x01)			//接收中断么?
	{
		do
		{
			can_status = STATUS_REG;
			CAN_RX_buffer[0] = Rx_ID_0_REG;		
			CAN_RX_buffer[1] = Rx_ID_1_REG;	
			CAN_RX_buffer[2] = Rx_Data_1_REG;
			CAN_RX_buffer[3] = Rx_Data_2_REG;
			CAN_RX_buffer[4] = Rx_Data_3_REG;
			CAN_RX_buffer[5] = Rx_ID_0_REG;		
			CAN_RX_buffer[6] = Rx_ID_1_REG;	 
			CAN_RX_buffer[7] = Rx_Data_1_REG;
			CAN_RX_buffer[8] = Rx_Data_2_REG;
			CAN_RX_buffer[9] = Rx_Data_2_REG;

			COMMAND_REG |= Release_Rx_buf;		//释放接收缓冲区
		}
		while ((can_status&0x01) == 0x01);		//接收缓冲区不空则继续接收

		UART_transmit_flag = YES;
	}
	else
	{
		CAN_ERROR_flag = YES;					//CAN总线出错
	}

	EA = 1;	
}

//------------------------------------------------------------
//		函数:		CAN总线发送函数
//		入口参数:	无
//		返回值	:	无
//		函数说明:	发送一个CAN报文
//------------------------------------------------------------
void CAN_Transmit(void)
{
	unsigned char can_status;
	

	do									
	{
		can_status = STATUS_REG;
	}
	while ((can_status&0x04) != 0x04);		//发送缓冲区空么?

	Tx_ID_0_REG	=  CAN_TX_buffer[0];	
	Tx_ID_1_REG	=  CAN_TX_buffer[1];
	Tx_Data_1_REG =	CAN_TX_buffer[0];
	Tx_Data_2_REG =	CAN_TX_buffer[1];
	Tx_Data_3_REG =	CAN_TX_buffer[2];
	Tx_Data_4_REG =	CAN_TX_buffer[3];
	Tx_Data_5_REG =	CAN_TX_buffer[4];
	Tx_Data_6_REG =	CAN_TX_buffer[5];
	Tx_Data_7_REG =	CAN_TX_buffer[6];
	Tx_Data_8_REG =	CAN_TX_buffer[7];

	COMMAND_REG |= Tx_Request;				//启动发送请求
}


//------------------------------------------------------------
//		函数:		定时器0初始化
//		入口参数:	无
//		返回值	:	无
//		函数说明:	50mS定时中断设置,定时器0,方式1
//------------------------------------------------------------
void Timer0_ini(void)
{
	TMOD = 0x01;		  
	TL0 = T0_L;					  
	TH0 = T0_H;					  
	ET0 = 1;
	TCON = 0x10;	
}

//------------------------------------------------------------
//		函数:		定时器0中断服务函数
//		入口参数:	无
//		返回值	:	无
//		函数说明:	50ms中断一次
//------------------------------------------------------------
void Timer0_INT(void) interrupt 1 using 1
{
	Timer0_counter += 1;
	TL0 = T0_L;
	TH0 = T0_H;
}

//------------------------------------------------------------
//		函数:		串口初始化
//		入口参数:	无
//		返回值	:	无
//		函数说明:	波特率9600
//------------------------------------------------------------
void UART_ini(void)
{
	SCON = 0x50;		//方式1,8bits,接受允许,无校验位
	PCON = 0x80;		//SMOD = 1
	TMOD = 0x20;		//timer1 mode 2
	TL1 = 0xe8;			//				     f
	TH1 = 0xe8;			//	波特率=---------------------
						//			32*2^smod*12*(256-TL1)
	TCON = 0x40;		//start
	ES = 1;				//串行中断使能
}

//------------------------------------------------------------
//		函数:		串口发送函数
//		入口参数:	无
//		返回值	:	无
//		函数说明:	,查询方式发送,把接收到的CAN报文发送到计算机
//------------------------------------------------------------
void UART_transmit(void) 
{
	unsigned char i;
	for ( i=0; i<11; i++)
	{
		SBUF = CAN_RX_buffer[i];	
		while (TI == 0)		//等待发送完毕
		{
		}
	}				
}

//------------------------------------------------------------
//		函数:		串口接收中断函数
//		入口参数:	无
//		返回值	:	无
//		函数说明:	本实例未使用,留作扩展
//------------------------------------------------------------
void Rx_INT(void) interrupt 4 using 3
{
	unsigned char temp;
	RI = 0;
	temp = SBUF;			
}

//------------------------------------------------------------
//		函数:		延时子函数
//		入口参数:	延时常数
//		返回值	:	无
//		函数说明:	软件延时,不要求精确
//------------------------------------------------------------
void Delay(unsigned char m)
{
	unsigned char i;
	unsigned int j;

	for( i = 0; i < m; i++)
	{
		for( j = 0; j < 3000; j++)
		{
			
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -