全志之时间函数、定时器(蜂鸣器、超声波、SG90舵机)

前期准备:

wiringPi外设SDK安装

方法一:

git clone https://github.com/orangepi-xunlong/wiringOP //下载源码 
cd wiringOP //进入文件夹 
sudo ./build clean //清除编译信息 
sudo ./build //编译

方法二:

通过windows浏览器打开https://github.com/orangepi-xunlong/wiringOP 
下载压缩包 把压缩包通过xterm传到开发板 
解压 unzip xxx.zip 
cd xxx sudo 
./build 
gpio readall//验证指令



如下图,这样就完成了:
在这里插入图片描述

vim的设置,修改/etc/vim/vimrc文件,需要用超级用户权限

sudo vim /etc/vim/vimrc 
set tabstop=4 设置tab键缩进4个空格 
set shiftwidth=4 设置批量对齐时候的tab键空格数为4

shell脚本

shell脚本处理参数,可以通过$?来处理,这里的$1是要编译的文件

vi build.sh
//简易编译的shell脚本: 
gcc $1 -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt
chmod +x build.sh//加权限

蜂鸣器的开发

在这里插入图片描述

#include <stdio.h>
#include <wiringPi.h>
#include <unistd.h>
#define BEEP 0

int main()
{
    wiringPiSetup();//初始化wiringPi库
    pinMode(BEEP,OUTPUT); //设置IO口的输出
    while(1){
        //sleep(1);
        usleep(1000000);
        digitalWrite(BEEP,HIGH);//设置IO口输出高电平

        usleep(1000000);
        digitalWrite(BEEP,LOW);//设置IO口输出低电平,蜂鸣器响
    }

    return 0;

}

超声波测距

测距原理基本说明

超声波测距模块是用来测量距离的一种产品,通过发送和收超声波,利用时间差和声音传播速度,
计算出模块到前方障碍物的距离
在这里插入图片描述
型号:HC-SR04
接线参考:模块除了两个电源引脚外,还有TRIG,ECHO引脚
在这里插入图片描述
怎么让它发波
Trig,给Trig端口至少10us的高电平

怎么知道开始发了
Echo信号,由低电平跳转到高电平,表示开始发送波

怎么知道接收了返回波
Echo,由高电平跳转回低电平,表示波回来了

怎么算时间
Echo引脚维持高电平的时间!
波发出去的那一下,开始启动定时器
波回来的拿一下,我们开始停止定时器,计算出中间经过多少时间

怎么算距离
距离=速度(340m/s)*时间/2

时序
在这里插入图片描述

时间函数

函数原型

#include<sys/time.h>
int gettimeofday(struct timeval *tv,struct timezone *tz )
gettimeofday()会把目前的时间用tv 结构体返回,当地时区的信息则放到tz所指的结构中测试代码

struct timeval { 
long tv_sec;/*秒*/ 
long tv_usec;/*微妙*/ 
};

测试代码

#include <stdio.h>
#include <sys/time.h>


//计算程序在当前环境中数数10万次耗时多少
void mydelay()
{
    int i,j;
    for(i=0;i<100;i++)
        for(j=0;j<100;j++);

}


int main()
{
    struct timeval startTime;
    struct timeval stopTime;

    gettimeofday(&startTime,NULL);

    mydelay();

    gettimeofday(&stopTime,NULL);

    long diffTime = 1000000*(stopTime.tv_sec - startTime.tv_sec)+(stopTime.tv_usec-startTime.tv_usec);

    printf("全志H6的Linux数100000耗时:%ldus\n",diffTime);

    return 0;

}

代码实现:

#include <stdio.h>
#include <wiringPi.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>

#define Trig 0
#define Echo 1

double getDistance()
{
	double dis;

	struct timeval start;
	struct timeval stop;

	pinMode(Trig,OUTPUT);
	pinMode(Echo,INPUT);
	
	//超声波发波
	digitalWrite(Trig,LOW);
	usleep(5);
	digitalWrite(Trig,HIGH);
	usleep(10);
	digitalWrite(Trig,LOW);
	//计算波回来的时间
	while(!digitalRead(Echo));
	gettimeofday(&start,NULL);
	while(digitalRead(Echo));
	gettimeofday(&stop,NULL);

	long diffTime = 1000000*(stop.tv_sec-start.tv_sec)+(stop.tv_usec - start.tv_usec);

	printf("diffTime = %ld\n",diffTime); 
	//计算波的距离
	dis = (double)diffTime/1000000 * 34000 / 2; 
	
	return dis;


}




int main()
{
	double dis;


	if(wiringPiSetup()== -1){
		fprintf(stderr,"%s","initWringPi error");
		exit(-1);
	}

	while(1){
	
		dis = getDistance();
		printf("dis = %lf\n",dis);
		usleep(500000);

	}


	return 0;
}


SG90舵机开发

舵机基本介绍

如下图所示,最便宜的舵机sg90,常用三根或者四根接线,黄色为PWM信号控制用处:垃圾桶项目开盖
用、智能小车的全比例转向、摄像头云台、机械臂等
常见的有0-90°、0-180°、0-360°

在这里插入图片描述
怎么控制转角

向黄色信号线“灌入”PWM信号。
PWM波的频率不能太高,50hz,即周期=1/频率=1/50=0.02s,20ms左右数据:
不同的PWM波形对应不同的旋转角度,以20ms为周期,50hz为频率的PWM波
在这里插入图片描述
定时器需要定时20ms,关心的单位0.5ms, 20ms = 0.5ms * 40:

Linux定时器

分析:实现定时器,通过itimerval结构体以及函数setitimer产生的信号,系统随之使用signal信号处理
函数来处理产生的定时信号。从而实现定时器。
先看itimerval的结构体

struct itimerval {
    /* Value to put into `it_value' when the timer expires. */ 
	struct timeval it_interval; 
	/* Time to the next timer expiration. */ 
	struct timeval it_value; 
}; 

it_interval:计时器的初始值,一般基于这个初始值来加或者来减,看控制函数的参数配置 
it_value:程序跑到这之后,多久启动定时器 

struct timeval { 
	__time_t tv_sec; /* Seconds. */
	__suseconds_t tv_usec; /* Microseconds. */ };

int setitimer (__itimer_which_t __which, const struct itimerval *__restrict __new, struct itimerval *__restrict __old)

setitimer()将value指向的结构体设为计时器的当前值,如果ovalue不是NULL,将返回计时器原有值。

which:三种类型
ITIMER_REAL //数值为0,计时器的值实时递减,发送的信号是SIGALRM。
ITIMER_VIRTUAL //数值为1,进程执行时递减计时器的值,发送的信号是SIGVTALRM。
ITIMER_PROF //数值为2,进程和系统执行时都递减计时器的值,发送的信号是SIGPROF。

很明显,这边需要捕获对应的信号进行逻辑相关处理 signal(SIGALRM,signal_handler);
返回说明:
成功执行时,返回0。失败返回-1

测试代码

/*该代码实现的功能是: 1s后开启定时器,然后每隔1s向终端打印hello。*/
#include <stdio.h> 
#include <sys/time.h> 
#include <stdlib.h> 
#include <signal.h>

void signal_handler()
{
	i++; 
	if(i == 2000){ 
	printf("hello\n"); 
	i = 0; 
	}

}	



int main()
{
	struct itimerval itv;



	//设定定时时间
	itv.it_interval.tv_sec  = 0;
	itv.it_interval.tv_usec = 500;
	//设定开始生效,启动定时器的时间
	itv.it_value.tv_sec = 1;
	itv.it_value.tv_usec = 0;



	//设定定时方式
	if(-1 == setitimer(ITIMER_REAL,&itv,NULL)){
		perror("error"); 
		exit(-1);
	}

	//信号处理
	signal(SIGALRM,signal_handler);

	while(1);

	return 0;
}

实现代码

//SG90编程实现:键盘输入不同的值,让舵机转动,软件PWM实现
#include <stdio.h>
#include <sys/time.h>
#include <wiringPi.h>
#include <stdlib.h> 
#include <signal.h>

#define SG90Pin 2  

int jd = 0;

static int i = 0;

void signal_handler()
{
	if(i <= jd){ 
		digitalWrite(SG90Pin, HIGH);
	}else{
		digitalWrite(SG90Pin, LOW);
	}if(i == 40){
		i = 0;
	}

	i++;

}	



int main()
{
	struct itimerval itv;

	wiringPiSetup();
	pinMode(SG90Pin, OUTPUT);

	//设定定时时间
	itv.it_interval.tv_sec  = 0;
	itv.it_interval.tv_usec = 500;
	//设定开始生效,启动定时器的时间
	itv.it_value.tv_sec = 1;
	itv.it_value.tv_usec = 0;



	//设定定时方式
	if(-1 == setitimer(ITIMER_REAL,&itv,NULL)){
		perror("error"); 
		exit(-1);
	}

	//信号处理
	signal(SIGALRM,signal_handler);

	while(1){ 
		printf("input jd: 1-0 2-45 3-90 4-135 \n"); scanf("%d",&jd); 
	}


	return 0;
}

这种方法需要注意的是,一个进程只能创建一个定时器

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈学弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值