最近在看一本书,受益匪浅,作者是李宁,下边是编写本次蜂鸣器的全程实录:
1. 了解开发板中的蜂鸣器
1) 查看蜂鸣器buzzer在底板中的管脚信息
2) 查看蜂鸣器在总线中的信息
3) 翻看S3C6410芯片手册,查看GPF15相关信息
2. 在了解了开发板中蜂鸣器之后,编写代码对它进行控制。
由于蜂鸣器是通过PWM(脉冲宽度调制)进行开关控制的,故也称为PWM。
1) 编写pwm.c(包含Linux驱动模块的主要模型代码)
#include 'pwm_fun.h'
static struct semaphore lock; /* 创建信号量*/
//文件打开时,自动操作此函数,使用信号量控制其访问
static int s3c6410_pwm_open(struct inode *inode, struct file *file){
if (!down_trylock(&lock)) /* 使用信号量控制只能由一个进程打开 */
{
return 0;
}
else{
return -EBUSY;
}
}
//文件关闭时,自动操作此函数,使用信号量控制其访问
static int s3c6410_pwm_close(struct inode *inode, struct file *file){
up(&lock); /* 释放信号量 */
return 0;
}
//文件中关于ioctl的操作
static long s3c6410_pwm_ioctl(struct file *filep, unsigned int cmd, unsigned long arg){
switch ( cmd ) {
case PWM_IOCTL_START:
pwm_start();
break;
case PWM_IOCTL_STOP:
pwm_stop();
break;
default:
break;
} /* ----- end switch ----- */
return 0;
}
//文件操作的指针
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.open = s3c6410_pwm_open,
.release = s3c6410_pwm_close,
.unlocked_ioctl = s3c6410_pwm_ioctl,
};
//设备的属性
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
//驱动的入口函数
static int __init dev_init(void){
int ret;
init_MUTEX(&lock); /* 初始化信号量 */
ret = misc_register(&misc);
printk(DEVICE_NAME'tinitializedn');
return ret;
}
//驱动的退出函数
static void __exit dev_exit(void){
misc_deregister(&misc);
printk(DEVICE_NAME'texitedn');
}
module_init(dev_init);
module_exit(dev_exit);
2) 编写pwm_fun.c(包含对蜂鸣器控制的主要代码)
#include 'pwm_fun.h'
void pwm_start(void){
unsigned int tmp;
tmp = ioread32(S3C64XX_GPFCON);
tmp &= ~(0x3U<<30); /* 最高两位清零,保留其他位 */
tmp |= (0x2U<<30); /* 最高两位设置为10,蜂鸣器发出尖叫声 */
iowrite32(tmp, S3C64XX_GPFCON);
}
void pwm_stop(void){
unsigned tmp;
tmp = ioread32(S3C64XX_GPFCON);
tmp &= ~(0x3U<<30); /* 最高两位清零,蜂鸣器停止尖叫 */
iowrite32(tmp, S3C64XX_GPFCON);
}
3) 编写pwm_fun.h(包含一些必须的头文件及宏定义信息)
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEVICE_NAME 'pwm_dev' #define PWM_IOCTL_START 1 #define PWM_IOCTL_STOP 0 extern void pwm_start(void); extern void pwm_stop(void); 4) 编写Makefile文件(使编译过程自动完成) obj-m := pwm_driver.o pwm_driver-objs := pwm.o pwm_fun.o PWD := $(shell pwd) CROSS_COMPILE ?= arm-none-linux-gnueabi- CC := $(CROSS_COMPILE)gcc CFLAGS += -static KPATH := /media/Source/Forlinx/android2.3_kernel_v1.01 all: ioctl make -C $(KPATH) M=$(PWD) modules ioctl: ioctl.c $(CC) $(CFLAGS) $^ -o $@ clean: rm -rf *.o *.ko *.mod.c Module.* modules.* ioctl 5) 编写测试程序ioctl(用于对驱动程序的测试) #include #include #include #include #include /* * === FUNCTION ====================================================================== * Name: main * Description: 对驱动程序进行测试 * ===================================================================================== */ int main ( int argc, char *argv[] ) { int file_handler = 0; int cmd = 0; int arg = 0; if (argc < 4) { printf('Usage: ioctl return EXIT_FAILURE; } cmd = atoi(argv[2]); arg = atoi(argv[3]); printf('dev:%sn', argv[1]); printf('cmd:%dn', cmd); printf('arg:%dn', arg); file_handler = open(argv[1], 0); if (file_handler<0) { printf('open %s failure.n', argv[1]); } ioctl(file_handler, cmd, arg); close(file_handler); return EXIT_SUCCESS; 3. 编写好源代码程序之后,交叉编译,上传至OK6410A开发板,进行测试 1) 配置好交叉编译工具链arm-none-linux-gnueabi-gcc之后,在终端输入make即可自动完成编译 2) OK6410A(Android2.3.4操作系统)通过USB线连接至PC端,通过adb上传至开发板: adb push pwm_driver.ko /tmp/pwm_driver.ko adb push ioctl /tmp/ioctl 3) 通过adb shell打开并控制OK6410A开发板,输入命令安装驱动模块: adb shell insmod /tmp/pwm_driver.ko 4) 测试蜂鸣器驱动程序 /tmp/ioctl /dev/pwm_dev 1 0 #打开蜂鸣器 /tmp/ioctl /dev/pwm_dev 0 0 #关闭蜂鸣器
上一篇:关于Android的HAL的一些理解
下一篇:Android深度探索--HAL与驱动开发第五章读后感
推荐阅读最新更新时间:2024-11-08 11:39
设计资源 培训 开发板 精华推荐
- AM1DR-2412SH30Z 12V 1 瓦 DC-DC 转换器的典型应用
- 使用 Microchip Technology 的 PD70210ILD 的参考设计
- 开源穿戴手表(含固件,原理图和3D打印图)
- LTC1728ES5-2.5、3.3V 双电源监视器的典型应用
- 使用 Analog Devices 的 LT4276AHUFD 的参考设计
- Cube-436_迷你示波器
- MC78M20CTG 20V可调输出稳压器的典型应用
- 使用 Analog Devices 的 LTC1315CG 的参考设计
- NCV887720BSTGEVB:汽车启停非同步升压控制器评估板
- DC161A,LT1373HV 演示板,SLIC 电源,-20Vout at 60mA 和 -60Vout at 35mA+