前言
人體紅外模塊 是一種能夠檢測人或動物發(fā)射的紅外線而輸出電信號的傳感器。廣泛應(yīng)用于各種自動化控制裝置中。比如常見的樓道自動開關(guān)、防盜報警等。
一、SR501模塊介紹
引腳 : VCC,OUT, GND
。
功能 :一種常見的人體紅外傳感器模塊,用于檢測人體的活動。
紅外感應(yīng)原理 :SR501 模塊內(nèi)部包含一個紅外傳感器探測單元,該單元可以檢測環(huán)境中的紅外輻射變化。即使在黑暗中,人體也會通過輻射紅外能量來體現(xiàn)溫度差異。
- 靜止?fàn)顟B(tài)(無人靠近)時,OUT 引腳通常為低電平。
- 當(dāng)有人體靠近時,OUT 引腳通常會從低電平變?yōu)?mark>高電平。
2 個電位器 : 可以通過電位器實現(xiàn)封鎖時間和檢測距離的調(diào)節(jié) ( 延時控制,距離調(diào)節(jié) )。
二、設(shè)備樹添加節(jié)點
配置設(shè)備樹需要對 GPIO 引腳 以及相關(guān)的 pincontrol 配置。由于本實驗是使用 SR501 模塊,所以不需要配置 pincontrol 。
通過 SR501人體紅外模塊 的原理圖得到 該模塊 高電平有效
。我將其接到開發(fā)板的 gpio4-19
引腳。
compatible :用于 和 驅(qū)動程序進(jìn)行匹配。
使用 gpio4 組的 19 號引腳。(每一組有 32 個引腳)
三、驅(qū)動程序
- 定義字符設(shè)備結(jié)構(gòu)體。
由于 使用 模塊 SR501,只需要讀出引腳電平即可。
static struct file_operations sr501_ops={
.owner = THIS_MODULE,
.read = sr501_read,
};
- 實現(xiàn) read 函數(shù)。
wait_event_interruptible(sr501_wq, sr501_data); : 這是一個等待隊列的函數(shù)調(diào)用。當(dāng)前執(zhí)行的線程(或進(jìn)程)進(jìn)入睡眠狀態(tài),直到滿足指定的條件。
sr501_wq :等待隊列頭對象。
sr501_data 是條件。如果 sr501_data 為真(非零),表示數(shù)據(jù)已經(jīng)準(zhǔn)備好,線程可以繼續(xù)執(zhí)行。否則,線程將進(jìn)入睡眠狀態(tài),并被放入等待隊列。
copy_to_user 函數(shù)的作用是將內(nèi)核空間中的數(shù)據(jù)復(fù)制到用戶空間的緩沖區(qū)(buf)中。
static wait_queue_head_t sr501_wq; // 定義隊列頭
static ssize_t sr501_read (struct file *file, char __user *buf, size_t size, loff_t *oddset)
{
int err;
int len = (size < 4) ? size : 4;
wait_event_interruptible(sr501_wq, sr501_data); /* 無數(shù)據(jù)休眠,有數(shù)據(jù)喚醒 */
err = copy_to_user(buf, &sr501_data, len);
sr501_data = 0;
return len;
}
- 定義一個platform_driver
sr501_table 數(shù)組 用于和設(shè)備樹里的 信息進(jìn)行匹配。
匹配成功后 直接調(diào)用 sr501_probe 函數(shù)。
static const struct of_device_id sr501_table[] = {
{ .compatible = "my,sr501"},
{},
};
static struct platform_driver sr501_driver = {
.driver = {
.name = "sr501",
.of_match_table = sr501_table,
},
.probe = sr501_probe,
.remove = sr501_remove,
};
- 注冊一個 file_operations 結(jié)構(gòu)體,platform_driver。
在 入口函數(shù)里進(jìn)行注冊,在出口函數(shù)里進(jìn)行 卸載。
init_waitqueue_head:這是一個內(nèi)核函數(shù),用于初始化一個等待隊列頭對象
。等待隊列頭用于管理等待隊列。
&sr501_wq:這是等待隊列頭對象的地址
。
static int sr501_init(void)
{
int err;
major = register_chrdev(0, "sr501", &sr501_ops);
class = class_create(THIS_MODULE, "sr501_class");
err = PTR_ERR(class);
if (IS_ERR(class)) {
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
unregister_chrdev(major, "sr501");
return -1;
}
platform_driver_register(&sr501_driver);
init_waitqueue_head(&sr501_wq); // 初始化等待隊列頭
return 0;
}
static void sr501_exit(void)
{
platform_driver_unregister(&sr501_driver);
class_destroy(class);
unregister_chrdev(major, "sr501");
}
- 實現(xiàn) probe 函數(shù)。
當(dāng)設(shè)備樹 和 驅(qū)動和程序匹配成功后調(diào)用 probe 函數(shù)。
gpiod_get :從設(shè)備樹里獲取 GPIO 引腳信息。
==gpiod_direction_input ==: 設(shè)置引腳方向。()輸入
gpiod_to_irq :獲得中斷號。
request_irq : 申請中斷。第二個參數(shù)是 中斷處理函數(shù)。文章來源:http://www.zghlxwxcb.cn/news/detail-601215.html
static int sr501_probe(struct platform_device *pdev)
{
sr501_gpio = gpiod_get(&pdev->dev, NULL, 0); //獲取引腳信息
gpiod_direction_input(sr501_gpio); // 設(shè)置為 輸入引腳
irq = gpiod_to_irq(sr501_gpio); // 獲取中斷號
request_irq(irq, sr501_isr, IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, "sr501", NULL); //請求中斷
device_create(class, NULL, MKDEV(major, 0), NULL, "sr501"); //創(chuàng)建設(shè)備節(jié)點
return 0;
}
- 在 probe 里申請了,就需要在 remove 函數(shù)里進(jìn)行卸載.
device_destroy(class,MKDEV(major, 0));
free_irq(irq, NULL);
gpiod_put(sr501_gpio);
- 中斷處理函數(shù)。
wake_up 喚醒 在 read 函數(shù)里休眠的隊列。將 sr501_data 賦值為 1 ,則 read 函數(shù)里條件為真,執(zhí)行程序。
static irqreturn_t sr501_isr(int irq, void *dev_id)
{
sr501_data = 1;
wake_up(&sr501_wq); /* 喚醒隊列 */
return IRQ_HANDLED;
}
四、測試程序
首先判斷參數(shù) argc 是否正確。
以 O_RDWR 可讀可寫的方式打開設(shè)備節(jié)點,獲取設(shè)備句柄 fd 。
while 循環(huán)里讀引腳電平,當(dāng) 引腳為高電平 并且 正確讀出時,打印有人靠近。文章來源地址http://www.zghlxwxcb.cn/news/detail-601215.html
if(argc != 2)
{
printf("Usage: %s <dev>\n",argv[0]);
return -1;
}
//打開文件
fd = open(argv[1], O_RDWR);
if(-1 == fd)
{
printf("open %s error!\n",argv[1]);
return -1;
}
while (1)
{
ret = read(fd, &val, 4);
if((1 == val) && (ret == 4))
printf("有人靠近!\n");
}
close(fd);
五、上機(jī)測試及效果
- 將 .ko 文件加載到內(nèi)核。
使用 insmod 命令可以將 KO 文件加載到內(nèi)核中,使模塊生效。而使用rmmod 命令可以卸載已加載的模塊,lsmod 命令 可以觀察已加載到內(nèi)核的文件。 - 執(zhí)行測試程序。
/dev/sr501
是在驅(qū)動程序中創(chuàng)建的設(shè)備節(jié)點 ( device_create )。
當(dāng)有人靠近時,通過讀出引腳電平的變化判斷是否有人靠近。
總結(jié)
到了這里,關(guān)于SR501人體紅外模塊的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!