linux下mini2440按键驱动的PWM的第二个通道的驱动怎么写?我需要一个PWM通道带动

扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
MINI2440开发板PWM驱动与测试程序简要分析
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口下次自动登录
现在的位置:
& 综合 & 正文
mini2440的pwm驱动程序和测试程序详解
一 pwm 驱动
位置: 内核/drivers/char/mini2440_pwm.c
#include &linux/module.h&#include &linux/kernel.h&#include &linux/fs.h&#include &linux/init.h&#include &linux/delay.h&#include &linux/poll.h&#include &asm/irq.h&#include &asm/io.h&#include &linux/interrupt.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 &asm/mach/time.h&#include &linux/clk.h&#include &linux/cdev.h&#include &linux/device.h&#include &linux/miscdevice.h&
#define DEVICE_NAME
//设备名 pwm
#define PWM_IOCTL_SET_FREQ
//定义宏常量,用于后面的ioctl中的switch case#define PWM_IOCTL_STOP
//定义信号量 lock
/* freq: pclk/50/16/65536 ~ pclk/50/16
* if pclk = 50MHz, freq is 1Hz to 62500Hz* human ear : 20Hz~ 20000Hz*/static void PWM_Set_Freq( unsigned long freq )
//设置pwm的频率,配置各个寄存器{unsigned long tcfg1;unsigned long tcfg0;
struct clk *clk_p;
//set GPB0 as tout0, pwm output
设置GPB0为tout0,pwm输出s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_TOUT0);
tcon = __raw_readl(S3C2410_TCON);
//读取寄存器TCON到tcontcfg1 = __raw_readl(S3C2410_TCFG1);
//读取寄存器TCFG1到tcfg1tcfg0 = __raw_readl(S3C2410_TCFG0);
//读取寄存器TCFG0到tcfg0
//prescaler = 50tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
// S3C2410_TCFG_PRESCALER0_MASK定时器0和
1的预分频值的掩码,TCFG[0~8]
tcfg0 |= (50 - 1);
// 预分频为50
//mux = 1/16tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
//S3C2410_TCFG1_MUX0_MASK定时器0分割值的掩
//码:TCFG1[0~3]tcfg1 |= S3C2410_TCFG1_MUX0_DIV16;
//定时器0进行16分割
__raw_writel(tcfg1, S3C2410_TCFG1);
//把tcfg1的值写到分割寄存器S3C2410_TCFG1中__raw_writel(tcfg0, S3C2410_TCFG0);
//把tcfg0的值写到预分频寄存器S3C2410_TCFG0中
clk_p = clk_get(NULL, "pclk");
//得到pclkpclk = clk_get_rate(clk_p);tcnt = (pclk/50/16)/
//得到定时器的输入时钟,进而设置PWM的调制频率__raw_writel(tcnt, S3C2410_TCNTB(0));
//PWM脉宽调制的频率等于定时器的输入时钟
__raw_writel(tcnt/2, S3C2410_TCMPB(0));
//占空比是50%
tcon &= ~0x1f;tcon |= 0
//disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0__raw_writel(tcon, S3C2410_TCON);
tcon &= ~2;
//clear manual update bit__raw_writel(tcon, S3C2410_TCON);
//把tcon写到计数器控制寄存器S3C2410_TCON中}
void PWM_Stop( void ){s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP);
//设置GPB0为输出s3c2410_gpio_setpin(S3C2410_GPB0, 0);
//设置GPB0为低电平,使蜂鸣器停止}
static int s3c24xx_pwm_open(struct inode *inode, struct file *file){if (!down_trylock(&lock))
//是否获得信号量,是down_trylock(&lock)=0,否则非0
return 0;else
return -EBUSY;
//返回错误信息:请求的资源不可用}
static int s3c24xx_pwm_close(struct inode *inode, struct file *file){
up(&lock);
//释放信号量lock
return 0;}
/*cmd 是1,表示设置频率;cmd 是2 ,表示停止pwm*/static int s3c24xx_pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){switch (cmd) {
case PWM_IOCTL_SET_FREQ:
//if cmd=1 即进入case PWM_IOCTL_SET_FREQ
if (arg == 0)
//如果设置的频率参数是0
return -EINVAL;
//返回错误信息,表示向参数传递了无效的参数
PWM_Set_Freq(arg);
//否则设置频率
case PWM_IOCTL_STOP:
// if cmd=2 即进入case PWM_IOCTL_STOP
PWM_Stop();
//停止蜂鸣器}
//成功返回}
/*初始化设备的文件操作的结构体*/static struct file_operations dev_fops = {
THIS_MODULE,
s3c24xx_pwm_open,
.release =
s3c24xx_pwm_close,
s3c24xx_pwm_ioctl,};
static struct miscdevice misc = {.minor = MISC_DYNAMIC_MINOR,.name = DEVICE_NAME,.fops = &dev_fops,};
static int __init dev_init(void){
init_MUTEX(&lock);
//初始化一个互斥锁ret = misc_register(&misc);
//注册一个misc设备
printk (DEVICE_NAME"/tinitialized/n");}
static void __exit dev_exit(void){misc_deregister(&misc);
//注销设备}
module_init(dev_init);module_exit(dev_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("FriendlyARM Inc.");MODULE_DESCRIPTION("S3C0 PWM Driver");
1 计数器控制寄存器
1)配置定时器输入时钟
TCFG0-时钟配置寄存器0,用于获得预分频值(1~255)
TCFG1-时钟配置寄存器1,用于获得分割值(2,4,8,16,32)
定时器输入时钟频率=PLCK/{预分频+1}/{分割值}
2)配置PWM的占空比
TCNTB0-定时器0计数缓存寄存器 ,是由定时器的输入时钟分频得到,是脉宽调制的频率
TCMTB0-定时器0比较缓存寄存器 ,用于设定PWM的占空比 ,寄存器值为高定平的
假设TCNTB0的频率是160,如果TCMTB0是110,则PWM在110个周期是高定平,50周期是低电平,从而占空比为11:5
3)定时器控制寄存器TCON
TCON[0~4]用于控制定时器0
2.__raw_readl和__raw_writel
读端口寄存器用__raw_readl(a ),该函数从端口a 返回一个32 位的值。相关的定义在include/asm-arm/io.h 中。#define __raw_readl(a) (*(volatile unsigned int*)(a)),写端口寄存器用__raw_writel(v,a),该函数将一个32 位的值写入端口a 中。相关的定义在include/asm-arm/io.h 中。#define __raw_writel(v,a) (*(volatile unsigned int*)(a) = (v))。此处设置功能控制寄存器,将相应的引脚设为输出状态。
3 .gpio操作
gpio_cfgpin 配置相应GPIO口的功能
gpio_setpin IO口为输出功能时,写引脚
4 基于信号量的Llinux 的并发控制
在驱动程序中,当多个线程同时访问相同的资源时,可能会引发“竞态”,因此必须对共享资源进行并发控制。信号量(绝大多数作为互斥锁使用)是一种进行并发控制的手段(还有自旋锁,它适合于保持时间非常短的时间)。信号量只能在进程的上下文中使用。
void init_MUTEX(&lock)初始化一个互斥锁,即他把信号量lock设置为1
void up (&lock) 释放信号量,唤醒等待者
int down_trylock(&lock) 尝试获得信号量lock ,如果能够立刻获得,就获得信号量,并返回为0.否则返回非0.并且它不会导致休眠,可以在中断上下文中使用。在PWM中,当计数值溢出时,就会引发计数中断。所以在这里用这个函数来获得信号。
二 PWM的测试函数
pwm_test.c代码注释
#include &stdio.h&
//标准输入输出定义#include &termios.h&
//POSIX终端控制定义#include &unistd.h&
//Unix 标准函数定义#include &stdlib.h&
//标准函数库定义
#define PWM_IOCTL_SET_FREQ
1#define PWM_IOCTL_STOP
#define ESC_KEY
//定义ESC_KEY 为ESC按键的键值
static int getch(void)
//定义函数在终端上获得输入,并把输入的量(int)返回{struct termios oldt,
//终端结构体struct termios
if (!isatty(STDIN_FILENO)) {
//判断串口是否与标准输入相连
fprintf(stderr, "this problem should be run at a terminal/n");
exit(1);}// save terminal settingif(tcgetattr(STDIN_FILENO, &oldt) & 0) {
//获取终端的设置参数
perror("save the terminal setting");
// set terminal as neednewt =newt.c_lflag &= ~( ICANON | ECHO );
//控制终端编辑功能参数ICANON 表示使用标准输入模
//式;参数ECH0表示显示输入字符if(tcsetattr(STDIN_FILENO,TCSANOW, &newt) & 0) {
//保存新的终端参数
perror("set terminal");
ch = getchar();
// restore termial settingif(tcsetattr(STDIN_FILENO,TCSANOW,&oldt) & 0) {
//恢复保存旧的终端参数
perror("restore the termial setting");
exit(1);}}
static int fd = -1;static void close_buzzer(void);static void open_buzzer(void)
//打开蜂鸣器{fd = open("/dev/pwm", 0);
//打开pwm设备驱动文件if (fd & 0) {
perror("open pwm_buzzer device");
//打开错误,则终止进程。退出参数为1}
// any function exit call will stop the buzzeratexit(close_buzzer);
//退出回调close_buzzer}
static void close_buzzer(void)
//关闭蜂鸣器{if (fd &= 0) {
ioctl(fd, PWM_IOCTL_STOP);
//停止蜂鸣器
close(fd);
//关闭设备驱动文件
fd = -1;}}
static void set_buzzer_freq(int freq){// this IOCTL command is the key to set frequencyint ret = ioctl(fd, PWM_IOCTL_SET_FREQ, freq);
//设置频率if(ret & 0) {
//如果输入的频率错误
perror("set the frequency of the buzzer");
//退出,返回1}}static void stop_buzzer(void){int ret = ioctl(fd, PWM_IOCTL_STOP);
//关闭蜂鸣器if(ret & 0) {
//如果无法关闭蜂鸣器
perror("stop the buzzer");
//退出返回1}}
int main(int argc, char **argv){int freq = 1000 ;
open_buzzer();
//打开蜂鸣器
printf( "/nBUZZER TEST ( PWM Control )/n" );printf( "Press +/- to increase/reduce the frequency of the BUZZER/n" ) ;printf( "Press 'ESC' key to Exit this program/n/n" );
while( 1 ){
set_buzzer_freq(freq);
//设置蜂鸣器频率
printf( "/tFreq = %d/n", freq );
key = getch();
switch(key) {
if( freq & 20000 )
freq += 10;
if( freq & 11 )
freq -= 10 ;
case ESC_KEY:
stop_buzzer();
1 STDIN_FILENO 标准输入的文件描述符
(kernel)利用文件描述符(file descriptor)来访问。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件标准输入(standard input)的文件描述符是 0,标准输出(standard output)是 1,标准错误(standard error)是 2。 POSIX 定义了 STDOUT_FILENO 和 STDERR_FILENO 来代替 0、1、2。这三个符号常量的定义位于头文件 unistd.h。
2 串口终端的操作。定义在&termios.h&中
通过对串口终端的操作,实现从标准输入得到一个int型的char
1) isatty(STDIN_FILENO) 判断是否有串口与标准输入相连,是返回0,否返回1
2) tcgetattr(STDIN_FILENO, &oldt) 读取终端结构体oldt的属性,获取终端的相关参数。成功返回0,失败返回-1
3) newt.c_lflag&=~(ICANON|ECH0)
c_lflag:本地模式标志,控制终端编辑功能
参数ICANON 表示使用标准输入模式;参数ECH0表示显示输入字符。
4)tcsetattr(STDIN_FILENO,TCSANOW,&oldt)
tcsetattr 函数用于设置终端参数,成功返回0,失败返回-1。
TCSANOW:不等数据传输完毕就立即改变属性。
&&&&推荐文章:
【上篇】【下篇】mini2440_pwm_motor_module.c.tar 这是 的pwm波驱动程序,它试图利用 输出 来控制步进电机 Embeded Linux 嵌入式
238万源代码下载-
&文件名称: mini2440_pwm_motor_module.c.tar
& & & & &&]
&&所属分类:
&&开发工具: Unix_Linux
&&文件大小: 2 KB
&&上传时间:
&&下载次数: 23
&&提 供 者:
&详细说明:这是mini2440的pwm波驱动程序,它试图利用mini2440输出pwm波来控制步进电机-This is
the driver for mini2440 to output pwm wave, it is trying to use the mini2440 s pwm wave to control a stepper motor
文件列表(点击判断是否您需要的文件,如果是垃圾请在下面评价投诉):
&&mini2440_pwm_motor_module.c.tar
&近期下载过的用户:
&输入关键字,在本站238万海量源码库中尽情搜索:
&[] - 基于mini2440 pwm的驱动与测试程序
&[] - 该程序是一个基于s3c2440的步进电机驱动程序和测试程序,编译内核版本为linux-2.6.13。
&[] - 控制小车的寻迹,避障,刹车等功能,算法较为简单,基本以驱动电机为主
&[] - mini2440 单片机 驱动马达小程序
&[] - 24BYJ48步进电机驱动程序,步数、速度可调Mini2440开发板PWM驱动与测试程序简要分析
第2页_Linux编程_Linux公社-Linux系统门户网站
你好,游客
Mini2440开发板PWM驱动与测试程序简要分析
来源:Linux社区&
作者:ssdsafsdsd
分析,这个程序的结构比较简单,只实现了open(),ioctl(),close()功能,其中最主要的就是ioctl()功能,在ioctl()中最重要的核心函数为static void PWM_Set_Freq( unsigned long freq );所以说只要分析懂了这个函数,这个驱动也都全懂了。要是做过这个裸机程序的就更简单了。里面出现的一些没分析的,在本博客另一篇LED驱动分析中基本都说过了,不清楚的可以去看那个。
首先分析static void PWM_Set_Freq( unsigned long freq );
static void PWM_Set_Freq( unsigned long freq )
unsigned long tcfg1;
unsigned long tcfg0;
struct clk *clk_p;
//set GPB0 as tout0, pwm output
s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);//功能配置
tcon = __raw_readl(S3C2410_TCON);& & //获得定时器控制寄存器的数值
tcfg1 = __raw_readl(S3C2410_TCFG1);&
//获得定时器配置寄存器0的值
tcfg0 = __raw_readl(S3C2410_TCFG0);&
//获得定时器配置寄存器1的值
//prescaler = 50
tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
tcfg0 |= (50 - 1);
& & //上面的两句是设置预分频器
//mux = 1/16
tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
tcfg1 |= S3C2410_TCFG1_MUX0_DIV16;
& & //上面两句设置MUX0
__raw_writel(tcfg1, S3C2410_TCFG1);
__raw_writel(tcfg0, S3C2410_TCFG0);
& & //上面两句将配置好的数值写入到配置寄存器
clk_p = clk_get(NULL, "pclk");
pclk& = clk_get_rate(clk_p);
& & //上面两句用于获取PCLK
tcnt& = (pclk/50/16)/
//上面这个数值决定了频率,
__raw_writel(tcnt, S3C2410_TCNTB(0));
__raw_writel(tcnt/2, S3C2410_TCMPB(0));
//上面两句将tcnt寄存器写入到TCNTB0,同时设置S3C2410_TCMPB0,也就是说占空比为50%& & & & & & & & & & & &
tcon &= ~0x1f;& & //低五位清零
tcon |= 0& & & & & & &
//disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0
__raw_writel(tcon, S3C2410_TCON);
tcon &= ~2;& & & & & & & & & & & &
//clear manual update bit
__raw_writel(tcon, S3C2410_TCON);
看几个宏定义:
#define S3C2410_TCFG_PRESCALER0_MASK (255&&0)& & //0xff&&0
#define S3C2410_TCFG1_MUX0_MASK&
(15&&0)& & &
#define S3C2410_TCFG1_MUX0_DIV16& (3&&0)& & & &2
相关资讯 & & &
& (02月27日)
& (06/08/:51)
& (05/15/:26)
& (01月12日)
& (05/15/:47)
& (05/06/:48)
图片资讯 & & &
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款

我要回帖

更多关于 mini2440 usb下载驱动 的文章

 

随机推荐