pwm设备驱动--platform总线

文章来源:http://blog.csdn.net/zqixiao_09/article/details/50888795

采用设备模型的概念,总线,设备,驱动。先将设备(驱动)挂载到总线上,等待另一个同名的驱动(设备),用match函数进行匹配。如果找到了就调用driver的probe函数将设备和驱动绑定在一起;当设备拔出时,driver调用remove函数清除一些相关的操作


device.c:

<span style="font-size:18px;">
#include <linux/module.h>  
#include <linux/device.h>  
#include <linux/platform_device.h>  
#include <linux/ioport.h>  

static struct resource beep_resource[] =  
{  
    [0] ={  
        .start = 0x114000a0,  
        .end =  0x114000a0 + 0x4,  
        .flags = IORESOURCE_MEM,  
    },  
  
    [1] ={  
        .start = 0x139D0000,  
        .end =  0x139D0000 + 0x14,  
        .flags = IORESOURCE_MEM,  
    }  
};  
  
static void hello_release(struct device *dev)  
{  
    printk("hello_release\n");  
    return ;  
}  
  
  
/*定义设备结构体*/
static struct platform_device hello_device=  
{  
    .name = "bigbang",  
 	.id = -1,  
    .dev.release = hello_release,  
    .num_resources = ARRAY_SIZE(beep_resource),  
    .resource = beep_resource,  
};  
  
static int hello_init(void)  
{  
    printk("hello_init");  
    return platform_device_register(&hello_device);/*将设备挂到platform总线上*/
}  
  
static void hello_exit(void)  
{  
    printk("hello_exit");
    platform_device_unregister(&hello_device);/*从platform总线上撤销*/
    return;  
}  
  
MODULE_LICENSE("GPL");  
module_init(hello_init);  
module_exit(hello_exit);  </span>

driver.c

<span style="font-size:18px;">
#include <linux/module.h>  
#include <linux/fs.h>  
#include <linux/cdev.h>  
#include <linux/device.h>  
#include <linux/platform_device.h>  
#include <asm/io.h>  
  
static int major = 250;  
static int minor=0;  
static dev_t devno;  
static struct class *cls;  
static struct device *test_device;  
           
#define TCFG0         0x0000                 
#define TCFG1         0x0004                              
#define TCON          0x0008               
#define TCNTB0        0x000C            
#define TCMPB0        0x0010             
  
static unsigned int *gpd0con;  
static void *timer_base;  
  
#define  MAGIC_NUMBER    'k'  
#define  BEEP_ON    _IO(MAGIC_NUMBER    ,0)  
#define  BEEP_OFF   _IO(MAGIC_NUMBER    ,1)  
#define  BEEP_FREQ   _IO(MAGIC_NUMBER   ,2)  
  
static void fs4412_beep_init(void)  
{     
    writel ((readl(gpd0con)&~(0xf<<0)) | (0x2<<0),gpd0con);  
    writel ((readl(timer_base +TCFG0  )&~(0xff<<0)) | (0xff <<0),timer_base +TCFG0);   
    writel ((readl(timer_base +TCFG1 )&~(0xf<<0)) | (0x2 <<0),timer_base +TCFG1 );   
  
    writel (500, timer_base +TCNTB0  );  
    writel (250, timer_base +TCMPB0 );  
    writel ((readl(timer_base +TCON )&~(0xf<<0)) | (0x2 <<0),timer_base +TCON );   
}  

void fs4412_beep_on(void)  
{  
    writel ((readl(timer_base +TCON )&~(0xf<<0)) | (0x9 <<0),timer_base +TCON );  
}  
  
void fs4412_beep_off(void)  
{  
    writel ((readl(timer_base +TCON )&~(0xf<<0)) | (0x0 <<0),timer_base +TCON );  
}  
  
static void beep_unmap(void)  
{  
        iounmap(gpd0con);  
        iounmap(timer_base);  
}  
  
static int beep_open (struct inode *inode, struct file *filep)  
{  
    fs4412_beep_on();  
    return 0;  
}  
  
static int beep_release(struct inode *inode, struct file *filep)  
{  
     fs4412_beep_off();  
     return 0;  
}  
#define BEPP_IN_FREQ 100000  
static void beep_freq(unsigned long arg)  
{  
    writel(BEPP_IN_FREQ/arg, timer_base +TCNTB0  );  
    writel(BEPP_IN_FREQ/(2*arg), timer_base +TCMPB0 );  
  
}  
  
static long beep_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)  
{  
    switch(cmd)  
    {  
        case BEEP_ON:  
            fs4412_beep_on();  
            break;  
        case BEEP_OFF:  
            fs4412_beep_off();  
            break;  
        case BEEP_FREQ:  
            beep_freq( arg );  
            break;  
        default :  
            return -EINVAL;  
    }  
    return 0;  
}  

/*操作*/
static struct file_operations beep_ops=  
{  
    .open     = beep_open,  
    .release = beep_release,  
    .unlocked_ioctl      = beep_ioctl,  
};  

/*在platform总线上找到同名的设备,调用该函数
 *对设备资源进行初始化以及注册驱动生成设备文件 
 */
static int beep_probe(struct platform_device *pdev)  
{  
    int ret;      
    printk("match ok!");  
      
    gpd0con = ioremap(pdev->resource[0].start,pdev->resource[0].end - pdev->resource[0].start);  
    timer_base = ioremap(pdev->resource[1].start, pdev->resource[1].end - pdev->resource[1].start);  
  
    devno = MKDEV(major,minor);  
    ret = register_chrdev(major,"beep",&beep_ops);  
  
    cls = class_create(THIS_MODULE, "myclass");  
    if(IS_ERR(cls))  
    {  
        unregister_chrdev(major,"beep");  
        return -EBUSY;  
    }  
  
    test_device = device_create(cls,NULL,devno,NULL,"beep");
    if(IS_ERR(test_device))  
    {  
        class_destroy(cls);  
        unregister_chrdev(major,"beep");  
        return -EBUSY;  
    }  
      
    fs4412_beep_init();  
      
    return 0;  
}  
/*设备拔出时调用该函数*/
static int beep_remove(struct platform_device *pdev)  
{  
    beep_unmap();  
    device_destroy(cls,devno);  
    class_destroy(cls);   
    unregister_chrdev(major,"beep");  
  
    return 0;  
}  
  
/*定义驱动结构体
 *probe和remove函数的入口
 */
static struct platform_driver beep_driver=  
{  
    .driver.name = "bigbang",  
    .probe = beep_probe,  
    .remove = beep_remove,  
};  
  
static int beep_init(void)  
{  
    printk("beep_init");  
    /*将驱动挂到platform总线上*/
    return platform_driver_register(&beep_driver);  
}  
  
static void beep_exit(void)  
{  
    printk("beep_exit");
	/*从platform总线上撤销*/  
    platform_driver_unregister(&beep_driver);  
      
    return;  
}  
MODULE_LICENSE("GPL");  
module_init(beep_init);  
module_exit(beep_exit);  </span>

test.c

<span style="font-size:18px;">
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
#include<sys/ioctl.h>

#define MAGIC_NUMBER 'k'
#define BEEP_ON _IO(MAGIC_NUMBER  ,0)
#define BEEP_OFF _IO(MAGIC_NUMBER ,1)
#define BEEP_FREQ _IO(MAGIC_NUMBER ,2)

int main(void)
{
	int fd;
	fd=open("/dev/beep",O_RDWR);
	if(fd<0)
	{
		perror("open fail\n");
		return 0;
	}

	ioctl(fd,BEEP_ON);

	sleep(6);
	ioctl(fd,BEEP_OFF);

	close(fd);
	return 0;
}
</span>

Makefile:

<span style="font-size:18px;">
ifneq ($(KERNELRELEASE),)
obj-m:=driver.o device.o
else
KDIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
all:
	make -C $(KDIR) M=$(PWD) modules
	gcc -Wall -o test test.c
clean:
	make -C $(KDIR) M=$(PWD) clean
endif</span>



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 你好!我可以理解你想要了解有关PWM-ON-PWM调制技术的问题。PWM-ON-PWM调制技术是一种用于控制电机转速的技术,通常应用于机器人控制和工业自动化领域。 PWM-ON-PWM调制技术的原理是通过将一个PWM信号嵌入到另一个PWM信号的占空比上,从而控制电机的转速。具体来说,PWM-ON-PWM调制技术需要两个PWM信号,一个称为“载波信号”,另一个称为“调制信号”。载波信号的频率通常较高,通常为10 kHz到20 kHz之间。调制信号的频率则较低,通常在几百Hz左右。通过将调制信号的占空比嵌入到载波信号的占空比上,可以控制电机的转速。 如果需要进一步了解PWM-ON-PWM调制技术的原理和应用,我建议你可以查阅一些相关的资料或教程。希望我的回答能够帮助到你! ### 回答2: PWM-ON-PWM调制模式是一种特殊的调制技术,主要用于控制和调节电子设备中的电压和电流。PWM代表脉宽调制,是一种通过对电压或电流的占空比进行调节来实现信号传输的方法。 PWM-ON-PWM调制模式则是在PWM调制的基础上进一步优化和改进的一种技术。它通过叠加两个或多个PWM信号来实现更高级的控制和调节效果。 在PWM-ON-PWM调制模式中,每个PWM信号都有自己的频率和占空比。这些PWM信号按照一定的顺序和时序进行叠加,形成一个更复杂的信号波形。通过调整各个PWM信号的频率和占空比,可以实现更精确的电压和电流调节,以满足不同应用场景的需求。 PWM-ON-PWM调制模式具有很高的灵活性和可调节性。它可以应用于许多领域,如电力电子、通信、无线电等。在电力电子领域,PWM-ON-PWM调制模式可以用于高效率的能量转换和传输,实现能源的有效利用。在通信和无线电领域,它可以用于数据传输、调频和数模转换等应用。 总之,PWM-ON-PWM调制模式是一种高级的调制技术,通过叠加多个PWM信号来实现更复杂和精确的电压和电流调节。它的应用范围广泛,可以满足各种电子设备的控制需求。 ### 回答3: PWM-ON-PWM调制模式是一种常用的电力电子调制技术。PWM代表脉宽调制(Pulse Width Modulation),是一种通过控制信号的脉冲宽度来调节信号的平均功率的方法。 在PWM-ON-PWM调制模式中,使用两个PWM信号进行调制。第一个PWM信号被称为载波信号,具有固定的频率和幅度。第二个PWM信号被称为调制信号,用来调节载波信号的占空比。 具体来说,调制信号的脉冲宽度和载波信号的周期相比较短,通常是载波信号周期的几分之一。调制信号的脉宽决定了输出信号的功率级别,通过改变调制信号的脉宽可以改变输出信号的平均功率。 PWM-ON-PWM调制模式的优点是可以灵活地控制输出信号的功率级别,可以适应不同的功率需求。它还具有较高的调制精度和线性性能,能够提供较高的输出电压和电流质量。此外,这种调制模式在许多领域中都有广泛的应用,如电力电子变频器、电力传输和电力调节等。 总之,PWM-ON-PWM调制模式是一种经典的电力电子调制技术,通过控制信号的脉冲宽度来调节信号的平均功率。它具有灵活的功率调节能力和较高的调制精度,在不同的应用中发挥着重要作用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值