基于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