老朋友蜂鸣器
#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;
}
小插曲:
链库写的太麻烦?shell脚本来帮忙
1. vi build.sh
2. gcc $1 -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt
3. shell脚本没有权限加执行权限 chmod +x build.sh
4.使用 ./build xxx.c
/build beep.c
$0 $1
shell脚本处理参数,可以通过$?
vim的设置,修改/etc/vim/vimrc文件,需要用超级用户权限
sudo vi /etc/vim/vimrc set tabstop=4 设置tab键缩进4个空格 set shiftwidth=4 设置批量对齐时候的tab键空格数为4
时间函数
函数原型
#include <sys/time.h> #includeint 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>
//#include<sys/time.h>
//int gettimeofday(struct timeval *tv,struct timezone *tz )
//struct timeval
//{
//long tv_sec;/*秒*/
//long tv_usec;/*微妙*/
//};
void cnttime()
{
int i,j;
for(i;i<100;i++)
for(j;j<10000;j++);
}
int main()
{
struct timeval timestart;
struct timeval timestop;
gettimeofday(×tart,NULL);
cnttime();
gettimeofday(×top,NULL);
long timediff = (timestop.tv_sec-timestart.tv_sec)*1000000+(timestop.tv_usec-timestart.tv_usec);
printf("H616 count 100W time:%ld\n",timediff);
return 0;
}
超声波测距代码
#include<wiringPi.h>
#include<unistd.h>
#include<sys/time.h>
#include<stdio.h>
#include<stdlib.h>
#define TRIG 23
#define ECHO 25
void init_hardware(){
int retn;
retn=wiringPiSetup();
if(retn < 0){
perror("init hardware");
exit(-1);
}
}
void init_pins(){
pinMode(ECHO,INPUT);
pinMode(TRIG,OUTPUT);
}
float measure_distance(){
long start_usec,stop_usec;
struct timeval rawtime1,rawtime2;
float distance;
digitalWrite(TRIG,LOW);
delayMicroseconds(2);
digitalWrite(TRIG,HIGH);
delayMicroseconds(10);
digitalWrite(TRIG,LOW);//start send ultrasonic
// printf("%d\n",digitalRead(ECHO));
while(!(digitalRead(ECHO) == 1));
gettimeofday(&rawtime1, NULL);
while(!(digitalRead(ECHO) == 0));//low
gettimeofday(&rawtime2,NULL);
start_usec =rawtime1.tv_sec*1000000+rawtime1.tv_usec;
stop_usec =rawtime2.tv_sec*1000000+rawtime2.tv_usec;
distance=(float)(stop_usec-start_usec)/1000000*17000;
return distance;
}
int main(){
float distance;
init_hardware();
init_pins();
while(1){
distance = measure_distance();
printf("%0.2f cm\n",distance);
delay(1000);
}
return 0;
}
Linux定时器
#include <sys/time.h>
int setitimer (__itimer_which_t __which, const struct itimerval *__restrict __new, struct itimerval *__restrict __old);
参数1:which指定定时器的定时方式
参数2:_restrict_new
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:当定时器被设置OK,延时多久时间去执行定时器计时 ,值不能为0!!
struct timeval {
__time_t tv_sec; /* Seconds. */
__suseconds_t tv_usec; /* Microseconds. */
};
成功执行时,返回0。失败返回-1
参数3:old_value
传出参数,表示上一次定时剩余的时间(一般传NULL即可)
当定时器超时的时候,会产生SIGALRM信号。因此,要设置超时行为,就得在SIGALRM信号上设置相应的函数,信号进行逻辑相关处理 signal(SIGALRM,signal_handler);
一个进程只能创建一个定时器!!!
定时器案例
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <signal.h>基于定时器控制sg90
static int i = 0;
void signal_handler()
{
i++;
if(i == 2000){
printf("hellow\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 = 0;
itv.it_value.tv_usec = 100;
if((setitimer(ITIMER_REAL,&itv,NULL)) == -1){
perror("setitimer");
exit(-1);
}
signal(SIGALRM,signal_handler);
while(1);
return 0;
}
基于定时器控制sg90
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <signal.h>
#include <wiringPi.h>
#define SG90 0
static int i = 0;
int angle;
void signal_handler()
{
if(i == 40){
i = 0;
}
if(i < angle){
digitalWrite(SG90,HIGH);
}else{
digitalWrite(SG90,LOW);
}
i++;
}
int main()
{
struct itimerval itv;
angle = 0;
wiringPiSetup();
pinMode(SG90,OUTPUT);
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 500;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = 100;
if((setitimer(ITIMER_REAL,&itv,NULL)) == -1){
perror("setitimer");
exit(-1);
}
signal(SIGALRM,signal_handler);
while(1){
printf("please input angle ps:1-0 2-45 3-90 4-135 5-180\n ");
scanf("%d",&angle);
}
return 0;
}
OLED屏应用-IIC协议
由 26pin 的原理图可知, Orange Pi Zero 2 可用的 i2c 为 i2c3
确认/dev下存在i2c-3的设备节点
从命令运行结果能观察到系统支持I2C-3和I2C-5的驱动,而H616的外设我们看到只有一个IIC接 口,用的是IIC-3 Linux一切皆文件,每个硬件设备“对应”一个文件,由驱动程序提供映射
安装i2c-tools 指令:sudo apt-get install i2c-tools
检测当前i2c设备 指令:sudo i2cdetect -y 3
oled_demo.c
/*
* Copyright (c) 2015, Vladimir Komendantskiy
* MIT License
*
* SSD1306 demo of block and font drawing.
*/
//
// fixed for OrangePiZero by HypHop
//
#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_demo(struct display_info *disp) {
int i;
char buf[100];
//putstrto(disp, 0, 0, "Spnd spd 2468 rpm");
// oled_putstrto(disp, 0, 9+1, "Spnd cur 0.46 A");
oled_putstrto(disp, 0, 9+1, "Welcome to");
disp->font = font1;
// oled_putstrto(disp, 0, 18+2, "Spnd tmp 53 C");
oled_putstrto(disp, 0, 18+2, "----OrangePi----");
disp->font = font2;
// oled_putstrto(disp, 0, 27+3, "DrvX tmp 64 C");
oled_putstrto(disp, 0, 27+3, "This is 0.96OLED");
oled_putstrto(disp, 0, 36+4, "");
oled_putstrto(disp, 0, 45+5, "");
disp->font = font1;
// oled_putstrto(disp, 0, 54, "Total cur 2.36 A");
oled_putstrto(disp, 0, 54, "*****************");
oled_send_buffer(disp);
disp->font = font3;
for (i=0; i<100; i++) {
sprintf(buf, "Spnd spd %d rpm", i);
oled_putstrto(disp, 0, 0, buf);
oled_putstrto(disp, 135-i, 36+4, "===");
oled_putstrto(disp, 100, 0+i/2, ".");
oled_send_buffer(disp);
}
//oled_putpixel(disp, 60, 45);
//oled_putstr(disp, 1, "hello");
return 0;
}
void show_error(int err, int add) {
//const gchar* errmsg;
//errmsg = g_strerror(errno);
printf("\nERROR: %i, %i\n\n", err, add);
//printf("\nERROR\n");
}
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);
if (e < 0) {
show_error(1, e);
} else {
e = oled_init(&disp);
if (e < 0) {
show_error(2, e);
} else {
printf("---------start--------\n");
if (oled_demo(&disp) < 0)
show_error(3, 777);
printf("----------end---------\n");
}
}
return 0;
}
编译运行的时候要注意加上i2c-3这个驱动文件不然无法运行:
正确的运行方式:
观察上面的oled_demo.c的代码,其实只要把oled_demo()函数稍微改一下就可以显示指定内容。
#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");
disp->font = font1;
oled_putstrto(disp, 0, 9+9, "orangepi i2c oled");
disp->font = font3;
oled_send_buffer(disp);
return 0;
}
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;
}
串口通讯
基于wiringPi的串口开发
serial.c
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <wiringPi.h>
#include <wiringSerial.h>
#include <stdlib.h>
#include <pthread.h>
int fd;
void *sendHandle()
{
char *sendBuf;
sendBuf = (char *)malloc(128*sizeof(char));
while(1){
memset(sendBuf,'\0',128);
scanf("%s",sendBuf);
while(*sendBuf !='\0'){
serialPutchar(fd,*sendBuf++);
}
}
}
int main ()
{
pthread_t send;
if ((fd = serialOpen ("/dev/ttyS5", 115200)) < 0)
{
fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
return 1 ;
}
if (wiringPiSetup () == -1)
{
fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ;
return 1 ;
}
pthread_create(&send,NULL,sendHandle,NULL);
while(1){
while (serialDataAvail (fd))
{
printf ("%c", serialGetchar(fd));
fflush (stdout);
}
}
return 0 ;
}
不使用wiringPi库实现串口通讯
serialtools.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>
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 ;
default:
return -2 ;
}
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 ;
}
int serialSendString (const int fd, const char *s)
{
int ret;
ret = write (fd, s, strlen (s));
if (ret < 0)
printf("Serial Puts Error\n");
return ret;
}
int serialRcvString (const int fd,char *buf)
{
int ret;
if((ret = read (fd, buf, 128)) < 0)
return -1 ;
return ret;
}
serialtools.h
int myserialOpen (const char *device, const int baud);
int serialSendString (const int fd, const char *s);
int serialRcvString (const int fd,char *buf);
serial.c
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include "serialtools.h"
int fd;
void *sendHandle()
{
char buf[128] ={0};
while(1){
memset(buf,'\0',sizeof(buf));
printf("->");
scanf("%s",buf);
serialSendString(fd,buf);
serialSendString(fd,"\r\n")
}
}
void *receiveHandle()
{
char buf[128] ={0};
while(1){
memset(buf,'\0',sizeof(buf));
serialRcvString(fd,buf);
printf("%s\n",buf);
}
}
int main(int argc,char **argv)
{
if(argc != 2){
printf("arg num is error!\n");
return -1;
}
pthread_t send_t;
pthread_t receive_t;
if((fd = myserialOpen (argv[1], 115200)) < 0){
printf("serial open error!\n");
return -2;
}
pthread_create(&send_t,NULL,sendHandle,NULL);
pthread_create(&receive_t,NULL,receiveHandle,NULL);
while(1){
sleep(1);
}
return 0;
}