本文檔概述了一種基于 SCI/UART 輸入信號(hào),可以自動(dòng)校準(zhǔn)本設(shè)備SCI/UART波特率的方法,該方法適用與所有第三代C2000芯片,比如F2807x/37x,F(xiàn)28004x,F(xiàn)28002x等等。
一 原理說(shuō)明
假設(shè)有2塊電路板通過(guò)SCI進(jìn)行通信。“Transmitter”向“Receiver”發(fā)送未知波特率的數(shù)據(jù),“ Receiver”則使用 eCAP 測(cè)量未知的波特率,然后修改其自身的波特率和“Transmitter”匹配。
下面款圖是一種情況,其中“Transmitter” 的波特率設(shè)置為 9889,而“Receiver”的初始波特率設(shè)置為 9601 ,相比之下“Receiver”的波特率為 -3% 偏差。 經(jīng)過(guò)算法的自動(dòng)校準(zhǔn)以后,“Receiver”將會(huì)把自身波特率校正為與“Transmitter”相同的9889。
下面框圖則是另一種情況,假如“Receiver”和“Transmitter”的初始波特率都是9889,但“Receiver”的內(nèi)部晶振INTOSC有-3%的偏差。使用上述完全相同的方法原理和步驟,“Receiver”波特率設(shè)置將會(huì)從9889校準(zhǔn)成9601,這樣“Receiver”的波特率設(shè)置被自動(dòng)校準(zhǔn)抵消內(nèi)部晶振的偏差。在測(cè)量實(shí)際信號(hào)時(shí),“Receiver”輸出到“Transmitter”的信號(hào)會(huì)是正確的 9889 波特率。
二 Receiver 的校準(zhǔn)代碼
1. 初始化
需要配置以下模塊來(lái)校準(zhǔn)波特率:
時(shí)鐘:使用 INTOSC2 并選擇 100MHz 的 LSPCLK
#define DEVICE_SETCLOCK_CFG (SYSCTL_OSCSRC_OSC2 | SYSCTL_IMULT(20) |
SYSCTL_FMULT_NONE | SYSCTL_SYSDIV(2) |
SYSCTL_PLL_ENABLE)
//
// Set up PLL control and clock dividers
//
SysCtl_setClock(DEVICE_SETCLOCK_CFG);
//
// Make sure the LSPCLK divider is set to the default (divide by 4)
//
SysCtl_setLowSpeedClock(SYSCTL_LSPCLK_PRESCALE_1);
SCI 模塊:通訊數(shù)據(jù)使用,發(fā)出校準(zhǔn)以后的波形
// Initialize SCIA and its FIFO.
//
SCI_performSoftwareReset(SCIA_BASE);
//
// Configure SCIA for communications.
//
SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, TARGETBAUD, (SCI_CONFIG_WLEN_8 |
SCI_CONFIG_STOP_ONE |
SCI_CONFIG_PAR_NONE));
SCI_resetChannels(SCIA_BASE);
SCI_resetRxFIFO(SCIA_BASE);
SCI_resetTxFIFO(SCIA_BASE);
SCI_clearInterruptStatus(SCIA_BASE, SCI_INT_TXFF | SCI_INT_RXFF);
SCI_enableFIFO(SCIA_BASE);
SCI_enableModule(SCIA_BASE);
SCI_performSoftwareReset(SCIA_BASE);
Xbar 輸入:將 GPIO28/SCI 內(nèi)部連接到 INPUTXBAR7 與 ECAP1 配合使用
//
// Configure GPIO 28 as eCAP input
//
XBAR_setInputPin(XBAR_INPUT7, 28);
ECAP 模塊:監(jiān)控接收到的 SCI 通信脈沖寬度
//
// Disable ,clear all capture flags and interrupts
//
ECAP_disableInterrupt(ECAP1_BASE,
(ECAP_ISR_SOURCE_CAPTURE_EVENT_1 |
ECAP_ISR_SOURCE_CAPTURE_EVENT_2 |
ECAP_ISR_SOURCE_CAPTURE_EVENT_3 |
ECAP_ISR_SOURCE_CAPTURE_EVENT_4 |
ECAP_ISR_SOURCE_COUNTER_OVERFLOW |
ECAP_ISR_SOURCE_COUNTER_PERIOD |
ECAP_ISR_SOURCE_COUNTER_COMPARE));
ECAP_clearInterrupt(ECAP1_BASE,
(ECAP_ISR_SOURCE_CAPTURE_EVENT_1 |
ECAP_ISR_SOURCE_CAPTURE_EVENT_2 |
ECAP_ISR_SOURCE_CAPTURE_EVENT_3 |
ECAP_ISR_SOURCE_CAPTURE_EVENT_4 |
ECAP_ISR_SOURCE_COUNTER_OVERFLOW |
ECAP_ISR_SOURCE_COUNTER_PERIOD |
ECAP_ISR_SOURCE_COUNTER_COMPARE));
//
2. 中斷
捕獲傳入 SCI 通信的脈沖寬度,每捕獲 4 次就中斷一次。 將這 4 個(gè)捕獲添加到陣列中。
__interrupt void ecap1ISR(void)
{
if(stopCaptures==0)
{
//
// Get the capture counts, interrupt every 4. Can be 1-bit or more wide.
// add one to account for partial eCAP counts at higher baud rates
// (e.g. count = 40, but if had higher resolution, this would be 40.5)
//
capCountArr[0] = 1+ECAP_getEventTimeStamp(ECAP1_BASE, ECAP_EVENT_1);
capCountArr[1] = 1+ECAP_getEventTimeStamp(ECAP1_BASE, ECAP_EVENT_2);
capCountArr[2] = 1+ECAP_getEventTimeStamp(ECAP1_BASE, ECAP_EVENT_3);
capCountArr[3] = 1+ECAP_getEventTimeStamp(ECAP1_BASE, ECAP_EVENT_4);
//
// Add samples to a buffer. Get average baud and tune INTOSC if buffer filled.
//
capCountIter = 0;
for (capCountIter=0; capCountIter<4; capCountIter++)
{
//
3. 主循環(huán)
捕獲陣列滿后,計(jì)算陣列的平均脈沖寬度 (也就是波特率),并更新SCI波特率寄存器,使其盡可能接近計(jì)算的平均值。
//
// Loop forever. Suspend or place breakpoints to observe the buffers.
//
for(;;)
{
//
// Array is filled, begin tuning
//
if(stopCaptures==1)
{
//
// Get an average baud rate from the array of samples
//
uint32_t avgBaud = getAverageBaud(samplesArr,NUMSAMPLES,TARGETBAUD);
//
// if the baud function returns the error code '0', then flag an error
//
if(avgBaud==0)
{
ESTOP0;
4. 平均脈沖寬度
對(duì)于許多應(yīng)用的SCI 通信,傳輸?shù)臄?shù)據(jù) (例如 0xA5)是變化不固定的,因此SCI的高低電平脈沖寬度就是變化的。所以必須對(duì)樣本陣列進(jìn)行如下的預(yù)處理,然后才能計(jì)算平均脈沖寬度。
a) 丟棄大于 10 位寬的脈沖寬度 (丟棄空閑時(shí)間)
b) 將 n 位值除以 n
c) 對(duì)修改后的樣本數(shù)組進(jìn)行平均化
uint32_t getAverageBaud(volatile float arr[], int size, float targetBaudRate)
{
//
// clean up variable width array to single-bit-width array
//
uint16_t pass = arrTo1PulseWidth(arr, size, (float)DEVICE_SYSCLK_FREQ/targetBaudRate);
//
// pass only if enough good samples provided
//
if(pass == 0)
{
return 0;
}
//
// convert 2-bit width, 3-bit width, etc. to 1-bit width values by dividing, and average these values.
// skip unrelated values
//
float averageBitWidth = computeAvgWidth(arr, size);
以下是平均脈寬計(jì)算的原理和代碼流程圖
三 結(jié)果
按照以下設(shè)置進(jìn)行測(cè)試,結(jié)果詳見(jiàn)表格,校準(zhǔn)以后的誤差從3% 改善為0.1%左右甚至更小。
“Transmitter”設(shè)置為正確的波特率 (我們嘗試匹配的波特率)
“Receiver”設(shè)置為錯(cuò)誤波特率 (-3% 或 +3%)
“Receiver”運(yùn)行校準(zhǔn)程序以匹配“Transmitter”
100K 波特率 | 9601波特率 | ||||
-3% | +3% | -3% | +3% | ||
Transmitter (我們正在嘗試匹配的內(nèi)容) |
理想波特率 (僅供參考) |
103306 | 96899 | 9889 | 9314. |
實(shí)際波特率 (必須與此匹配) |
104174. | 96906 | 9890 | 9315. | |
Receiver (初始錯(cuò)誤波特率) |
波特率 (校準(zhǔn)前) |
100154. | 100157. | 9622. | 9622. |
出錯(cuò)百分比 (校準(zhǔn)前) |
-3.859% | 3.355% | -2.706% | 3.296% | |
Receiver (校準(zhǔn)后波特率) |
波特率 (校準(zhǔn)后) |
104336. | 97047. | 9888 | 9314. |
出錯(cuò)百分比 (校準(zhǔn)后) |
0.156% | 0.146% | -0.016% | -0.012% |
-
寄存器
+關(guān)注
關(guān)注
31文章
5363瀏覽量
121192 -
電路板
+關(guān)注
關(guān)注
140文章
4997瀏覽量
98878 -
uart
+關(guān)注
關(guān)注
22文章
1243瀏覽量
101773
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論