6.DB410c开发板基于GPIO模型实现蜂鸣器功能测试。
时间:10-02
整理:3721RD
点击:
这个帖子主要理解如何自己实现一个简单驱动。
自己使用是某宝买来的无源蜂鸣器,它内部不带震荡源所以直流信号无法令其鸣叫,必须用2K~5K的方波去驱动它。广泛应用于计算机、报警器、电子玩具、汽车电子设备、定时器等电子产品中作发声器件。
驱动代码主要是参考论坛某人的大作,这个特意表示感谢。
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/i2c-gpio.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/cdev.h>
#include "buzzer_drv.h"
static int major;
static int minor;
struct cdev *buzzer; /* cdev 数据结构 */
static dev_t devno; /* 设备编号 */
static struct class *buzzer_class;
#define DEVICE_NAME "buzzer"
#define GPIO_BUZZER_PIN_NUM 12 //(2*32 + 12) /*gpio 2_12 */
static int buzzer_open(struct inode *inode,struct file *file )
{
try_module_get(THIS_MODULE);
gpio_direction_output(GPIO_BUZZER_PIN_NUM,1);
return 0;
}
static int buzzer_release(struct inode*inode, struct file *file )
{
module_put(THIS_MODULE);
gpio_direction_output(GPIO_BUZZER_PIN_NUM,1);
return 0;
}
#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,36)
static int buzzer_ioctl(struct file *filp,unsigned int cmd, unsigned long arg)
#else
static int buzzer_ioctl(struct inode*inode, struct file *file, unsigned int cmd, unsigned long arg)
#endif
{
printk(KERN_INFO "buzzer_ioctl cmd=%d BUZZER_IOC_MAGIC=%d BUZZER_IOCTL_MAXNR=%d\n", cmd, BUZZER_IOC_MAGIC, BUZZER_IOCTL_MAXNR);
#if 0
if(cmd != BUZZER_IOC_MAGIC) {
return -ENOTTY;
}
if(cmd > BUZZER_IOCTL_MAXNR) {
return -ENOTTY;
}
#endif
printk(KERN_INFO "buzzer_ioctl cmd=%d BUZZER_ON=%d BUZZER_OFF=%d\n", cmd, BUZZER_ON, BUZZER_OFF);
switch(cmd){
case BUZZER_ON:
gpio_set_value(GPIO_BUZZER_PIN_NUM,1);
break;
case BUZZER_OFF:
gpio_set_value(GPIO_BUZZER_PIN_NUM,0);
break;
default:
break;
}
return 0;
}
struct file_operations buzzer_fops = {
.owner= THIS_MODULE,
.open= buzzer_open,
.release= buzzer_release,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
.unlocked_ioctl = buzzer_ioctl,
#else
.ioctl= buzzer_ioctl,
#endif
};
static int __init buzzer_init(void)
{
int ret;
gpio_free(GPIO_BUZZER_PIN_NUM);
if(gpio_request(GPIO_BUZZER_PIN_NUM, "buzzer_bee")) {
printk("request%s gpio faile \n", "led_bee");
return-1;
}
ret= alloc_chrdev_region(&devno, minor, 1, "buzzer"); /* 从系统获取主设备号 */
major= MAJOR(devno);
if(ret < 0) {
printk(KERN_ERR"cannot get major %d \n", major);
return-1;
}
buzzer= cdev_alloc(); /* 分配 buzzer 结构 */
if(buzzer != NULL) {
cdev_init(buzzer,&buzzer_fops); /* 初始化 buzzer 结构 */
buzzer->owner= THIS_MODULE;
if(cdev_add(buzzer, devno, 1) != 0) { /* 增加 buzzer 到系统中 */
printk(KERN_ERR"add cdev error!\n");
goto error;
}
}else {
printk(KERN_ERR"cdev_alloc error!\n");
return-1;
}
buzzer_class = class_create(THIS_MODULE, "buzzer_class");
if(IS_ERR(buzzer_class)) {
printk(KERN_INFO"create class error\n");
return-1;
}
device_create(buzzer_class,NULL, devno, NULL, "buzzer");
return 0;
error:
unregister_chrdev_region(devno,1); /* 释放已经获得的设备号 */
return ret;
}
static void __exit buzzer_exit(void)
{
cdev_del(buzzer);/* 移除字符设备 */
unregister_chrdev_region(devno,1); /* 释放设备号 */
device_destroy(buzzer_class,devno);
class_destroy(buzzer_class);
}
module_init(buzzer_init);
module_exit(buzzer_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zxl_zxl");
代码几乎没有做任何变动,除非有必要,比如适合自己硬件的GPIO定义GPIO_BUZZER_PIN_NUM。还有一些相关头文件定义。
下面是测试程序代码。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include "buzzer_drv.h"
#define DEV_NAME "/dev/buzzer"
int main(int argc, char *argv[])
{
int i;
int fd = 0;
fd = open (DEV_NAME, O_RDONLY);
if(fd < 0) {
perror("Open"DEV_NAME" Failed!\n");
exit(1);
}
while(1){
printf("BUZZER_ON then sleep 1 \n");
ioctl(fd,BUZZER_ON);
sleep(1);
ioctl(fd,BUZZER_OFF);
printf("BUZZER_ON then BUZZER_OFF 1 \n");
sleep(1);
}
close(fd);
return 0;
}
编译命令:make ARCH=arm64 CROSS_COMPILE=${DB410C_CROSSTOOL}
insmod buzzer_drv.ko加载驱动
./buzzer_test开始测试,可以听到蜂鸣器根据代码反复响,停。
蜂鸣器接入开发板pin24,gpio为12.

自己使用是某宝买来的无源蜂鸣器,它内部不带震荡源所以直流信号无法令其鸣叫,必须用2K~5K的方波去驱动它。广泛应用于计算机、报警器、电子玩具、汽车电子设备、定时器等电子产品中作发声器件。
驱动代码主要是参考论坛某人的大作,这个特意表示感谢。
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/i2c-gpio.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/cdev.h>
#include "buzzer_drv.h"
static int major;
static int minor;
struct cdev *buzzer; /* cdev 数据结构 */
static dev_t devno; /* 设备编号 */
static struct class *buzzer_class;
#define DEVICE_NAME "buzzer"
#define GPIO_BUZZER_PIN_NUM 12 //(2*32 + 12) /*gpio 2_12 */
static int buzzer_open(struct inode *inode,struct file *file )
{
try_module_get(THIS_MODULE);
gpio_direction_output(GPIO_BUZZER_PIN_NUM,1);
return 0;
}
static int buzzer_release(struct inode*inode, struct file *file )
{
module_put(THIS_MODULE);
gpio_direction_output(GPIO_BUZZER_PIN_NUM,1);
return 0;
}
#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,36)
static int buzzer_ioctl(struct file *filp,unsigned int cmd, unsigned long arg)
#else
static int buzzer_ioctl(struct inode*inode, struct file *file, unsigned int cmd, unsigned long arg)
#endif
{
printk(KERN_INFO "buzzer_ioctl cmd=%d BUZZER_IOC_MAGIC=%d BUZZER_IOCTL_MAXNR=%d\n", cmd, BUZZER_IOC_MAGIC, BUZZER_IOCTL_MAXNR);
#if 0
if(cmd != BUZZER_IOC_MAGIC) {
return -ENOTTY;
}
if(cmd > BUZZER_IOCTL_MAXNR) {
return -ENOTTY;
}
#endif
printk(KERN_INFO "buzzer_ioctl cmd=%d BUZZER_ON=%d BUZZER_OFF=%d\n", cmd, BUZZER_ON, BUZZER_OFF);
switch(cmd){
case BUZZER_ON:
gpio_set_value(GPIO_BUZZER_PIN_NUM,1);
break;
case BUZZER_OFF:
gpio_set_value(GPIO_BUZZER_PIN_NUM,0);
break;
default:
break;
}
return 0;
}
struct file_operations buzzer_fops = {
.owner= THIS_MODULE,
.open= buzzer_open,
.release= buzzer_release,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
.unlocked_ioctl = buzzer_ioctl,
#else
.ioctl= buzzer_ioctl,
#endif
};
static int __init buzzer_init(void)
{
int ret;
gpio_free(GPIO_BUZZER_PIN_NUM);
if(gpio_request(GPIO_BUZZER_PIN_NUM, "buzzer_bee")) {
printk("request%s gpio faile \n", "led_bee");
return-1;
}
ret= alloc_chrdev_region(&devno, minor, 1, "buzzer"); /* 从系统获取主设备号 */
major= MAJOR(devno);
if(ret < 0) {
printk(KERN_ERR"cannot get major %d \n", major);
return-1;
}
buzzer= cdev_alloc(); /* 分配 buzzer 结构 */
if(buzzer != NULL) {
cdev_init(buzzer,&buzzer_fops); /* 初始化 buzzer 结构 */
buzzer->owner= THIS_MODULE;
if(cdev_add(buzzer, devno, 1) != 0) { /* 增加 buzzer 到系统中 */
printk(KERN_ERR"add cdev error!\n");
goto error;
}
}else {
printk(KERN_ERR"cdev_alloc error!\n");
return-1;
}
buzzer_class = class_create(THIS_MODULE, "buzzer_class");
if(IS_ERR(buzzer_class)) {
printk(KERN_INFO"create class error\n");
return-1;
}
device_create(buzzer_class,NULL, devno, NULL, "buzzer");
return 0;
error:
unregister_chrdev_region(devno,1); /* 释放已经获得的设备号 */
return ret;
}
static void __exit buzzer_exit(void)
{
cdev_del(buzzer);/* 移除字符设备 */
unregister_chrdev_region(devno,1); /* 释放设备号 */
device_destroy(buzzer_class,devno);
class_destroy(buzzer_class);
}
module_init(buzzer_init);
module_exit(buzzer_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zxl_zxl");
代码几乎没有做任何变动,除非有必要,比如适合自己硬件的GPIO定义GPIO_BUZZER_PIN_NUM。还有一些相关头文件定义。
下面是测试程序代码。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include "buzzer_drv.h"
#define DEV_NAME "/dev/buzzer"
int main(int argc, char *argv[])
{
int i;
int fd = 0;
fd = open (DEV_NAME, O_RDONLY);
if(fd < 0) {
perror("Open"DEV_NAME" Failed!\n");
exit(1);
}
while(1){
printf("BUZZER_ON then sleep 1 \n");
ioctl(fd,BUZZER_ON);
sleep(1);
ioctl(fd,BUZZER_OFF);
printf("BUZZER_ON then BUZZER_OFF 1 \n");
sleep(1);
}
close(fd);
return 0;
}
编译命令:make ARCH=arm64 CROSS_COMPILE=${DB410C_CROSSTOOL}
insmod buzzer_drv.ko加载驱动
./buzzer_test开始测试,可以听到蜂鸣器根据代码反复响,停。
蜂鸣器接入开发板pin24,gpio为12.

栏目分类
射频专业培训教程推荐