linux wiringPi库 c语言(二)

目录

十、Makefile的简单知识


十、Makefile的简单知识

为了方便我们编译,这里学习一下Makefile的简单知识

1、准备文件

main.c   调用一个头文件实现一个简单的功能

#include <stdio.h>
#include "function.h"

int main()
{
    printfhello();
    int a = abc(2,3,4);
    printf("%d\n",a);
    return 0;
}

 abc.c

#include <stdio.h>

int abc(int a, int b, int c)
{
    return a+b+c;
}

 printfhello.c

#include <stdio.h>


void printfhello()
{
    printf("printfhello\n");
}

function.h   

#ifndef _FUNCTIONS_H_
#define _FUNCTIONS_H_

void printfhello();
int abc(int a, int b, int c);


#endif // !_FUNCTIONS_H_

2、Makefile的简单使用  1

Makefile文件:解释注释里都有

#运行make命令,make命令会去找当前目录下面的Makefile文件,如果你的文件名不是Makefile,也可以指定文件名
#make -f file

## VERSION 1
#生成的可执行程序为main,main的生成依赖于main.c abc.c printfhello.c
main:main.c abc.c printfhello.c
#gcc前面一定时tab而不是空格
	gcc -Wall -o main main.c abc.c printfhello.c 

使用make运行Makefile文件

 这样就不用我们每次编译都输入gcc....很麻烦,但这样也有缺点,就是每次修改编译文件时,会将每一个文件·都编译,如果文件过多就很慢,下面进行简单修改。

3、Makefile的简单使用 2

Makefile

## VERSION 2
#编译器
CXX = gcc
#目标
TARGET = main
OBJ = main.o printfhello.o abc.o

#寻找名为TARGET的文件,没有则依赖于OBJ生成如果OBJ有更新的则执行下一条命令:	$(CXX) -o $(TARGET) $(OBJ)
$(TARGET): $(OBJ)
	$(CXX) -o $(TARGET) $(OBJ)

main.o:main.c
	$(CXX) -c main.c

printfhello.o:printfhello.c
	$(CXX) -c printfhello.c

abc.o:abc.c
	$(CXX) -c abc.c

这样修改之后每次执行Makefile文件时仅仅会对更新的文件进行编译,下面来实验一下:

第一次编译因为所以的文件都是新的所以所有的文件都参与编译:

现在我对abc.c文件进行修改(没啥改动就是加了个空格),再次执行make,发现仅仅对修改的文件进行了编译。

但是这样还有一个问题,如果有很多.c文件的话,那我如果写Makefile不就很烦琐了,所以为了可以更加的灵活,对Makefile进行简单修改

4、Makefile的简单使用 3

Makefile

## VERSION 3
# 编译器
CXX = gcc
# 要生成的可执行文件名
TARGET = main
# patsubst替换,将SRC里面.c文件替换成.o文件
OBJ = main.o printfhello.o abc.o

CXXFLAGS = -c -Wall

# 这里按需修改
# $@就是$(TARGET)   $^就是$(OBJ)
# 寻找名为"@(也就是TARGET)"的文件,若没有则依赖于"^(也就是OBJ)"生成。如果^(也就是OBJ)有更新则执行下一条语句
$(TARGET): $(OBJ)
	$(CXX) -o $@ $^

#写一个统一的规则来生成.o文件  $<是指%.c
%.o: %.c
	$(CXX) $(CXXFLAGS) $< -o $@

# 当执行"make clean"时删除所生成的.o文件,与生成的可执行文件"TARGET"
.PHONY: clean
clean:
	rm -f *.o $(TARGET)

这里我们写了一个统一的规则来生成.o文件,只要是这个目录下的.c文件,运行make是我们会将所有的.c文件生成.o  运行一下,正常

这里我们对任意一个文件进行修改,再运行

这里只重新编译了我修改的printfhello.c文件。

这里使用make clean可以执行clean,这里的功能是移除所有生成的.o文件,还有生成的可执行文件main,很方便

我们虽然对Makefile文件进行修改后简单方便了很多,在添加.c文件时只要在OBJ里加上对应的.o文件就可以了,但是每次添加一个文件都要修改一次Makefile,当文件很多时仍然会感到很繁琐,那这里对Makefile文件再进行简单修改

5、Makefile的简单使用

# VERSION 4 最终版 使用时按需修改,比如CXX、TARGET...

#运行make命令,make命令会去找当前目录下面的Makefile文件,如果你的文件名不是Makefile,也可以指定文件名
# 编译器
CXX = gcc
# 要生成的可执行文件名
TARGET = test
# 所以的当前文件的.c文件都放在SRC文件中
SRC = $(wildcard *.c)
# patsubst替换,将SRC里面.c文件替换成.o文件
OBJ = $(patsubst %.c, %.o, $(SRC))

# 这里按需修改
CXXFLAGS = -c -Wall 
CFLAGS = -lwiringPi -Wall

# $@就是$(TARGET)   $^就是$(OBJ)
# 寻找名为"@(也就是TARGET)"的文件,若没有则依赖于"^(也就是OBJ)"生成。如果^(也就是OBJ)有更新则执行下一条语句
$(TARGET): $(OBJ)
    $(CXX)  -o $@ $^ $(CFLAGS)

# 写一个统一的规则来生成.o文件  $<是指%.c
%.o: %.c
    $(CXX) $(CXXFLAGS) $< -o $@
 
# 当执行"make clean"时删除所生成的.o文件,与生成的可执行文件"TARGET"
.PHONY: clean
clean:
    rm -f *.o $(TARGET)

在这个文件里我们实现了自动识别当前目录下最新的.c文件,然后生成对应的.o文件,这时候我们再添加文件就不用对Makefile文件进行修改了,只要开始时修改一下生成的可执行文件名

执行一下看看:正常

 对abc.c文件进行修改再执行一下

一切正常,当然还有很多可以实验观察对比的地方,比如删除某个文件,执行时会怎么样这里就不作过多说明了,大家自己试一试

十一、光照度传感器 bh1750

1、bh1750.c

// Filename: bh1750.c
// Function: 光照传感器bh1750
#include <wiringPi.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <errno.h>
// #include <stdlib.h>
#include <unistd.h>
// #include <time.h>
#include <sys/time.h>
#include <string.h>
#include <sys/ioctl.h>
//sudo gcc -o bh1750 bh1750.c

//具体查看手册中的Instruction Set Architecture
//1、发送上电命令	0000 0001
//2、发送测量命令(有一次测量、连续测量)这里选择连续高分辨模式2  0001 0001
//3、等待测量结束	延时一段时间,120ms~180ms,我这里选择200ms
//4、读取数据
//5、计算结果

//i2c设备地址
#define I2C_ADDR 0x23


 int main()
 {
    printf("hello word\n");
	printf("%x\n",I2C_ADDR);

	int fd;
	char buf[3];
	char val;
	// char value;
	float flight;
	//获取设备地址
	fd = open("/dev/i2c-1",O_RDWR);
	if(fd < 0)
	{
		printf("打开文件错误:%s\r\n",strerror(errno));
		return 1;
	}
	if(ioctl(fd,I2C_SLAVE,I2C_ADDR)<0)
	{
		printf("ioctl错误:%s\r\n",strerror(errno));
		return 1;
	}

	printf("%x\n",fd);
	//发送上电命令 0x01
	val = 0x01;
	printf("%x\n",val);

	if(write(fd,&val,1)<0)
	{
		printf("上电失败\n");
	}
	//发送测量命令,连续高分辨率模式2
	val = 0x11;
	// printf("%x\n",val);

	if(write(fd,&val,1)<0)
	{
			printf("开启高分辨率模式2\n");
	}
	//高分辨率测量需等待时间最长,平均120ms,最大180ms,这里取200ms
	usleep(200000);
	while (1)
	{	
		if(read(fd,&buf,3))
		{
			//光照强度 = (寄存器值[15 : 0] * 分辨率)/1.2		单位:勒克斯lx
			flight = (buf[0]*256 +buf[1])*0.5/1.2;
			printf("光照度%6.2flx\r\n", flight);
		}
		else
		{
			printf("读取错误\n");
		}
			usleep(200000);

	}
	return 0;
}

2、Makefile

上一节简单学习了Makefile在这里试用一下

## VERSION 4
CXX = gcc
TARGET = bh1750
#所以的当前文件的.c文件都放在SRC文件中
SRC = $(wildcard *.c)
#patsubst替换,将SRC里面.c文件替换成.o文件
OBJ = $(patsubst %.c, %.o, $(SRC))

CXXFLAGS = -c -Wall

$(TARGET): $(OBJ)
	$(CXX) -o $@ $^ -lwiringPi

%.o: %.c
	$(CXX) $(CXXFLAGS) $< -o $@

.PHONY: clean
clean:
	rm -f *.o $(TARGET)

使用后感觉很好用:

运行生成的可执行文件

 使用make clean 删除生成的文件

十二、温湿度传感器DHT11

1、DHT11.c

/******************************************
 * 1、DHT11上电后(DHT11上电后要等待1S以越过不稳定状态在此期间不能发送任何指令),
 * 测试环境温湿度数据,并记录数据,同时DHT11的DATA数据线由上拉电阻拉高一直保持高电平,
 * 此时DHT11的DATA引脚处于输入状态时刻检测外部信号。
 * 2、微处理器的/0设置为输出同时输出低电平,且低电平保持时间不能小于18ms(最大不得超过30ms),
 * 然后微处理器的I/0设置为输入状态,由于上拉电阻,微处理器的I/0即DHT11的DATA数据线也随之变高,
 * 等待DHT11作出回答信号
 * 3、DHT11的DATA引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后DHT11的DATA引脚
 * 处于输出状态,输出83微秒的低电平作为应答信号,紧接着输出87微秒的高电平通知外设准备接收数据,
 * 微处理器的I/O此时处于输入状态,检测到/O有低电平(DHT11回应信号)后,等待87微秒的高电平后的数据接收。
 * 4、由DHT11的DATA引脚输出40位数据,微处理器根据1/0电平的变化接收40位数据,位数据
 * 微秒的低电平和23-27微秒的高电平,位数据“1”的格式为: 54微秒的低电平加68-74微秒的高电平
 * 的格式为:54
 * 
*/


#include <stdio.h>
#include <wiringPi.h>
#include <time.h>

//定义GPIO口
#define Data 0

/**DHT11读取温湿度
 * @param temperature_int:温度整数部分
 * @param temperature_dec: 温度小数部分
 * @param humidity_int: 湿度整数部分
 * @param humidity_dec: 湿度小数部分
*/
char DHT11_Read(char* temperature_int, char* temperature_dec, char* humidity_int, char* humidity_dec)
{
    unsigned char t, i, j;
    // unsigned char t, i;

    unsigned char buf[5] = {0, 0, 0, 0, 0};

    //主机发送信号 让DHT11工作
    pinMode(Data, OUTPUT);
    // pullUpDnControl(Data, PUD_UP);      //将GPIO口打开
    digitalWrite(Data, 0);              // 1:向Data输出低电平20ms,18~30ms,主机发送开始信号
    delay(23);
    digitalWrite(Data, 1);              // 2:向Data输出高电平30us,主机拉高20~40us
    delayMicroseconds(30);              
    pinMode(Data, INPUT);

    //DHT11响应
    while(digitalRead(Data) && t < 100)     // 3:DHT11响应83us低电平,这里检测一下,100us后还是高电平说明出错了
     {
        t++;
        delayMicroseconds(1);
    }
    if(t > 100)return 1;
    t = 0;
    while(!digitalRead(Data) && t < 100)    // 4:DHT11响应87us高电平
    {
        t++;
        delayMicroseconds(1);
    }
    if(t > 100)return 2;

    //数据采集5个八位数据
    for(i = 0;i < 5;i++)        // DHT11向主机发送5个8位数据
    {
        buf[i]=0;
        for(j = 0;j < 8;j++)
        {
            buf[i] <<= 1;

            t = 0;
            while(digitalRead(Data) && t < 100)        
            {
                t++;
                delayMicroseconds(1);
            }
            if(t >= 100)return 3;

            t = 0;
            while(!digitalRead(Data) && t < 100)
            {
                t++;
                delayMicroseconds(1);
            }
            if(t >= 100)return 4;

            delayMicroseconds(40);
            if(1 == digitalRead(Data))
            {
                buf[i] += 1;
            }
        }

    }
    //buf[0]:前八位表示湿度整数部分 buf[1]:9-16位表示湿度小数部分 buf[2]:17-24位为温度整数部分 
    //buf[3]:25-32位为温度小数部分 buf[4]:33-40位为校验位
    if(buf[0] + buf[1] + buf[2] + buf[3] != buf[4])return 5;
    *humidity_int = buf[0];
    *humidity_dec = buf[1];
    *temperature_int = buf[2];
    *temperature_dec = buf[3];
    return 0;
}

int main()
{
    printf("hello world\n");
    char humidity_int;
    char humidity_dec;
    char temperature_int;
    char temperature_dec;

    char value;
        // FILE *fp = NULL;

    if(wiringPiSetup() < 0)return 1;

    while(1)
    {
        delay(1000);
        value = DHT11_Read(&temperature_int, &temperature_dec, &humidity_int, &humidity_dec);

        switch (value)
        {
        case 0:
            printf("\nhumidity = %d\n",humidity_int);
            printf("temperature = %d.%d\n",temperature_int,temperature_dec);
            break;
        case 1:
            printf("\nerr1\n");
            break;
        case 2:
            printf("\nerr2\n");
            break;
        case 3:
            printf("\nerr3\n");
            break;
        // case 4:
        //     printf("\nerr4\n");
        //     break;
        case 5:
            printf("\nerr5\n");
            break;      
        default:
            break;
        }
    }


    // return 0;
}

2、Makefile


CXX = gcc
TARGET = DHT11
#所以的当前文件的.c文件都放在SRC文件中
SRC = $(wildcard *.c)
#patsubst替换,将SRC里面.c文件替换成.o文件
OBJ = $(patsubst %.c, %.o, $(SRC))

CXXFLAGS = -c -Wall

$(TARGET): $(OBJ)
	$(CXX) -o $@ $^ -lwiringPi

%.o: %.c
	$(CXX) $(CXXFLAGS) $< -o $@

.PHONY: clean
clean:
	rm -f *.o $(TARGET)

### 回答1: #include <wiringPi.h> int main (void) { wiringPiSetup(); pinMode (0, OUTPUT); digitalWrite(0, HIGH); delay(1000); digitalWrite(0, LOW); return 0; } ### 回答2: 为了使用树莓派控制GPIO,可以使用WiringPi编写C语言代码。以下是使用WiringPi控制GPIO的示例代码: ```c #include <wiringPi.h> int main() { // 初始化WiringPi if (wiringPiSetup() == -1) { return 1; } // 设置GPIO引脚模式 pinMode(0, OUTPUT); pinMode(1, INPUT); // 控制LED digitalWrite(0, HIGH); // 打开LED // 读取按钮状态 int buttonState = digitalRead(1); // 输出按钮状态 printf("按钮状态: %d\n", buttonState); // 清理引脚状态 digitalWrite(0, LOW); // 关闭LED return 0; } ``` 上述代码使用WiringPi中的函数进行初始化、配置和控制GPIO引脚。在示例中,我们将GPIO引脚0设置为输出模式,GPIO引脚1设置为输入模式。通过调用`digitalWrite()`函数,我们可以控制GPIO引脚的电平状态,例如打开或关闭LED。`digitalRead()`函数用于读取输入引脚的状态。 此代码仅为一个简单示例,你可以根据特定的需求和电路配置进行适当的修改。同时,确保在编译代码之前已经安装了WiringPi。 ### 回答3: 树莓派是一款非常受欢迎的单板电脑,它搭载的是Linux操作系统,并且拥有丰富的GPIO接口。要运用wiringpi控制GPIO,需要先在树莓派上安装wiringpi。下面是一个简单的示例,演示了如何使用C语言代码来控制GPIO。 首先,确保你的树莓派上已经安装了wiringpi。如果没有安装,可以使用以下命令进行安装: sudo apt-get update sudo apt-get install wiringpi 然后,创建一个名为gpio_control.c的文件,并将以下代码粘贴到该文件中: #include <stdio.h> #include <wiringPi.h> #define LED_PIN 0 // 这里的0表示使用的GPIO引脚编号为0,也可以根据实际情况更改 int main(void) { if (wiringPiSetup() == -1) { // 初始化wiringPi,若失败则退出程序 printf("初始化wiringPi失败!\n"); return 1; } pinMode(LED_PIN, OUTPUT); // 设置GPIO为输出模式 while(1) { digitalWrite(LED_PIN, HIGH); // 将GPIO置高电平 delay(1000); // 延迟1秒 digitalWrite(LED_PIN, LOW); // 将GPIO置低电平 delay(1000); // 延迟1秒 } return 0; } 保存并关闭文件后,打开终端,进入文件所在目录。然后使用以下命令编译该文件并运行: gcc -o gpio_control gpio_control.c -lwiringPi sudo ./gpio_control 这样,你就可以通过GPIO控制树莓派上的LED灯了。这个示例中,LED连接到GPIO引脚0(即物理引脚11),程序会不断循环地让LED灯亮一秒,熄灭一秒。你也可以根据需要更改引脚和控制逻辑。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值