//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//描述:
// INT0按键程序+显示程序+CAN自收发程序 &
// 数码管1-2(从右至左)显示本节点计数结果,数码管3-4显示接收到的数据 &
// 十进制显示 &
// CAN主要参数: PeliCAN模式,扩展帧EFF模式 &
// 29位标示码结构: &
// 发送数据结构:计数结果,0x02,0x03,0x04,0x05,0x06,0x07,0x08 &
// 接收数据结构: 待显示数据+其它7个字节的数据 &
// 本节点的地址: 0x11,0x22,0x33,0x00;可以接收全部节点的数据 &
// 目的节点地址:0x01,0x02,0x03,0x00;可以被能接收全部节点数据的节点接收 &
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//【声明】 此程序仅用于学习与参考,引用请注明版权和作者信息! &
//【声明】 作者: PIAE小组 &
#include <reg52.h>
#include <intrins.h>
#include <can_selfdef.h>
void INT0_Counter( void ) interrupt 0 using 1
{//INT0按键为计数按键
EA = 0;
Txd_data++; //存储计数结果,并为待发送的数据
TXD_flag = 1;//要发送数据标志位
EA = 1;
}
void CAN_RXD( void ) interrupt 2
{//接收数据函数,在中断服务程序中调用
uchar data Judge;
EA = 0;//关CPU中断
IE0 = 0;
Judge = IR;
if( Judge & 0x01)
{//IR.0 = 1 接收中断
RX_buffer[0] = RBSR;
RX_buffer[1] = RBSR1;
RX_buffer[2] = RBSR2;
RX_buffer[3] = RBSR3;
RX_buffer[4] = RBSR4;
RX_buffer[5] = RBSR5;
RX_buffer[6] = RBSR6;
RX_buffer[7] = RBSR7;
RX_buffer[8] = RBSR8;
RX_buffer[9] = RBSR9;
RX_buffer[10] = RBSR10;
RX_buffer[11] = RBSR11;
RX_buffer[12] = RBSR12;
RXD_flag = 1;//置有接收标志
CMR = 0X04;
Judge = ALC;//释放仲裁随时捕捉寄存器
Judge = ECC;//释放错误代码捕捉寄存器
}
IER = 0x01;// .0=1--接收中断使能;
EA = 1;//打开CPU中断
}
void main(void)
{
//CPU初始化
SJA_RST = 1;//CAN总线复位管脚,复位无效
SJA_CS = 0;//CAN总线片选有效
EX1 = 1;
IT1 = 0;//CAN总线接收中断
IT0 = 1;//外部中断0负边沿触发
EX0 = 1;//打开外部中断0
EA = 1; //打开总中断
SJA_CS = 1;//CAN总线片选无效,使对数据总线的操作不会影响SJA1000。
//CPU初始化
CAN_init( ); //SJA1000初始化,对 SJA1000寄存器的读写是采用外部寄存器寻址方式,所以不需要程序单独控制片选有效无效
_nop_();
_nop_();
while(1)
{
_nop_();
_nop_();
Rxd_deal();//接收处理程序
Txd_deal();//发送处理程序
led_seg7(1,Txd_data);
led_seg7(3,Rxd_data);
}
}
//*********************处理函数********************************
void Rxd_deal(void)
{//////// 接收处理程序//////////////
if( RXD_flag )
{
EA = 0;//关闭CPU中断
RXD_flag = 0;
Rxd_data = RX_buffer[5];
EA = 1;
}
}//////// 接收处理程序//////////////
void Txd_deal(void)
{//发送处理函数,主要是准备数据,并且调用发送函数
if( TXD_flag == 1 )
{
_nop_();
TXD_flag = 0;
TX_buffer[5] = Txd_data;//
CAN_TXD();
_nop_();
_nop_();
}
}
//*********************处理函数********************************
//*********************CAN子函数***********************
void CAN_init( void )
{//SJA1000 的初始化
uchar bdata Judge;
uchar ACRR[4];
uchar AMRR[4];
ACRR[0] = 0x11;
ACRR[1] = 0x22;
ACRR[2] = 0x33;
ACRR[3] = 0x44;//接收代码寄存器,节点1
AMRR[0] = 0xff;
AMRR[1] = 0Xff;
AMRR[2] = 0xff;
AMRR[3] = 0xff;//接收屏蔽寄存器。 只接收主机发送的信息
do
{// .0=1---reset MODRe,进入复位模式,以便设置相应的寄存器
//防止未进入复位模式,重复写入
MODR = 0x09;
Judge = MODR ;
}
while( !(Judge & 0x01) );
CDR = 0x88;// CDR.3=1--时钟关闭, .7=0---basic CAN, .7=1---Peli CAN
BTR0 = 0x31;
BTR1 = 0x1c;//总线波特率设定
IER = 0x01;// .0=1--接收中断使能; .1=0--关闭发送中断使能
OCR = 0xaa;// 配置输出控制寄存器
CMR = 0x04;//释放接收缓冲器
ACR = ACRR[0];
ACR1 = ACRR[1];
ACR2 = ACRR[2];
ACR3 = ACRR[3];//初始化标示码
AMR = AMRR[0];
AMR1 = AMRR[1];
AMR2 = AMRR[2];
AMR3 = AMRR[3];//初始化掩码
do
{//确保进入自接收模式
MODR = 0x04;
Judge = MODR;
}
while( !(Judge & 0x04) );
}//SJA1000 的初始化
void CAN_TXD( void )
{
uchar data Judge;
uchar data TX_buffer[ N_can ] ;
//初始化标示码头信息
TX_buffer[0] = 0x88;//.7=0扩展帧;.6=0数据帧; .3=1数据长度
TX_buffer[1] = 0x01;//本节点地址
TX_buffer[2] = 0x02;//
TX_buffer[3] = 0x03;//
TX_buffer[4] = 0x00;//
//初始化标示码头信息
//初始化发送数据单元
TX_buffer[5] = Txd_data;
TX_buffer[6] = 0x22;
TX_buffer[7] = 0x33;
TX_buffer[8] = 0x44;//
TX_buffer[9] = 0x55;//
TX_buffer[10] = 0x66;//
TX_buffer[11] = 0x77;//
TX_buffer[12] = 0x88;//
//初始化数据信息
EA = 0; //关中断
do
{
Judge = SR;
LED_RED = 0;//
}
while( Judge & 0x10 ); //SR.4=1 正在接收,等待
do
{
Judge = SR;
LED_RED = 0;//
}
while(!(Judge & 0x08)); //SR.3=0,发送请求未处理完,等待
do
{
Judge = SR;
LED_RED = 0;//
}
while(!(Judge & 0x04)); //SR.2=0,发送缓冲器被锁。等待
LED_RED = !LED_RED;
LED_GRE = !LED_GRE;//灯闪烁
TBSR = TX_buffer[0];
TBSR1 = TX_buffer[1];
TBSR2 = TX_buffer[2];
TBSR3 = TX_buffer[3];
TBSR4 = TX_buffer[4];
TBSR5 = TX_buffer[5];
TBSR6 = TX_buffer[6];
TBSR7 = TX_buffer[7];
TBSR8 = TX_buffer[8];
TBSR9 = TX_buffer[9];
TBSR10 = TX_buffer[10];
TBSR11 = TX_buffer[11];
TBSR12 = TX_buffer[12];
CMR = 0x10;//置位自发送接收请求
EA = 1;
}
void Delay(uchar delay_time)
{//延时程序
while(delay_time--)
{}
}
//*********************CAN子函数*************************
void led_seg7(uchar from,uchar number) //from(1_4):数码管显示起始位置(从右到左),number:显示的数
{
uchar digit,temp_l;
uchar temp_h=0x7f;
temp_h = _cror_(temp_h,from-1); //确定从哪一位开始显示,即确定高四位
temp_h = temp_h & 0xf0; //取高四位
temp_l = P2 & 0x0f; //取P2的低四位
P2 = temp_h | temp_l; //设定P2口
if(number==0)
{
P0 = led[0];
Delay(5);
P0 = 0xff;
}
else
{
while(number)
{
digit = number%10 ;
number /= 10;
P0 = led[digit] ;
Delay(5);
temp_h = P2 & 0xf0; //取P2的高四位
temp_h = temp_h | 0x0f; //拼装 temp_h,进行位选
temp_h = _cror_(temp_h,1);
temp_h = temp_h & 0xf0; //取高四位
temp_l = P2 & 0x0f; //取P2的低四位
P0 = 0xff;
P2 = temp_h | temp_l; //设定P2口
}//while结束
}//else结束
}
|