【问题标题】:Efficiently Controlling a DAC with a micro controller使用微控制器有效控制 DAC
【发布时间】:2016-02-17 00:27:40
【问题描述】:

我有一个模拟设备的 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。

【问题讨论】:

  • 这就是为什么人们也应该在设计硬件时考虑一下。将接线更改为更智能的接线。
  • @Olaf 您的评论毫无用处,因为我已经指出布局超出了我的控制范围。
  • 不,你没有。仍然但是踢硬件设计师至少会带来一些满足感。几乎没有一种有效的方法可以使代码变得更好,甚至更多,因为信号不仅在单个端口上混合,而且在多个端口上混合。他们做了什么,为引脚排列掷骰子?即使是查找表也几乎无法使用 - 即使您可以节省 8KiB 闪存。
  • @Olaf 来自原始帖子“问题是电路板的布局需要我使用的特定端口/引脚分配。”布局使引脚分配非常适合启动板上的分线板。为什么 TI 决定按照他们的方式安排启动板引脚我永远不会知道。谢谢你们的cmets,我认为没有什么比我有更好的了
  • 你期待什么?您可以拉直引脚排列,也可以忍受蹩脚的开销软件。这就是我不喜欢评估板的原因。

标签: c embedded bit-manipulation microcontroller bit


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

【讨论】:

  • 也许这不是你想要的......如果速度是你想要的。告诉我,如果是,我会删除我的帖子
  • 我添加了另一个解决方案来避免 if/else 语句。请注意确定它是否更快,但它可能会有所帮助。
  • 第二种解决方案不起作用。 (int)(data &amp; 0x02) 等于 2(或零,当然!)。
【解决方案2】:

哎呀,还有很大的优化空间!

  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
    

【讨论】:

    猜你喜欢
    • 2011-02-24
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-08
    相关资源
    最近更新 更多