2.3 UCD3138 軟件中的數(shù)據(jù)處理
截止到上節(jié),用戶可以在GUI 中新增一條信息欄并輸入數(shù)據(jù),然后通過對應的PMBUS 命令,將該數(shù)據(jù)傳輸?shù)経CD3138 中。但為了使UCD3138 接收該數(shù)據(jù)并調(diào)整相應的模擬比較器閾值,還需要修改UCD3138 的軟件。
(1)、定義變量和結(jié)構(gòu)體
如下代碼,定義了新的結(jié)構(gòu)體變量PMBUS_DCDC_CONFIG,包含成員iout_oc_fault_limit 和reserved。隨后定義了該結(jié)構(gòu)體類型的外部變量pmbus_dcdc_config 和pmbus_dcdc_config_translated,分別用于接收和保存GUI 傳輸?shù)経CD3138 的數(shù)據(jù)和格式轉(zhuǎn)換后的數(shù)據(jù)。
typedef struct
{
Uint16 iout_oc_fault_limit;
Uint16 reserved;
}PMBUS_DCDC_CONFIG; //must be even number of int16
EXTERN PMBUS_DCDC_CONFIG pmbus_dcdc_config[1];
EXTERN PMBUS_DCDC_CONFIG pmbus_dcdc_config_translated[1];
(2)、創(chuàng)建新的PMBUS 讀與寫函數(shù)
由于從GUI 傳輸過來的數(shù)據(jù)的首個字節(jié)是對應的PMBUS 命令的代碼, 如0x46, 并會存放在pmbus_buffer[0]中。因此,可以在函數(shù) pmbus_write_message()中創(chuàng)建新的case 語句,并返回一個新創(chuàng)建的函數(shù)pmbus_write_iout_oc_fault_limit(),該新函數(shù)用來處理接收到的數(shù)據(jù)。這樣就實現(xiàn)了一旦 UCD3138 接收到新的數(shù)據(jù)后,且該數(shù)據(jù)是用戶重新編輯的“輸出過流保護點”信息,則就會調(diào)用pmbus_write_iout_oc_fault_limit()函數(shù)進行處理。
switch (pmbus_buffer[0])
{
case 0x46:
return pmbus_write_iout_oc_fault_limit();
}
同時, 也需要在函數(shù)pmbus_read_message() 中創(chuàng)建新的case 語句, 并返回一個新創(chuàng)建的函數(shù)pmbus_read_iout_oc_fault_limit(),用來返回接收到的信息到GUI 中,以確保信息傳輸正確。這種讀取后再返回驗證的操作是PMBUS 協(xié)議的規(guī)定。
switch (pmbus_buffer[0])
{
case 0x46:
return pmbus_read_iout_oc_fault_limit();
}
(3)、數(shù)據(jù)處理函數(shù)的設(shè)計
◎ 接收數(shù)據(jù)處理函數(shù)pmbus_write_iout_oc_fault_limit()
該函數(shù)用來接收來自GUI 的數(shù)據(jù),并將該數(shù)據(jù)的格式由Linear Data Format 轉(zhuǎn)換為浮點型數(shù)據(jù),最后強制轉(zhuǎn)換為整數(shù)型賦給模擬比較器。關(guān)鍵代碼分析如下:
上文提到,來自GUI 的數(shù)據(jù)的首字節(jié)是對應的PMBUS 命令代碼。隨后的兩個字節(jié)便是Linear Data 格式的數(shù)據(jù)。將該數(shù)據(jù)保存在pmbus_dcdc_config 結(jié)構(gòu)體的iout_oc_fault_limit 成員中,如下代碼所示。
Pmbus_dcdc_config[0].iout_oc_fault_limit = pmbus_buffer[1] + (pmbus_buffer[2] 《《 8);
下面代碼是調(diào)用格式轉(zhuǎn)換函數(shù)linear11_to_float(),將上面接收到的數(shù)據(jù)轉(zhuǎn)換為浮點型數(shù)據(jù)。
local_variable = linear11_to_float(pmbus_dcdc_config[0].iout_oc_fault_limit);
由于轉(zhuǎn)換后的浮點型數(shù)據(jù)與最終需要賦給模擬比較器閾值的數(shù)據(jù)存在一定的比例,需要一個轉(zhuǎn)換系數(shù)(scaler)。縮放后存放在pmbus_dcdc_config_tanslated 結(jié)構(gòu)體的iout_oc_fault_limit 成員中。
pmbus_dcdc_config_translated[0].iout_oc_fault_limit = (int)(local_variable*2.54);
最終該值賦給模擬比較器的閾值,用來做快速保護。
FaultMuxRegs.ACOMPCTRL0.bit.ACOMP_B_THRESH=pmbus_dcdc_config_translated[0].iout_oc_fault_limit;
◎ 返回數(shù)據(jù)處理函數(shù)pmbus_read_iout_oc_fault_limit
該函數(shù)用來返回UCD3138 軟件接收的數(shù)據(jù)到GUI 中,以使GUI 將寫入和讀取的數(shù)據(jù)做比較(比較判斷等操作在GUI 軟件中完成) , 保證數(shù)據(jù)正確。該函數(shù)調(diào)用pmbus_read_two_byte_handler() 將保存在Pmbus_dcdc_config[0].iout_oc_fault_limit 的數(shù)據(jù)返回到GUI。關(guān)鍵代碼如下:
pmbus_read_two_byte_handler(pmbus_dcdc_config[0].iout_oc_fault_limit);
而在pmbus_read_two_byte_handler()函數(shù)中的關(guān)鍵代碼為:
pmbus_buffer[1] = value 》》 8;
pmbus_buffer[0] = value & 0xff;
pmbus_buffer 字節(jié)中的數(shù)據(jù)會最終上傳到GUI 軟件中。
(4)、數(shù)據(jù)轉(zhuǎn)換函數(shù)的設(shè)計
◎ Linear Data Format 數(shù)據(jù)格式
上文提到,來自GUI 的數(shù)據(jù)遵循PMBUS 協(xié)議,其格式為Linear Data Format。如圖5,其低11 位為“尾數(shù)”,以補碼形式保存;高5 位為“指數(shù)”,亦是以補碼形式保存。該數(shù)據(jù)與實際數(shù)據(jù)的關(guān)系為:X=Y× 2N 。
圖 5:PMBUS 協(xié)議中的Linear Data Format
◎ ARM 編譯器中的浮點型數(shù)據(jù)
如圖6,為ARM 編譯器中對單精度浮點型數(shù)據(jù)的存儲格式。其最高位為符號位,接下的8 位為指數(shù),后面的23 位為尾數(shù)。在編譯器中定義的浮點數(shù)據(jù),將以該格式存儲在硬件存儲空間。
圖 6:ARM 編譯器中的浮點型數(shù)據(jù)格式
◎ 定義結(jié)構(gòu)體和聯(lián)合體
如下, 定義了結(jié)構(gòu)體FLOAT_ELEMENTS , 用以保存上文提到的浮點型數(shù)據(jù)。還定義了聯(lián)合體FLOAT_OPEN,成員包括浮點型數(shù)據(jù)“all”和結(jié)構(gòu)體類型數(shù)據(jù)“bit”,用以保存轉(zhuǎn)換完畢的浮點型數(shù)據(jù)。
struct FLOAT_ELEMENTS {
Uint32 SIGN:1;
Uint32 EXPONENT:8;
Uint32 MANTISSA:23;
};
union FLOAT_OPEN {
float all;
struct FLOAT_ELEMENTS bit;
Uint32 word;
};
◎ 轉(zhuǎn)換函數(shù)linear11_to_float()
該函數(shù)完成將來自GUI 的Linear Data Format 格式的數(shù)據(jù)轉(zhuǎn)換為浮點型數(shù)據(jù),并作為返回值返回。包含的關(guān)鍵代碼如下。
定義變量,包括整型“mantissa”和“exponent”及結(jié)構(gòu)體變量“final”。
int16 mantissa, exponent;
union FLOAT_OPEN final;
下面代碼完成對輸入?yún)?shù)的分析,并擴展到16 位。如果輸入?yún)?shù)的尾數(shù)是負值,前5 位補1;如果是正值,前5 位補0。
if(linear11 & 0x0400)// if mantissa is negative
{ mantissa = linear11 | 0xfc00; //put it in there at minimum mantissa }
else
{ mantissa = linear11 & 0x07FF; }
下面代碼首先是將mantissa 左移16 位(16+16=32),以使其數(shù)據(jù)長度符合單精度浮點型數(shù)據(jù)的長度,然后exponent 減去16,保證了原始數(shù)據(jù)的大小沒有變化。
final.all = ((int32)mantissa) 《《 16; //set it up for minimum exponent.
exponent = (linear11 》》 11) - 16; //get exponent to match shifted value
下面代碼首先判斷單精度浮點型的指數(shù)是否為負。如果是負,則改寫其為零,原因是對應的“輸出過流保護點”不會出現(xiàn)負值;如果是正,則將指數(shù)信息放置在單精度浮點型數(shù)據(jù)的指數(shù)位置。
if((final.bit.EXPONENT + exponent) 《 0)//if it‘s so low it will wrap
{ final.bit.EXPONENT = 0; }
else
{ final.bit.EXPONENT = final.bit.EXPONENT + exponent; }
上述操作完畢后,final.all 中就保存了轉(zhuǎn)換后的浮點型數(shù)據(jù),因此可以作為返回值返回。
return final.all;
評論