一、wiringPi外设SDK安装
git clone https://github.com/orangepi-xunlong/wiringOP | //下载源码 |
cd wiringOP | //进入文件夹 |
sudo ./build clean | //清除编译信息 |
sudo ./build | //编译 |
验证指令: gpio readall
二、蜂鸣器开发
1 .蜂鸣器响的原理
基本IO口的应用
2.蜂鸣器配合时间函数开发
#include <stdio.h>
#include <wiringPi.h>
#include <unistd.h>
#define BEEP 0 //设置针脚0为蜂鸣器的控制引脚
int main (void)
{
wiringPiSetup () ;//初始化wiringPi库i
pinMode (BEEP, OUTPUT) ;//设置IO口的输入输出,输出
while(1){
//sleep(1);
usleep(100000);
digitalWrite (BEEP, HIGH) ; //设置IO口输出低电平,蜂鸣器响
//sleep(1);
usleep(100000);
digitalWrite (BEEP, LOW) ; //设置IO口输出低电平,蜂鸣器响
}
return 0;
}
•小插曲:修改按下tap键4个字间隔
sudo vim /etc/vim/vimrc
set tabstop=4 设置tab键缩进4个空格
set shiftwidth=4 设置批量对齐时候的tab键空格数为4
•shell脚本小插曲:
shell脚本处理参数,可以通过$?来处理,这里的$1是要编译的文件
vi build.sh
gcc $1 -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt
三、超声波测距
1.测距原理
•怎么让它发波?
Trig,给Trig端口至少10us的高电平
•怎么知道开始发了?
Echo信号,由低电平跳转到高电平,表示开始发送波
•怎么知道接收了返回波?
Echo,由高电平跳转回低电平,表示波回来了
•怎么算时间?
Echo引脚维持高电平的时间!
波发出去的那一下,开始启动定时器
波回来的拿一下,我们开始停止定时器,计算出中间经过多少时间
•怎么算距离?
距离=速度(340m/s)*时间/2
![](https://i-blog.csdnimg.cn/blog_migrate/e46e660c6608dc501f9a871f404e4c65.png)
2.编程开发
a.时间函数
#include<sys/time.h>
int gettimeofday(struct timeval *tv,struct timezone *tz )
gettimeofday()会把目前的时间用tv 结构体返回,当地时区的信息则放到tz所指的结构中
struct timeval
{
long tv_sec;/*秒*/
long tv_usec;/*微妙*/
};
b.编程实现
#include <stdio.h>
#include <sys/time.h>
#include <wiringPi.h>
#include <stdlib.h>
#include <unistd.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);//低
/*above init CSB*/
while(!digitalRead(Echo));//等待Echo高电平,表示波回来了
gettimeofday(&start,NULL);
while(digitalRead(Echo));//等待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舵机开发
![](https://i-blog.csdnimg.cn/blog_migrate/04bad54e8822800f8f6d5ad91e197589.png)
1.转动原理
向黄色信号线“灌入”PWM信号。
PWM波的频率不能太高,50hz,即周期=1/频率=1/50=0.02s,20ms左右数据:不同的PWM波形对应不同的旋转角度,以20ms为周期,50hz为频率的PWM波。
定时器需要定时20ms,关心的单位0.5ms, 20ms = 0.5ms * 40。
2.Linux定时器
分析:实现定时器,通过itimerval结构体以及函数setitimer产生的信号,系统随之使用signal信号处理函数来处理产生的定时信号。从而实现定时器。
(1)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. */
};
(2)setitimer 函数
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
3.SG90编程实现
键盘输入不同的值,让舵机转动,软件PWM实现
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <signal.h>
#include <wiringPi.h>
#define SG90Pin 5
int jd;
static int i = 0;
void signal_handler(int signum)
{
if(i <= jd){
digitalWrite(SG90Pin, HIGH);
}else{
digitalWrite(SG90Pin, LOW);
}
if(i == 40){
i = 0;
}
i++;
}
int main()
{
struct itimerval itv;
jd = 0;
wiringPiSetup();
pinMode(SG90Pin, OUTPUT);
//设定开始生效,启动定时器的时间
itv.it_value.tv_sec = 1;
itv.it_value.tv_usec = 0;
//设定定时时间
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 500;
//设定定时方式
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;
}
五、OLED屏应用-IIC协议
1.Orangepi的IIC接口
由 26pin 的原理图可知, Orange Pi Zero 2 可用的 i2c 为 i2c3
•启动 linux 系统后, 先确认下/dev 下存在 i2c-3 的设备节点
•开始测试 i2c, 首先安装 i2c-tools
sudo apt-get install i2c-tools
2. 实战OLED屏幕开发
利用SourceInsight进行源码阅读
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include "oled.h"
#include "font.h"
int oled_show(struct display_info *disp)
{
int i;
char buf[100];
oled_putstrto(disp, 0, 9+1, "Welcome to My HomeAssitant");
disp->font = font2;
oled_putstrto(disp, 0, 20, " ---Mr.chen HenShuai--- ");
disp->font = font2;
oled_send_buffer(disp);
return 0;
}
void show_error(int err, int add)
{
printf("\nERROR: %i, %i\n\n", err, add);
}
void show_usage(char *progname)
{
printf("\nUsage:\n%s <I2C bus device node >\n", progname);
}
int main(int argc, char **argv)
{
int e;
char filename[32];
struct display_info disp;
if (argc < 2) {
show_usage(argv[0]);
return -1;
}
memset(&disp, 0, sizeof(disp));
sprintf(filename, "%s", argv[1]);
disp.address = OLED_I2C_ADDR;
disp.font = font2;
e = oled_open(&disp, filename);
e = oled_init(&disp);
oled_show(&disp);
return 0;
}
六、Linux串口开发
原生串口开发
uartTool.c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "wiringSerial.h"
int myserialOpen (const char *device, const int baud)
{
struct termios options ;
speed_t myBaud ;
int status, fd ;
switch (baud){
case 9600: myBaud = B9600 ; break ;
case 115200: myBaud = B115200 ; break ;
}
if ((fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1)
return -1 ;
fcntl (fd, F_SETFL, O_RDWR) ;
// Get and modify current options:
tcgetattr (fd, &options) ;
cfmakeraw (&options) ;
cfsetispeed (&options, myBaud) ;
cfsetospeed (&options, myBaud) ;
options.c_cflag |= (CLOCAL | CREAD) ;
options.c_cflag &= ~PARENB ;
options.c_cflag &= ~CSTOPB ;
options.c_cflag &= ~CSIZE ;
options.c_cflag |= CS8 ;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;
options.c_oflag &= ~OPOST ;
options.c_cc [VMIN] = 0 ;
options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds)
tcsetattr (fd, TCSANOW, &options) ;
ioctl (fd, TIOCMGET, &status);
status |= TIOCM_DTR ;
status |= TIOCM_RTS ;
ioctl (fd, TIOCMSET, &status);uartTool.h
usleep (10000) ; // 10mS
return fd ;
}
void serialSendstring (const int fd, const char *s)
{
int ret;
ret = write (fd, s, strlen (s));
if (ret < 0)
printf("Serial Puts Error\n");
}
int serialGetstring (const int fd, char *buffer)
{
int n_read;
n_read = read(fd, buffer,32);
return n_read;
}
uartTool.h
int myserialOpen (const char *device, const int baud);
void serialSendstring (const int fd, const char *s);
int serialGetstring (const int fd, char *buffer);
uartTest.c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pthread.h>
#include "uartTool.h"
int fd;
void* readSerial()
{
char buffer[32];
while(1){
memset(buffer,'\0',sizeof(buffer));
serialGetstring(fd, buffer);
printf("GET->%s\n",buffer);
}
}
void* sendSerial()
{
char buffer[32];
while(1){
memset(buffer,'\0',sizeof(buffer));
scanf("%s",buffer);
serialSendstring(fd, buffer);
}
}
int main(int argc, char **argv)
{
char deviceName[32] = {'\0'};
pthread_t readt;
pthread_t sendt;
if(argc < 2){
printf("uage:%s /dev/ttyS?\n",argv[0]);
return -1;
}
strcpy(deviceName, argv[1]);
if( (fd = myserialOpen(deviceName, 115200)) == -1){
printf("open %s error\n",deviceName);
return -1;
}
pthread_create(&readt, NULL, readSerial,NULL);
pthread_create(&sendt, NULL, sendSerial,NULL);
while(1){sleep(10);}
return 0;
}