使用微控制器高效控制DAC

时间:2016-02-17 00:27:41

标签: c embedded bit-manipulation microcontroller bit

我有一个模拟设备的DAC8562。这是一份数据表:

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。

2 个答案:

答案 0 :(得分: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很慢。它读取修改然后写回寄存器。您应该在同一端口上多次调用该函数,而不是在同一端口上多次调用该函数,在内存中本地修改其所有引脚,然后再将其写回一次。

答案 1 :(得分:0)

哦,有很多优化空间!

  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