完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
查看kernel的dts文件:
./build.sh kernel 在文件目录Z:kernelarcharm64bootdtsrockchip下找到rk3308b-roc-cc-plus-amic_emmc然后在里面添加pwm配置,如下所示:配置了一个pwm10 pwm-roll { status = "okay"; compatible = "pwm-roll"; pwms = <&pwm10 0 25000 0>; }; 在下面添加有&符号后面添加一个: &pwm10 { status = "okay"; pinctrl-names = "active"; pinctrl-0 = <&pwm10_pin_pull_down>; }; 在Z:kerneldrivers(自己创建的文件夹): 创建一个如下的文件夹: Z:kerneldrivers的makefile最后添加: obj-y += (自己文件夹名字)/pwm_roll/ 切换到: 除了pwm_roll文件以外都可以在drivers文件中找到,复制过来后只用修改Makefile和Kconfig,将其串联进kernel中: Makefile文件如下 obj-y += pwm_roll.o Kconfig文件如下 config PWM_ROLL bool "PWM_ROLL" default y depends on PWM_SYSFS ---help--- Serial Port Transmitter support 编写pwm_roll.c #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct pwm_roll roll_pwm; static const struct of_device_id pwm_roll_match[] = { { .compatible = "pwm-roll", }, { }, }; MODULE_DEVICE_TABLE(of, pwm_roll_match); static ssize_t pwm_roll_ioctl(struct file *filp,unsigned int cmd,unsigned long arg) { int tmp,ret; void __user *argp = (void __user *)arg; switch(cmd) { case ROLL_PWM_SET_PERIOD: pwm_disable(roll_pwm.pwm); printk("roll_pwm_SET_DUTY."); ret =copy_from_user(&tmp, argp, sizeof(int)); if(ret) { printk("copy_to_user failed."); return -EINVAL; } //频率= 1000,000,000 /time roll_pwm.period_ns =(int)( ROLL_PWM_PERIOD/tmp); roll_pwm.period = tmp; pwm_set_period(roll_pwm.pwm,roll_pwm.period_ns); pwm_enable(roll_pwm.pwm); printk("ROLL_PWM_SET_PERIOD. =%d hz,period_ns = %dnsn",roll_pwm.period,roll_pwm.period_ns); break; case ROLL_PWM_SET_DUTY: ret =copy_from_user(&tmp, argp, sizeof(int)); printk("ret%dn",ret); if(ret) { printk("copy_to_user failed."); return -EINVAL; } if(abs(tmp) > roll_pwm.period_ns) {printk("temp%dn",tmp); roll_pwm.duty_cycle = abs(tmp); pwm_config(roll_pwm.pwm, roll_pwm.period_ns, roll_pwm.period_ns); } else {printk("temp%dn",tmp); roll_pwm.duty_cycle = abs(tmp); pwm_config(roll_pwm.pwm, roll_pwm.duty_cycle, roll_pwm.period_ns); } printk("ROLL_PWM_SET_PDUTY = %d ns.n",roll_pwm.duty_cycle); break; case ROLL_PWM_GET_DUTY: ret = copy_to_user(argp, &roll_pwm.duty_cycle, sizeof(unsigned int)); if(ret) { printk("copy_to_user failed."); return -EINVAL; } printk("ROLL_PWM_GET_DUTY %d nsn.",roll_pwm.duty_cycle); break; case ROLL_PWM_GET_PERIOD: ret = copy_to_user(argp, &roll_pwm.period, sizeof(unsigned int)); if(ret) { printk("copy_to_user failed.n"); return -EINVAL; } printk("ROLL_PWM_GET_PERIOD %d hz.n",roll_pwm.period); break; case ROLL_PWM_ENABLE: printk("ROLL_PWM_ENABLE.n"); pwm_config(roll_pwm.pwm, 0, roll_pwm.period_ns); pwm_enable(roll_pwm.pwm); break; case ROLL_PWM_DISABLE: pwm_config(roll_pwm.pwm, 0, roll_pwm.period_ns); pwm_disable(roll_pwm.pwm); printk("ROLL_PWM_DISABLE.n"); break; } return 0; } static int roll_pwm_open(struct inode *inode, struct file *filp) { printk("roll pwm open n"); return 0; } static int roll_pwm_release(struct inode *inode, struct file *filp) { printk("roll pwm release n"); return 0; } static ssize_t roll_pwm_read(struct file *filp, char __user *buf, size_t len, loff_t *pos) { printk("roll pwm read n"); return 0; } static ssize_t roll_pwm_write(struct file *filp, const char __user *buf, size_t len, loff_t *pos) { printk("roll pwm write len=%ldn",len); return 0; } static struct file_operations ROLL_PWM_fops = { .owner = THIS_MODULE, .open = roll_pwm_open, .release = roll_pwm_release, .write = roll_pwm_write, .read = roll_pwm_read, .unlocked_ioctl = pwm_roll_ioctl, }; struct miscdevice ROLL_PWM_dev = { .minor = MISC_DYNAMIC_MINOR, .fops = &ROLL_PWM_fops, .name = "roll_pwm", }; static int pwm_roll_probe(struct platform_device *pdev) { int ret =0; struct pwm_device *pwm; static struct pwm_roll *roll = &roll_pwm; struct device *dev; dev =&pdev->dev; if(!dev->of_node) { dev_err(dev,"dev->of_node is not n"); return -ENODEV; } pwm = devm_pwm_get(dev, NULL); if(IS_ERR(pwm)) { dev_err(dev,"get pwm errorn"); // goto ROLL_IRQ_ERROR; } ret = pwm_adjust_config(pwm); if(ret) { misc_register(&ROLL_PWM_dev); //goto ROLL_IRQ_ERROR; } pwm_set_period(pwm,10000); pwm_enable(pwm); roll->period = (int)(ROLL_PWM_PERIOD/10000); roll->duty_cycle = 0; roll->period_ns = 10000; roll->pwm = pwm; ret =misc_register(&ROLL_PWM_dev); if(ret != 0) { dev_err(dev,"failed misc registern"); //goto ROLL_MISC_ERROR; } return 0; } static struct platform_driver roll_driver = { .probe = pwm_roll_probe, .driver = { .name = "pwm-roll", .of_match_table = of_match_ptr(pwm_roll_match), }, }; module_platform_driver(roll_driver); MODULE_DESCRIPTION("PWM ROLL"); MODULE_AUTHOR("Y <sean@mess.org>"); MODULE_LICENSE("GPL"); roll.h如下:该文件放在Z:kernelincludelinux下 #include #define ROLL_PWM_SET_DUTY _IOW('Y', 0x11, unsigned int) //设置占空比 #define ROLL_PWM_SET_PERIOD _IOW('Y', 0x12, unsigned int) //设置频率 #define ROLL_PWM_GET_DUTY _IOR('Y', 0x13, unsigned int) //获取当前占空比 #define ROLL_PWM_GET_PERIOD _IOR('Y', 0x14, unsigned int) //获取频率 #define ROLL_PWM_ENABLE _IO('Y', 0x17) //开启pwm #define ROLL_PWM_DISABLE _IO('Y', 0x18) //关闭pwm #define ROLL_PWM_PERIOD 1000000000 //用于计算 频率 = 1000,000,000 /time struct pwm_roll { unsigned int period; //频率 unsigned int duty_cycle; //占空比 unsigned int period_ns; //占空比周期 struct pwm_device *pwm; }; 然后运行./build.sh重新进行编译,将我们得到的镜像烧录到RK3308的板子上。 编写运行程序demo.c: #include #include #include #include #include #include #include #define ROLL_PWM_SET_DUTY _IOW('Y', 0x11, unsigned int) //设置占空比 #define ROLL_PWM_SET_PERIOD _IOW('Y', 0x12, unsigned int) //设置频率 #define ROLL_PWM_GET_DUTY _IOR('Y', 0x13, unsigned int) //获取当前占空比 #define ROLL_PWM_GET_PERIOD _IOR('Y', 0x14, unsigned int) //获取频率 #define ROLL_PWM_ENABLE _IO('Y', 0x15) //开启pwm #define ROLL_PWM_DISABLE _IO('Y', 0x16) //关闭pwm #define DEV_NAME "/dev/roll_pwm" int main(int argc, char *argv[]) { int fd; int duty, period; if(argc <2) { printf("no valuen"); return 1; } printf("argc =%dn",argc); fd = open(DEV_NAME,O_RDWR); if(fd < 0) { printf("hello worldn"); } switch (*(argv[1] +1)) { case 'p': period=atoi(argv[2]); ioctl(fd, ROLL_PWM_SET_PERIOD, &period); printf("period = %dn",period); break; case 'd': duty=atoi(argv[2]); ioctl(fd, ROLL_PWM_SET_DUTY, &duty); printf("duty =%dn",duty); break; case 'a': ioctl(fd, ROLL_PWM_GET_PERIOD, &period); printf("get period =%dn",period); break; case 'b': ioctl(fd, ROLL_PWM_GET_DUTY, &duty); printf("get duty =%dn",duty); break; default: break; } close(fd); return 0; } 使用demo -p 10000设置周期 使用demo -d 500000设置占空比 使用demo -a 查看周期 使用demo -b 查看设置的周期 最后用cat sys/kernel/debug/pwm就可以查看我们设置的pwm了 这样一个完成的pwm就设置好了,使用示波器会呈现一个方波 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
基于米尔瑞芯微RK3576核心板/开发板的人脸疲劳检测应用方案
2825 浏览 0 评论
2928 浏览 1 评论
2412 浏览 1 评论
3750 浏览 1 评论
4497 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-28 07:39 , Processed in 0.462290 second(s), Total 40, Slave 32 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号