Linux的GPIO和PWM应用编程

GPIO应用编程

 对于给定的一个 GPIO 引脚,如何计算它在 sysfs 中对应的编号呢?其实非常简单,譬如给定一个 GPIO引脚为 GPIO4_IO16,那它对应的编号是多少呢?首先我们要确定 GPIO4 对应于 gpiochip96,该组 GPIO 引 脚的最小编号是 96(对应于 GPIO4_IO0),所以 GPIO4_IO16 对应的编号自然是 96 + 16 = 112;同理GPIO3_IO20 对应的编号是 64 + 20 = 84。

#define GPIO_TO_PIN(bank, gpio)		(32 * (bank) + (gpio))

 

 

 gpio_ctrl.c


#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

#include "gpio_ctrl.h"

 /****************************************************************
 * Constants
 ****************************************************************/

#define GPIO_CMD_MAX_BUF		64

#ifdef PLATFORM_X86
#define PERROR
#else
#define PERROR perror
#endif

#ifndef RT_KERNEL

#define SYSFS_GPIO_DIR			"/sys/class/gpio"
#define SYSFS_PWM_DIR			"/sys/class/pwm/pwmchip0/"

/****************************************************************
 * gpio_export
 ****************************************************************/
int gpio_export(unsigned int gpio)
{
  int fd, len;
  char buf[GPIO_CMD_MAX_BUF];
 
  fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY);
  if (fd < 0) {
    PERROR("gpio/export");
    return fd;
  }
 
  len = snprintf(buf, sizeof(buf), "%d", gpio);
  write(fd, buf, len);
  close(fd);
 
  return 0;
}

/****************************************************************
 * gpio_unexport
 ****************************************************************/
int gpio_unexport(unsigned int gpio)
{
  int fd, len;
  char buf[GPIO_CMD_MAX_BUF];
 
  fd = open(SYSFS_GPIO_DIR "/unexport", O_WRONLY);
  if (fd < 0) {
    PERROR("gpio/export");
    return fd;
  }
 
  len = snprintf(buf, sizeof(buf), "%d", gpio);
  write(fd, buf, len);
  close(fd);
  return 0;
}

/****************************************************************
 * gpio_set_dir
 ****************************************************************/
int gpio_set_dir(unsigned int gpio, int dir)
{
  int fd, len;
  char buf[GPIO_CMD_MAX_BUF];
 
  len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR  "/gpio%d/direction", gpio);
 
  fd = open(buf, O_WRONLY);
  if (fd < 0) {
    PERROR("gpio/direction");
    return fd;
  }
 
  if (dir == GPIO_DIR_OUT)
    write(fd, "out", 4);
  else
    write(fd, "in", 3);
 
  close(fd);
  return 0;
}

/****************************************************************
 * gpio_set_edge
 ****************************************************************/
int gpio_set_edge(unsigned int gpio, int edge)
{
  int fd, len;
  char buf[GPIO_CMD_MAX_BUF];

  len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/edge", gpio);
 
  fd = open(buf, O_WRONLY);
  if (fd < 0) {
    PERROR("gpio/set-edge");
    return fd;
  }

	const char *pedge;
	if(edge==EDGE_TYPE_RISING){
		pedge = "rising";
	}
	else if(edge==EDGE_TYPE_FALLING){
		pedge = "falling";
	}
	else if(edge==EDGE_TYPE_BOTH){
		pedge = "both";
	}
	else{
		pedge = "none";
	}
	
  write(fd, pedge, strlen(pedge) + 1); 
  close(fd);
  return 0;
}

int gpio_open_value(unsigned int gpio, int flag)
{
	int fd, len;
	char buf[GPIO_CMD_MAX_BUF];
	char ch;

	len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
 
	fd = open(buf, flag);
	if (fd < 0) {
		PERROR("gpio/get-value");
		return fd;
	}
	return fd;
}

/****************************************************************
 * gpio_set_value
 ****************************************************************/
int gpio_set_value(unsigned int gpio, int value)
{
  int fd;

  fd = gpio_open_value(gpio, O_WRONLY);
 
  if (value)
    write(fd, "1", 2);
  else
    write(fd, "0", 2);
 
  close(fd);
  return 0;
}


/****************************************************************
 * gpio_get_value
 ****************************************************************/
int gpio_get_value(unsigned int gpio)
{
	int fd;
	char ch;

	fd = gpio_open_value(gpio, O_RDONLY);
 
	read(fd, &ch, 1);
	close(fd);
	
	return ch == '0' ? 0:1;
}

void gpio_set_value_by_fd(int fd, int value)
{
	write(fd, value ? "1":"0", 2);
}

int gpio_get_value_by_fd(int fd)
{
	char ch;

	read(fd, &ch, 1);
	lseek(fd, 0, SEEK_SET);
	return ch == '0' ? 0:1;
}

void gpio_pulse_by_fd(int fd, int pulse, int time)
{
	gpio_set_value_by_fd(fd, pulse);
	usleep(time*1000);
	gpio_set_value_by_fd(fd, !pulse);	
}

int gpio_open(int gpio, GPIO_DIR_TYPE inout, EDGE_TYPE edge, int flag)
{
	//printf("gpio_open+++gpio=%d, inout=%d, edge=%d\n", gpio, inout, edge);
	gpio_export(gpio);
	gpio_set_dir(gpio, inout);
	gpio_set_edge(gpio, edge);
	return gpio_open_value(gpio, flag);
}

int gpio_read_only_open(int gpio)
{
	return gpio_open(gpio, GPIO_DIR_IN, EDGE_TYPE_NONE, O_RDONLY);
}

int gpio_write_only_open(int gpio, int init_value)
{
	int fd = gpio_open(gpio, GPIO_DIR_OUT, EDGE_TYPE_NONE, O_WRONLY);
	if(fd >= 0 && init_value>=0){
		gpio_set_value_by_fd(fd, init_value);
	}
	return fd;
}

int gpio_select_open(int gpio, int edge)
{
	return gpio_open(gpio, GPIO_DIR_IN, (EDGE_TYPE)edge, O_RDONLY);
}

int pwm_open(int pwm, int fre, int duty, int init_value)
{
	int fd, len;
	char buf[GPIO_CMD_MAX_BUF];

	//open export
	fd = open(SYSFS_PWM_DIR "/export", O_WRONLY);
	if (fd < 0) {
	  PERROR("export");
	  return fd;
	}
	//write export
	len = snprintf(buf, sizeof(buf), "%d", pwm);
	write(fd, buf, len);
	close(fd);

	//open period
	len = snprintf(buf, sizeof(buf), SYSFS_PWM_DIR "/pwm%d/period", pwm);
	fd = open(buf, O_WRONLY);
	if (fd < 0) {
	  PERROR("period");
	  return fd;
	}
	//write period
	len = snprintf(buf, sizeof(buf), "%d", fre);
	write(fd, buf, len);
	close(fd);

	//open duty_cycle
	len = snprintf(buf, sizeof(buf), SYSFS_PWM_DIR "/pwm%d/duty_cycle", pwm);
	fd = open(buf, O_WRONLY);
	if (fd < 0) {
	  PERROR("period");
	  return fd;
	}
	//write duty
	len = snprintf(buf, sizeof(buf), "%d", duty);
	write(fd, buf, len);
	close(fd);

	//open enable
	len = snprintf(buf, sizeof(buf), SYSFS_PWM_DIR "/pwm%d/enable", pwm);
	fd = open(buf, O_WRONLY);
	if (fd < 0) {
	  PERROR("period");
	  return fd;
	}

	if(init_value>=0){
		gpio_set_value_by_fd(fd, init_value);
	}

	return fd;
}

#else

#define DEV_GPIO_DIR				"/dev/rtdm/gpio"

int gpio_read_only_open(int gpio)
{
	int fd, len;
	char buf[GPIO_CMD_MAX_BUF];

	len = snprintf(buf, sizeof(buf), DEV_GPIO_DIR "/gpio%d", gpio);
 
	fd = open(buf, O_RDONLY | O_NONBLOCK );
	if(fd >= 0){
		ioctl(fd, GPIO_RTIOC_DIR_IN);
	}
	return fd;
}

int gpio_write_only_open(int gpio, int init_value)
{
	int fd, len;
	char buf[GPIO_CMD_MAX_BUF];

	len = snprintf(buf, sizeof(buf), DEV_GPIO_DIR "/gpio%d", gpio);
 
	fd = open(buf, O_WRONLY);
	if(fd >= 0){
		ioctl(fd, GPIO_RTIOC_DIR_OUT, &init_value);
	}
	return fd;
}

int gpio_select_open(int gpio, int edge)
{
	int fd, len;
	char buf[GPIO_CMD_MAX_BUF];

	len = snprintf(buf, sizeof(buf), DEV_GPIO_DIR "/gpio%d", gpio);
 
	fd = open(buf, O_RDWR);
	if(fd >= 0){
		int trigger;
		if(edge==EDGE_TYPE_RISING){
			trigger = GPIO_TRIGGER_EDGE_RISING;
		}
		else if(edge==EDGE_TYPE_FALLING){
			trigger = GPIO_TRIGGER_EDGE_FALLING;
		}
		else if(edge==EDGE_TYPE_BOTH){
			trigger = GPIO_TRIGGER_EDGE_RISING | GPIO_TRIGGER_EDGE_FALLING;
		}
		else{
			trigger = GPIO_TRIGGER_EDGE_RISING;
		}
		ioctl(fd, GPIO_RTIOC_IRQEN, &trigger);
	}

	return fd;
}

/****************************************************************
 * gpio_set_value
 ****************************************************************/
void gpio_set_value_by_fd(int fd, int value)
{
	write(fd, &value, sizeof(value));
}

int gpio_get_value_by_fd(int fd)
{
	int value = 10;
	
	int ret = read(fd, &value, sizeof(value));
	//lseek(fd, 0, SEEK_SET);
	return value;
}

void gpio_pulse_by_fd(int fd, int pulse, int time)
{
	gpio_set_value_by_fd(fd, pulse);
	usleep(time*1000);
	gpio_set_value_by_fd(fd, !pulse);	
}

#endif

gpio_ctrl.h


#ifndef _GPIO_CTRL_H_
#define _GPIO_CTRL_H_

#ifdef RT_KERNEL
#include <rtdm/gpio.h>
#endif


#define GPIO_TO_PIN(bank, gpio)		(32 * (bank) + (gpio))

typedef enum
{
	GPIO_DIR_IN,
	GPIO_DIR_OUT,
}GPIO_DIR_TYPE;

typedef enum
{
	EDGE_TYPE_NONE,
	EDGE_TYPE_RISING,
	EDGE_TYPE_FALLING,
	EDGE_TYPE_BOTH,
}EDGE_TYPE;

int gpio_read_only_open(int gpio);
int gpio_write_only_open(int gpio, int init_value);
int gpio_select_open(int gpio, int trigger);

void gpio_set_value_by_fd(int fd, int value);
int gpio_get_value_by_fd(int fd);
void gpio_pulse_by_fd(int fd, int pulse, int time);

int pwm_open(int pwm, int fre, int duty, int init_value);

#endif

测试代码如下

#include "gpio_ctrl.h"
#define BEEP_GPIO_NUM				GPIO_TO_PIN(0, 7)

void main(void)
{
	int beep_gpio_fd = gpio_write_only_open(BEEP_GPIO_NUM, 0);
	sleep(1000);
	
	gpio_set_value_by_fd(beep_gpio_fd, 1);
	sleep(1000);
	
	gpio_set_value_by_fd(beep_gpio_fd, 0);
	sleep(1000);
	
	close(beep_gpio_fd);
	reutrn 0;
}
#include "gpio_ctrl.h"
#define KEY_GPIO_NUM				GPIO_TO_PIN(0, 8)

void main(void)
{
	int value;
	int key_gpio_fd = gpio_read_only_open(BEEP_GPIO_NUM);
	while(1)
	{
		value=gpio_get_value_by_fd(key_gpio_fd);
        printf("value:%d\n",value);
		sleep(100);
	}
	
	close(key_gpio_fd);
	reutrn 0;
}
#include "gpio_ctrl.h"
#include <poll.h>
#define KEY1_GPIO_NUM				GPIO_TO_PIN(0, 7)
#define KEY2_GPIO_NUM				GPIO_TO_PIN(0, 8)
#define KEY3_GPIO_NUM				GPIO_TO_PIN(0, 9)
void main(void)
{
	int ret;
	char buf[16];
	struct pollfd fds[3];

	int key1_gpio_fd = gpio_select_open(KEY1_GPIO_NUM, EDGE_TYPE_BOTH);
	int key2_gpio_fd = gpio_select_open(KEY1_GPIO_NUM, EDGE_TYPE_RISING);
	int key3_gpio_fd = gpio_select_open(KEY1_GPIO_NUM, EDGE_TYPE_FALLING);
	
	fds[0].fd = key1_gpio_fd;
	fds[0].events = POLLPRI;
	
	fds[1].fd = key2_gpio_fd;
	fds[1].events = POLLPRI;
	
	fds[2].fd = key3_gpio_fd;
	fds[2].events = POLLPRI;
	while(1)
	{
		ret = poll(fds, ARRAYLEN(fds), -1);
		if (ret > 0){
			if(fds[0].revents & POLLPRI){
				read(fds[0].fd, buf, sizeof(buf));
				lseek(fds[0].fd, 0, SEEK_SET);
			}
			
			if(fds[1].revents & POLLPRI){
				read(fds[1].fd, buf, sizeof(buf));
				lseek(fds[1].fd, 0, SEEK_SET);
			}
			
			if(fds[2].revents & POLLPRI){
				read(fds[2].fd, buf, sizeof(buf));
				lseek(fds[2].fd, 0, SEEK_SET);
			}
		}
	}
	
	close(key1_gpio_fd);
	close(key2_gpio_fd);
	close(key3_gpio_fd);
	reutrn 0;
}

PWM  应用编程

 

 

 

//pwm_open接口这里只是 对pwmchip0这个pwm控制器生效,一般SOC都会有多个PWM控制器,每个控制器又有多路pwm输出
#define SYSFS_PWM_DIR			"/sys/class/pwm/pwmchip0/"

int pwm_open(int pwm, int fre, int duty, int init_value)
{
	int fd, len;
	char buf[GPIO_CMD_MAX_BUF];

	//open export
	fd = open(SYSFS_PWM_DIR "/export", O_WRONLY);
	if (fd < 0) {
	  PERROR("export");
	  return fd;
	}
	//write export
	len = snprintf(buf, sizeof(buf), "%d", pwm);
	write(fd, buf, len);
	close(fd);

	//open period
	len = snprintf(buf, sizeof(buf), SYSFS_PWM_DIR "/pwm%d/period", pwm);
	fd = open(buf, O_WRONLY);
	if (fd < 0) {
	  PERROR("period");
	  return fd;
	}
	//write period
	len = snprintf(buf, sizeof(buf), "%d", fre);
	write(fd, buf, len);
	close(fd);

	//open duty_cycle
	len = snprintf(buf, sizeof(buf), SYSFS_PWM_DIR "/pwm%d/duty_cycle", pwm);
	fd = open(buf, O_WRONLY);
	if (fd < 0) {
	  PERROR("period");
	  return fd;
	}
	//write duty
	len = snprintf(buf, sizeof(buf), "%d", duty);
	write(fd, buf, len);
	close(fd);

	//open enable
	len = snprintf(buf, sizeof(buf), SYSFS_PWM_DIR "/pwm%d/enable", pwm);
	fd = open(buf, O_WRONLY);
	if (fd < 0) {
	  PERROR("period");
	  return fd;
	}

	if(init_value>=0){
		gpio_set_value_by_fd(fd, init_value);
	}

	return fd;
}

测试代码

#include "gpio_ctrl.h"

void main(void)
{
	int beep_gpio_fd = pwm_open(0, 4000, 60, 0);//以 ns(纳秒)为单位
	sleep(2000);
	reutrn 0;
}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PWM-GPIO驱动程序是Linux内核中的一个驱动模块,用于控制嵌入式系统中的GPIO引脚产生PWM信号。该驱动程序允许开发人员通过编程的方式来控制GPIO引脚的电平变化,从而产生不同占空比的PWM信号。 在Linux内核中,PWM-GPIO驱动程序通过向用户空间提供了相应的接口来实现PWM信号的控制。开发人员可以通过打开相应的设备节点,并使用相应的系统调用函数来设置PWM的频率、占空比等参数,从而实现对GPIO引脚的PWM信号的控制。 驱动程序的核心部分是一个PWM子系统,它与GPIO子系统紧密集成。PWM子系统负责管理PWM信号的生成和控制,而GPIO子系统负责管理GPIO引脚的配置和操作。PWM-GPIO驱动程序在这两个子系统之间起着桥梁的作用。 PWM-GPIO驱动程序的实现方式与硬件平台相关,每个平台可能有不同的具体实现。在驱动程序的初始化过程中,必须先配置GPIO引脚的功能为PWM模式,并将相应的寄存器映射到内核中,以便能够通过对寄存器的操作来控制GPIO引脚。驱动程序还需要初始化PWM子系统,为每个GPIO引脚分配相应的PWM通道,并根据需求设置PWM的频率、占空比等参数。 通过PWM-GPIO驱动程序,开发人员可以方便地利用Linux内核的功能来实现对嵌入式系统中GPIO引脚产生PWM信号的控制。这为开发PWM驱动、控制舵机、LED等应用提供了便捷的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值