tq2440 pwm 驱动

来源:互联网 发布:淘宝搜索模型 编辑:程序博客网 时间:2024/05/30 12:30
/*************************************************************
基于tq2440开发板,内核2.6.30

功能
神奇了,加了几条打印语句后蜂鸣器就叫了。
估计是tcon 的写入速度比较慢吧,需要点延时。
真心伤不起啊
还有就是不知道为什么tcon  寄存器值的输出好像不对劲
这个pwm 设置其实和其他的单片机也差不多,
只不过多了个死区的概念,就是防止电器驱动时候的开关同时开启
当tcnt 和tcnp 的相等时候电平反转。
tcnt 为递减计数器
为什么出现奇怪数据的原因 是寄存器没有清零,
虽然它默认是0 但是当你错误操作,板子没有重启,
可能那寄存器的值就改变了。
没有测过时间,闲麻烦,而且蜂鸣器的接口好像没有外接。算了 。将就了。
没有写成定时器中断的原因是中断函数找不到啊,咋写。。。。
2012年7月10日22:16:37

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

#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/poll.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/clk.h>


#include <mach/regs-gpio.h>
#include <mach/hardware.h>

#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>

#include <plat/regs-timer.h>

#define DEVICE_NAME "driver_pwm"

//gpb0 tout0
//
volatile unsigned long *gpbcon = NULL;
volatile unsigned long *gpbdat = NULL;

volatile unsigned long *tcfg0 = NULL; //用来设置预分频
volatile unsigned long *tcfg1 = NULL; //用来设置分频
volatile unsigned long *tcon  = NULL; //定时器控制器
volatile unsigned long *tcntb0 = NULL; //计数缓冲寄存器
volatile unsigned long *tcmpb0 = NULL; //比较缓冲寄存器
volatile unsigned long *tcnto0 = NULL; //计数观察寄存器


//*gpbdat &= ~((1<<5) );



// ------------------- OPEN ------------------------
ssize_t drive_open (struct inode * inode ,struct file * file)
{
*gpbcon &=~(3<<0*2);
*gpbcon |= (2<<0*2);//设置b0 为 tout0

//*gpbcon &= ~( (3<<0*2)|(3<<5*2) );
//*gpbcon |= (1<<0*2)|(1<<5*2);
printk("-----------------drive open ok----------------\n");
return 0;


}


// ------------------- RELEASE/CLOSE ---------------
ssize_t drive_release (struct inode  * inode ,struct file * file)
{
printk("-----------------drive close ok----------------\n");
return 0;
}


// ------------------- READ ------------------------
ssize_t drive_read (struct file * file ,char * buf, size_t count, loff_t * f_ops)
{
printk("-----------------drive read ok----------------\n");
//copy_to_user( buf,(const void *)press_cnt,sizeof(press_cnt) );
return 0;
}


// ------------------- WRITE -----------------------
ssize_t drive_write (struct file * file ,const char * buf, size_t count, loff_t * f_ops)
{
printk("-----------------drive write ok----------------\n");
return 0;
}

// ------------------- IOCTL -----------------------
ssize_t drive_ioctl (struct inode * inode ,struct file * file, unsigned int cmd, unsigned long arg)
{
struct clk *clk_p;
       unsigned long pclk;
unsigned long tcnt;

printk("-----------------drive ioctl ok----------------\n");

//if(cmd==0)
// return 0;

//定时器时钟频率=pclk /( 预分频器的值+1) / 分频器
//62.5k
*tcfg0 &= ~0xff;//定时器0预分配清零
*tcfg0 |=(50-1);//预分频 50

*tcfg1 &= ~0xf;//定时器0 mux 输入分频清零
*tcfg1 |=3; //mux 分频 16

 clk_p = clk_get(NULL, "pclk"); 
        pclk = clk_get_rate(clk_p);
tcnt = (pclk/50/16)/10;  
printk("pclk =  %d\n",pclk);
printk("tcnt =  %d\n",tcnt);
*tcntb0 &=0x0000;//16位寄存器
*tcmpb0 &=0x0000;
*tcntb0 |= 1000;
*tcmpb0|=500;

//*tcon &=0x0;
// printk("tcon=%d\n",*tcon);
printk("tcntb0=%d\n",*tcntb0);
 printk("tcmpb0=%d\n",*tcmpb0);
 
*tcon &= ~0x1f;//清零
// printk("tcon=%d\n",*tcon);
msleep(10);
//第一次必须手动更新
       *tcon |= 0xb;  //关闭死区、自动重载、关反相器、手动更新TCNTB0&TCMPB0、启动定时器0
//1011
//printk("tcon=%d\n",*tcon);
msleep(10);
 *tcon &= ~2;  //清除定时器0的手动更新位
 
//printk("tcon=%d\n",*tcon);
 printk("tcfg0=%d\n",*tcfg0);
 printk("tcfg1=%d\n",*tcfg1);
 printk("tcntb0=%d\n",*tcntb0);
 printk("tcmpb0=%d\n",*tcmpb0);
 printk("tcon=%d\n",*tcon);
 
//-----------------------------------------------------
/*
pclk =  50000000
tcnt =  6250
tcon=5242889
tcfg0=561
tcfg1=3
tcntb0=7295
tcmpb0=7295
tcon=5242889


pclk =  50000000
tcnt =  6250
tcntb0=8191
tcmpb0=7679
tcfg0=561
tcfg1=3
tcntb0=8191
tcmpb0=7679
tcon=5242889

*gpbdat |= 1<<0;
*gpbdat |= 1<<5;
msleep(500);
*gpbdat &= ~(1<<0);
*gpbdat &= ~(1<<5);
*/
//-----------------------------------------------------
//msleep(500);
return 0;
}


// -------------------------------------------------

static struct file_operations drive_ops ={

.owner  = THIS_MODULE,
.open   = drive_open,
.read    = drive_read,
.write   = drive_write,
.ioctl    = drive_ioctl,
.release = drive_release,
};


static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &drive_ops,
};


static int __init init_drive(void)  
{
int ret;
ret = misc_register(&misc);

gpbcon = (volatile unsigned long *)ioremap(0x56000010,32);
gpbdat = (volatile unsigned long *)ioremap(0x56000014, 32);

tcfg0    = (volatile unsigned long *)ioremap(0x51000000, 4);
tcfg1    = (volatile unsigned long *)ioremap(0x51000004, 4);
tcon     = (volatile unsigned long *)ioremap(0x51000008, 4);
tcntb0  = (volatile unsigned long *)ioremap(0x5100000c, 4);
tcmpb0 = (volatile unsigned long *)ioremap(0x51000010, 4);
tcnto0  = (volatile unsigned long *)ioremap(0x51000014, 4);



printk("-----------------drive button init ok----------------\n");
return 0;
}

static void __exit exit_drive(void)
{
*tcon &=~1;
misc_deregister(&misc);
printk("-----------------drive button exit ok----------------\n");
}



module_init(init_drive);
module_exit(exit_drive);
MODULE_LICENSE("GPL");




//--------------------------------------应用测试程序----------------------------------------------------




#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <fcntl.h>      // open() close()
#include <unistd.h>     // read() write()

#define DEVICE_NAME "/dev/driver_pwm"

//------------------------------------- main ---------------------------------------------
int main(int argc, char **argv)
{
int fd,ret;



       fd = open(DEVICE_NAME, O_RDWR);
 
if (fd == -1)
{
printf("can't open device mknod %s c zhu ci \n",DEVICE_NAME);
return 0;
}
ioctl(fd, 1);
while(1)
{

;
}


        // close 
ret = close(fd);

        return 0;
}// end main