TQ2440外接GPIO蜂鸣器驱动程序

本文通过TQ2440开发板上可外接的GPIO口GPG14连接蜂鸣器,通过控制GPG14引脚的高低电平的输出和高低电平输出之间的时间间隔来使蜂鸣器发出不同的声音。

1.打开S3C2440的底板原理图找到GPIO,如下图所示:

使用万用表先找到VDD5V那个引脚,然后对照图找到GPG14,将蜂鸣器的正极连上GPG14,负极连上GND接地。

2.蜂鸣器驱动程序源代码My_Beep.c:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h> //定义s3c2410的GPIO
#include <mach/hardware.h> //定义操作s3c2410的GPIO的函数  
#include <linux/device.h> //自动创建设备文件应该包含的头文件 

#define DEVICE_NAME  "My_Beep" //加载模块后执行cat/proc/devices中看到的设备名称
#define Beep_MAJOR        104        //主设备号
#define Beep_High        1
#define Beep_Low      0

static int My_Beep_open(struct inode *inode,struct file *file)
{
    s3c2410_gpio_cfgpin(S3C2410_GPG14,S3C2410_GPG14_OUTP);//配置GPG14为输出功能   
    printk("My_Beep  open\n");
    return 0;
}

static int My_Beep_ioctl(struct inode * inode, struct file * file,unsigned int cmd)
{
    switch(cmd)
    {
       case Beep_High:
            s3c2410_gpio_setpin(S3C2410_GPG14, 1);//设置GPG14引脚为输出电平为1
            return 0;
       case Beep_Low:
            s3c2410_gpio_setpin(S3C2410_GPG14, 0);//设置GPG14引脚为输出电平为0
            return 0;
    default:
    return  -1;
    }
}

//定义文件操作 file_operations
static struct file_operations My_Beep_fops =
{
  .owner = THIS_MODULE,
  .open = My_Beep_open,
  .ioctl = My_Beep_ioctl,
};

static struct class *Beep_class;

static int __init My_Beep_init(void)
{
   int ret;
   printk("My_Beep start\n");

   //注册字符设备驱动程序
   //参数为主设备号、设备名字、file_operations结构
   //这样主设备号就与file_operations联系起来
   ret = register_chrdev(Beep_MAJOR, DEVICE_NAME, &My_Beep_fops);
   if(ret < 0)
   {
       printk("can‘t register major number\n");
       return ret;
   }

   //注册一个类,使mdev可以在"/dev/目录下建立设备节点"
   Beep_class = class_create(THIS_MODULE, DEVICE_NAME);
   if(IS_ERR(Beep_class))
   {
      printk("failed in My_Beep class.\n");
      return -1;
   }
   device_create(Beep_class, NULL, MKDEV(Beep_MAJOR,0), NULL, DEVICE_NAME);
   printk(DEVICE_NAME "initialized\n");
   return 0;
}

static void __exit My_Beep_exit(void)
{
   unregister_chrdev(Beep_MAJOR, DEVICE_NAME);
   device_destroy(Beep_class, MKDEV(Beep_MAJOR,0));//注销设备节点
   class_destroy(Beep_class);//注销类
}

module_init(My_Beep_init);
module_exit(My_Beep_exit);

MODULE_LICENSE("GPL");

源码分析:

本驱动程序通过linux系统内核中对S3C2410 GPIO操作的函数来实现对GPG14引脚输出功能和引脚高低电平输出功能的配置。

s3c2410_gpio_cfgpin(S3C2410_GPG14,S3C2410_GPG14_OUTP) 这行代码实现了配置GPG14为输出模式的功能。s3c2410_gpio_cfgpin这个函数定义在内核源码中的hardware.h头文件中,使用此函数需要包含头文件 #include<mach/hardware.h> 。

S3C2410_GPG14是GPIO的编号,S3C2410_GPG14_OUTP是端口的功能,他们都定义在内核源码的regs-gpio.h头文件中。

regs-gpio.h头文件的源码路径为 :arch/arm/mach-s3c2410/include/mach/regs-gpio.h ,打开源码来看下他们的定义:

#define S3C2410_GPG14         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 14)
      #define S3C2410_GPG14_INP     (0x00 << 28)
      #define S3C2410_GPG14_OUTP    (0x01 << 28)

在源码中我们可以看到其实S3C2410_GPG14_OUTP就是一个二进制数,再打开S3C2440的芯片手册找到端口GPG14,如下图所示:

可以知道,只要将GPG14的二进制位的29位和28位分别配置成0和1,这个端口便被设置成了输出模式,S3C2410_GPG14_OUTP就实现了二进制29位和28位的正确配置,所以他实现了对GPG14配置成输出模式的功能。

s3c2410_gpio_setpin函数同样定义在hardware.h头文件中,此函数实现了对GPG14输出高低电平的功能。说到这干脆来系统整理下常用的S3C2410 GPIO的操作函数,在hardware.h文件(源码路径:arch/arm/mach-s3c2410/include/mach/hardware.h)中 有:

void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function) //配置端口的GPIO的功能

其中pin为端口的编号,function为端口的功能。

unsigned int s3c2410_gpio_getcfg(unsigned int pin)    //读取功能配置

void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)    //配置上拉电阻

unsigned int s3c2410_modify_misccr(unsigned int clr, unsigned int chg)  //杂项配置

int s3c2410_gpio_getirq(unsigned int pin)  //给定端口,转换出IRQ号

int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on, unsigned int config);   //配置IRQ过滤使能与否

void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)    //写数据到端口

其中pin为端口的编号,to为你想要写进端口的数据。

unsigned int s3c2410_gpio_getpin(unsigned int pin)    //从端口读数据

3.Makefile文件:

obj-m:=My_Beep.o
CC=arm-linux-gcc
KERNELDIR=/usr/local/opt/EmbedSky/linux-2.6.30.4
PWD:=$(shell pwd)
default:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

4.驱动程序对应的上层应用程序源码My_Beep_Test.c

#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>      
#include <sys/types.h>    
#include <sys/stat.h>  
#include <fcntl.h>    

int main()  
{  
    int fd,i,cmd=0;
    long t;      
    fd=open("/dev/My_Beep",0); 
    if (fd<0)  
    {  
        printf("open Beep_driver error");  
        exit(1);  
    }
    printf("please input t\n");
    scanf("%ld",&t);
    while(1)
    {
       switch(cmd)
       {
          case 0:
          printf("Beep Low \n");
          ioctl(fd,0); 
          for(i=0;i<t;++i);
          
          case 1:
          printf("Beep High \n");
          ioctl(fd,1); 
          for(i=0;i<t;++i);          
       }
    }  
    return 0;  
}

运行此程序时可以通过scanf("%ld",&t)来设置不同的t,从而实现高低电平之间的时间间隔的变化,最终实现蜂鸣器发出不同声音的功能,本人经过尝试发现只要t的值取得恰当,你甚至可以使蜂鸣器发出美妙的音乐出来

时间: 2024-10-12 14:13:23

TQ2440外接GPIO蜂鸣器驱动程序的相关文章

树莓派上的GPIO字符驱动程序

前言 主要是在嵌入式Linux(树莓派)中如何使用已有的函数库编写应用程序操纵GPIO,如何编写字符设备驱动程序在内核程序中使用GPIO 硬件连接图 虚拟文件系统操作GPIO Linux可以通过访问sys/class/gpio下的一些文件,通过对这些文件的读写来实现对于GPIO的访问. 树莓派下面的可用的GPIO如下图所示,需要注意树莓派一代和二代的区别 首先用一个小灯来测试下操作.首先向export中写入18,表示启用18号gpio端口,执行之后,可以看到该目录下多出了一个gpio18的目录.

Android 驱动 (一) GPIO

前面的博文对Lichee做了系列分析,其实就是对在<七年之痒>中所说的,Android BSP具备的一项基本素质-SHELL脚本,所以我们Lichee系列的文章着重分析了SHELL脚本和Lichee的基本结构,当然作为一名合格的Android BSP工程师来说,掌握Linux的驱动程序的移植,也是一项基本技能.所以从本文开始,将对sun4i的一些驱动程序做深入分析.当然了,驱动程序涉及的面很广,比如摄像头的驱动涉及到sensor的移植和内核队列等数据结构相关内容,SD卡驱动又涉及到DMA的基本

zedboard的板级支持包GPIO例子

板级支持包例子 xgpio_example.c This file contains a design example using the GPIO driver(XGpio) and hardware * device.  It onlyuses a channel 1 of a GPIO device. * * This example can be ran on the Xilinx ML300 boardusing the Prototype Pins & * LEDs of thebo

第8章 让开发板发出声音,蜂鸣器驱动 心得体会

第8章让开发板发出声音,蜂鸣器驱动 心得体会 通过学习Android深度探索(卷1)HAL与驱动开发的第8章 让开发板发出声音,蜂鸣器驱动,我加深对驱动的认识.以下主要是我对本节实验和参考在Linux驱动开发中使用PWM控制蜂鸣器中的一些见解. 先编写一个简单的蜂鸣器驱动程序,根据开发板上的硬件IO接口和Android驱动规范,在kernel中的driver目录中新建一个Buzzer文件,新建一个buzzer.c的源文 在目录下创建一个Makefile文件 先运行make clean命令清楚到编

IMX257实现GPIO-IRQ中断按键驱动程序

IMX257实现GPIO-IRQ中断按键驱动程序 2015-02-18 李海沿 ????昨天我们已经实现了中断查询的方式实现GPIO按键驱动程序,但是,有一个缺点就是,当我们把应用程序放在后台执行时,即便没有按键,应用程序while循环中的read函数也不断的在运行,严重的导致了CPU资源的浪费. ????本文中,我们在前面按键查询驱动程序的基础上来修改. ????大概介绍一下设计思路吧: ????和前面的差不多,当我们加载驱动时,首先在init函数中,对GPIO功能进行模式设置,都设置为GPI

(14)树莓派B+使用L298N驱动控制四驱车并实现一个简单的web控制端

在系列文章第12篇中提到了L298N,它是H桥双路直流电机驱动,可以使双路直流电机实现正转或者反转,并且通过ENDA和ENDB输入PWM信号,还可以实现加减速.本文用2块L298N驱动板成功驱动了4个直流电机,实现了4轮同时向前.向后以及前向左转.前向右转甚至是后向左转和后向右转的功能,最后通过python的BaseHTTPServer模块(python3中是http.server模块)实现了一个控制小车的HTTP接口,另外用lighttpd启动一个网页,通过网页中的ajax调用控制小车的HTT

(14)树莓派B+使用L298N驱动控制四驱车

在系列文章第12篇中提到了L298N,它是H桥双路直流电机驱动,可以使双路直流电机实现正转或者反转,并且通过ENDA和ENDB输入PWM信号,还可以实现加减速.本文用2块L298N驱动板成功驱动了4个直流电机,实现了4轮同时向前.向后以及前向左转.前向右转甚至是后向左转和后向右转的功能,最后通过python的BaseHTTPServer模块(python3中是http.server模块)实现了一个控制小车的HTTP接口,另外用lighttpd启动一个网页,通过网页中的ajax调用控制小车的HTT

ARM+Linux 嵌入式开发环境搭建

这些都是自个从一月份开始学习ARM+Linux中遇到的问题做的笔记,我觉得很有用,所以分享出来! 因为没有老师教,自己琢磨遇到的问题很多,欢迎交流! -------------------------------------------------------------------------------------------------- 零点漂移队:封尘浪 ------------------------------------------------------------------

五到八章心得

第五章 本章主要学习关于开发板的测试环境,由于我们所开发的Linux驱动,不管使用何种方法编译后,都需要在开发板上进行测试,这是因为在ARM架构的开发板可以在X86架构的PC在CPU指令及二进制格式上有所不同 ,而且在Linux所需要的硬件在PC上很难进行模拟,因此要在开发板上进行调试和测试. 本章主要介绍了S3C6410开发板,这是一款低功耗.高性价比的RISC,可广泛应用于移动电话和通用处理等领域. 安装串口调试工具minicom的步骤:1.检测当前系统是否支持usb转串口:2.安装mini