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

📄 basiccan.c

📁 基于51单片机的CAN总线节点程序
💻 C
📖 第 1 页 / 共 3 页
字号:

		P0=code_led[SetSystemBuf[0]];
		P14=1;//选通第四个LED
		P15=1;
		P17=1;
    	P17=0;
		delay_ms(1);
		num--;
	}

}

//将数据分别在四个LED上显示
void transform(uint rec_buf)
{	uint temp;
	temp=rec_buf;
	SetSystemBuf[0]=temp%10;//个位
	SetSystemBuf[1]=temp/10%10;//十位
	SetSystemBuf[2]=temp/100%10;//百位
	SetSystemBuf[3]=temp/1000;//千位  
}

//表示清空0000
void display_init(void)
{
	SetSystemBuf[0]=0;//个位
	SetSystemBuf[1]=0;//十位
	SetSystemBuf[2]=0;//百位
	SetSystemBuf[3]=0;//千位	
	display_s();	
}

//表示初始化成功A-A-
void display_init_ok(void)
{
	SetSystemBuf[0]=16;//个位
	SetSystemBuf[1]=10;//十位
	SetSystemBuf[2]=16;//百位
	SetSystemBuf[3]=10;//千位	
	display_s();	
}

//表示发送数据成功H-H-
void display_Ok(void)
{
	SetSystemBuf[0]=16;//个位
	SetSystemBuf[1]=17;//十位
	SetSystemBuf[2]=16;//百位
	SetSystemBuf[3]=17;//千位	
	display_s();	
}

//表示数据发送失败E-E-
void display_Err(void)
{
	SetSystemBuf[0]=16;//个位
	SetSystemBuf[1]=14;//十位
	SetSystemBuf[2]=16;//百位
	SetSystemBuf[3]=14;//千位	
	display_s();	
}

//表示数据发送溢出F-F-
void display_flow(void)
{
	SetSystemBuf[0]=16;//个位
	SetSystemBuf[1]=15;//十位
	SetSystemBuf[2]=16;//百位
	SetSystemBuf[3]=15;//千位	
	display_s();	
}

//表示唤醒中断P-P-
void display_awake(void)
{
	SetSystemBuf[0]=16;//个位
	SetSystemBuf[1]=18;//十位
	SetSystemBuf[2]=16;//百位
	SetSystemBuf[3]=18;//千位	
	display_s();	
}



      
void main()
{	
    delay_ms(100);
    
    IT0=0;//外中断0为电平触发方式
	IT1=1;//外中断1为脉冲触发方式,后沿负跳有效
    
    TMOD=0x60;//计数器1以工作方式2工作,以TR1启动定时器
	TH1=0xFF;
	TL1=0xFF;//一次计数则中断(T1负跳变时计一次)
	TR1=1;//启动计数
		
	EX0=1;//允许外中断0中断

	EA=1;//中断总允许
    
    if(SJA_1000_Init()==0)
	{
		P16=0;//开启蜂鸣器,表示初始化成功
        display_init_ok();//表示初始化成功A-A-
		delay_ms(200);
		P16=1;//关闭蜂鸣器
	}
    else
        display_Err();//表示初始化失败E-E-

	ET1=1;//允许计数器1中断
	EX1=1;//允许外中断0中断


	//启动ADC0809
    ST=0;						//用三个ST产生一个正跳变和负跳变;
	OE=0;						 //选通ADC;
    ST=1;
    ST=0;
    	 	 
	 while(1)
     {
     	display_s();
     }	 
      	 				   
}



//该函数现实键盘扫描,去抖动,实现要求功能
void keyboard() interrupt 3 using 0
{
	static uchar num_send=0;//定义一个静态变量,并初始化为0,用于计算S1键按下的次数,即要发送的数据
	static uchar num_rate=0x0D;//用于记录S3按下的次数,从而智能的选择波特率
	static bit mode_ch=1;//用于选择操作模式,mode_ch为1表示采集电压值,为0表示用户自己设置发送数据以及波特率
	uchar key_code;//用于存储所按下的键值
	ET1=0;//关闭计数器1中断
	delay_ms(20);//去抖动,等待20ms
	if(!T1)
	{
		key_code=P1&0x0F;//读取P1口的前4位,即P10-P13

		switch(key_code)
		{
			case 0x07://按下S4的情况:用于选择操作模式,mode_ch为1表示采集电压值,为0表示用户自己设置发送数据以及波特率
				if(mode_ch)
				{
					mode_ch=0;
					display_init();//初始化输出0
					EX1=0;//关闭外中断1
					EX0=1;//开外部中断0
				}
				else
				{ 
					mode_ch=1;
					EX1=1;//开外中断1
				}
				break;
			case 0x0E://按下S1键的情况:设置发送数据,每按一次加1
				if(mode_ch==0)
				{
					EX0=0;//关闭外中断0
					num_send++;				
					transform(num_send);//将num_send转化为可以显示的十进制数,并存入SetSystemBuf中				
					display_s();
				}
				else EX1=1;//开外中断1
				break;
			case 0x0D://按下S2键的情况:将设置好的数据发送出去
				if(mode_ch==0)
				{
					send_data[0]=0x01;//标识符为0000 0001 000,十进制为8
					send_data[1]=0x01;
					send_data[2]=num_send;
					BCAN_DATA_WRITE(send_data);//将数据存放到REG_TxBuffer
					//delay_ms(100);
					BCAN_CMD_PRG(TR_CMD);//发送数据到CAN总线上,成功是否在中断判断
					num_send=0;//复位发送的数据
                	EX0=1;//开外中断0
				}
				else EX1=1;//开外中断1
				break;
			case 0x0B://按下S3键的情况:设置波特率
				if(mode_ch==0)
				{
					EX0=0;//关闭外中断0
					num_rate--;
					BCAN_ENTER_RETMODEL();//使CAN控制器进入复位工作模式
					BCAN_SET_BANDRATE(num_rate);//设置波特率
					BandRateBuf=num_rate;
					transform(band_rate[num_rate]);//将band_rate中的数据转化为可以显示的十进制数,并存入SetSystemBuf中
					display_s();
					if(!num_rate)
						num_rate=0x0D;
					BCAN_QUIT_RETMODEL();//使CAN控制器退出复位工作模式
					EX0=1;//开外中断0
				}
				else EX1=1;//开外中断1
				break;
				
			default:
				break;							
		}	
	}
	ET1=1;//开计数器中断					
}

//该中断实现接收显示,并当出现错误是给予显示:EEEE
void SJA_int() interrupt 0 using 0
{
	uchar reg_int; //存放中断寄存器的数据
	uchar rcv_buf[10];//接收数据存储
	EX0=0;//关闭外中断0
	SJA_BCANAdr=REG_INTERRUPT;//读取中断寄存器的数据
	reg_int=*SJA_BCANAdr;

	if(reg_int&0x01) //接收中断处理
	{
	 	BCAN_DATA_RECEIVE(rcv_buf);
		transform(rcv_buf[2]);//显示数据
		display_s();
		BCAN_CMD_PRG(RRB_CMD);//释放接收缓存区
	}
    else if(reg_int & 0x02)
    {
        display_Ok();//若是发送中断,则显示H-H-,表示发送成功
    }

    else if(reg_int & 0x04)
    {
        display_Err();//若是错误中断,则显示E-E-,表示有错误产生
		P16=0;//开启蜂鸣器,表示错误报警
		delay_ms(200);
		P16=1;//关闭蜂鸣器
    }

    else if(reg_int & 0x08)
    {
        display_flow();//若是数据溢出中断,则显示F-F-,表示有数据溢出中断
    }

	else
	{
		display_awake();//表示唤醒中断,显示P-P-
	}


	EX0=1;//开外中断0
}

//该函数用于接收AD上来的数据,转发到CAN总线上,并转化成LED上可以正确显示的代码
void ADC0809_Rec() interrupt 2 using 0	//外部中断1
{
	uint rec_buf;
	uchar num=10;

	EX0=0;//关闭外部中断1
	EX1=0;//关闭外部中断1

	OE=1;//输出转换得到的数据

	P0=0xFF;//这句话很重要,没有的话基本上很难正确输出电压值

	rec_buf=P0;//读取ADC传来的数据

	OE=0;

	rec_buf=rec_buf*1.0/255*5000;

	transform(rec_buf);//将rec_buf转化为可以显示的十进制数,并存入SetSystemBuf中

	while(num)														
	{
		display_s();
		num--;
	}

	send_data[0]=0x02;//标识符为0000 0010 000,十进制为16
	send_data[1]=0x02;//发送8个字节,数据帧
	send_data[2]=0;
	send_data[3]=rec_buf;
	BCAN_DATA_WRITE(send_data);//将数据存放到REG_TxBuffer
	BCAN_CMD_PRG(TR_CMD);//发送数据到CAN总线上

	//启动ADC0809
    ST=0;						//用三个ST产生一个正跳变和负跳变;
    ST=1;
    ST=0;

	EX1=1;//开外部中断1
	

}

⌨️ 快捷键说明

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