赞
踩
方式一:
git clone https://github.com/orangepi-xunlong/wiringOP //下载源码
cd wiringOP //进入文件夹
sudo ./build clean //清除编译信息
sudo ./build //编译
方式二
通过windows浏览器打开https://github.com/orangepi-xunlong/wiringOP
下载压缩包
把压缩包通过mobaxterm传到开发板
解压 unzip xxx.zip
cd xxx
sudo ./build
gpio readall
验证指令:gpio readall
如下图所示,外设库就完成安装了
置低电平响
置高电平不响
#include<stdio.h> #include<wiringPi.h> #include<unistd.h> #define BEEP 2 // 设置2引脚为蜂鸣器控制引脚 int main(void) { wiringPiSetup(); // 初始化wriping库 pinMode(BEEP, OUTPUT); // 设置蜂鸣器为输出引脚 while(1) { digitalWrite(BEEP, LOW); // 输出低电平 sleep(5); break; } digitalWrite(BEEP,HIGH); return 0; }
#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; }
如果你在vim的环境编辑,方便缩进可以修改一下缩进
vim的设置,修改/etc/vim/vimrc文件,需要用超级用户权限
sudo vim /etc/vim/vimrc
set tabstop=4 设置tab键缩进4个空格
set shiftwidth=4 设置批量对齐时候的tab键空格数为4
不过我在这里更推荐vscode编写,http://t.csdn.cn/GdZte,远程开发
shell脚本小插曲
./build beep.c
$0 $1
shell脚本处理参数,可以通过$?来处理,这里的$1是要编译的文件
简易编译的shell脚本:
gcc $1 -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt
1. 怎么让它发波 Trig,给Trig端口至少10us的高电平 2. 怎么知道开始发了 Echo信号,由低电平跳转到高电平,表示开始发送波 3. 怎么知道接收了返回波 Echo,由高电平跳转回低电平,表示波回来了 4.怎么算时间 Echo引脚维持高电平的时间! 5. 波发出去的那一下,开始启动定时器 波回来的拿一下,我们开始停止定时器,计算出中间经过多少时间 6. 怎么算距离 距离=速度(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;/*微妙*/
};
测试代码
//计算程序在当前环境中数数10万次耗时多少 #include <sys/time.h> #include <stdio.h> //int gettimeofday(struct timeval *tv,struct timezone *tz ) void mydelay() { int i,j; for(i=0;i<100;i++){ for(j=0;j<1000;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 <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)); 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,常用三根或者四根接线,黄色为PWM信号控制用处:垃圾桶项目开盖用、智能小车的全比例转向、摄像头云台、机械臂等常见的有0-90°、0-180°、0-360°
分析:实现定时器,通过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> static int i; void signal_handler(int signum) { 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; //设定定时方式 if( -1 == setitimer(ITIMER_REAL, &itv, NULL)){ perror("error"); exit(-1); } //信号处理 signal(SIGALRM,signal_handler); while(1); return 0; }
这种方法需要注意的是,一个进程只能创建一个定时器
#include<stdio.h> #include<sys/time.h> #include<stdlib.h> #include<signal.h> #include<wiringPi.h> #define SG90pin 8 int jd; void signal_handler(int signum) { static int i=0; if(i<=jd) { digitalWrite(SG90pin,HIGH); } else { digitalWrite(SG90pin,LOW); } if(i==40) { i=0; } i++; } int main() { struct itimerval itv; jd=0; if(wiringPiSetup()==-1) { perror("error"); exit(-1); } pinMode(SG90pin,OUTPUT); //1.设定定时时间 itv.it_interval.tv_sec=0; itv.it_interval.tv_usec=500; //2.设定开始生效,启动定时器的时间 itv.it_value.tv_sec=1; itv.it_value.tv_usec=0; //3.设定定时方式 if(setitimer(ITIMER_REAL,&itv,NULL)==-1) { perror("error"); exit(-1); } //4.信号处理 signal(SIGALRM,signal_handler); while(1) { printf("input jd:1 -0 2-45 3-90 4-135 5-180\n"); scanf("%d",&jd); } return 0; }
IIC全称Inter-Integrated Circuit (集成电路总线)
是由PHILIPS公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备。IIC属于半双
工同步通信方式
由于接口直接在组件之上,因此IIC总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降
低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件
其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。
IIC总线在传输数据的过程中一共有三种类型信号,分别为:开始信号、结束信号和应答信号。
//起始位,停止位,数据位,速度
这些信号中,起始信号是必需的,结束信号和应答信号
起始信号
终止信号
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Asg0RIiB-1688746961767)(C:\Users\xie19\Pictures\Camera Roll\屏幕截图 2023-07-07 234444.png)]
应答信号
发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。
应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;
应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6ysoeEZE-1688746961767)(C:\Users\xie19\Pictures\Camera Roll\屏幕截图 2023-07-07 234743.png)]
由 26pin 的原理图可知, Orange Pi Zero 2 可用的 i2c 为 i2c3
启动 linux 系统后, 先确认下/dev 下存在 i2c-3 的设备节点
从命令运行结果能观察到系统支持I2C-3和I2C-5的驱动,而H616的外设我们看到只有一个IIC接
口,用的是IIC-3
Linux一切皆文件,每个硬件设备“对应”一个文件,由驱动程序提供映射!
![在这里插入图片描述
开始测试 i2c, 首先安装 i2c-tools
sudo apt-get install i2c-tools
#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; }
串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口(Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢
RXD:数据输入引脚,数据接受;
TXD:数据发送引脚,数据发送;
交叉接线
/* * serialTest.c: */ #include <stdio.h> #include <string.h> #include <errno.h> #include <pthread.h> #include <wiringPi.h> #include <wiringSerial.h> #include <stdlib.h> int fd; void* Sendhandler() { char *sendBuf; sendBuf = (char *)malloc(32*sizeof(32)); while(1){ memset(sendBuf,'\0',32); scanf("%s",sendBuf); while(*sendBuf){ serialPutchar (fd, *sendBuf++) ; } } } void* Revhandler() { while(1){ while (serialDataAvail(fd)) { printf ("%c", serialGetchar(fd)) ; fflush (stdout) ; } } } int main () { int count ; unsigned int nextTime ; pthread_t idSend; pthread_t idRev; if ((fd = serialOpen ("/dev/ttyS5", 115200)) < 0) { fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ; return 1 ; } pthread_create(&idSend, NULL,Sendhandler,NULL); pthread_create(&idRev, NULL,Revhandler,NULL); if (wiringPiSetup () == -1) { fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ; return 1 ; } while(1){sleep(10);} printf ("\n") ; return 0 ; }
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); 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);} }
继电器(英文名称:relay)是一种电控制器件,是当输入量(激励量)的变化达到规定要求时,在电气输出电路中使被控量发生预定的阶跃变化的一种电器
实现功能:输入不同的指令,点亮不同的LED灯
实现方式一:
#include<wiringPi.h> #include<stdio.h> #include<string.h> #define sw1 16 #define sw2 15 #define sw3 13 #define sw4 10 void pinModeOutPut() { pinMode(sw1,OUTPUT); pinMode(sw2,OUTPUT); pinMode(sw3,OUTPUT); pinMode(sw4,OUTPUT); } void allHigh() { digitalWrite(sw1,HIGH); digitalWrite(sw2,HIGH); digitalWrite(sw3,HIGH); digitalWrite(sw4,HIGH); } void allLow() { digitalWrite(sw1,LOW); digitalWrite(sw2,LOW); digitalWrite(sw3,LOW); digitalWrite(sw4,LOW); } int main() { char cmd[12]={0}; if(wiringPiSetup()==-1) { printf("init error\n"); return -1; } pinModeOutPut(); allHigh(); while(1) { printf("1/2/3/4代表灯,on-打开,off-关闭\n"); memset(cmd,0,sizeof(cmd)); fgets(cmd, 12, stdin); if(strncmp(cmd,"1on",3)==0) { digitalWrite(sw1,LOW); } else if(strncmp(cmd,"2on",3)==0) { digitalWrite(sw2,LOW); } else if(strncmp(cmd,"3on",3)==0) { digitalWrite(sw3,LOW); } else if(strncmp(cmd,"4on",3)==0) { digitalWrite(sw4,LOW); } else if(strncmp(cmd,"1off",4)==0) { digitalWrite(sw1,HIGH); } else if(strncmp(cmd,"2off",4)==0) { digitalWrite(sw2,HIGH); } else if(strncmp(cmd,"3off",4)==0) { digitalWrite(sw3,HIGH); } else if(strncmp(cmd,"4off",4)==0) { digitalWrite(sw4,HIGH); } else if(strncmp(cmd,"allon",5)==0) { allLow(); } else if(strncmp(cmd,"alloff",6)==0) { allHigh(); } } return 0; }
实现方式二:
#include <wiringPi.h> #include <stdio.h> #include <string.h> #define sw1 16 #define sw2 15 #define sw3 13 #define sw4 10 #define one 1 #define two 2 #define there 3 #define four 4 #define five 5 #define six 6 #define seven 7 #define eight 8 #define night 9 #define ten 10 void pinModeOutPut() { pinMode(sw1, OUTPUT); pinMode(sw2, OUTPUT); pinMode(sw3, OUTPUT); pinMode(sw4, OUTPUT); } void allHigh() { digitalWrite(sw1, HIGH); digitalWrite(sw2, HIGH); digitalWrite(sw3, HIGH); digitalWrite(sw4, HIGH); } void allLow() { digitalWrite(sw1, LOW); digitalWrite(sw2, LOW); digitalWrite(sw3, LOW); digitalWrite(sw4, LOW); } int get_cmd_type(char *cmd) { if (strncmp(cmd, "one", 3) == 0) return 1; if (strncmp(cmd, "two", 3) == 0) return 2; if (strncmp(cmd, "there", 5) == 0) return 3; if (strncmp(cmd, "four", 4) == 0) return 4; if (strncmp(cmd, "five", 4) == 0) return 5; if (strncmp(cmd, "six", 3) == 0) return 6; if (strncmp(cmd, "seven", 5) == 0) return 7; if (strncmp(cmd, "eight", 5) == 0) return 8; if (strncmp(cmd, "night", 5) == 0) return 9; if (strncmp(cmd, "ten", 3) == 0) return 10; return -1; } int main() { char cmd[12] = {0}; int ret; if (wiringPiSetup() == -1) { printf("init error\n"); return -1; } pinModeOutPut(); allHigh(); while (1) { printf("1/2/3/4/9-on,5/6/7/8/10-off,9-allon,10-alloff\n"); memset(cmd, 0, sizeof(cmd)); fgets(cmd, 12, stdin); ret = get_cmd_type(cmd); switch (ret) { case 1: digitalWrite(sw1, LOW); break; case 2: digitalWrite(sw2, LOW); break; case 3: digitalWrite(sw3, LOW); break; case 4: digitalWrite(sw4, LOW); break; case 5: digitalWrite(sw1, HIGH); break; case 6: digitalWrite(sw2, HIGH); break; case 7: digitalWrite(sw3, HIGH); break; case 8: digitalWrite(sw4, HIGH); break; case 9: allLow(); break; case 10: allHigh(); break; default: printf("cmd error\n"); break; } } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。