在車載控制器中,CAN采樣點的測試是控制器的基本測試之一,那CAN總線的采樣點一般怎么測試呢?今天一起來捋一捋。
首先CAN報文的位將分割為同步段(Sync Segment)、時間片段 1(TSEG1 Segment)和時間片段 2(TSEG2 Segment)。這些片段由不同數(shù)量的 TQ 組成, TQ 為該總線電平中最小的時間單位。預(yù)分頻(Prescaler)值以及收發(fā)器使用的時鐘頻率直接影響了一個位長度的總 TQ 數(shù)量。采樣點位置將由各個片段中 TQ 的數(shù)量計算得到。
![]()
1 個位中包含 8 或 16 個 TQ 的分段示意圖
采樣點的理論計算值可由下式得到:
= ( + 1)/( + 1 + 2)
在此必須知道所使用的 CAN 時鐘頻率,以此來計算一個標(biāo)稱位時間所使用的總 TQ 數(shù)量。
例如:若一個 TQ 的長度為 0.0625us,時鐘頻率是 16MHz(通常 CAN 所使用的時鐘頻率),預(yù)分頻數(shù)為1。這就導(dǎo)致在 500kBaud 下一個位含有 32 個 TQ。若預(yù)分頻數(shù)為 2,則一個位包含 16 個 TQ。
同步段(Sync Segment)在任何情況下均僅為 1 個 TQ 長度,剩余的 TQ 將會被分為 TSEG1 和 TSEG2。
例如:若一個位的總 TQ 數(shù)為 16,采樣點位置為 75%,則 TSEG1 的 TQ 數(shù)為 11, TSEG2 的 TQ 數(shù)為 4。
CAN采樣點測試的原理是節(jié)點判斷信號邏輯電平的位置,對 CAN總線來說極其重要,尤其是在一個CAN網(wǎng)絡(luò)里,多個節(jié)點要保持同一個采樣點。如果其中一個偏差較大,有可能使整個網(wǎng)絡(luò)出現(xiàn)故障,所以對 CAN節(jié)點進行采樣點的測試顯得尤為重要,采樣點測試目的用于檢查控制器的采樣點設(shè)置是否遵守規(guī)范要求。
采樣點的位置不受控制器所處的收發(fā)狀態(tài)影響,故針對采樣點測試既可以干擾控制器發(fā)送的指定報文的某個位,也可以通過測試工具發(fā)送特定干擾報文去檢測控制器的行為。
下面以CANoe發(fā)送特定干擾報文的方法為例。VH6501 在檢測到總線空閑時,發(fā)送較高優(yōu)先級的特定干擾報文,完成一個干擾循環(huán)。每次干擾循環(huán)發(fā)送結(jié)束,微調(diào) CRC Delimiter 位長度,使其逐次縮短,導(dǎo)致后一位 ACK Slot前移,并將 ACK Slot 長度增加,保證整幀報文的長度不變。當(dāng)顯性位電平由后往前,移至 DUT 采樣點位置,會被 DUT 采到并判定 CRC Delimiter 位為高電平,出現(xiàn)格式錯誤,DUT 隨即發(fā)送錯誤幀,并被 CANoe 采集到。另外每次干擾循環(huán)結(jié)束, VH6501 將發(fā)送 30 次控制器正常接收的任意一幀正常報文,從而使 DUT 始終保持 Error Active 狀態(tài),因其主動錯誤幀容易辨認(rèn)。
![]()
那CANoe工程如何配置呢?首先打開軟件后,選擇CANoe的示例工程Disturbance SamplePoint Test (CAN)。進入工程后,將 VH6501 通道分配給軟件通道 CAN1,在下圖所示界面設(shè)置 Mode 為 CAN,并勾選 Activate 選項使能 VH6501 總線干擾功能。
![]()
VH6501 的采樣點設(shè)置盡量靠前,確保優(yōu)先干擾到控制器的采樣點,此處BTL Cycles(指的是TQ數(shù)量,將一個位分為16個TQ) 和SJW(同步跳變寬度) 要選擇數(shù)值較大的組合,可參考下圖配置。
![]()
配置完成之后,就可以寫capl測試腳本了。
/*@!Encoding:936*/
includes
{
}
variables
{
CanDisturbanceFrameTrigger frameTrigger;
CanDisturbanceFrameSequence frameSequence;
CanDisturbanceSequence sequence;
CanDisturbanceTriggerRepetitions repetitions;
const int repetition_times_in_one_cycle = 10;
//Number of disturbance repetitions in a cycle
long result;
long errfrmcount; //The error frame count in one cycle
long first_err_bit_length,first_error_occur, ten_error_occur;
long validityMask;
long cycleFlag;
message 0x100 triggerMessage; //The trigger
message.(ID is not important.)
message 0x0 spTestMsg; //The disturbance frame sequence which CRC DEL need to be shorten.
message 0x1 Keep_DUT_ErrorActive;
const long CountMsgKeepErrorActive = 30;
long MsgCntKeepErrorActive = 0;
char spTestDone[33] = "SPDone";
}
on errorFrame
{
if(this.msgChannel == @sysvar::CANDisturbanceInterface1::ChannelNo)
{
errfrmcount++;
if((errfrmcount == 1) && (first_error_occur == 0))
{
first_err_bit_length = frameSequence.CRCDelimiter.BitSequence[0].segmentLength[0];
first_error_occur = 1;
write("+++++++++First error frame occurs+++++++++++.");
}
if(errfrmcount == repetition_times_in_one_cycle)
{
ten_error_occur = 1;
testSupplyTextEvent(spTestDone);
}
}
}
on message 0x1
{
if(MsgCntKeepErrorActive <= CountMsgKeepErrorActive)
{
++MsgCntKeepErrorActive;
output(Keep_DUT_ErrorActive);
}
else
{
ActivateTriggerAgain();
}
}
void ActivateTriggerAgain()
{
if(ten_error_occur == 0)
{
errfrmcount = 0;
//CRC Delimiter is shorten with 6.25ns per cycle.
--frameSequence.CRCDelimiter.BitSequence[0].segmentLength[0];
++frameSequence.AckSlot.BitSequence[0].segmentLength[0];
result = canDisturbanceTriggerEnable(@sysvar::CANDisturbanceInterface1::DeviceNo,frameTrigger, frameSequence, repetitions);
if(result == 1)
{
write("Trigger is enabled,
frameSequence.CRCDelimiter.BitSequence[0].segmentLength[0] = %d",
frameSequence.CRCDelimiter.BitSequence[0].segmentLength[0]);
}
else
{
write("Enable trigger error Result = %d", result);
}
}
}
on sysvar sysvar::CANDisturbanceInterface1::Trigger::State
{
//6501 is Idle after repetition_times_in_one_cycle finish
if(@sysvar::CANDisturbanceInterface1::Trigger::State == 0)
{
//At the end of each disturbance cycle, the VH6501 need to outputsome normal message to prevent the DUT from being in a passive error state
//because the passive error frame is not easily to be observed and
//identified.
MsgCntKeepErrorActive = 0;
output(Keep_DUT_ErrorActive);
}
}
testcase SamplePointTest_forVH6501()
{
first_error_occur = 0;
ten_error_occur = 0;
errfrmcount = 0;
cycleFlag = 1;
frameSequence.SetMessage(@sysvar::CANDisturbanceInterface1::DeviceNo,spTestMsg);
validityMask = 0; //trigger on any CAN messages
frameTrigger.SetMessage(triggerMessage,
@sysvar::CANDisturbanceInterface1::DeviceNo, validityMask);
frameTrigger.TriggerFieldType =
@sysvar::CanDisturbance::Enums::FieldType::EndOfFrame;
frameTrigger.TriggerFieldOffset = 9; //Trigger position is the thirdbit of IFS.
write("CRC Delimiter Bit Length = %d",
frameSequence.CRCDelimiter.BitSequence[0].segmentLength[0]);
repetitions.Cycles = 1;
repetitions.HoldOffCycles = 0;
repetitions.HoldOffRepetitions = 0;
repetitions.Repetitions = repetition_times_in_one_cycle;
result = canDisturbanceTriggerEnable(@sysvar::CANDisturbanceInterface1::DeviceNo,frameTrigger,frameSequence,repetitions);
if(result == 1)
{
write("Trigger is enabled.");
}
else
{
write("Enable trigger error Result = %d", result);
}
result = testWaitForTextEvent(spTestDone, 10000);
if(result == 1)
{
write("frameSequence.CRCDelimiter.BitSequence[0].segmentLength[0] = %d
, sample point lies in %f%%~%f%%",
frameSequence.CRCDelimiter.BitSequence[0].segmentLength[0],
(frameSequence.CRCDelimiter.BitSequence[0].segmentLength[0] * 100.00) /
frameSequence.DLC.BitSequence[1].segmentLength[0], (first_err_bit_length *
100.00) / frameSequence.DLC.BitSequence[1].segmentLength[0]);
}
}
void maintest()
{
SamplePointTest_forVH6501();
}那采樣點的測試結(jié)果一般受什么影響呢?一般來說受3個因素影響。
![]()
在總線信號和 RxD 引腳信號上影響采樣點測試結(jié)果的因素示意圖
?指VH6501每次縮短或增長的步進長度。
?指控制器的CAN參數(shù)配置中一個TQ的時間長度。
?指總線上一個位的電平長度與控制器內(nèi)部主控芯片 RxD 引腳上的一個位電平長度的時間差。? = () - ()
如果一個 CAN 的設(shè)備使用的時鐘對應(yīng)的最小 TQ 時間長度在?的范圍內(nèi),并且實際 TQ 配置在此范圍內(nèi),則?所帶來的誤差需要考慮在采樣點測試的結(jié)果中 。ISO11898-2: 2015規(guī)定了在2MBaud下,規(guī)定了?的允許范圍為-65ns 到+40ns。而對于 2MBaud下,一個位時間長度為500ns, 這意味著在RxD引腳上的為時間長度將會比在總線上的為時間長度短13%或長 8%。而 TQ 時間長度的計算公式為:? =/
如果在 2MBaud 下, 一個 TQ 的時間長度小于一個位的 13%, 則?將會被考慮進采樣點測試的結(jié)果當(dāng)中。具體的誤差將取決于 CAN 發(fā)送器和使用的波特率。
假設(shè) CAN 時鐘頻率為 80MHz, ?為 25ns,預(yù)分頻(Prescaler) 為 1, ?為 12.5ns, ?為6.25ns。仲裁相為 500kBaud,數(shù)據(jù)相為 2MBaud。
這意味著?所帶來的誤差在仲裁相為 1.25%,在數(shù)據(jù)相則會上升到 5%(由于單個位時間長度縮短了) 。這幾乎相當(dāng)于 2 個 TQ 的時間長度。測試工具 VH6501 步進長度?所帶來的誤差分別為0.3125%和 1.25%。
由于 CAN 協(xié)議 11898 中并未規(guī)定重同步后跳變沿一定要在同步段(Sync Segment) 的哪個位置,從同步段(Sync Segment) 的開始到結(jié)束均可以,因此這會帶來 1 個 TQ 的誤差。在仲裁相和數(shù)據(jù)相中帶來的誤差分別為 0.625%和 2.5%。
因此綜上所述,在仲裁相中總的最大誤差為 2.1875%(1.25% + 0.3125% + 0.625%) ,在數(shù)據(jù)相中總的最大誤差為 8.75%(5% + 1.25% + 2.5%)。
由上可知, 由 VH6501 所帶來的誤差所占比例是很小的。而大部分是由于 CAN 協(xié)議本身所帶來的誤差。
-end-
分享不易,懇請點個【】和【在看】
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺“網(wǎng)易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.