基于S3C2440芯片的蜂鸣器驱动开发

来源:互联网 发布:费舍住宅尺寸数据 编辑:程序博客网 时间:2024/05/18 09:08

1、首先说一下,我使用的开发板是Tiny210的开发板,蜂鸣器的电路原理图和控制引脚图如下:






2、S3C2440的控制寄存器和数据寄存器

(1)控制寄存器


(2)数据寄存器



(3)参考代码:

1)buzzer.c

#include<linux/fs.h>#include<linux/device.h>#include<linux/types.h>#include<linux/module.h>#include<linux/init.h>#include<linux/cdev.h>#include<linux/slab.h>#include<asm/io.h>#include<asm/uaccess.h>#define DEV_NAME "buzzer"#define BUZZER_STOP 0#define BUZZER_START 1#defien GPD0_CON_ADDR 0xE02000A0static struct cdev buzzer_dev ;//定义一个设备驱动结构体static int buzzer_major = 0 ; //定义主设备号dev_t dev_num ; //定义一个设备号变量static int *map = NULL ; //定义一个map指针,在下面记录转换的地址MODULE_LICENSE("Dual BSD/GPL"); //模块遵从的协议GPLvoid buzzer_start(void) //启动蜂鸣器{unsigned int data;data = ioread32(map+0x01); //data = data|0x01; // 将data和1相或得1,即高电平iowrite32(data, map+0x01); //}void buzzer_stop(void) //关闭蜂鸣器{unsigned int data;data = ioread32(map+0x01); //data&=~0x01; //将data与0相与得到0,即低电平iowrite32(data, map+0x01); //}/* 打开操作 */int buzzer_open(struct inode *node, struct file *fp){unsigned int data;request_mem_region(GPD0_CON_ADDR, 4, DEV_NAME); //实现物理地址到虚拟地址的映射map = ioremap(GPD0_CON_ADDR, 8); //ioremap主要是检查传入地址的合法性,建立页表(包括访问权限),完成物理地址到虚拟地址的转换。data = ioread32(map); //data = data&(~0x01<<1); //data = data&(~0x01<<2); //data = data&(~0x01<<3); //data = data|0x01; //iowrite32(data,map);  //return 0;}/* 关闭操作 */int buzzer_release(struct inode *node, struct file *fp){printk("buzzer_release...\n");return 0;}/* 读写操作 */ssize_t buzzer_read(struct file *fp, char __user* buf, size_t size, loff_t *offp){return 0;}ssize_t buzzer_write(struct file *fp, const char __user* buf, size_t size, loff_t *offp){return 0;}/* IO端口控制 */int buzzer_ioctl(struct inode *node, struct file *fp, unsigned int cmd, unsigned long arg) {switch(cmd){case BUZZER_STOP: buzzer_stop(); break;case BUZZER_START: buzzer_start(); break;default:break;}return 0;}/*定义并初始化设备文件操作结构体*/struct file_operations buzzer_ops={ .owner = THIS_MODULE,.read = buzzer_read,.write = buzzer_write,.open = buzzer_open,.release = buzzer_release,.ioctl = buzzer_ioctl};static int __init buzzer_init(void) //初始化函数{int ret;cdev_init(&buzzer_dev, &buzzer_ops); //初始化设备,参数分别为设备驱动结构体和设备文件操作结构体if(buzzer_major){ret = register_chrdev_region(dev_num, 1, DEV_NAME);}else{alloc_chrdev_region(&dev_num, 0, 1, DEV_NAME);  //此函数的功能是动态分配设备编号,该函数需要传递给它指定的第一个次设备号firstminor(一般为0)和要分配的设备数count,以及设备名,调用该函数后自动分配得到的设备号保存在dev中。buzzer_major = MAJOR(dev_num);    //通过宏MAJOR获取主设备号printk("major %d\n", buzzer_major);}if(ret < 0){printk("get dev_num error\n");return ret;}buzzer_dev.owner = THIS_MODULE;   //初始化设备主buzzer_dev.ops = &buzzer_ops;    //初始化设备文件操作结构体cdev_add(&buzzer_dev, dev_num, 1);  //向内核注册设备字符驱动,参数本别为:设备驱动结构体,设备号,设备数量return 0;}static void __exit buzzer_exit(void) //设备卸载函数{printk("buzzer_exit...\n");unregister_chrdev_region(dev_num, 1); //释放字符设备设备号cdev_del(&buzzer_dev); //注销字符设备}module_init(buzzer_init); //设备驱动模块从这里加载module_exit(buzzer_exit); //卸载设备驱动

2)Makefile

ifeq ($(KERNELRELEASE),)KERNELDIR ?=/home/cf/ARM/linux-2.6.35.7PWD := $(shell pwd)modules:$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesmodules_install:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_installclean:rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions.PHONY: modules modules_install cleanelseobj-m :=buzzer.oendif


3) test.c

#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>#include<stdio.h>#define BUZZER_STOP 0#define BUZZER_START 1int main(){int dev_fd;dev_fd=open("/dev/test", O_RDWR); //打开设备驱动if(dev_fd<0) //检测设备能否正常打开{printf("cannot open buzzer_dev...\n");return -1;}while(1){ioctl(dev_fd,BUZZER_START,0); //打开蜂鸣器sleep(1);ioctl(dev_fd,BUZZER_STOP,0); //关闭蜂鸣器sleep(1);}close(dev_fd); //关闭设备驱动return 0;}


0 0
原创粉丝点击