我有一个设备,它有数字 I/O、模拟 I/O。我向设备发送以下命令进行通信。设备具有 gpio 模块。我的设备文档在这里
写入数字输入:gpio set/clear x
从数字输出gpio read x
读取:从数字输出读取:adc read x
(x:引脚编号)
如何创建正弦波/方波并计算幅度?创建方波:
- 打开设备
- 睡觉
- 写入设备低模式(t0)
- 睡觉
- 写入设备高模式
- 睡觉
- 写入设备低模式(t1)
期间 = (t1 - t0)
这是方波吗?
我有一个设备,它有数字 I/O、模拟 I/O。我向设备发送以下命令进行通信。设备具有 gpio 模块。我的设备文档在这里
写入数字输入:gpio set/clear x
从数字输出gpio read x
读取:从数字输出读取:adc read x
(x:引脚编号)
如何创建正弦波/方波并计算幅度?创建方波:
期间 = (t1 - t0)
这是方波吗?
看来你的例子确实是方波
如果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
是+1
和0
是-1
;现在只需添加一些索引:
int ix=0'
偶尔(可能在某个计时器上)增加它并将输出设置为新值:
ix=(ix+1)&31;
如果到达结束,31
只会导致重新从开始循环索引(sintab 的大小必须为 2)。周期是定时器频率/sintab 大小
[笔记]
您可以根据您的目的对其进行修改,例如制作sintab[][]
一个二维数组,其中第一个索引表示幅度,第二个是ix
现在。在较旧的平台(MCU)上,您可以直接对PWM序列进行编码以sintab
结束,依此类推...
您可以像这样预先计算sintab
值:
sintab[ix]=128.0+127.0*sin(float(2.0*M_PI*ix)/32.0);
或者,如果您的平台支持足够快,sin
您可以直接使用上面的行,而不需要实际的数组...
[编辑1]
因为sinwave
你可以只使用0/1
状态。如果您需要模拟输出并且:
你有 DAC(数模转换器)
然后将实际幅度发送给它,这样dac write sintab[ix];
将为您在输出引脚上创建模拟电压。
您没有任何备用 DAC,而是使用 PWM 脉冲宽度调制
避免使用DAC并且仍然具有来自数字引脚的模拟输出是一个老派的技巧。它是这样工作的:
输出值是每个时间块的累积能量/电压,因此您可以生成方波信号
输出为H的时间越多,输出值越大。这仍然是数字输出,但如果您在其上连接任何非线性设备,如电容器或线圈,energy inertia
则会导致 H 电压下降到取决于方波比的某个水平。最常见的是RC滤波器(R是串联的,C是与地并联的)。如果你想驱动一些线圈(电机),那么你不需要滤波器。这种使用通常会产生在机械附近经常听到的高音(PWM频率)......
PWM频率必须足够高(比正弦波频率高很多倍)
具有幅度和频率设置的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;
}
}