嵌入式课程---嵌入式Linux的蜂鸣器驱动开发

实验环境准备

实验材料:GEC6818实验箱、电脑、
实验环境:VMware下Linux系统、arm-linux-交叉编译环境,windows系统、secureCRT平台

第一步:测试三个系统是否连通

  1. 使用串口线、以太网线连接pc机与实验箱

  2. 禁用pc机的防火墙,并禁用无线网卡

  3. 设置pc机上以太网网卡的ip地址、子网掩码、网关(注意,不可设为主动获取,需要手动设置,因为目前只连接pc机与实验箱)

  4. 在secureCRT下设置实验箱Linux系统的ip地址,使其与pc机处于同一网段下(此处注意,开启实验箱时,直接等待其进入Linux系统,而不是u-boot模式,接着按CTRL+c即可进入Linux系统命令行)

  5. 在pc机上的vmware虚拟机的Linux系统下设置ip地址(此处注意要先设置好与pc机的网络连接模式,这里选择桥接模式桥接到外部机的一张网卡(该网卡可能是虚拟出来的)
    在这里插入图片描述

  6. 前面三个ip地址一定要保证在同一网段下,例如pc机设ip为192.168.1.160、子网掩码为255.255.255.0、网关为192.168.1.1
    实验箱ip地址设为192.168.1.180,虚拟机上Linux系统ip地址设为192.168.1.170

  7. 然后确保两两相互能ping得通

第二步:编写并编译驱动与测试程序

编写蜂鸣器驱动程序pwm.c

/*---------------------------------------

*功能描述:  蜂鸣器驱动 

*创建者:   粤嵌技术部

*创建时间: 2015,01,01

---------------------------------------

*修改日志:

*修改内容:

*修改人:

*修改时间:

----------------------------------------*/

/*************************************************

*头文件

*************************************************/

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/cdev.h>

#include <linux/uaccess.h>

#include <linux/fs.h>

#include <linux/ioport.h>

#include <linux/miscdevice.h>

#include <linux/ioctl.h>

#include <linux/delay.h>

#include <linux/gpio.h>

#include <cfg_type.h>



#include <linux/platform_device.h>

#include <linux/err.h>

#include <linux/io.h>

#include <linux/init.h>

#include <linux/pwm.h>

#include <linux/slab.h>



#include <mach/platform.h>

#include <mach/devices.h>

#include <mach/soc.h>





#define DEVICE_NAME				"pwm"



#define PWM_IOCTL_SET_FREQ		1

#define PWM_IOCTL_STOP			0



#define NS_IN_1HZ				(1000000000UL)

#define NS_IN_HZ                (1000000000UL)

#define TO_PERCENT(duty, period)                (((duty)*100)/(period))

#define TO_HZ(period)                                   (NS_IN_HZ/(period))





#define BUZZER_PWM_ID			2

#define BUZZER_PMW_GPIO			(PAD_GPIO_C + 14)



static struct pwm_device *pwm2buzzer;



static struct semaphore lock;





static void pwm_set_freq(unsigned long freq) {

	int period_ns = NS_IN_1HZ / freq;



	pwm_config(pwm2buzzer, period_ns / 4, period_ns);

	pwm_enable(pwm2buzzer);

}



static void pwm_stop(void) {

	pwm_config(pwm2buzzer, 0, NS_IN_1HZ / 100);

	pwm_disable(pwm2buzzer);

}





static int gec6818_pwm_open(struct inode *inode, struct file *file) {

	if (!down_trylock(&lock))

		return 0;

	else

		return -EBUSY;

}



static int gec6818_pwm_close(struct inode *inode, struct file *file) {

	up(&lock);

	return 0;

}



static long gec6818_pwm_ioctl(struct file *filep, unsigned int cmd,

		unsigned long arg)

{

	switch (cmd) {

		case PWM_IOCTL_SET_FREQ:

			if (arg == 0)

				return -EINVAL;

			pwm_set_freq(arg);

			break;



		case PWM_IOCTL_STOP:

			pwm_stop();

		default:

			break;

	}



	return 0;

}





static struct file_operations gec6818_pwm_ops = {

	.owner			= THIS_MODULE,

	.open			= gec6818_pwm_open,

	.release		= gec6818_pwm_close, 

	.unlocked_ioctl	= gec6818_pwm_ioctl,

};



static struct miscdevice gec6818_misc_dev = {

	.minor = MISC_DYNAMIC_MINOR,

	.name = DEVICE_NAME,

	.fops = &gec6818_pwm_ops,

};



static int __init gec6818_pwm_dev_init(void) {

	int ret;



	ret = gpio_request(BUZZER_PMW_GPIO, DEVICE_NAME);

	if (ret) {

		printk("request GPIO %d for pwm failed\n", BUZZER_PMW_GPIO);

		return ret;

	}

	

	gpio_direction_output(BUZZER_PMW_GPIO, 0);



	pwm2buzzer = pwm_request(BUZZER_PWM_ID, DEVICE_NAME);

	if (IS_ERR(pwm2buzzer)) {

		printk("request pwm %d for %s failed\n", BUZZER_PWM_ID, DEVICE_NAME);

		return -ENODEV;

	}



	pwm_stop();

	

	gpio_free(BUZZER_PMW_GPIO);



	//init_MUTEX(&lock);

	sema_init(&lock,1);

	ret = misc_register(&gec6818_misc_dev);



	printk(DEVICE_NAME "\tinitialized\n");



	return ret;

}



static void __exit gec6818_pwm_dev_exit(void) {

	pwm_stop();



	misc_deregister(&gec6818_misc_dev);

}



module_init(gec6818_pwm_dev_init);

module_exit(gec6818_pwm_dev_exit);



MODULE_LICENSE("GPL");

MODULE_AUTHOR("kaoyangou");

MODULE_DESCRIPTION("S5PV6818 PWM Driver");

编写驱动程序的Makefile文件

INSTALLDIR   =  /home/Hello

ifneq ($(KERNELRELEASE),)
obj-m:=pwm.o
else
KERNELDIR:=/home/Hello/demo/6818GEC/kernel
CROSS_COMPILE:=/home/Hello/demo/6818GEC/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi-

PWD:=$(shell pwd)

default:
	$(MAKE) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNELDIR) M=$(PWD) modules

clean:
	rm -rf *.o *.order .*.cmd *.mod.c *.symvers
endif

编写蜂鸣器测试程序buzzer.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/ioctl.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <sys/select.h>

#include <sys/time.h>

#include <errno.h>

#include <limits.h>



#define  BUZZER_IOCTL_SET_FREQ 1

#define  BUZZER_IOCTL_STOP 0





void Usage(char *args)

{

	printf("Usage: %s <on/off> <freq>\n",args);

	return ;

}



int main(int argc , char **argv)

{

	int buzzer_fd;

	unsigned long freq = 0;

	char *endstr, *str;

	

	if(argc==3){	

		buzzer_fd = open("/dev/pwm",O_RDWR);

		if(buzzer_fd<0){

			perror("open device:");

			exit(1);

		}

		

		str = argv[2];

		errno = 0;

		freq = strtol(str , &endstr, 0);

	

		if((errno == ERANGE &&(freq == LONG_MAX ||freq ==LONG_MIN))||(errno !=0 && freq ==0)){

			perror("freq :");

			exit(EXIT_FAILURE);

		}

		if(endstr ==str){

			fprintf(stderr , "Please input a digits for freq\n");

			exit(EXIT_FAILURE);

		}

		

		if(!strncmp(argv[1], "on" ,2)){

			ioctl(buzzer_fd, BUZZER_IOCTL_SET_FREQ , freq );

		}	

		else if(!strncmp(argv[1], "off", 3)){

			ioctl(buzzer_fd , BUZZER_IOCTL_STOP , freq);

		}

		else{

			close(buzzer_fd);

			exit(EXIT_FAILURE);

		}	

	}

	else if(argc ==2){

		buzzer_fd = open("/dev/pwm",O_RDWR);

		if(buzzer_fd<0){

			perror("open device:");

			exit(1);

		}



		if(!strncmp(argv[1], "off", 3)){

			ioctl(buzzer_fd , BUZZER_IOCTL_STOP , freq);

		}

		else{

			close(buzzer_fd);

			exit(EXIT_FAILURE);

		}		

	}

	else {

		Usage(argv[0]);

		exit(EXIT_FAILURE);

	}

	

	

	close(buzzer_fd);

	return 0;

}

编写测试程序的Makefile文件

#
# Makefile for Linux application test example.
#
#---------------------------------------------------------------
# Linux application Makefile sample
# make          -- the optical output without debug info
# make clean    -- clean the object file(s)
# make install  -- install the execute file(s) to INSTALLDIR
#---------------------------------------------------------------
# History:
#			

INSTALLDIR	= /home/Hello/

#---------------------------------	/* execute file(s) */
TESTFILE 	= buzzer
#---------------------------------	/* object file(s) */
SRCFILE		= buzzer.c
#---------------------------------	/* header file(s) */
TESTFILE_H	=

CROSS = arm-none-linux-gnueabi-
CC = $(CROSS)gcc
AS = $(CROSS)as
LD = $(CROSS)ld

CFLAGS  += -O2 -Wall

all:   $(TESTFILE)

$(TESTFILE):  $(SRCFILE) $(TESTFILE_H) Makefile
	mkdir -p $(INSTALLDIR) 
	$(CC) $(CFLAGS) -o $@ $@.c
	cp --target-dir=$(INSTALLDIR) $(TESTFILE)

clean:
	rm -f $(TESTFILE)
	

第三步:编译生成pwm.ko与buzzer二进制执行文件

  1. 将驱动程序pwm.c与其对应Makefile文件放在同一目录下,然后在该目录下执行命令make,生成目标文件pwm.ko
    注意:Makefile中可能制定了生成的二进制执行文件安装路径:INSTALLDIR = 某某某
  2. 将驱动程序buzzer.c与其对应Makefile文件放在同一目录下,然后在该目录下执行命令make,生成目标文件buzzer
    注意:Makefile中可能制定了生成的二进制执行文件安装路径:INSTALLDIR = 某某某
    需要知道的是,以上的编译属于交叉编译,Makefile文件中已指定相应的交叉编译器

第四步:将pwm.ko文件与buzzer文件挂载到实验箱板子

  1. 将pwm.ko文件与buzzer文件统一放在虚拟机的nfs_share目录上
  2. 在secureCRT命令框使用mount命令进行挂载,命令中的ip地址是虚拟机的ip地址
mount -o nolock,tcp 192.168.0.190:/home/Hello/nfs_share /mnt

第五步:在实验箱装载驱动并使用程序进行测试

  1. 在secureCRT中输入命令lsmod,然后回车,在返回的消息中如果找到有led字眼的一行,则使用rmmod pwm进行卸载原有驱动,确保实验箱系统不存在蜂鸣器的驱动程序
lsmod    //查看已存在驱动

rmmod pwm   //卸载buzzer的驱动,注意,可能不是pwm,看系统中原有pwm驱动具体的名字
  1. 进入到目录 /mnt,然后插入驱动pwm.ko,因为刚才把自己制作的驱动挂载到了/mnt目录下
insmod pwm.ko   
  1. 测试,输入命令打开蜂鸣器
./buzzer on 1000

如果没声音试试把1000改大一点

  1. 测试,输入命令关闭蜂鸣器
./buzzer off

如果蜂鸣器能正常打开与关闭,则蜂鸣器的驱动程序开发实验完成

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值