在软件上为模拟输入/输出生成方波

时间:2014-11-15 15:36:35

标签: c driver analog-digital-converter digital-analog-converter

我有一个设备,它有数字i / o,模拟i / o。我发送到设备下面的命令进行通信。设备有gpio模块。我的设备文档是here

写入数字输入:gpio set/clear x
从数字输出中读取:gpio read x
从数字输出中读取:adc read x
(x:密码)

如何创建正弦波/方波并计算幅度?要创建方波:

  • 打开设备
  • 睡眠
  • 写入设备低模式(t0)
  • 睡眠
  • 写入设备高模式
  • 睡眠
  • 写入设备低模式(t1)

期间=(t1 - t0)

这是方波吗?

1 个答案:

答案 0 :(得分:1)

看起来你的例子确实是方波

如果write to device low mode(t0)将输出引脚设置为低电平且write to device low mode(t1)设置为高电平或反向电压,则周期为睡眠总和+设置 GPIO 状态的时间。不知道为什么你有时间在 GPIO 设置行内,而不是在睡眠中...(可能是平台依赖的东西?)

去犯罪浪潮

使用 DAC PWM + RC滤波器和一些预先计算的幅度表,其中索引会定期增加。

BYTE sintab[32]={ 128,...,255,...,128,...,0,....,127  };

已编码:128为零,255+10-1;现在只需添加一些索引:

int ix=0'

并偶尔(在一些计时器上)增加它并将输出设置为新值:

ix=(ix+1)&31;

那和31只是因为如果达到结束而使索引从重新开始循环(sintab必须是2的大小幂)。周期是定时器频率/ sintab大小

<强> [注释]

您可以将此修改为您的目的,例如make sintab[][]一个2D数组,其中第一个索引表示振幅,第二个索引是ix。在较旧的平台(MCU&#39; s)上,您可以将 PWM 序列直接编码到sintab端,等等......

您可以预先计算sintab这样的值:

sintab[ix]=128.0+127.0*sin(float(2.0*M_PI*ix)/32.0);

或者如果您的平台支持足够快sin,您可以在没有实际数组的情况下直接使用上面的行...

<强> [EDIT1]

对于sinwave,您只能使用0/1个州。如果您需要模拟输出并且:

  1. 您有DAC(数模转换器)

    然后将实际幅度发送到它dac write sintab[ix];,这将为您在输出引脚上创建模拟电压。

  2. 您没有任何备用DAC使用PWM脉冲宽度调制

    这是一个老派的伎俩,以避免需要 DAC ,并且仍然具有来自数字引脚的模拟输出。它的工作原理如下:

    输出值是每个时间块的累积能量/电压,因此您可以生成方波信号

    • 比率1:1表示半个周期为H,其余为L
    • 比率2:1表示期间的2/3为H,其余为L

    输出H越多,输出值越大。这仍然是数字输出,但如果连接任何非线性器件,如电容器或线圈,则energy inertia将导致H电压降至某个水平,具体取决于方波比。最常见的是 RC 过滤器( R 是串行的, C 与地面平行)。如果你想驱动一些线圈(电机),那么你不需要过滤器。这种使用通常会产生在机械附近经常听到的高音(PWM频率)......

    img

    PWM 频率必须足够高(比sinwave频率高很多倍)

  3. 带有幅度和频率设置的 PWM 的一些代码:

    const int timer_T=1;        // used timer interval [ms]
    const int PWM_max=10;       // PWM max amplitude+1 
    int PWM_s=0;                 // PWM actual step
    int PWM_t=0;                 // PWM actual time
    
    int PWM_a=3;                 // PWM amplitude <0,PWM_ratio_max)
    int PWM_T=200;               // PWM period [ms]
    
    void OnTimer()
     {
     int PWM_T0=PWM_T/PWM_max; // PWM step period must be >=1 !!!
     PWM_t+=timer_T;
     if (PWM_t>=PWM_T0)
      {
      if (PWM_s<=pwm_a) gpio set x; else gpio clear x;
      PWM_s++; if (PWM_s>=PWM_max) PWM_s=0;
      PWM_t-=PWM_T0;
      }
     }