📄 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 + -