混杂设备驱动--输出两路PWM

尝试用2440的TOUT0和TOUT1输出PWM驱动两个电机,电机的硬件驱动电路是使用L298N。
先单独测试TOUT0的PWM输出:
(1)驱动程序:使用misc混杂设备驱动模型,当然也可以使用基本的字符设备模型。
使用misc设备驱动模型步骤:
①初始化一个struct miscdevice结构体:主要是file_operation结构体成员和name
②使用misc_register和misc_deregister注册和注销这个结构体
代码示例:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <plat/regs-timer.h>
#include <mach/regs-irq.h>
#include <linux/clk.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/miscdevice.h>

#define DEVICE_NAME "pwm" //设备名

#define IOCTL_SET_PWM_DUTY 	1 
#define IOCTL_PWM_STOP 		2

/* 定义信号量 lock用于互斥,因此,改驱动程序只能同时有一个进程使用 */
static struct semaphore lock;

static void pwm_set_duty(unsigned long duty)
{
    unsigned long tcon;
    unsigned long tcnt0,tcmp0;
    unsigned long tcfg1;
    unsigned long tcfg0;
    
	tcfg0 = __raw_readl(S3C2410_TCFG0);
    tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
    tcfg0 |= (50 - 1); 
    
    tcfg1 = __raw_readl(S3C2410_TCFG1);
    tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK; 
    tcfg1 |= S3C2410_TCFG1_MUX0_DIV16;
    
    __raw_writel(tcfg0, S3C2410_TCFG0);
    __raw_writel(tcfg1, S3C2410_TCFG1); 
    
    tcnt0 = 1000;//设置PWM频率
    tcmp0 = duty;//设置PWM占空比
    __raw_writel(tcnt0, S3C2410_TCNTB(0));
    __raw_writel(tcmp0, S3C2410_TCMPB(0));
     
	tcon = __raw_readl(S3C2410_TCON);
    tcon |= 0xf; //设置输出电平反转,start pwm output
    __raw_writel(tcon, S3C2410_TCON); 
    tcon &= ~2;   /* clear manual update bit */
    __raw_writel(tcon, S3C2410_TCON);
}

static void pwm_stop(void)
{
	unsigned long tcon;
	tcon = __raw_readl(S3C2410_TCON);
    tcon &= ~(1<<3);//Turn off the auto reload bit
    __raw_writel(tcon, S3C2410_TCON); // 
}

static int my_pwm_open(struct inode *inode, struct file *file)
{
    if (!down_trylock(&lock))//不会导致进程休眠
    {	
    	s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_TOUT0);
        return 0;
    }
    else
        return -EBUSY; 
}

static int my_pwm_close(struct inode *inode, struct file *file)
{
    pwm_stop();
    s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPIO_INPUT);
    up(&lock);
    return 0;
}

static int my_pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
    switch (cmd) {
        case IOCTL_SET_PWM_DUTY: 
            if (arg == 0) 
                return -EINVAL;
            pwm_set_duty(arg);
            break;
        case IOCTL_PWM_STOP:
            pwm_stop();
            break;
        default:
        	printk(KERN_INFO"cmd error!\n");
        	break;
    }
    return 0;
}

static struct file_operations dev_fops = {
    .owner = THIS_MODULE,
    .open = my_pwm_open,
    .release = my_pwm_close,
    .ioctl = my_pwm_ioctl,
};

//混杂设备驱动
static struct miscdevice misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = &dev_fops,
};

static int __init dev_init(void)
{
	int ret;
	init_MUTEX(&lock); /* 初始化一个互斥锁 */
	ret = misc_register(&misc);
	printk (DEVI
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值