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

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

写入数字输入: gpio set/clear x
从数字输出gpio read xgpio read x
从数字输出adc read xadc read x
(x:密码)

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

  • 打开设备
  • 睡觉
  • 写入器件低电平模式(t0)
  • 睡觉
  • 写入设备高模式
  • 睡觉
  • 写入设备低电平模式(t1)

句号=(t1 – t0)

这是方波吗?

看来你的例子确实是方波

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

去犯罪浪潮

使用DACPWM + RC滤波器和一些预先计算的幅度表,其中索引周期性地增加。

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

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

 int ix=0' 

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

 ix=(ix+1)&31; 

如果最终到达(sintab必须是2的大小幂),那么31和41只会导致索引从重新开始循环。 周期是定时器频率/ sintab大小

[笔记]

您可以将此修改为您的目的,例如make sintab[][]是一个2D数组,其中第一个索引表示振幅,第二个索引表示ix 。 在较旧的平台(MCU)上,您可以将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];一样将实际幅度发送给它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与地并联)。 如果你想驱动一些线圈(电机),那么你不需要filter。 这种用途通常会产生机械附近经常听到的高音(PWM频率)……

    IMG

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

一些带有幅度和频率设置的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; } }