Orangepi Zero2使用外设驱动库wiringOP配合定时器驱动SG90舵机

目录

一、舵机的基本认知和硬件接线

[1.1 舵机的基本认知:](#1.1 舵机的基本认知:)

[1.2 硬件接线:](#1.2 硬件接线:)

[1.3 怎么控制舵机旋转不同的角度:](#1.3 怎么控制舵机旋转不同的角度:)

二、Linux定时器

[2.1 定时器setitimer()函数原型和头文件:](#2.1 定时器setitimer()函数原型和头文件:)

[2.2 信号处理函数signal()原型和头文件:](#2.2 信号处理函数signal()原型和头文件:)

[2.3 定时器setitimer()函数应用实例:](#2.3 定时器setitimer()函数应用实例:)

[2.4 使用wiringOP库配合定时器驱动舵机旋转0-180°:](#2.4 使用wiringOP库配合定时器驱动舵机旋转0-180°:)


一、舵机的基本认知和硬件接线

1.1 舵机的基本认知:

如下图所示:是一个SG90舵机 ,常用三根或者四根接线,红色为电源VCC棕色为电源GND黄色为PWM信号

控制用处:垃圾桶项目开盖用、智能小车的全比例转向、摄像头云台、机械臂等常见的有0-90°、0-180°、0-360°

1.2 硬件接线:

1.3 怎么控制舵机旋转不同的角度:

  • 向黄色信号线"灌入"PWM信号PWM波的频率不能太高,50hz ,即周期=1/频率=1/50=0.02s20ms左右数据:不同的PWM波形对应不同的旋转角度,以20ms为周期,50hz为频率的PWM波

定时器需要定时20ms,关心的单位0.5ms, 20ms = 0.5ms * 40

二、Linux定时器

2.1 定时器setitimer()函数原型和头文件:

cpp 复制代码
/*	setitimer 是一个UNIX系统上的系统调用函数,用于设置和管理定时器。它通常用于定期触发信号或执行某些操作	*/
#include <sys/time.h>

int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);

int 		函数返回值,成功执行时返回0,失败返回-1
    
int whic	指定要设置的定时器类型,可以是 ITIMER_REAL、ITIMER_VIRTUAL 或 ITIMER_PROF 中的一个
1. ITIMER_REAL 		//数值为0,计时器的值实时递减,发送的信号是SIGALRM。
2. ITIMER_VIRTUAL 	//数值为1,进程执行时递减计时器的值,发送的信号是SIGVTALRM。
3. ITIMER_PROF 		//数值为2,进程和系统执行时都递减计时器的值,发送的信号是SIGPROF。
    
struct itimerval *new_value		一个struct itimerval结构,用于指定新的定时器值。struct itimerval 结构定义如下:
    
struct itimerval {
        struct timeval it_interval;  // 定时器重复的间隔时间
        struct timeval it_value;     // 定时器的初始值
};

it_interval		计时器的初始值,一般基于这个初始值来加或者来减,看控制函数的参数配置
it_value		程序跑到这之后,多久启动定时器
    
struct timeval {  
        __time_t      tv_sec;   /* 秒 */  
        __suseconds_t tv_usec;  /* 微秒 */  
};

struct itimerval *old_value		一个struct itimerval 结构,用于存储旧的定时器值(可选参数)
    
/*
函数说明:
实现定时器,通过itimerval结构体以及函数setitimer产生的信号,系统随之使用signal信号处理函数来处理产生的定时信号。从而实现定时器。
*/

2.2 信号处理函数signal()原型和头文件:

cpp 复制代码
/*
	Linux下 man 2 signal查看手册
*/
#include <signal.h>
 
typedef void (*sighandler_t)(int);
 
sighandler_t signal(int signum, sighandler_t handler);
 
sighandler_t			函数返回值,返回信号处理程序的前一个值,或者在错误时SIG ERR。如果发生错误,则设置errno来指示原因。
 
int signum				指明了所要处理的信号类型,它可以取除了SIGKILL和SIGSTOP外的任何一种信号
 
sighandler_t handler	描述了与信号关联的动作,它可以取以下三种值:  
    
1. 一个无返回值的函数地址
此函数必须在signal()被调用前声明,handler中为这个函数的名字。当接收到一个类型为signum的信号时,就执行handler 所指定的函数。这个函数应有如下形式的定义:
void handler(int signum);
 
2. SIG_IGN
这个符号表示忽略该信号,执行了相应的signal()调用后,进程会忽略类型为sig的信号。
    
3. SIG_DFL
这个符号表示恢复系统对信号的默认处理。

2.3 定时器setitimer()函数应用实例:

实现的功能是:1秒后打开定时器,然后每隔一秒打印一次Hello

cpp 复制代码
#include <stdio.h>          // 包含标准输入输出库,用于输入输出操作
#include <sys/time.h>       // 包含时间处理库,用于获取系统时间
#include <stdlib.h>         // 包含标准库,用于内存分配和程序终止等操作
#include <signal.h>         // 包含信号处理库,用于处理系统信号

static int i = 0;                                                                               //全局变量i 

void signal_handler(int signum)                                                             //信号处理函数
{
    i++;
    if(i == 2000){                                                                             //每2000次触发一次
        printf("Hello\n");
        i = 0;
    }
}

int main()
{
    struct itimerval itv;                                               		//定义一个itimerval结构体变量

    //设定定时时间
    itv.it_interval.tv_sec = 0;
    itv.it_interval.tv_usec = 500;                                                     //每隔0.5毫秒触发一次 
    //设定启动定时器时间
    itv.it_value.tv_sec = 1;                                                             //启动定时器1秒后触发    
    itv.it_value.tv_usec = 0;               
    //设定定时方式
    //int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);
    if(setitimer(ITIMER_REAL, &itv, NULL) == -1){                                        //设置定时器  
        perror("setitimer");
        exit(-1);
    }
    //信号处理
    signal( SIGALRM, signal_handler);                                                     //设置信号处理函数

    while(1);
    
    return 0;
}

2.4 使用wiringOP库配合定时器驱动舵机旋转0-180°:

cpp 复制代码
#include <stdio.h>          // 包含标准输入输出库,用于输入输出操作
#include <sys/time.h>       // 包含时间处理库,用于获取系统时间
#include <stdlib.h>         // 包含标准库,用于内存分配和程序终止等操作
#include <signal.h>         // 包含信号处理库,用于处理系统信号
#include <wiringPi.h>       // 包含WiringPi库,用于控制GPIO

#define SG90Pin 5           // 定义SG90的引脚号

static int i = 0;                                                        	//全局变量i 
int jd;                                                                   	//全局变量jd 

void signal_handler(int signum)                                            	//信号处理函数
{
    if(i <= jd){
        digitalWrite(SG90Pin, HIGH);                        				//设置SG90引脚为高电平
    }else{
        digitalWrite(SG90Pin, LOW);                          				//设置SG90引脚为低电平
    }
    if(i == 40){                                                    //每40次信号处理函数被调用一次,输出一次当前时间
        i = 0;                                              				//i归零
    }
    i++;
}

int main()
{
    struct itimerval itv;                                                  	//定义一个itimerval结构体变量
    jd = 0;                                                                 //初始化jd为0    
    wiringPiSetup();                                                     	//初始化WiringPi库
    pinMode(SG90Pin, OUTPUT);                                             	//设置SG90引脚为输出模式

    //设定定时时间
    itv.it_interval.tv_sec = 0;
    itv.it_interval.tv_usec = 500;                                         	//每隔0.5毫秒触发一次 
    //设定启动定时器时间
    itv.it_value.tv_sec = 1;                                          		//启动定时器1秒后触发    
    itv.it_value.tv_usec = 0;               
    //设定定时方式
    //int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);
    if(setitimer(ITIMER_REAL, &itv, NULL) == -1){                      		//设置定时器  
        perror("setitimer");
        exit(-1);
    }
    //信号处理
    signal( SIGALRM, signal_handler);                                      	//设置信号处理函数

    while(1){
        printf("请输入你想要的角度: 1-0 2-45 3-90 4-135 5-180\n");
        scanf("%d",&jd);                                                 	 //输入角度   
    }
    
    return 0;
}
相关推荐
张文君3 分钟前
树莓派根目录满了可以使用外部存储吗
linux·ubuntu
m0_7471245321 分钟前
将QT移植到IMX6ULL开发板
linux·单片机·qt·imx6ull
起个别名28 分钟前
必须掌握的Linux的九大命令
linux·服务器·网络
结衣结衣.1 小时前
完全理解C语言函数
java·linux·c语言·数据库·经验分享·笔记
零K沁雪1 小时前
VirtualBox 安装 Ubuntu Server24.04
linux·运维·ubuntu
Hundreds_N1 小时前
kali改回官方源后更新失败
linux·kali
wenhui.wang1 小时前
Linux/Ubuntu访问局域网共享文件夹
linux·ubuntu
yannan201903132 小时前
【算法】(C语言):二分查找
c语言·算法
光亮§那方2 小时前
linux - cp 命令
linux·ubuntu
小龙在慢慢变强..2 小时前
C语言学习笔记--第一个程序
c语言·笔记·学习