不使用wiringPi库 分别编写一个应用程序和字符驱动程序实现wiringPi的digitalWrite(pin, value)功能 ,代码内带有注释
时间: 2024-04-29 18:23:06 浏览: 65
应用程序实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#define GPIO_DIR "/sys/class/gpio"
#define GPIO_MAX_BUF 64
// 定义GPIO的编号以及方向
typedef struct {
int gpio_num; // GPIO编号
int dir; // GPIO方向:0-输入,1-输出
} gpio_info_t;
// GPIO信息数组,根据需要添加
gpio_info_t gpios[] = {
{2, 1}, // GPIO2,输出
{3, 1} // GPIO3,输出
};
// 导出GPIO,设置方向
int gpio_init(int gpio_num, int dir) {
char buf[GPIO_MAX_BUF];
int fd;
// 导出GPIO
snprintf(buf, sizeof(buf), GPIO_DIR "/export");
fd = open(buf, O_WRONLY);
if (fd < 0) {
perror("open");
return -1;
}
snprintf(buf, sizeof(buf), "%d", gpio_num);
write(fd, buf, sizeof(buf));
close(fd);
// 设置GPIO方向
snprintf(buf, sizeof(buf), GPIO_DIR "/gpio%d/direction", gpio_num);
fd = open(buf, O_WRONLY);
if (fd < 0) {
perror("open");
return -1;
}
if (dir == 0) {
write(fd, "in", 2);
} else if (dir == 1) {
write(fd, "out", 3);
}
close(fd);
return 0;
}
// 设置GPIO输出值
int gpio_write(int gpio_num, int value) {
char buf[GPIO_MAX_BUF];
int fd;
// 打开GPIO文件
snprintf(buf, sizeof(buf), GPIO_DIR "/gpio%d/value", gpio_num);
fd = open(buf, O_WRONLY);
if (fd < 0) {
perror("open");
return -1;
}
// 设置GPIO输出值
if (value == 0) {
write(fd, "0", 1);
} else if (value == 1) {
write(fd, "1", 1);
}
close(fd);
return 0;
}
int main(int argc, char *argv[]) {
int i, value;
// 初始化GPIO
for (i = 0; i < sizeof(gpios) / sizeof(gpio_info_t); i++) {
gpio_init(gpios[i].gpio_num, gpios[i].dir);
}
// 设置GPIO输出值
if (argc == 3) {
i = atoi(argv[1]);
value = atoi(argv[2]);
gpio_write(i, value);
}
return 0;
}
```
字符驱动程序实现:
```c
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/gpio.h>
#define GPIO_MAX_NUM 64
static int major;
static struct cdev cdev;
static int gpio_num[GPIO_MAX_NUM];
static int gpio_count;
static int mygpio_open(struct inode *inode, struct file *filp) {
return 0;
}
static int mygpio_release(struct inode *inode, struct file *filp) {
return 0;
}
static ssize_t mygpio_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) {
char kbuf[32];
int ret, gpio, value;
if (count > sizeof(kbuf)) {
return -EINVAL;
}
ret = copy_from_user(kbuf, buf, count);
if (ret != 0) {
return -EFAULT;
}
kbuf[count] = '\0';
ret = sscanf(kbuf, "%d %d", &gpio, &value);
if (ret != 2) {
return -EINVAL;
}
if (gpio < 0 || gpio >= gpio_count) {
return -EINVAL;
}
gpio_set_value(gpio_num[gpio], value);
return count;
}
static struct file_operations mygpio_fops = {
.owner = THIS_MODULE,
.open = mygpio_open,
.release = mygpio_release,
.write = mygpio_write,
};
static int __init mygpio_init(void) {
int i, ret;
// 初始化GPIO
gpio_count = 0;
for (i = 0; i < GPIO_MAX_NUM; i++) {
if (gpio_is_valid(i)) {
gpio_num[gpio_count] = i;
gpio_direction_output(i, 0);
gpio_count++;
}
}
// 注册字符设备
ret = alloc_chrdev_region(&major, 0, 1, "mygpio");
if (ret < 0) {
return ret;
}
cdev_init(&cdev, &mygpio_fops);
cdev.owner = THIS_MODULE;
ret = cdev_add(&cdev, major, 1);
if (ret < 0) {
unregister_chrdev_region(major, 1);
return ret;
}
return 0;
}
static void __exit mygpio_exit(void) {
int i;
// 取消GPIO输出
for (i = 0; i < gpio_count; i++) {
gpio_direction_input(gpio_num[i]);
}
// 注销字符设备
cdev_del(&cdev);
unregister_chrdev_region(major, 1);
}
module_init(mygpio_init);
module_exit(mygpio_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Author");
MODULE_DESCRIPTION("Description");
```
注意:字符驱动程序需要在内核中编译运行,无法直接在用户空间运行。
阅读全文