/* ================================================ Name : my2440_pwm.c Author : Huang Gang Date : 25/11/09 Copyright : GPL Description : my2440 pwm driver ================================================ */ #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/clk.h> #include <linux/device.h> #include <asm/io.h> #include <mach/hardware.h> #include <mach/regs-gpio.h> #include <plat/regs-timer.h> #define PWM_MAJOR 0 //主设备号 #define PWM_NAME "my2440_pwm" //设备名称 static int device_major = PWM_MAJOR; //系统动态生成的主设备号 //打开设备 static int pwm_open(struct inode *inode, struct file 保安服务条例*file) { //第一次熬夜对GPB0复用口进行复用功能设置,设置为TOUT0 PWM输出 s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_TOUT0); return 0; } //关闭设备 static int pwm_close(struct inode *inode, struct file *file) { return 0; } //对设备进行控制 static int pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { if唐璜作者(cmd <= 0)//如果输入的参数小于或等于0的话,就让蜂鸣器停止工作 { //这里又恢复GPB0口为IO口输出功能,由原理图可知直接给低电平可让蜂鸣器停止工作 s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP); s3c2410_gpio_setpin(S3C2410_GPB0, 0); } else//如果输入的参数大于商城县卫生局0,就让蜂鸣器开始工作,不同的参数,蜂鸣器的频率也不一样 { //定义一些局部变量 unsigned long tcon; unsigned long tcnt; unsigned long tcfg1; unsigned long tcfg0; struct clk *clk_p; unsigned long pclk; //以下对各寄存器的操作结合上面讲的开始一个PWM定时器的步骤和2440手册PWM寄存器操作部分来看就比较容易理解 tcfg1 = __raw_readl(S3C2410_TCFG1); //读取定时器配置寄存器1的值 tcfg0 = __raw_readl(S3C2410_TCFG0); //读取定时器配置寄存器0的值 tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK; tcfg0 |= (50 - 1); //设置tcfg0的值为49 tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK; tcfg1 |= S3C2410_TCFG1_MUX0_DIV16; //设置tcfg1的值为0x0011即:1/16 __raw_writel(tcfg1, S3C2410_TCFG1); //将值恳谈会tcfg1写入定时器配置寄存器1中 __raw_writel(tcfg0, S3C2410_TCFG0); //将值tcfg0写入定时器配置寄存器0中 clk_p = clk_get(NULL, "pclk"); pclk = clk_get_rate(clk_p); //从系统平台时钟队列中获取pclk的时钟频率,在include/linux/clk.h中定义 tcnt = (pclk/50/16)/cmd; //计算定时器0的输出时钟频率(pclk/{prescaler0 + 1}/divider value) __raw_writel(tcnt, S3C2410_TCNTB(0)); //设置定时器0计数缓存寄存器的值 __raw_writel(tcnt/2, S3C2410_TCMPB(0)); //设置定时器0比较缓存寄存器的值 tcon = __raw_readl(S3C2410_TCON); //读取定时器控制寄存器的值 tcon &= ~0x1f; tcon |= 0xb; //关闭死区、自动重载、关反相器、更新TCNTB0&TCMPB0、启动定时器0 __raw_writel(tcon, S3C2410_TCON); //设置定时器控制寄存器的0-4位,即对定时器0进行控制 tcon &= ~2; __raw_writel(tcon, S3C2410_TCON); //清除定时器0的手动更新位 } return 0; } //设备操作结构体 static struct file_operations pwm_fops = { .owner = THIS_MODULE, .open = pwm_open, .release = pwm_close, .ioctl = pwm_ioctl, }; //定义一个设备类 static struct class *pwm_class; static int __init pwm_init(void) { //注册为字符设备,主设备号为0让系统自动分配,设备名为my2440_pwm,注册成功返回动态生成的主设备号 device_major = register_chrdev(PWM_MAJOR, PWM_NAME, &pwm_fops); if(device_major < 0) { printk(PWM_NAME " register falid!\n"); return device_major; } //注册一个设备类,使mdev可以在/dev/目录下自动建立设备节点 pwm_class = class_create(THIS_MODULE, PWM_NAME); if(IS_ERR(pwm_class)) { printk(PWM_NAME " register class falid!\n"); return -1; } //创建一个设备节点,设备名为PWM_NAME,即:my2440_pwm device_create(pwm_class, NULL, MKDEV(device_major, 0), NULL, PWM_NAME); return 0; } static void __exit pwm_exit(void) { //注销设备 unregister_chrdev(device_major, PWM_NAME); //删除设备节点 device_destroy(pwm_class, MKDEV(device_major, 0)); //注销设备类 class_destroy(pwm_class); } module_init(pwm_init); module_exit(pwm_exit); MODULE_LICENSE("PGL"); MODULE_AUTHOR("Huang Gang"); MODULE_DESCRIPTION(河北招生考试信息服务网"my2440 pwm driver"); |
#cp -f my2440_pwm.c /linux-2.6.30.4/drivers/char //把驱动源码复制到内核驱动的字符设备下 |
#gedit /linux-2.6.30.4/drivers/char/Kconfig //添加PWM蜂鸣器设备配置 |
config MY2440_PWM_BEEP tristate "My2440 PWM Beep Device" depends on ARCH_S3C2440 default y ---help--- My2440 PWM Beep |
#gedit /linux-2.6.30.4/drivers/char/Makefile //添加PWM蜂鸣器设备配置 |
obj-$(CONFIG_MY2440_PWM_BEEP) += my2440_pwm.o |
#make menuconfig |
Device Drivers ---> Character devices ---> <*> My2440 PWM Beep Device (NEW) |
/* ============================================== Name : pwm_test.c Author : Huang Gang Date : 25/11/2009 Copyright : GPL Description : my2440 pwm driver test ============================================== */ #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/ioctl.h> int main(int argc, char **argv) { int tmp; int fd; int i; //打开蜂鸣器设备 fd = open("/dev/my2440_pwm", O_RDWR); if(fd < 0) { printf("Open PWM Device Faild!\n"); exit(1); } //提示用户输入一个参数来对蜂鸣器进行调频,0表示停止工作 printf("please enter the times number(0 is stop):\n"); while(1) { //输入参数 scanf("%d", &tmp); printf("times = %d\n", tmp); //IO控制 ioctl(fd, tmp); if(tmp <= 0) { break; } } //关闭设备 close(fd); return 0; } |
#arm-linux-gcc -o pwm_test pwm_test.c |
本文发布于:2024-09-22 03:50:09,感谢您对本站的认可!
本文链接:https://www.17tex.com/xueshu/264793.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |