嵌入式学习4--混杂设备驱动
混雜設備驅動主要用于一些功能簡單的器件,將之整合到一起,major為10,minor一般為動態(tài)分配,其實實際的還是字符設備驅動。
比常規(guī)字符設備驅動更好的地方就是在于它簡化了編寫過程,將一些步驟整合到了一起,使代碼更加簡潔,可讀性更高,也便于維護和移植。
以下代碼為超聲波傳感器的驅動代碼
1.超聲波SRF05傳感器,在這里只用了Vcc、Trig、Echo、GND四個腳
A.Vcc 接5V電源
B.Trig接主板輸出端,主要是發(fā)送啟動信號
C.Echo接輸入端,主要檢測這個腳傳回來的值進行距離計算
D.GND接地
使用注意:如果帶電操作,一定要保證先接地,否則極易損壞器件
?
?
2.時序圖
A.觸發(fā)信號為至少維持20uS的高電平信號,需要控制Trig引腳來做啟動
B.模塊會發(fā)出8個40KHz的脈沖信號,并檢測回波
C.如果有回波,就輸出回響信號,回響信號會通過Echo引腳檢測,檢測到后做相應的處理
D.計算的公式為
?
3.以下為驅動代碼,Linux驅動代碼需要從下向上看
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <mach/platform.h>
#include <linux/errno.h>
#include <linux/input.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>
#define DEVICE_NAME "ultra_drv"
#define GPIOC_CFG_ULTRA_TRIG (PAD_GPIO_B + 28) ? ?//Trig引腳
#define GPIOC_CFG_ULTRA_ECHO (PAD_GPIO_B + 29) ?//Echo引腳
static int echo_data_in(void) ??
{
?? ?gpio_direction_input(GPIOC_CFG_ULTRA_ECHO); ?//設置為輸入引腳
?? ?return gpio_get_value(GPIOC_CFG_ULTRA_ECHO); ?//檢測當前電平
}
static int ultra_read_data(void)
{
?? ?unsigned int time_cnt = 0;
?? ?unsigned int distance = 0;
?? ?int ret = 0;
?? ?
?? ?ret = echo_data_in(); ? ? ? ? ? ? ? ? ? ?
?? ?if(ret){
?? ??? ?while(echo_data_in() && ((time_cnt++) < 50000)) ? ? ?//如果返回的是高電平代表有回波信號,開始記錄高電平持續(xù)時間
?? ??? ?{
?? ??? ??? ?udelay(10);
?? ??? ?}
?? ??? ?
?? ??? ?distance = ((time_cnt * 3) / 2); ?//當Echo拉低的時候,代碼測距完成,開始計算
?? ?}
?? ?return (distance);
}
int ultra_drv_open(struct inode *inode, struct file *filp)
{
?? ?printk("<4>" "ultra drv open\n");
?? ?
?? ?return 0;
}
ssize_t ultra_drv_read(struct file *filp, char __user *user_buf, size_t size, loff_t *offset)
{
?? ?int ret = 0;
?? ?unsigned int distance = 0;
?? ?
?? ?if(size != 4)
?? ??? ?return -EINVAL;
?? ?
?? ?gpio_direction_output(GPIOC_CFG_ULTRA_TRIG, 1); ?//啟動信號,控制Trig引腳拉高
?? ?udelay(20); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //至少維持10uS的高電平
?? ?gpio_set_value(GPIOC_CFG_ULTRA_TRIG, 0); ? ? ? ? ? ?//拉低Trig引腳,啟動成功
?? ?
?? ?distance = ultra_read_data(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//開始檢測Echo是否有回波信號
?? ?
?? ?ret = copy_to_user((int *)user_buf, &distance, sizeof(distance)); ?//將檢測到的距離copy到用戶空間,通過read讀取到
?? ?
?? ?return 0;
}
static struct file_operations ultra_drv_fops = { ? ? ?//文件操作集
?? ?.owner = THIS_MODULE,
?? ?.open ?= ultra_drv_open,
?? ?.read ?= ultra_drv_read
};
static struct miscdevice ultra_drv_miscdev = { ? //混雜設備
?? ?.minor = MISC_DYNAMIC_MINOR, ?//動態(tài)分配minor(此設備號)
?? ?.name ?= DEVICE_NAME, ? ? ? ? ? ? ? ? //設備名,使用open打開的就是這個名字
?? ?.fops ?= &ultra_drv_fops ? ? ? ? ? ? ? ? ? ? //文件操作集
};?
static int __init ultra_drv_init(void)
{
?? ?int ret = 0;
?? ?
?? ?gpio_free(GPIOC_CFG_ULTRA_TRIG); ? ? //野路子,避免內(nèi)核中已經(jīng)有功能使用該引腳,先釋放掉
?? ?
?? ?ret = gpio_request(GPIOC_CFG_ULTRA_TRIG, "ultra_drv"); ? ? ? //釋放后再申請給我們使用
?? ?if(ret < 0){
?? ??? ?printk("<4>" "gpio_request %s %d fail\n", DEVICE_NAME, GPIOC_CFG_ULTRA_TRIG);
?? ??? ?return ret;
?? ?}
?? ?ret = misc_register(&ultra_drv_miscdev); ? ? ? ?//注冊混雜設備
?? ?if(ret < 0){
?? ??? ?printk("<4>" "misc_register fail\n");
?? ??? ?return ret;
?? ?}
?? ?
?? ?printk("<4>" "ultra drv init\n");
?? ?
?? ?return 0;
}
static void __exit ultra_drv_exit(void)
{
?? ?gpio_free(GPIOC_CFG_ULTRA_TRIG);
?? ?
?? ?misc_deregister(&ultra_drv_miscdev);
?? ?
?? ?printk("<4>" "ultra drv exit\n");
}
module_init(ultra_drv_init);
module_exit(ultra_drv_exit);
MODULE_AUTHOR("ayl0521@sina.com"); ?//如有問題,可郵件探討
MODULE_DESCRIPTION("ultrasonic drv");
MODULE_LICENSE("GPL");
總結
以上是生活随笔為你收集整理的嵌入式学习4--混杂设备驱动的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决Ubuntu系统中文乱码显示问题
- 下一篇: MCMC算法学习总结