s3c2440 杂项驱动实现蜂鸣器

这个驱动本来是非常简单的,但是我就是想做个杂项驱动。

Linux驱动中把无法归类的五花八门的设备定义为混杂设备(用miscdevice结构体表述)。miscdevice共享一个主设备号MISC_MAJOR(即10),但次设备号不同。

蜂鸣器控制原理

先来看下蜂鸣器的电路图:

其实做了前面的LED点灯驱动,那做这个驱动就是分分钟钟的事。从上面的电路图可以知道控制蜂鸣器的引脚就是GPB0;这样就非常简单了,需要操作的就是。

1、初始化

s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);// 设置GPBCON

s3c2410_gpio_setpiin(S3C2410_GPB(0), 1); // 设置GPBDAT

2、根据参数开关蜂鸣器

s3c2410_gpio_setpin(S3C2410_GPB(0), flag); // 根据flag来开关蜂鸣器;

杂项设备知识

杂项设备结构体(杂项设备的主设备号固定为10,不同的杂项设备是通过次设备号来区分的)

struct miscdevice  {
	int minor; // 次设备号
	const char *name;// 设备名称
	const struct file_operations *fops; // 关联的操作函数
	struct list_head list;
	struct device *parent;
	struct device *this_device;
	const char *nodename;
	mode_t mode;
};

其实从上面的结构体可以知道,杂项设备驱动只能驱动一个设备,因为杂项驱动主设备号固定为10(不同杂项设备通过次设备号来区分),而结构体中只有一个次设备号,所以可以看出杂项驱动只能驱动一个设备;如果要驱动多个设备,则不能用杂项驱动;(同类设备要靠次设备来区分)

下面要说的两个杂项驱动操作函数都在:/devices/char/Misc.c;创建和初始化杂项驱动:int misc_register(struct miscdevice * misc);这个函数就大概相当于:字符驱动中的设备号创建,字符设备的申请和初始化等(alloc_chrdev_region()设备号申请;cdevp = cdev_alloc()申请字符结构;cdev_init(cdevp, &fops)让字符结构和操作函数绑定;cdev_add(cdevp, devNum,
1)绑定主设备号;)

当然和创建初始化相反的就是:int misc_deregister(struct miscdevice *misc);函数了,该函数的功能和上面的创建函数相反;

驱动代码

#include<linux/init.h>
 #include<linux/module.h>
 #include<linux/fs.h>
 #include<linux/miscdevice.h>
 #include<linux/gpio.h>
 #include<mach/regs-gpio.h>

 #define DEV_NAME "yzhBuzzer"

 ssize_t myOpen(struct inode *inode, struct file *file)
 {
     printk(KERN_INFO"in myOpen!\n");
     s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);
     s3c2410_gpio_setpin(S3C2410_GPB(0), 1);
     return 0;
 }

 int myIoctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long  arg)
 {
     printk(KERN_INFO"in myIoctl  cmd:%u, arg:%ld\n", cmd, arg);
     if (!cmd)
         s3c2410_gpio_setpin(S3C2410_GPB(0), 0);
     else
         s3c2410_gpio_setpin(S3C2410_GPB(0), 1);
     return 0;
 }

 struct file_operations fop =
 {
     .owner = THIS_MODULE,
     .ioctl = myIoctl,
     .open  = myOpen,
 };

 static struct miscdevice misc =
 {
     .minor = MISC_DYNAMIC_MINOR,
     .name  = DEV_NAME,
     .fops  = &fop,
 };

 static int __init buzzer_init(void)
 {
     int ret;
     printk(KERN_INFO"buzzer init!\n");
     ret = misc_register(&misc);
     return ret;
 }

 static void __exit buzzer_exit(void)
 {
     printk(KERN_INFO"buzzer exit!\n");
     misc_deregister(&misc);
 }

 module_init(buzzer_init);
 module_exit(buzzer_exit);
 MODULE_LICENSE("Dual BSD/GPL");

附上一个Makefile,现在写的驱动都是非常简单的,所以Makefile基本是可以通用的:

obj-m:=buzzer.o

 CC=arm-linux-gcc

 #KERDIR=/lib/modules/$(shell uname -r)/build
 KERDIR=/home/kernel/linux-2.6.32.2

 CURDIR=$(shell pwd)

 all:
     make -C $(KERDIR) M=$(CURDIR) modules

 clean:
     make -C $(KERDIR) M=$(CURDIR) clean

测试代码

测试代码非常简单,这个驱动加载进去后会自动在dev下面创建设备文件。直接操作这个文件就可以了;因为只有一个蜂鸣器,所以用ioctl函数实现有个参数是多余的。

 #include<stdio.h>
 #include<stdlib.h>
 #include<errno.h>
 #include<fcntl.h>

 int main(int argc, char *argv[])
 {
     int flag = 0;
     int fd = open("/dev/yzhBuzzer", O_RDWR);
     if(fd < 0)
         printf("int open error:%d\n", errno);
     if (argc > 1)
         flag = 1;

     if(ioctl(fd, flag, 0) < 0)
         printf("int ioctl error:%d", errno);

     return 0;
 }

转载请注明作者和原文出处,原文地址:http://blog.csdn.net/yuzhihui_no1/article/details/45131611

若有不正确之处,望大家指正,共同学习!谢谢!!!

时间: 2024-11-02 11:33:13

s3c2440 杂项驱动实现蜂鸣器的相关文章

第三十四天:按键驱动与蜂鸣器驱动以及MMU

编写按键驱动的过程和编写LED灯的驱动类似.区别在于按键是在底板上的.要从底板的电路图开始看.   使用key为关键字查找电路图: 可以得知的信息:按键松开时候XEINT26为高电平.按下时候为底电平.所以要判断按键是否被按下,就要检测XEINT26的状态. 使用XEINT26为关键字,在核心板上查看其定义.找到下图: XEINT26在核心板上链接到GPX3_2上.然后就是去datasheet中查找GPX3_2的说明了. 按键为检测,GPX3CON置0,GPX3DAT置1,表示按键被按下.代码如

SPI在linux3.14.78 FS_S5PC100(Cortex A8)和S3C2440上驱动移植(deep dive)

由于工作的原因,对SPI的理解最为深刻,也和SPI最有感情了,之前工作都是基于OSEK操作系统上进行实现,也在US/OS3上实现过SPI驱动的实现和测试,但是都是基于基本的寄存器操作,没有一个系统软件架构的思想,感觉linux SPI驱动很强大,水很深,废话少说,SPI总线上有两类设备:一类是主机端,通常作为SOC系统的一个子模块出现,比如很多嵌入式MPU中都常常包含SPI模块.一类是从机被控端,例如一些SPI接口的Flash.传感器等等.主机端是SPI总线的控制者,通过使用SPI协议主动发起S

S3C2440 LCD驱动(FrameBuffer)实例开发&lt;一&gt;(转)

1. 背景知识 在多媒体的推动下,彩色LCD越来越多地应用到嵌入式系统中,PDA和手机等大多都采用LCD作为显示器材,因此学习LCD的应用很有实际意义! LCD工作的硬件需求:要使一块LCD正常的显示文字或图像,不仅需要LCD驱动器,而且还需要相应的LCD控制器.在通常情况下,生产厂商把LCD驱动器会以COF/COG的形式与LCD玻璃基板制作在一起,而LCD控制器则是由外部的电路来实现,现在很多的MCU内部都集成了LCD控制器,如S3C2410/2440等.TQ2440是采用了S3C2440,S

s3c2440 LED驱动分析

这个开发板已经很久没有动了,这一次辞职后想来想去还是选择去做驱动吧.以前写的那些驱动代码早就不知道哪里去了,当然更不记得了.所以现在从头开始学习,也顺便记录下笔记: 原理 首先看看LED的电路图: 不难看出,LED1==GPB5   LED2==GPB6   LED3==GPB7    LED4==GPB8 然后就去看看IO端口图: 要设置的非常简单,就是把GPBCON设置为输出,GPBDAT设置为0时,则灯亮:设置为1时,则灯灭: 相关知识点 其实上一篇中s3c2440系统自带的管脚宏和函数已

S3C2440触摸屏驱动实例开发讲解

出处:http://www.embeddedlinux.org.cn/html/yingjianqudong/ 一.开发环境 主  机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand, Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2 二.前提知识 1.Linux输入子系统(Input Subsystem): 在Linux中,输入子系统是由输入子系统设备驱动层.输入子系统核心层(Input Core)和输入子系统事件处理层(Even

【转】s3c2440 按键驱动 — 字符设备

原文网址:http://www.xuebuyuan.com/632893.html 主机:VM - redhat 9.0 开发板:FL2440,linux-2.6.12 arm-linux-gcc:3.4.1 (1)原理图上的按键模块,可以看到相应的GPIO口,以及中断号. 由图可以得知GPF0等接高电平,当按键按下,则接低电平,所以将中断响应设置为下降沿触发. (2)驱动程序gzliu_2440_key.c,实现为一般的字符设备驱动,完整的源码如下,其中: // 定时器的使用参考:http:/

S3C2440 LCD驱动(FrameBuffer)实例开发&lt;二&gt;(转)

开发板自带的LCD驱动是基于platform总线写的,所以如果要使其它的LCD能够在自己的开发板上跑起来,那么就先了解platform驱动的架构,下面简单记录下自己看platform驱动时体会,简单的说platform是一种虚拟总线,那么它也是一条总线,所以它分为3个部分,platform_bus,platform_device,platform_driver.在platform_device向platform_bus注册设备,platform_driver向platform_bus注册驱动,注

S3C2440 DMA 驱动示例

将 DMA 抽象为一个字符设备,在初始化函数中调用 void *dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp) 函数来分配两段物理地址连续的空间,一段作为源空间,一段作为目的空间. 然后将物理地址进行 ioremap 供驱动使用,最后调用 register_chrdev 来注册这个字符设备. DMA 的 regs: #define DMA0_BASE_ADDR 0x4B0

pwm驱动原理和代码实现

学这个pwm真是非常曲则,首先是看s3c2440的datasheet,全英文的,而且还有硬件的时序图(很多是硬件的工作原理,和软件控制不相关).看了很久加上网上看了资料才把这个pwm弄通.当然,其中牵扯到了几个知识,基本都弄通了.后面会通过blog一一列出来. 第一个知识点:I/O映射和内存映射所牵扯到的知识点,包括统一编址和独立编址,以及linux下怎么对这两种方式编程,以及这两种方式下怎么访问外设. 第二个知识点:映射到内存哪里?怎么映射?所以就涉及到linux内核的内存分布问题,顺便也分析