?? can_self.c
字號:
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//描述:
// 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>
#define uchar unsigned char
bit receive; //接收標志
uchar i,buffer[8];//串口緩沖區
uchar sbuffer;
uchar cmd_numb ;//發送緩沖區填充完成標志
uchar data TX_buffer[ N_can ] ;
void led_seg7(uchar ,uchar ) ;
/********************************系統初始化函數************************/
void initial(void)
{ uchar j;
SCON=0x50; //串口工作方式1,允許接收
PCON=0x80; //波特率翻倍
TCON=0;
TMOD=0x26; //T1用于串口波特率控制
TL1=0xfa; //初始化T1,波特率為9600(晶振11.0592M)
TH1=0xfa;
TR1=1; //開定時器
ES=1; //開串口中斷
receive = 0; //接收標志清零
cmd_numb = 0; //接受計數器清零
// P1 = 0xb0; //RS485允許接收
for(j=0; j<8; j++) //串口緩沖區清空
buffer[j] = 0xff; //table[18]為空顯示
// cash[0] = 15;
//CPU初始化
SJA_RST = 1;//CAN總線復位管腳,復位無效
SJA_CS = 0;//CAN總線片選有效
IT1 = 0;//CAN總線低電平接收中斷
// IT0 = 1;//外部中斷0負邊沿觸發
// EX0 = 1;//打開外部中斷0
EX1 = 1; // 打開外部中斷1
EA = 1; //打開總中斷
SJA_CS = 1;//CAN總線片選無效,使對數據總線的操作不會影響SJA1000。
//CPU初始化
//初始化標示碼頭信息
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] = 0xff;
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;//
//初始化數據信息
}
/*****************************串口中斷響應處理函數***********************/
void serial(void) interrupt 4
{ uchar k;
if(RI)//為接收中斷
{
RI=0; //清接收中斷標志
LED_RED= ~LED_RED; //閃串口指示LED
sbuffer = SBUF; //讀取串口緩沖區數據
if((sbuffer == 's') && (receive == 0)) //判斷是否為數據頭 ,是數據頭則準備接收
{
receive = 1; //開始接收標志
cmd_numb = 0; //清接收計數器
TXD_flag = 0; //清接收完成標志
}
else if(sbuffer == 'e') //判斷數據尾
{
if(cmd_numb<8)//接收到的字符少于8個
for(k=cmd_numb;k<8;k++)//則空位填空顯示
buffer[k] = 0;
TXD_flag = 1; //置接收完成標志
receive =0; //清接收標志
}
else if(receive){ //判斷當前是否處于接收狀態
buffer[cmd_numb++] = sbuffer; //當前字符送緩沖區
Txd_data=cmd_numb ;
}
else //無效命令則返回
return;
}
}
void CAN_RXD( void ) interrupt 2 //接收數據函數,在中斷服務程序中調用
{
uchar data Judge;
EA = 0; //關CPU中斷
// IE0 = 0; //禁止INT0
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)
{
initial( );//串口初始化
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)
{//////// CAN接收處理程序//////////////
if( RXD_flag ) //RXD_flag=0說明無數據可以接收,RXD_flag=1說明有數據可以接收
{ uchar i ;
// EA = 0; //關閉CPU中斷
EX1=0;
RXD_flag = 0; //RXD_flag清零,以便下次查詢
for(i=0;i<8;i++)
{ LED_GRE=~LED_GRE;
TI=0;
SBUF = RX_buffer[i+5]; //CAN總線要接收的數據,也是要在數碼管3-4位置顯示的數據
while(!TI);
}
EX1 = 1;
// TI=1;
}
}//////// 接收處理程序//////////////
void Txd_deal(void) //CAN發送處理函數,主要是準備數據,并且調用發送函數
{
if( TXD_flag )
{
_nop_();
TXD_flag = 0;
TX_buffer[5] = buffer[0];//
TX_buffer[6] = buffer[1];
TX_buffer[7] = buffer[2];
TX_buffer[8] = buffer[3];
TX_buffer[9] = buffer[4];
TX_buffer[10] = buffer[5];
TX_buffer[11] = buffer[6];
TX_buffer[12] = buffer[7];
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;
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 = 0x01;//置位自發送接收請求
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結束
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -