日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

sja1000调试经验

發布時間:2024/3/12 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 sja1000调试经验 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

sja1000調試經驗

去年年底的時候,一個公司給我打電話,問我最近有沒有空,說要請我幫忙做一個基于CAN總

這里寫代碼片線通訊的東西,我去看了看,是一個數據采集系統,下面是一系列數據采集的智能板卡,上位機是

基于WINBOND的一塊486的工業嵌入式控制板,操作系統使用的是WINCE。智能板卡通過工業底板和數據線兩種方式和上位機通訊,通信協議選擇的是CAN,其中底板上的通信選用高速波特率(1Mbps),數據線選用低速(100kbps)。
去公司的時候,公司給了我一個參考的東西,采用SST單片機+SJA1000的方案構成的智能板卡

,同時告訴我可以自己設計方案。考慮到SST的東西沒有用過,P8X591是PLCC封裝的,燒寫起來不

方便,于是我設計了如下的方案:
1、智能板卡上的通訊采用AT89S51+兩塊SJA1000的方式進行;
2、上位機通過PC104總線和一塊CAN控制板卡連接,CAN控制板卡上同樣采用AT89S51+兩塊

SJA1000的方案。AT89S51和上位機通過PC104總線共享內存(使用IDT的雙口RAM);
3、采用西門子的組態軟件進行WINCE下的板卡驅動開發;
由于以前沒有做過CAN的東西,于是決定了先調試CAN通信,然后設計板卡的方案。
方案確定之后,首先是上www.zlgmcu.com上下載了全部的SJA1000和PCA82C250的資料。然后開

始設計電路板。采用了SJA1000應用指南中推薦的方案,采用SJA1000的時鐘輸出為AT89S51的時鐘

,沒有采用光電隔離芯片,把TX1接地,TX0和RX0分別連接到PCA82C250的TXD和RXD引腳上,RX1連

接到PCA82C250的VR上;加上了5歐姆的限流電阻和120歐姆的匹配電阻(用110歐姆替代),另外加上

了一個調試用的串口。沒有注意而且要命的是把SJA1000的復位引腳和單片機的復位引腳連接到了

一起。
第一次的板子用的加急,用了三天,結果那次的板子做的極差——連銅皮都翻起來了;我馬上

讓那個電路板廠重新做了三塊。在做板的過程中我發現了復位引腳的錯誤,SJA1000的文檔上提供的

是一個復位電路,但是沒有給出電路的詳細組成,于是我就誤以為和單片機的復位電路是一樣的了

。在設計這塊電路板的時候,最擔心的事情就是SJA1000的輸出時鐘能不能夠驅動AT89S51,如果不

能夠驅動,那么一切就OVER了,可惜的是我的擔心成為了現實,板子焊好之后系統不工作,在

SJA1000的時鐘輸入引腳上有信號輸入,而且輸出時鐘也正常,但是單片機就是不工作。于是我先

把SJA1000的復位引腳連線割斷,連接到了AT89S51的IO引腳上,再把S51的XTAL的兩個引腳連接到

SJA晶體的上,可惜系統還是不工作,這次電路板設計失敗了。
在總結了第一次失敗的經驗后,參看了21IC上的一個設計,決定把AT89S51和SJA的晶體分開。

并且用單片機的一個IO引腳來控制對SJA的復位。
第二次的電路板比較成功,焊接好了之后首先測試單片機的串口和LED指示燈,一切OK。然后

就開始測試SJA。ZLG提供了一個BASIC模式下的參考例程,我看了一下,然后又找了本《現場總線

CAN的原理和測試》把SJA的寄存器詳細看了看(由于開始的時候比較忙,所以直到這個時候才算是

仔細看了看SJA的內部,至于CAN的基礎協議我是根本沒有看,這給我后面帶來了極大的麻煩)。然

后就參考ZLG的程序開始寫SJA的測試程序,那個程序寫的很大,也很全,因為我想快點把東西給做

出來,于是弄了一個1000多行的程序,以前我的調試程序一般都很小的。寫好程序之后就開始測試

,首先測試的是測試寄存器,然后一步步測試下去,在BASIC模式下所有的寄存器都正常,但是在

發送的時候是總是不正常,啟動發送之后就一直在發送,狀態寄存器的標志位一直處在發送的狀態

下,然后就是報總線錯誤,不知道是怎么會事情,很郁悶,上bbs看了一下。bullfrog告訴我單個

CAN節點發送是成功不了的,如果沒有收到接受CAN節點的應答,發送節點就會一直發送,直到超出

錯誤計數器的允許值使得總線關閉。同時在精華區發現在peli模式下有ECC(錯誤寄存器),可以跟

蹤錯誤,于是開始看peli模式操作過程。這個東西比較麻煩,zlg沒有提供公開的c代碼,我找了一

個匯編的作為參考。
我第一步的目標是自發送,在peli模式下有自發送這種模式,在有匹配電阻的情況下可以進行

單個節點的接收和發送。第一次調試的時候沒有成功,給北京zlg打電話,北京分公司說讓我給廣

州打電話,給廣州打電話,幾個問題都得到了很好的解答(在此謝謝zlg的工程師了):
1、自發送的時候必須加上匹配電阻;
2、5歐的限流電阻可以不需要;
3、每次發送完成之后
4、建議使用中止發送來進行單步發送;
另外他告訴我可以在zlg的論壇上找到很多很有用的東西。
聽了他的建議,我第一件事情就是檢查我的電路板,檢查的結果讓我大吃一驚——我的ch和cl

竟然是短路的,萬用表的狂叫不止。一步步檢查,發現那個110歐的匹配電阻有問題,萬用表碰上

去就叫,于是把那個電阻剪下來,量量還是短路。于是我懷疑把5歐的限流電阻當成了110歐的電阻

,于是把匹配電阻都去掉了。沒有想到的是當我把新的110歐電阻拿來的時候,萬用表還是叫,這

時候才發現這塊萬用表在300歐姆以下都要叫,可憐我又打理了n長時間的電路板……
再仔細閱讀了一次peli模式下的操作指南,又仔細閱讀了zlg提供的初始化規范,發現在子發

送的時候發送的命令應該是0x10或者是0x12(即CMR寄存器里面有一個專門的控制位是用來控制自發

送的,和普通的發送命令位是不同的)。在發現了這個問題之后,自發送一切順利的通過了。
接下來就是兩個節點的互調了,我首先用自發送程序把兩個節點都調試了一下,保證單個節點

發送硬件沒有任何問題。然后就用雙絞線通過接線端子把兩個系統連接到了一起。第一次調試采用

的是1M的波特率(由于ZLG只給出了16M晶體下的BTR0和BTR1的初始值,我在ZLG的論壇上找到了一個

網友自己計算的數值,后來證明這個東西有些問題),沒有成功。發送節點通過串口利用串口調試助

手來控制發送,接收節點通過仿真器觀察數據。雖然沒有發送成功,但是通過串口的反饋數據和仿

真器的觀察窗,可以看到ECC寄存器都發生了變化,證明數據線上有數據過去(由于我沒有示波器,

只有采用這種辦法)。于是我改變了兩次波特率,最低到了5k,都沒有成功,最后我從21IC上的一

篇應用文章上找到了兩個參數,這次就成功了,通訊速率20k。現在一切穩定,在寫這篇文章的時

候哪幾個LED正歡快的閃爍著。
最后,總結幾個經驗:
1、一定要詳細的閱讀sja的手冊和CAN的相關知識;
2、SJA的復位是低電平,而且不是用一個非們把單片機的RST反相就可以的,有兩種解決方式

:第一種是使用單片機的IO引腳來控制SJA的復位引腳,好處是單片機完全控制SJA的復位過程;第

二種是采用適當的復位芯片,ZLG給我推薦的是CAT1161,我沒有用過,其好處是同步復位。
3、在自發送的模式下,需要匹配電阻,而且自發送的啟動命令和普通發送的啟動命令不相同


4、BRT0和BRT1的選擇,和串口通信中只要兩個的誤差一樣就可以了不同,一定要精心選擇,

建議SJA的外部晶體選擇16M的,這樣有利于參考ZLG的標準數值
5、SJA和其他外部器件連接的時候,數據線在373前后都可以;
6、最好有一個示波器;
7、不要太大意的相信萬用表的蜂鳴器;
8、這是從ZLG網站上轉載過來的peli模式下的初始化流程
a)檢測硬件連接是否正確
b)進入復位狀態
c)設置時鐘分頻寄存器
d)設置輸出控制寄存器
e)設置通訊波特率
f)設置代碼驗收寄存器
g)設置代碼屏蔽寄存器
h)退出復位狀態
i)設置工作模式
j)設置中斷使能寄存器

這是一個自發收程序,采用at89s51+sja1000,分離晶體,at89s51晶體11.0592
sja1000外部晶體為12M,通過串口進行監控


以下為頭文件定義
copyright by alloy


#define SJA_REG_BaseADD 0x7800#define REG_MODE XBYTE[SJA_REG_BaseADD + 0x00] #define REG_CMD XBYTE[SJA_REG_BaseADD + 0x01] #define REG_SR XBYTE[SJA_REG_BaseADD + 0x02] #define REG_IR XBYTE[SJA_REG_BaseADD + 0x03] #define REG_IR_ABLE XBYTE[SJA_REG_BaseADD + 0x04] #define REG_BTR0 XBYTE[SJA_REG_BaseADD + 0x06] //05保留 #define REG_BTR1 XBYTE[SJA_REG_BaseADD + 0x07] #define REG_OCR XBYTE[SJA_REG_BaseADD + 0x08] #define REG_TEST XBYTE[SJA_REG_BaseADD + 0x09] #define REG_ALC XBYTE[SJA_REG_BaseADD + 0x0b] //0a保留 #define REG_ECC XBYTE[SJA_REG_BaseADD + 0x0c] #define REG_EMLR XBYTE[SJA_REG_BaseADD + 0x0d] #define REG_RXERR XBYTE[SJA_REG_BaseADD + 0x0e] #define REG_TXERR XBYTE[SJA_REG_BaseADD + 0x0f]#define REG_ACR0 XBYTE[SJA_REG_BaseADD + 0x10] #define REG_ACR1 XBYTE[SJA_REG_BaseADD + 0x11] #define REG_ACR2 XBYTE[SJA_REG_BaseADD + 0x12] #define REG_ACR3 XBYTE[SJA_REG_BaseADD + 0x13] #define REG_AMR0 XBYTE[SJA_REG_BaseADD + 0x14] #define REG_AMR1 XBYTE[SJA_REG_BaseADD + 0x15] #define REG_AMR2 XBYTE[SJA_REG_BaseADD + 0x16] #define REG_AMR3 XBYTE[SJA_REG_BaseADD + 0x17]#define REG_RxBuffer0 XBYTE[SJA_REG_BaseADD + 0x10] #define REG_RxBuffer1 XBYTE[SJA_REG_BaseADD + 0x11] #define REG_RxBuffer2 XBYTE[SJA_REG_BaseADD + 0x12] #define REG_RxBuffer3 XBYTE[SJA_REG_BaseADD + 0x13] #define REG_RxBuffer4 XBYTE[SJA_REG_BaseADD + 0x14]#define REG_TxBuffer0 XBYTE[SJA_REG_BaseADD + 0x10] #define REG_TxBuffer1 XBYTE[SJA_REG_BaseADD + 0x11] #define REG_TxBuffer2 XBYTE[SJA_REG_BaseADD + 0x12] #define REG_TxBuffer3 XBYTE[SJA_REG_BaseADD + 0x13] #define REG_TxBuffer4 XBYTE[SJA_REG_BaseADD + 0x14]#define REG_DataBuffer1 XBYTE[SJA_REG_BaseADD + 0x15] #define REG_DataBuffer2 XBYTE[SJA_REG_BaseADD + 0x16] #define REG_DataBuffer3 XBYTE[SJA_REG_BaseADD + 0x17] #define REG_DataBuffer4 XBYTE[SJA_REG_BaseADD + 0x18] #define REG_DataBuffer5 XBYTE[SJA_REG_BaseADD + 0x19] #define REG_DataBuffer6 XBYTE[SJA_REG_BaseADD + 0x1a] #define REG_DataBuffer7 XBYTE[SJA_REG_BaseADD + 0x1b] #define REG_DataBuffer8 XBYTE[SJA_REG_BaseADD + 0x1c]#define REG_RBSA XBYTE[SJA_REG_BaseADD + 0x1e] #define REG_CDR XBYTE[SJA_REG_BaseADD + 0x1f] #define REG_Receive_Counter XBYTE[SJA_REG_BaseADD + 0x1d]#define OK 1 #define Fail 0 #define ON 1 #define OFF 0 #define True 1 #define False 0

sbit SJARst = P2 ^ 6; //復位控制
sbit LED0 = P1 ^ 0;
sbit LED1 = P1 ^ 1;
sbit Key0 = P1 ^ 2;
sbit Key1 = P1 ^ 3;
sbit Key2 = P1 ^ 4;
sbit Key3 = P1 ^ 5;

bit step_flg;
bit Tx_flg;
bit Rx_flg;

unsigned char step_counter;
unsigned char Tx_counter;
unsigned char PC_RX_Buffer;
unsigned char temp_data1;
unsigned char Rx_Buffer[6];

void MCU_Init(void);
void SJA_Init(void);
void send(unsigned char S_Data);
void Serial(void);
void Delay(unsigned char Delay_time);
void step(void);


以下為c的主程序
copyright by alloy


#include <stdio.h> #include <string.h> #include <REG51.h> #include <TxMCU.h> #include <absacc.h>

main()
{

unsigned char i; MCU_Init(); SJA_Init(); REG_MODE = 0x01; //進入復位模式temp_data1 = REG_MODE;temp_data1 = temp_data1 & 0x01; if(temp_data1 == 0x01) //在復位模式中 {REG_BTR0 = 0x85;REG_BTR1 = 0xb4; //100kREG_OCR = 0x1a; //00011010 只設置了TX0,因為TX1懸空REG_CDR = 0xc0; //11000000 PeliCANREG_RBSA = 0x00; //RX緩沖器起始地址寄存器置0,表示內部RAM地址REG_ACR0 = 0xff;REG_ACR1 = 0xff;REG_ACR2 = 0xff;REG_ACR3 = 0xff;REG_AMR0 = 0xff;REG_AMR1 = 0xff;REG_AMR2 = 0xff;REG_AMR3 = 0xff;REG_IR_ABLE = 0xff; } REG_MODE = 0x0c; //進入自接收模式 REG_MODE = 0x0c;for(i = 0;i<100;i++); temp_data1 = REG_Receive_Counter; send(temp_data1); for(;;) {while(Tx_flg == False);Tx_flg = False;Tx_counter++;send(Tx_counter);temp_data1 = REG_SR;while((temp_data1 & 0x10) == 0x10); //若CPU在接收報文則等待temp_data1 = REG_SR;if((temp_data1 & 0x04) == 0x04) //若CPU可以向發送緩沖器寫報文則執行寫操作{REG_RxBuffer0 = 0x08; //標準幀,長度為8REG_RxBuffer1 = 0xff;REG_RxBuffer2 = 0xff;REG_RxBuffer3 = 0x01;REG_RxBuffer4 = 0x02;REG_DataBuffer1 = 0x03;REG_DataBuffer2 = 0x04;REG_DataBuffer3 = 0x05;REG_DataBuffer4 = 0x06;REG_DataBuffer5 = 0x07;REG_DataBuffer6 = 0x08;REG_DataBuffer7 = 0x09;REG_DataBuffer8 = 0x0a;}REG_CMD = 0x10; //自接收請求位置1,當前信息可以同時被發送和接收temp_data1 = REG_SR;temp_data1 = temp_data1 & 0x20;while(temp_data1 == 0x20) //檢查是否發送完成,若還在發送,則向上位機發送錯誤代碼捕捉寄存器內容{//send(0xaa);temp_data1 = REG_ECC;send(temp_data1);temp_data1 = REG_SR;temp_data1 = temp_data1 & 0x20;//send(temp_data1);}send(0x66);temp_data1 = REG_ALC;send(temp_data1);temp_data1 = REG_ECC;send(temp_data1);temp_data1 = REG_SR;send(temp_data1);temp_data1 = REG_Receive_Counter;send(temp_data1);PC_RX_Buffer = 0x77;LED0 = ~LED0;

// Tx_counter = 0x00;
}
}

void MCU_Init(void)
{
SJARst = 1;
LED0 = OFF;
LED1 = OFF;
PC_RX_Buffer = 0x77;
step_counter = 0x00;
step_flg = False;
Tx_flg = False;
temp_data1 = 0x00;
TMOD = 0x20;
TH1 = 0xff;
TL1 = 0xff;
TR1 = 1;
SCON = 0x50;
PCON = 0x80;
EA = 1;
ES = 1;
Tx_counter = 0x00;

}

void SJA_Init(void)
{
unsigned char i;
for(i = 0;i < 125;i++);
SJARst = 0;
for(i = 0;i < 125;i++);
SJARst = 1;
for(i = 0;i < 125;i++);
}

void send(unsigned char S_Data)
{
SBUF = S_Data;
while(TI == 0);
TI =0;
}

void Serial() interrupt 4 using 2
{

if(RI == 1) {PC_RX_Buffer = SBUF;RI = 0;if(PC_RX_Buffer == 0xaa){send(0x13);Tx_flg = True;PC_RX_Buffer = 0x77;}else if(PC_RX_Buffer == 0x55){send(0x14);Rx_flg = True;PC_RX_Buffer = 0x77;}else{send(0x15);PC_RX_Buffer = 0x77;} }

}這里寫代碼片

總結

以上是生活随笔為你收集整理的sja1000调试经验的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。