4412 4路pwm输出
一、4412 xpwmTOUT1
这是4412的GPD0_1路,itop中被使用为LCD的背光电路的pwm功能。因此如果使用教程中的代码,同样操作GPD0_1是行不通的。
会出现错误,所以需要解除在内核中的占用
修改arch/arm/mach-exynos/mach-itop4412.c,找到并注释
samsung_bl_set(&smdk4x12_bl_gpio_info, &smdk4x12_bl_data);
在内核中取消相关的模块编译,(不确定)
Device Driver>>Graphics support>>Backlight & LCD device support(取消)
然后在平台文件中增加注册设备:
&s3c_device_timer[],
然后是测试代码:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/backlight.h>
#include <linux/err.h>
#include <linux/pwm.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/ioctl.h>
#include <asm-generic/uaccess.h> #define DEVICE_NAME "my_pwm3_dev"
#define DRIVER_NAME "my_pwm3_drv" #define PWM_MAGIC 'p'
#define PWM_MAX_NR 3 #define PWM_IOCTL_STOP _IO(PWM_MAGIC, 0)
#define PWM_IOCTL_SET_FREQ _IO(PWM_MAGIC, 1)
#define PWM_IOCTL_SET_DUTY _IO(PWM_MAGIC, 2) #define NS_IN_1HZ (1000000000UL) #define BUZZER_PWM_ID 0
#define PWM1_ID 1
#define PWM2_ID 2
#define PWM3_ID 3 #define BUZZER_PMW_GPIO EXYNOS4_GPD0(0)
#define PWM1_GPIO EXYNOS4_GPD0(1)
#define PWM2_GPIO EXYNOS4_GPD0(2)
#define PWM3_GPIO EXYNOS4_GPD0(3) static struct pwm_device *pwm4buzzer;
static struct semaphore lock;
static int period_ns = ;
static unsigned long freq = ;
static unsigned long duty = ; static void pwm_set_freq(void)
{
//配置周期
period_ns = NS_IN_1HZ / freq;
//配置占空比
if(duty < )
duty = ;
pwm_disable(pwm4buzzer);
pwm_config(pwm4buzzer, period_ns / duty, period_ns);
pwm_enable(pwm4buzzer);
//配置相应的GPIO,蜂鸣器IO配置成PWM输出模式
s3c_gpio_cfgpin(PWM3_GPIO, S3C_GPIO_SFN());
} static void pwm_stop(void)
{
s3c_gpio_cfgpin(PWM3_GPIO, S3C_GPIO_OUTPUT); pwm_config(pwm4buzzer, , NS_IN_1HZ / );
pwm_disable(pwm4buzzer);
} static int ops_pwm_open(struct inode *inode, struct file *file)
{
if(!down_trylock(&lock))
return ;
else
return -EBUSY;
} static int ops_pwm_close(struct inode *inode, struct file *file)
{
up(&lock);
return ;
} static long ops_pwm_ioctl(struct file *filep, unsigned int cmd,
unsigned long arg)
{
if(_IOC_TYPE(cmd)!=PWM_MAGIC) return -EINVAL;
if(_IOC_NR(cmd) > PWM_MAX_NR) return -EINVAL; switch(cmd) {
case PWM_IOCTL_SET_FREQ:
if(arg == )
return -EINVAL;
get_user(freq, (unsigned long __user *)arg);
printk(KERN_EMERG "freq is %ld\n", freq);
pwm_set_freq();
break;
case PWM_IOCTL_STOP:
pwm_stop();
break;
case PWM_IOCTL_SET_DUTY:
get_user(duty, (unsigned long __user *)arg);
printk(KERN_EMERG "duty is %ld\n", duty);
pwm_set_freq();
break;
default:
pwm_stop();
break;
}
return ;
} static struct file_operations pwm_ops = {
.owner = THIS_MODULE,
.open = ops_pwm_open,
.release = ops_pwm_close,
.unlocked_ioctl = ops_pwm_ioctl,
}; static struct miscdevice pwm_misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &pwm_ops,
}; static int __init iTop4412_pwm_dev_init(void)
{
int ret;
gpio_free(PWM3_GPIO); ret = gpio_request(PWM3_GPIO, DEVICE_NAME);
if(ret) {
printk(KERN_EMERG "request GPIO %d for pwm failed\n", PWM3_GPIO);
return ret;
} gpio_set_value(PWM3_GPIO, );
s3c_gpio_cfgpin(PWM3_GPIO, S3C_GPIO_OUTPUT); pwm4buzzer = pwm_request(PWM3_ID, DEVICE_NAME);
if (IS_ERR(pwm4buzzer)) {
printk(KERN_EMERG "request pwm %d for %s failed\n", PWM3_ID, DEVICE_NAME);
return -ENODEV;
}
pwm_stop(); sema_init(&lock, );
ret = misc_register(&pwm_misc_dev);
if(ret < ) {
gpio_free(BUZZER_PMW_GPIO);
pwm_free(pwm4buzzer);
misc_deregister(&pwm_misc_dev);
} printk(KERN_EMERG "\tinitialized\n"); return ret;
} static void __exit iTop4412_pwm_dev_exit(void)
{
gpio_free(BUZZER_PMW_GPIO);
pwm_free(pwm4buzzer);
misc_deregister(&pwm_misc_dev); printk(KERN_EMERG "\texit\n");
return;
} module_init(iTop4412_pwm_dev_init);
module_exit(iTop4412_pwm_dev_exit); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chen Tuo");
MODULE_DESCRIPTION("Exynos4 PWM Driver");
my_pwm3.c
然后是应用程序:
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/ioctl.h> #define PWM2_NAME "/dev/my_pwm3_dev" #define PWM_MAGIC 'p'
#define PWM_MAX_NR 3 #define PWM_IOCTL_STOP _IO(PWM_MAGIC, 0)
#define PWM_IOCTL_SET_FREQ _IO(PWM_MAGIC, 1)
#define PWM_IOCTL_SET_DUTY _IO(PWM_MAGIC, 2) int fd = -; void open_pwm1(void);
void close_pwm1(void);
void set_pwm_freq(int freq);
void set_pwm_duty(int duty);
void stop_pwm(void); void open_pwm1(void)
{
fd = open(PWM2_NAME, O_RDWR);
if(fd < ) {
perror("open pwm1 device");
exit();
} // atexit(close_pwm1);
} void close_pwm1(void)
{
if(fd >= ) {
ioctl(fd, PWM_IOCTL_STOP);
close(fd);
fd = -;
}
} void set_pwm_freq(int freq)
{
int ret = ioctl(fd, PWM_IOCTL_SET_FREQ, &freq);
if(ret < ) {
perror("set the frequency of the buzzer");
exit();
}
} void set_pwm_duty(int duty)
{
int ret = ioctl(fd, PWM_IOCTL_SET_DUTY, &duty);
if(ret < ) {
perror("set the duty of the pwm");
exit();
}
} void stop_pwm(void)
{
int ret = ioctl(fd, PWM_IOCTL_STOP);
if(ret < ) {
perror("Stop the buzzer");
exit();
}
} int main(int argc, char *argv[])
{
int freq = ; open_pwm1();
stop_pwm();
if(argc < ) {
printf("usage:%s [cmd] [arg]\n", argv[]);
printf("\tstop:%s [0] [0] \n",argv[]);
printf("\tset freq:%s [1] [arg]\n", argv[]);
printf("\tset duty:%s [2] [arg]\n", argv[]);
}
switch(atoi(argv[]))
{
case :
set_pwm_duty(atoi(argv[]));
break;
case :
set_pwm_freq(atoi(argv[]));
break;
case :
default:
stop_pwm();
return -;
} return ;
}
my_pwm3_app.c
最后是Makefile:
TARGET_NAME = my_pwm3
#TARGET_NAME = example_pwm
APP1_NAME = my_pwm3_app
#APP2_NAME = open_atomic_int_two
obj-m += $(TARGET_NAME).o KDIR := /home/topeet/chen/kernel-3.0/iTop4412_Kernel_3. PWD ?= $(shell pwd) all:app1
make -C $(KDIR) M=$(PWD) modules
app1:
arm-none-linux-gnueabi-gcc $(APP1_NAME).c -o $(APP1_NAME) -static
#app2:
# arm-none-linux-gnueabi-gcc $(APP2_NAME).c -o $(APP2_NAME) -static clean:
rm -rf *.o *.ko *.mod.c *.symvers *.order \
.$(TARGET_NAME)* $(APP1_NAME) $(APP2_NAME)
Makefile
二、4412 I2C_SDA7和I2C_SCL7
注释平台文件中的代码:
// s3c_i2c7_set_platdata(NULL);
// i2c_register_board_info(7, i2c_devs7, ARRAY_SIZE(i2c_devs7));
和这个
// &s3c_device_i2c7,
然后make menuconfig
>>Device Drivers>>Input device support>>Touchscreens【】取消选择
三、尝试编写控制PWM波形的驱动和应用程序
my_pwm3.c(驱动)
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/backlight.h>
#include <linux/err.h>
#include <linux/pwm.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/ioctl.h>
#include <asm-generic/uaccess.h> #define DEVICE_NAME "my_pwm3_dev"
#define DRIVER_NAME "my_pwm3_drv" #define PWM_MAGIC 'p'
#define PWM_MAX_NR 3 #define PWM_IOCTL_STOP _IO(PWM_MAGIC, 0)
#define PWM_IOCTL_SET_FREQ _IO(PWM_MAGIC, 1)
#define PWM_IOCTL_SET_DUTY _IO(PWM_MAGIC, 2) #define NS_IN_1HZ (1000000000UL) #define BUZZER_PWM_ID 0
#define PWM1_ID 1
#define PWM2_ID 2
#define PWM3_ID 3 #define BUZZER_PMW_GPIO EXYNOS4_GPD0(0)
#define PWM1_GPIO EXYNOS4_GPD0(1)
#define PWM2_GPIO EXYNOS4_GPD0(2)
#define PWM3_GPIO EXYNOS4_GPD0(3) static struct pwm_device *pwm4buzzer;
static struct semaphore lock;
static int period_ns = ;
static unsigned long freq = ;
static unsigned long duty = ; static void pwm_set_freq(void)
{
//配置周期
period_ns = NS_IN_1HZ / freq;
//配置占空比
if(duty < )
duty = ;
pwm_disable(pwm4buzzer);
pwm_config(pwm4buzzer, period_ns / duty, period_ns);
pwm_enable(pwm4buzzer);
//配置相应的GPIO,蜂鸣器IO配置成PWM输出模式
s3c_gpio_cfgpin(PWM3_GPIO, S3C_GPIO_SFN());
} static void pwm_stop(void)
{
s3c_gpio_cfgpin(PWM3_GPIO, S3C_GPIO_OUTPUT); pwm_config(pwm4buzzer, , NS_IN_1HZ / );
pwm_disable(pwm4buzzer);
} static int ops_pwm_open(struct inode *inode, struct file *file)
{
if(!down_trylock(&lock))
return ;
else
return -EBUSY;
} static int ops_pwm_close(struct inode *inode, struct file *file)
{
up(&lock);
return ;
} static long ops_pwm_ioctl(struct file *filep, unsigned int cmd,
unsigned long arg)
{
if(_IOC_TYPE(cmd)!=PWM_MAGIC) return -EINVAL;
if(_IOC_NR(cmd) > PWM_MAX_NR) return -EINVAL; switch(cmd) {
case PWM_IOCTL_SET_FREQ:
if(arg == )
return -EINVAL;
get_user(freq, (unsigned long __user *)arg);
printk(KERN_EMERG "freq is %ld\n", freq);
pwm_set_freq();
break;
case PWM_IOCTL_STOP:
pwm_stop();
break;
case PWM_IOCTL_SET_DUTY:
get_user(duty, (unsigned long __user *)arg);
printk(KERN_EMERG "duty is %ld\n", duty);
pwm_set_freq();
break;
default:
pwm_stop();
break;
}
return ;
} static struct file_operations pwm_ops = {
.owner = THIS_MODULE,
.open = ops_pwm_open,
.release = ops_pwm_close,
.unlocked_ioctl = ops_pwm_ioctl,
}; static struct miscdevice pwm_misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &pwm_ops,
}; static int __init iTop4412_pwm_dev_init(void)
{
int ret;
gpio_free(PWM3_GPIO); ret = gpio_request(PWM3_GPIO, DEVICE_NAME);
if(ret) {
printk(KERN_EMERG "request GPIO %d for pwm failed\n", PWM3_GPIO);
return ret;
} gpio_set_value(PWM3_GPIO, );
s3c_gpio_cfgpin(PWM3_GPIO, S3C_GPIO_OUTPUT); pwm4buzzer = pwm_request(PWM3_ID, DEVICE_NAME);
if (IS_ERR(pwm4buzzer)) {
printk(KERN_EMERG "request pwm %d for %s failed\n", PWM3_ID, DEVICE_NAME);
return -ENODEV;
}
pwm_stop(); sema_init(&lock, );
ret = misc_register(&pwm_misc_dev);
if(ret < ) {
gpio_free(BUZZER_PMW_GPIO);
pwm_free(pwm4buzzer);
misc_deregister(&pwm_misc_dev);
} printk(KERN_EMERG "\tinitialized\n"); return ret;
} static void __exit iTop4412_pwm_dev_exit(void)
{
gpio_free(BUZZER_PMW_GPIO);
pwm_free(pwm4buzzer);
misc_deregister(&pwm_misc_dev); printk(KERN_EMERG "\texit\n");
return;
} module_init(iTop4412_pwm_dev_init);
module_exit(iTop4412_pwm_dev_exit); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chen Tuo");
MODULE_DESCRIPTION("Exynos4 PWM Driver");
my_pwm3.c
my_pwm3_app.c
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/ioctl.h> #define PWM2_NAME "/dev/my_pwm3_dev" #define PWM_MAGIC 'p'
#define PWM_MAX_NR 3 #define PWM_IOCTL_STOP _IO(PWM_MAGIC, 0)
#define PWM_IOCTL_SET_FREQ _IO(PWM_MAGIC, 1)
#define PWM_IOCTL_SET_DUTY _IO(PWM_MAGIC, 2) int fd = -; void open_pwm1(void);
void close_pwm1(void);
void set_pwm_freq(int freq);
void set_pwm_duty(int duty);
void stop_pwm(void); void open_pwm1(void)
{
fd = open(PWM2_NAME, O_RDWR);
if(fd < ) {
perror("open pwm1 device");
exit();
} // atexit(close_pwm1);
} void close_pwm1(void)
{
if(fd >= ) {
ioctl(fd, PWM_IOCTL_STOP);
close(fd);
fd = -;
}
} void set_pwm_freq(int freq)
{
int ret = ioctl(fd, PWM_IOCTL_SET_FREQ, &freq);
if(ret < ) {
perror("set the frequency of the buzzer");
exit();
}
} void set_pwm_duty(int duty)
{
int ret = ioctl(fd, PWM_IOCTL_SET_DUTY, &duty);
if(ret < ) {
perror("set the duty of the pwm");
exit();
}
} void stop_pwm(void)
{
int ret = ioctl(fd, PWM_IOCTL_STOP);
if(ret < ) {
perror("Stop the buzzer");
exit();
}
} int main(int argc, char *argv[])
{
int freq = ; open_pwm1();
stop_pwm();
if(argc < ) {
printf("usage:%s [cmd] [arg]\n", argv[]);
printf("\tstop:%s [0] [0] \n",argv[]);
printf("\tset freq:%s [1] [arg]\n", argv[]);
printf("\tset duty:%s [2] [arg]\n", argv[]);
}
switch(atoi(argv[]))
{
case :
set_pwm_duty(atoi(argv[]));
break;
case :
set_pwm_freq(atoi(argv[]));
break;
case :
default:
stop_pwm();
return -;
} return ;
}
my_pwm3_app.c
Makefile
TARGET_NAME = my_pwm3
#TARGET_NAME = example_pwm
APP1_NAME = my_pwm3_app
#APP2_NAME = open_atomic_int_two
obj-m += $(TARGET_NAME).o KDIR := /home/topeet/chen/kernel-3.0/iTop4412_Kernel_3. PWD ?= $(shell pwd) all:app1
make -C $(KDIR) M=$(PWD) modules
app1:
arm-none-linux-gnueabi-gcc $(APP1_NAME).c -o $(APP1_NAME) -static
#app2:
# arm-none-linux-gnueabi-gcc $(APP2_NAME).c -o $(APP2_NAME) -static clean:
rm -rf *.o *.ko *.mod.c *.symvers *.order \
.$(TARGET_NAME)* $(APP1_NAME) $(APP2_NAME)
Makfile
总结:内核接收ioctl的信息时需要使用特定的函数进行保护,防止被乱七八糟的传入数据。
4412 4路pwm输出的更多相关文章
- 16路PWM输出的pca9685模块
今天要介绍的就是该模块,该模块是16路pwm模块,使用I2C总线可以控制16路舵机(led). 接线OE空着就可以,其他VCC是芯片供电+5,SCL时钟线,SDA信号线,GND地线. 芯片介绍可以看: ...
- J20航模遥控器开源项目系列教程(五)| 制作STM32F0接收机,8路PWM输出,SBUS输出,PPM输出 | 加密狗无线化,畅玩飞行模拟器
我们的开源宗旨:自由 协调 开放 合作 共享 拥抱开源,丰富国内开源生态,开展多人运动,欢迎加入我们哈~ 和一群志同道合的人,做自己所热爱的事! 项目开源地址:https://github.com/J ...
- STM32 PWM输出(映射)
STM32 的定时器除了 TIM6 和 7.其他的定时器都可以用来产生 PWM 输出.其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出.而通用定时器也能同时产生多达 4 ...
- 定时器同步+触发三ADC采样+输出6路PWM波
为了熟悉定时器定时器和ADC 用STM32F407DIS做了一个简单的工程: 通过高级定时器TIM1溢出更新时间作为触发输出信号(TRGO),触发TIM8开始计数: 同时TIM1的通道1.2.3以及分 ...
- (五)转载:通用定时器PWM输出
1. TIMER输出PWM基本概念 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有 ...
- STM32 HAL库学习系列第4篇 定时器TIM----- 开始定时器与PWM输出配置
基本流程: 1.配置定时器 2.开启定时器 3.动态改变pwm输出,改变值 HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1); 函数总结: __HAL_TIM ...
- STM32(7)——通用定时器PWM输出
1.TIMER输出PWM基本概念 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种 ...
- stm32 PWM输出学习
STM32 的定时器除了 TIM6 和 7,其他的定时器都可以用来产生 PWM 输出.其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出.通用定时器也能同时产生多达 4路 ...
- STM32F103ZET6 PWM输出
1.通用定时器的PWM功能 STM32F103ZET6有4个通用定时器,分别是TIM2.TIM3.TIM4.TIM5. 通用定时器由一个可编程预分频器驱动的16位自动装载计数器构成. 通用定时器的很多 ...
随机推荐
- CSS-父元素宽度自适应子元素宽度之和
最近碰见这样一个需求,要让图片横向排列设置 x 方向的滚动条滚动查看,原本当直接创建一个 IFC(inline,float 什么的)就解决了,搞了半天发现搞不定(IFC 也是不能父元素宽度自适应子元素 ...
- web接口开发基础知识-什么是web接口?
比如我们访问百度的首页,输入的url地址是:https://www.baidu.com/ 那么当我们在浏览器地址栏中输入url,敲回车后,发生了什么事情?怎么就能通过1个url地址就能看到百度的首页了 ...
- Ubuntu查看端口使用情况,使用netstat命令:
https://www.cnblogs.com/fly-book/p/9827128.html
- Java的常用类 String
String类: 代表字符串, java程序中的所有字符串字面值(如, "abc")都是此类的实例实现 String是一个final类,代表不可变的字符序列 字符串是常量是用双引号 ...
- 求 主板型号 945GME - ICH7M/U 支持的最大内存,以及内存型号 10
https://zhidao.baidu.com/question/400302290.html 求 主板型号 945GME - ICH7M/U 支持的最大内存,以及内存型号 10 主板型号 明基 J ...
- Git使用gitignore建立项目过滤规则
在进行协作开发代码管理的过程中,常常会遇到某些临时文件.配置文件.或者生成文件等,这些文件由于不同的开发端会不一样,如果使用git add . 将所有文件纳入git库中,那么会出现频繁的改动和push ...
- PowerShell - Invoke VBA function
$xl = new-object -comobject Excel.Application $source_wb = $xl.workbooks.open($source) $xl.visible=$ ...
- .net Datatable
1. ROW remove vs delete datatable dt = new datatable() //fill 5 records for each row as datarow in d ...
- [暑假集训Day1T2]北极通讯网络
这题主要考察对“卫星电话”的理解,k个卫星电话相当于可以让k个联通块保持联通,因此我们只需要让原图连成k个联通块,然后给每个联通块的任意一个节点发一部卫星电话即可.因此我们需要连n-k条边,特别地,当 ...
- scite配置文件及常用设置
在linux系统中,SciTE的用户设置文件为 ~/.SciTEUser.properties,优先级高于全局配置文件. scite是个不错的IDE工具,只是本人发现,在开发团队中和其他成员的编辑工具 ...