2016-02-17 113 views
0

我有一個模擬器件的DAC8562。這裏是一個數據表:用微控制器有效控制DAC

http://www.analog.com/media/en/technical-documentation/data-sheets/DAC8562.pdf

它是一種並行12位DAC。我有一個用C語言寫的函數,它控制GPIO引腳將輸入值鎖存到DAC。我的問題是我的功能比較慢。這裏是代碼:

void setOut(uint16_t data) { 

//Set DATA 
if (data & 0x01) { 
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN2); 
} else { 
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN2); 
} 
if (data & 0x02) { 
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN0); 
} else { 
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN0); 
} 
if (data & 0x04) { 
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P6, GPIO_PIN1); 
} else { 
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN1); 
} 
if (data & 0x08) { 
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN7); 
} else { 
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN7); 
} 
if (data & 0x10) { 
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN6); 
} else { 
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN6); 
} 
if (data & 0x20) { 
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN4); 
} else { 
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN4); 
} 
if (data & 0x40) { 
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P5, GPIO_PIN6); 
} else { 
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN6); 
} 
if (data & 0x80) { 
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P6, GPIO_PIN6); 
} else { 
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN6); 
} 
if (data & 0x100) { 
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P6, GPIO_PIN7); 
} else { 
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN7); 
} 
if (data & 0x200) { 
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN3); 
} else { 
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN3); 
} 
if (data & 0x400) { 
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P5, GPIO_PIN1); 
} else { 
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN1); 
} 
if (data & 0x800) { 
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN5); 
} else { 
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN5); 
} 

// Set CE Low 
MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN4); 

// Set CE High 
MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN4);} 

問題是板的佈局需要我使用的特定端口/引腳分配。 截至目前,我正在逐個檢查每個位,並匹配該位表示爲高或低的引腳輸出。有沒有更有效的方法來做到這一點?

附加信息: 我正在使用和MSP432P401R微控制器。 我正在使用TI的驅動程序庫來控制GPIO。

+0

這就是爲什麼一個人應該花了心思設計的硬件了。將接線更改爲更智能的接線。 – Olaf

+1

@Olaf你的評論是無用的,因爲我已經解決了佈局是我的控制。 –

+0

不,你沒有。至少仍然踢硬件設計師會讓人滿意。幾乎沒有一種**高效的**方法可以使代碼更好,甚至更多,因爲信號不僅僅是混合在一個端口上,而是多個端口上。他們做了什麼,擲骰子的引腳?即使查找表幾乎不可用 - 即使您可以備用8KiB閃存。 – Olaf

回答

1

更好的代碼智能! 這裏有:

解決方案1:

struct param_t 
{ 
    uint8_t bitmask; 
    uint??_t gpio_port; 
    uint??_t gpio_pin; 
} 

const param_t param[XXXX] = 
{ 
    {0x01, GPIO_PORT_P4, GPIO_PIN2}, 
    {0x02, GPIO_PORT_P4, GPIO_PIN0}, 
    {...}, 
} 

void setOut(uint16_t data) 
{ 
    for(int i=0; i<XXXX; i++) 
    { 
    if(data & param[i].bitmask) 
    { 
     MAP_GPIO_setOutputHighOnPin(param[i].gpio_port, param[i].gpio_pin) 
    } 
    else 
    { 
     MAP_GPIO_setOutputLowOnPin(param[i].gpio_port, param[i].gpio_pin) 
    } 
    } 
} 

解決方案2:

const callback_t callback[2] = 
{ 
    MAP_GPIO_setOutputHighOnPin, 
    MAP_GPIO_setOutputLowOnPin 
} 

void setOut(uint16_t data) 
{ 
    callback[(int)(data & 0x01 == 0)](GPIO_PORT_P4, GPIO_PIN2}; 
    callback[(int)(data & 0x02 == 0)](GPIO_PORT_P4, GPIO_PIN0}; 
    ... 
} 

解決方案3:(不知道這是可能的)

之後,我假設MAP_GPIO_setOutputXxxxOnPin是慢。它讀取修改然後回寫寄存器。而不是在同一端口上多次調用該函數,您應該只讀一次,將其所有引腳修改爲在本地存儲器中,然後再寫回一次。

+0

也許這不是你想要的......如果速度是你想要的。告訴我,如果是這樣,我會刪除我的帖子 – Phong

+0

我添加了另一個解決方案,以避免if/else語句。注意確定它是否更快,但它可能會有所幫助。 – Phong

+0

第二種解決方案不起作用。 '(int)(data&0x02)'等於2(或零,當然!)。 –

0

Ooo,有很多優化的空間!

  1. 快速原料寄存器寫替換這個醜陋MAP_GPIO_setOutputXXX()

    include "msp432.h" // it is from TI DriverLib too 
    ... 
    if (data & 0x01) 
        P4OUT |= (1<<2); 
    else 
        P4OUT &= ~(1<<2); 
    // and so on ... 
    
  2. 相反位操作的,採用的Cortex核心功能bit banding

    // Convert SRAM address 
    #define BITBAND_SRAM_REF 0x20000000 
    #define BITBAND_SRAM_BASE 0x22000000 
    #define BITBAND_SRAM(a,b) HWREG32((BITBAND_SRAM_BASE + (&(a) - BITBAND_SRAM_REF)*32 + (b*4))) 
    
    // Convert PERI address 
    #define BITBAND_PERI_REF 0x40000000 
    #define BITBAND_PERI_BASE 0x42000000 
    #define BITBAND_PERI(a,b) HWREG32((BITBAND_PERI_BASE + (&(a) - BITBAND_PERI_REF)*32 + (b*4))) 
    
    ... 
    if (data & 0x01) 
        BITBAND_PERI (P4OUT, 2) = 1; 
    else 
        BITBAND_PERI (P4OUT, 2) = 0; 
    ... 
    
  3. 修改位段的方法,去除if()聲明。這是可能的,因爲對於位帶來說只寫最不重要的位就是問題。

    BITBAND_PERI (P4OUT, 2) = data >> 0; // bit 0 
    BITBAND_PERI (P4OUT, 0) = data >> 1; // bit 1 
    BITBAND_PERI (P6OUT, 1) = data >> 2; // bit 2 
    BITBAND_PERI (P2OUT, 7) = data >> 3; // bit 3 
    // etc