既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
#define gpio\_get\_value \_\_gpio\_get\_value
int \_\_gpio\_get\_value(unsigned gpio)
函数参数和返回值含义如下:
- gpio:要获取的 GPIO 标号。
- 返回值:非负值,得到的 GPIO 值;负值,获取失败。
6、gpio_set_value 函数
此函数用于设置某个 GPIO 的值,此函数是个宏,定义如下
#define gpio\_set\_value \_\_gpio\_set\_value
void \_\_gpio\_set\_value(unsigned gpio, int value)
函数参数和返回值含义如下:
- gpio:要设置的 GPIO 标号。
- value:要设置的值。
- 返回值:无
关于 gpio 子系统常用的 API 函数就讲这些,这些是我们用的最多的。
GPIO子系统示例 读取按键
/\*
\* @Copyright:
\* @FileNames:
\* @Description: 申请全局内存4096 并使用该内存进行 用户和内核之间的数据交换
\* @Author: yangyue19@hikvision.com.cn
\* @Date: 2022-07-29 09:03:02
\* @Version: V1.0
\* @LastEditTime: 2022-08-05 16:51:03
\*/
#include <linux/module.h>//MOUDLE\_XXX moudle\_xxx
#include <linux/fs.h> //file\_operations register\_chrdev\_region alloc\_chrdev\_region
#include <linux/init.h> //\_\_init \_\_exit
#include <linux/cdev.h> //cdev
#include <linux/uaccess.h>//copy\_to\_user copy\_from\_user
#include <linux/device.h> // device class
#include <linux/gpio.h>
#define KEY\_DEBUG 1
#define KEY\_CLASS\_NAME "key" //创建的类名称
#define KEY\_NODE\_NAME "key\_0" //创建的节点名称
#define KEY\_MAJOR 250
typedef struct {
//设备驱动变量
struct cdev cdev;
//设备号变量
dev\_t devid;
int major;
int minor;
//设备节点相关变量
struct class \*class;
struct device \*device;
//按键使用的GPIO编号
int key_index;
//用户变量
//上一次读取的按键数值
int last_value;
int value;
}rtl\_key\_t;
rtl\_key\_t key;
/\*\*
\* @function: key\_open
\* @description: 打开设备 并将内存清零
\* @input:
\* @output:
\* @return {\*}
\* @param {inode} \*inode
\* @param {file} \*flip
\*/
static int key\_open(struct inode \*inode ,struct file \*flip)
{
flip->private_data=(void \*)(&key);
return 0;
}
/\*\*
\* @function: key\_release
\* @description: 释放设备节点
\* @input:
\* @output:
\* @return {\*}
\* @param {inode} \*inode
\* @param {file} \*flip
\*/
static int key\_release(struct inode \*inode ,struct file \*flip)
{
return 0;
}
/\*\*
\* @function: key\_read
\* @description: 拷贝数据到用户区
\* @input:
\* @output:
\* @return {\*}
\* @param {file\*} flip 文件结构体
\* @param {char \_\_user} \*buf 从用户区拷贝出来的数据
\* @param {size\_t} size 传入数据大小
\* @param {loff\_t} \*ppos 当前数据位置
\*/
static ssize\_t key\_read(struct file\* flip, char __user \*buf,size\_t size ,loff\_t \*ppos)
{
int ret=0;
rtl\_key\_t\* dev=(rtl\_key\_t\*) flip->private_data;
ret= gpio\_get\_value(dev->key_index);
copy\_to\_user(buf,&ret,sizeof(ret));
return 4;
}
/\*\*
\* @function: key\_write
\* @description:
\* @input:
\* @output:
\* @return {\*}
\* @param {file\*} flip
\* @param {char \_\_user} \*buf
\* @param {size\_t} size
\* @param {loff\_t} \*ppos
\*/
static ssize\_t key\_write(struct file\* flip, const char __user \*buf,size\_t size ,loff\_t \*ppos)
{
int ret=0;
rtl\_key\_t\* dev=(rtl\_key\_t\*) flip->private_data;
if(ret<0)ret=-EFAULT;
else{
}
return ret;
}
static const struct file\_operations key_fops={
.owner=THIS_MODULE,
.open=key_open,
.release=key_release,
.read=key_read,
.write=key_write,
};
/\*\*
\* @function: static void key\_setup\_cdev(int minor\_index)
\* @description: 根据一个从设备号生成cdev
\* @input:
\* @output:
\* @return {\*}
\*/
static void key\_setup\_cdev(int minor_index)
{
int ret;
//得到设备号
int devno=MKDEV(key.major,minor_index);
cdev\_init(&key.cdev,&key_fops);
key.cdev.owner=THIS_MODULE;
ret=cdev\_add(&key.cdev,devno,1);
if(ret)printk(KERN_INFO"CDEV ADD ERROR:%d\n",minor_index);
}
/\*\*
\* @function: key\_init
\* @description: 申请设备号 并且注册cdev
\* @input: void
\* @output:
\* @return {\*}
\*/
static int __init key\_init(void)
{
int ret;
//如果定义了静态主设备号 就采用静态申请的方式
key.major=KEY_MAJOR;
printk(KERN_INFO "KEY INIT\r\n");
key.key_index=58;
gpio\_request(key.key_index, "key");
ret = gpio\_direction\_input(key.key_index);
if(ret<0)printk(KERN_INFO "CAN NOT SET PIN\n");
//得到需要注册的设备号
key.devid=MKDEV(key.major,key.minor);
if(key.major!=0){//从devno 静态申请 一个设备号
ret=register\_chrdev\_region(key.devid,1,"key");
}else{//从devno 动态申请一个设备号
ret=alloc\_chrdev\_region(&key.devid,0,1,"key");
key.major=MAJOR(key.devid);
key.minor=MINOR(key.devid);
}
if(KEY_DEBUG){
printk(KERN_INFO "major:%d\n",key.major);
printk(KERN_INFO "minor:%d\n",key.minor);
}
key\_setup\_cdev(key.minor);
//创建设备 创建类
key.class = class\_create(THIS_MODULE, KEY_CLASS_NAME);
key.device = device\_create(key.class, NULL, key.devid, NULL, KEY_NODE_NAME);
return 0;
}
module\_init(key_init);
static void __exit key\_exit(void)
{
cdev\_del(&key.cdev);
unregister\_chrdev\_region(key.devid,1);
gpio\_free(key.key_index);
//删除设备 删除类
device\_destroy(key.class, key.devid);
class\_destroy(key.class);
}
module\_exit(key_exit);
MODULE\_AUTHOR("YURI");
MODULE\_LICENSE("GPL");
/\*
\* @Copyright:
\* @FileNames:
\* @Description:
\* @Author: yangyue19@hikvision.com.cn
\* @Date: 2022-07-29 13:44:24
\* @Version: V1.0
\* @LastEditTime: 2022-08-05 17:06:38
\*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#define DEVICE\_NAME "/dev/key"
int main()
{
int i=0,ret=0,key=0;
int fd=open(DEVICE_NAME,O_RDWR);
if(ret<0)perror("open error");
while (1)
{
ret=read(fd,(void\*)&key,4);
printf("KEY VALUE:%d\n",key);
sleep(1);
}
close(fd);
return 0;
}
注意
因为权限问题,所以没有办法手动添加设备节点,也没有mdev,udev进行设备节点的管理,
所以需要手动添加设备节点。所以需要改一个脚本
rootfs\tools\mkimg
添加
echo “/dev/key c 666 root root 250 0” >> squashfs-pf-list.txt
收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
想自学提升的朋友。**
[外链图片转存中…(img-rdndJwSe-1715796793180)]
[外链图片转存中…(img-LaYobVnZ-1715796793181)]
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!