香橙派外设开发,时间函数、超声波、sg90、OLED(i2c)、Linux定时器

老朋友蜂鸣器

#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(&timestart,NULL);
    cnttime();
    gettimeofday(&timestop,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;
}                        
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值