我想用第一代RPI的gpio输出生成平方信号。
为此,我首先想使用wiringPi。
代码语言是固定的,应为C或C ++。
根据wireingPi的眨眼示例文档,解决方案应该很简单:
#include <wiringPi.h>
int main (void)
{
wiringPiSetup () ;
pinMode (0, OUTPUT) ;
for (;;)
{
digitalWrite (0, LOW) ; delay (500) ;
digitalWrite (0, HIGH) ; delay (500) ;
}
return 0 ;
}
但是我希望它们之间有约600微秒的暂停时间。
因此,我创建了另一个 delay 方法:
void myDelay(long int usec) {
struct timespec ts, rem;
ts.tv_sec = 0;
ts.tv_nsec = usec * 1000;
while (clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &rem)) {
ts = rem;
}
}
然后我将2个 delay(500)切换为 myDelay(600)。
这通常可以正常工作,但是有时myDelay等待600毫秒以上。
我如何在C / C ++中具有完全相同的平方?
我还尝试了pigpio的Python脚本:
pi = pigpio.pi()
pi.wave_add_new()
pi.set_mode(1, pigpio.OUTPUT)
wf=[]
for i in range (0, 100):
wf.append(pigpio.pulse(0, 1<<1, 600))
wf.append(pigpio.pulse(1<<1, 0, 600))
wf.append(pigpio.pulse(0, 1<<1, 1000))
pi.wave_add_generic(wf)
wid = pi.wave_create()
pi.wave_send_once(wid)
while pi.wave_tx_busy():
pass
pi.wave_delete(wid)
pi.stop()
此python给出了预期的结果(即:作用域上的所有平方均相等)。
现在的问题是,我怎么能用纯C / C ++实现获得相同的结果(而不必弄乱gpioWave *函数)?
答案 0 :(得分:2)
我通常喜欢睡到绝对的时间。剩余时间在不同平台上的处理方式有所不同,所以我尽量避免这种情况。
inline timespec init_clock() {
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts); // or try using CLOCK_MONOTONIC_RAW
return ts;
}
inline void add_usec(timespec& ts, long int usec) {
ts.tv_nsec += usec * 1000;
time_t sec = ts.tv_nsec / 1000000000;
ts.tv_sec += sec;
ts.tv_nsec -= sec * 1000000000;
}
inline void myDelay(long int usec) {
timespec ts = init_clock();
add_usec(ts, usec);
while(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, nullptr));
}
另一件事可能是测量自上次循环以来的时间。由于系统中的其他事件,这将消除许多模糊性。然后,只需将通话设置为static
,即可节省两次通话之间的时钟:
inline void myDelay(long int usec) {
static timespec ts = init_clock();
add_usec(ts, usec);
while(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, nullptr));
}
上述两种组合也可以使用标准C ++库<chrono>
完成。此示例节省了两次调用之间的时钟,从而获得了更准确的方波:
#include <wiringPi.h>
#include <chrono>
#include <thread>
inline void myDelay2(std::chrono::microseconds sleep_time) {
static auto cl = std::chrono::steady_clock::now();
cl += sleep_time;
std::this_thread::sleep_until(cl);
}
int main() {
using namespace std::literals::chrono_literals;
while(true) {
digitalWrite (0, LOW) ; myDelay2(600us) ;
digitalWrite (0, HIGH) ; myDelay2(600us) ;
}
}
答案 1 :(得分:2)
看看clock_nanosleep
的说明(摘自http://man7.org/linux/man-pages/man2/clock_nanosleep.2.html,重点是我的内容)
clock_nanosleep()暂停调用线程的执行,直到经过至少由请求指定的时间,或者传递了导致导致信号处理程序被调用或终止进程的信号为止
也就是说,唯一的保证是您至少会睡600微秒-但对于您最终会睡多长时间没有任何上限。
我假设您正在RaspberryPi上运行默认的Linux发行版之一。除了您的应用程序外,Linux还运行许多其他功能,默认情况下,Linux不是所谓的实时操作系统。在这种意义上,实时并不意味着性能(就其运行或处理数据的速度而言),而是要保证最大的等待上限(如上述)。
如果您想更贴近自己的需求,可以尝试以下一项或两项:
sched_setscheduler()
(http://man7.org/linux/man-pages/man2/sched_setscheduler.2.html)答案 2 :(得分:0)
这可能是由于delay()的实现方式所致。在操作系统环境中,最好将睡眠用于延迟时间超过非常短的间隔的任务。这会使任务经历排定的延迟,该延迟可能比请求的延迟长,以允许其他等待任务有时间运行。但是,通常不会抢先暂停它们以使先前的任务在睡眠到期时继续执行。在这种情况下,睡眠是最短时间保证的时间,然后再运行。
在操作系统之外,延迟通常是繁忙等待,因此在无法中断的情况下是可靠的。