分析:实现定时器,通过itimerval结构体以及函数setitimer产生信号,系统随之使用signal信号处理函数来处理产生的定时信号,从而实现定时器。
一、itimerval结构体原型
struct itimerval {
struct timeval it_interval; /* next value */ //定时器的初始值,一般基于这个初始值进行加\减,看控制函数具体参数设置
struct timeval it_value; /* current value */ //程序跑起来之后,多久启动定时器
};
用到的timeval结构体与先前获取当前的时间函数的第一个参数结构体类型相同( int gettimeofday(struct timeval* tv,struct timezone * tz ) )。
struct timeval结构体原型:
struct timeval
{
__time_t tv_sec; /* Seconds. */ //记录秒
__suseconds_t tv_usec; /* Microseconds. */ //记录微秒
};
二、setitimer处理函数原型:
#include <sys/time.h> //函数申明
int setitimer(int which,const struct itimerval *new_val,struct itimerval *old_value);
参数说明:
1、which:控制的方法(三种类型)
ITIMER_REAL:数值为0,计时器的值实时递减,发送的信号是:SIGALRM
ITIMER_VIRTUAL:数值为1,进程执行时递减计时器的值,发送的信号是:SIGVTALRM
ITIMER_FROF: 数值为2,进程和系统执行时都递减计时器的值,信号是:SIGPROF
2、new_val:配置的 struct itimerval结构体
3、old_value:记录上一次的定时的时间参量,一般不使用,指定NULL
返回值:成功执行时,返回0;失败,返回-1.
三、代码实例:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
static int i = 0;
void sighandler(int signal)
{
i++;
if(i == 2000){
printf("Hello World\n");
i = 0;
}
}
int main()
{
struct itimerval iTimer1;
iTimer1.it_interval.tv_sec = 0;
iTimer1.it_interval.tv_usec = 500; //初始值设置,决定了定时器的定时时间
iTimer1.it_value.tv_sec = 3;
iTimer1.it_value.tv_usec = 0; //程序跑到这之后多久启动
if(setitimer(ITIMER_REAL,&iTimer1,NULL) == -1){
perror("error\n");
exit(-1);
}
signal(SIGALRM, sighandler);
while(1);
return 0;
}
现象:循环间隔1s输出Hello World
=========配合SG90舵机的开发=========
分析:上方根据Linux定时器的开发,做到了固定的间隔时间循环输出,为了能够使SG90舵机得到不同的转向角度,需要用到定时器输出不同的PWM方波信号。PWM波的频率不能太高,50Hz,即周期 = 1/频率 = 1/50 = 0.02s,20ms左右的数据。
基本接线: 红色:5v
棕色:GND
橙色:信号
不同的方波对应不同的角度: t = 0.5ms——————-舵机会转动 0 °
t = 1.0ms——————-舵机会转动 45°
t = 1.5ms——————-舵机会转动 90°
t = 2.0ms——————-舵机会转动 135°
t = 2.5ms——————-舵机会转动180°
接线如图:
舵机控制代码:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
#include <wiringPi.h>
#define duoJi 0 //接线端,舵机的信号线接入香橙派zero 2的wiringPi引脚0.
static int i = 0;
int jd = 1; //角度控制变量
void sighandler()
{
i++;
if(i <= jd){
digitalWrite(duoJi,HIGH);
}else{
digitalWrite(duoJi,LOW);
}
if(i == 2000){
i = 0;
}
}
int main()
{
if(wiringPiSetup() == -1){
perror("wiringPi\n");
exit(-1);
}
pinMode(duoJi,OUTPUT);
struct itimerval iTimer1;
iTimer1.it_interval.tv_sec = 0;
iTimer1.it_interval.tv_usec = 500; //初始值设置,决定了定时器的定时时间
iTimer1.it_value.tv_sec = 1;
iTimer1.it_value.tv_usec = 0; //程序跑到这之后多久启动
if(setitimer(ITIMER_REAL,&iTimer1,NULL) == -1){
perror("error\n");
exit(-1);
}
signal(SIGALRM, sighandler);
while(1){
printf("1-0 / 2-45 / 3-90 / 4-135 / 5-180\n"); //循环输入,实现多角度
scanf("%d",&jd);
}
return 0;
}
======实现的结果======
0度
45度
180度
总结:Linux下的舵机开发与先前基于C51的开发没有太大区别,主要在于对Linux定时器开发的步骤的掌握。