精华内容
下载资源
问答
  • PWM

    2020-03-23 19:34:48
    PWM:即Pulse width modulation,中文脉冲宽度调制。 PWM是一种模拟控制方式 PWM 方法种类: 相电压控制PWM 脉宽PWM 随机PWM SPWM 线电压控制PWM 在镍氢电池智能充电器中采用的脉宽PWM法,它是把每一脉冲宽度均...

    PWM:即Pulse width modulation,中文脉冲宽度调制
    PWM是一种模拟控制方式

    PWM 方法种类:

    1. 相电压控制PWM
    2. 脉宽PWM
    3. 随机PWM
    4. SPWM
    5. 线电压控制PWM

    在镍氢电池智能充电器中采用的脉宽PWM法,它是把每一脉冲宽度均相等的脉冲列作为PWM波形,通过改变脉冲列的周期可以调频,改变脉冲的宽度或占空比可以调压,采用适当控制方法即可使电压与频率协调变化,可以通过调整PWM的周期、PWM的占空比而达到控制充电电流的目的。

    展开全文
  • pwm

    2013-12-26 22:02:00
    pwm_dev.c: #include <linux/init.h>#include <linux/module.h>#include <linux/ioport.h>#include <linux/platform_device.h>#include "pwm.h" struct resource pwm_dev_resource[] = { ...

    pwm_dev.c:

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/ioport.h>
    #include <linux/platform_device.h>
    #include "pwm.h"

    struct resource pwm_dev_resource[] = {
    [0]={
    .start = PWM_TCFG,
    .end = PWM_TCFG + S_T36 - 1,
    .flags = IORESOURCE_MEM,
    },
    };
    static void pwm_release(struct device *dev)
    {

    }

    struct platform_device pwm_plat_dev ={
    .name = "s5pc_pwm",
    .id = -1,
    .num_resources = ARRAY_SIZE(pwm_dev_resource),
    .resource = pwm_dev_resource,
    .dev = {
    .release = pwm_release,
    },
    };


    static int __init pwm_dev_init(void)
    {
    platform_device_register(&pwm_plat_dev);
    return 0;
    }

    static void __exit pwm_dev_exit(void)
    {
    platform_device_unregister(&pwm_plat_dev);
    }

    module_init(pwm_dev_init);
    module_exit(pwm_dev_exit);
    MODULE_LICENSE("GPL");

     

     

    pwm_drv.c

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/fs.h> //file_operations
    #include <linux/device.h> //class_create device_create
    #include <linux/cdev.h> //Struct cdev
    #include <linux/slab.h> //kmalloc
    #include <asm/io.h> //ioremap,writel,readl
    #include <asm/uaccess.h> //copy_from_user
    #include <asm-generic/poll.h>
    #include <linux/sched.h>
    #include <linux/platform_device.h>
    #include "pwm.h"

    #define PWM_DENO 252

    struct pwm_device {
    unsigned int pwm_major;
    struct cdev *pwm_cdev;
    struct class *pwm_class;
    struct device *pwm_device;
    void __iomem *pwm_base;
    void __iomem *pwm_gdpcon;
    dev_t devno;
    };

    struct pwm_device *pwm_dev = NULL;


    static int pwm_open(struct inode *inode, struct file *file)
    {
    writel(readl(pwm_dev->pwm_gdpcon) & (~(0xf<<4)), pwm_dev->pwm_gdpcon);
    writel(readl(pwm_dev->pwm_gdpcon) | ((0x2<<4)), pwm_dev->pwm_gdpcon);

    writel(readl(pwm_dev->pwm_base + PWM_TCFG0) & (~(0xff<<0)), pwm_dev->pwm_base + PWM_TCFG0);
    writel(readl(pwm_dev->pwm_base + PWM_TCFG0) | (249<<0), pwm_dev->pwm_base + PWM_TCFG0);

    writel(readl(pwm_dev->pwm_base + PWM_TCFG1) & (~(0xf<<4)), pwm_dev->pwm_base + PWM_TCFG1);
    writel(readl(pwm_dev->pwm_base + PWM_TCFG1) | (0x4<<4), pwm_dev->pwm_base + PWM_TCFG1);

    return 0;
    }
    static ssize_t pwm_write(struct file *file, const char __user *user_buf, size_t size, loff_t *offset)
    {
    char buf[10];
    unsigned length = size;

    if(copy_from_user(buf, user_buf, length))
    {
    return -EINVAL;
    }else{
    writel(6666, pwm_dev->pwm_base + PWM_TCNTB1);
    writel(3456, pwm_dev->pwm_base + PWM_TCMPB1);

    writel(readl(pwm_dev->pwm_base + PWM_TCON) | (0xf<<8), pwm_dev->pwm_base + PWM_TCON);
    writel(readl(pwm_dev->pwm_base + PWM_TCON) & (~(0x1<<9)), pwm_dev->pwm_base + PWM_TCON);
    }
    return length;
    }

    static int pwm_close(struct inode *inode, struct file *file)
    {
    writel(readl(pwm_dev->pwm_base + PWM_TCON) | (0xf<<8), pwm_dev->pwm_base + PWM_TCON);
    writel(readl(pwm_dev->pwm_gdpcon) & (~(0xf<<4)), pwm_dev->pwm_gdpcon);
    return 0;
    }


    struct file_operations pwm_fops = {
    .owner = THIS_MODULE,
    .open = pwm_open,
    .write = pwm_write,
    .release = pwm_close,
    };


    static int pwm_drv_probe(struct platform_device *pdev)
    {
    int ret;
    struct resource *res;
    pwm_dev = kmalloc(sizeof(struct pwm_device), GFP_KERNEL);
    if(pwm_dev == NULL)
    {
    printk(KERN_INFO "pwm_dev kmalloc failed!\n");
    ret = -EINVAL;
    }

    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

    if(PWM_DENO){
    pwm_dev->devno = MKDEV(PWM_DENO, 0);
    ret = register_chrdev_region(pwm_dev->devno, 1, "pwm_dev");
    if(ret < 0){
    printk(KERN_INFO "pwm_dev->devno register_chrdev_region failed!\n");
    ret = -EINVAL;
    goto output0;
    }
    }else{
    ret = alloc_chrdev_region(&pwm_dev->devno, 252, 1, "pwm_dev");
    if(ret < 0){
    printk(KERN_INFO "pwm_dev->devno register_chrdev_region failed!\n");
    ret = -EINVAL;
    goto output0;
    }
    }


    pwm_dev->pwm_base = ioremap(res->start, res->end - res->start +1);
    if(pwm_dev->pwm_base == NULL)
    {
    printk(KERN_INFO"pwm_dev->pwm_base remap failed! \n");
    ret = -EINVAL;
    goto output1;
    }

    pwm_dev->pwm_cdev = cdev_alloc();
    if(IS_ERR(&pwm_dev->pwm_cdev))
    {
    printk(KERN_INFO "pwm_dev->cdev alloc failed!\n");
    ret = -EINVAL;
    goto output2;
    }
    cdev_init(pwm_dev->pwm_cdev, &pwm_fops);
    cdev_add(pwm_dev->pwm_cdev, pwm_dev->devno, 1);

    pwm_dev->pwm_class = class_create(THIS_MODULE, "pwm_class");
    if(IS_ERR(&pwm_dev->pwm_class))
    {
    printk(KERN_INFO"pwm_dev->pwm_class create failed!\n");
    ret = -EINVAL;
    goto output3;
    }

    pwm_dev->pwm_device = device_create(pwm_dev->pwm_class, NULL, pwm_dev->devno, NULL, "pwm");
    if(IS_ERR(&pwm_dev->pwm_device))
    {
    printk(KERN_INFO"pwm_dev->pwm_device create failed!\n");
    ret = -EINVAL;
    goto output4;
    }

    pwm_dev->pwm_gdpcon = ioremap(PWM_GPDCON, 4);
    if(!pwm_dev->pwm_gdpcon)
    {
    printk(KERN_INFO "tm_dev->pwm_GDPCON ioremap failed!\n");
    ret = -EINVAL;
    goto output5;
    }
    return 0;

    output5:
    device_destroy(pwm_dev->pwm_class, pwm_dev->devno);
    output4:
    class_destroy(pwm_dev->pwm_class);
    output3:
    cdev_del(pwm_dev->pwm_cdev);
    output2:
    iounmap(pwm_dev->pwm_base);
    output1:
    unregister_chrdev_region(pwm_dev->devno, 1);
    output0:
    kfree(pwm_dev);

    return ret;
    }

    static int pwm_drv_remove(struct platform_device *pdev)
    {
    iounmap(pwm_dev->pwm_gdpcon);
    device_destroy(pwm_dev->pwm_class, pwm_dev->devno);
    class_destroy(pwm_dev->pwm_class);
    cdev_del(pwm_dev->pwm_cdev);
    iounmap(pwm_dev->pwm_base);
    unregister_chrdev_region( pwm_dev->devno, 1);
    kfree(pwm_dev);
    return 0;
    }


    struct platform_driver plat_drv={
    .probe = pwm_drv_probe,
    .remove = pwm_drv_remove,
    .driver = {
    .owner = THIS_MODULE,
    .name = "s5pc_pwm",
    },
    };


    static int __init pwm_drv_init(void)
    {
    platform_driver_register(&plat_drv);
    return 0;
    }

    static void __exit pwm_drv_exit(void)
    {
    platform_driver_unregister(&plat_drv);
    }

    module_init(pwm_drv_init);
    module_exit(pwm_drv_exit);
    MODULE_LICENSE("GPL");

     

     

    pwm_test.c:


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

    int main(void)
    {
    int fd = 0;
    int ret;
    char buf[10];

    fd = open("/dev/pwm", O_RDWR);
    if(fd <= 0)
    {
    perror("open failed!\n");
    exit(1);
    }

    printf("please input \"start\" or \"quit\"\n");
    while(1)
    {
    memset(buf, 0, 10);
    fgets(buf, 10, stdin);
    if(strncmp(buf, "start", 5) == 0){
    if(write(fd, buf, 10)!=10)
    {
    perror("write failed!\n");
    exit(1);
    }
    }else{
    break;
    }
    }

    close(fd);
    return 0;
    }

     

     

     

    makefile:

    ifeq ($(KERNELRELEASE),)
    KERNELDIR ?=/home/farsight/Linux_source/linux-2.6.35.5
    PWD :=$(shell pwd)
    modules:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
    arm-unknown-linux-gnueabi-gcc -o pwm_test pwm_test.c
    cp pwm_drv.ko pwm_dev.ko pwm_test /opt/rootfs/s5pc100_drv
    modules_install:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
    clean:
    rm -rf pwm_test *.o *~core *.ko *.mod.c .tmp_versions Module.symvers modules.order
    else
    obj-m :=pwm_drv.o pwm_dev.o
    endif

     

    pwm.h:

    #ifndef __PWM_H_
    #define __PWM_H_

    #define PWM_GPDCON 0xE0300080
    #define PWM_TCFG 0xEA000000
    #define PWM_TCFG0 0x0
    #define PWM_TCFG1 0x4
    #define PWM_TCON 0x8
    #define PWM_TCNTB1 0x18
    #define PWM_TCMPB1 0x1C
    #define PWM_TCNTO1 0x20
    #define S_T36 0x24
    #define PWM_MAJOR 251

    #endif

     

    转载于:https://www.cnblogs.com/weat/p/3493164.html

    展开全文
  • PWM原理 PWM频率与占空比详解

    万次阅读 多人点赞 2020-01-28 22:38:34
    什么是PWM ​ 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多...

    什么是PWM

    ​ 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。 ​



    pwm的频率

    是指1秒钟内信号从高电平到低电平再回到高电平的次数(一个周期);

    也就是说一秒钟PWM有多少个周期
    单位: Hz
    表示方式: 50Hz 100Hz

    pwm的周期:

    T=1/f
    周期=1/频率
    50Hz = 20ms 一个周期

    如果频率为50Hz ,也就是说一个周期是20ms 那么一秒钟就有 50次PWM周期

    占空比
    是一个脉冲周期内,高电平的时间与整个周期时间的比例
    单位: % (0%-100%)
    表示方式:20%

    在这里插入图片描述
    周期: 一个脉冲信号的时间         1s内测周期次数等于频率
    脉宽时间: 高电平时间

    上图中 脉宽时间占总周期时间的比例,就是占空比

    比方说周期的时间是10ms,脉宽时间是8ms 那么低电平时间就是2ms 总的占空比 8/8+2= 80%

    这就是占空比为80%的脉冲信号

    而我们知道PWM就是脉冲宽度调制 通过调节占空比,就可以调节脉冲宽度(脉宽时间) 而频率 就是单位时间内脉冲信号的次数,频率越大

    以20Hz 占空比为80% 举例 就是1秒钟之内输出了20次脉冲信号 每次的高电平时间为40ms

    我们换更详细点的图

    在这里插入图片描述
    上图中,周期为T
    T1为高电平时间
    T2 为低电平时间

    假设周期T为 1s 那么频率就是 1Hz 那么高电平时间0.5s ,低电平时间0.5s 总的占空比就是 0.5 /1 =50%

    PWM原理

    以单片机为例,我们知道,单片机的IO口输出的是数字信号IO口只能输出高电平和低电平

    假设高电平为5V 低电平则为0V 那么我们要输出不同的模拟电压,就要用到PWM,通过改变IO口输出的方波的占空比从而获得使用数字信号模拟成的模拟电压信号

    我们知道,电压是以一种连接1或断开0的重复脉冲序列被夹到模拟负载上去的(例如LED灯,直流电机等),连接即是直流供电输出,断开即是直流供电断开。通过对连接和断开时间的控制,理论上来讲,可以输出任意不大于最大电压值(即0~5V之间任意大小)的模拟电压

    比方说 占空比为50% 那就是高电平时间一半,低电平时间一半,在一定的频率下,就可以得到模拟的2.5V输出电压 那么75%的占空比 得到的电压就是3.75V
    在这里插入图片描述

    pwm的调节作用来源于对“占周期”的宽度控制,“占周期”变宽,输出的能量就会提高,通过阻容变换电路所得到的平均电压值也会上升,“占周期”变窄,输出的电压信号的电压平均值就会降低,通过阻容变换电路所得到的平均电压值也会下降

    也就是,在一定的频率下,通过不同的占空比 即可得到不同的输出模拟电压

    pwm就是通过这种原理实现D/A转换的。

    总结:
    PWM就是在合适的信号频率下,通过一个周期里改变占空比的方式来改变输出的有效电压

    PWM频率越大,相应越快,

    PWM输出呼吸灯

    那么,PWM信号的实际作用是什么呢?
    我们以经常使用的呼吸灯举例:

    一般人眼睛对于80Hz 以上刷新频率则完全没有闪烁感。

    频率太小的话 看起来就会闪烁

    那么我们平时见到的LED灯,当它的频率大于50Hz的时候,人眼就会产生视觉暂留效果,基本就看不到闪烁了,而是一个常亮的LED灯,

    你在1秒内,高电平0.5秒,低电平0.5秒,(频率1Hz)如此反复,那么你看到的电灯就会闪烁,

    但是如果是10毫秒内,5毫秒打开,5毫秒关闭,(频率100Hz) 这时候灯光的亮灭速度赶不上开关速度(LED灯还没完全亮就又熄灭了),由于视觉暂留作用 人眼不感觉电灯在闪烁,而是感觉灯的亮度少了 因为高电平时间(占空比)为50% 亮度也就为之前的50% ,

    频率很高时,看不到闪烁,占空比越大,LED越亮;
    频率很低时,可看到闪烁,占空比越大,LED越亮。

    所以,在频率一定下,可以用不同占空比改变LED灯的亮度。 使其达到一个呼吸灯的效果

    在这里插入图片描述

    PWM对电机转速的控制

    占空比可以实现对电机转速的调节,我们知道,占空比是高电平在一个周期之中的比值,高电平的所占的比值越大,占空比就越大,对于直流电机来讲,电机输出端引脚是高电平电机就可以转动,当输出端高电平时,电机会转动,但是是一点一点的提速,在高电平突然转向低电平时,电机由于电感有防止电流突变的作用是不会停止的,会保持这原有的转速,以此往复,电机的转速就是周期内输出的平均电压值,所以实质上我们调速是将电机处于一种,似停非停,似全速转动又非全速转动的状态,那么在一个周期的平均速度就是我们占空比调出来的速度了,

    在电机控制中,电压越大,电机转速越快,而通过PWM输出不同的模拟电压,便可以使电机达到不同的输出转速

    当然,在电机控制中,不同的电机都有其适应的频率 频率太低会导致运动不稳定,如果频率刚好在人耳听觉范围,有时还会听到呼啸声。频率太高的电机可能反应不过来

    正常的电机频率在 6-16kHZ之间为好

    PWM对舵机的控制

    舵机的控制就是通过一个固定的频率,给其不同的占空比的,来控制舵机不同的转角

    舵机的频率一般为频率为50HZ,也就是一个20ms左右的时基脉冲,而脉冲的高电平部分一般为0.5ms-2.5ms范围。来控制舵机不同的转角

    500-2500us的PWM高电平部分对应控制180度舵机的0-180度

    以180度角度伺服为例,那么对应的控制关系是这样的:
    0.5ms--------------0度;
    1.0ms------------45度;
    1.5ms------------90度;
    2.0ms-----------135度;
    2.5ms-----------180度;

    在这里插入图片描述

    在这里插入图片描述

    展开全文
  • 【STM32】通用定时器的PWM输出(实例:PWM输出)

    万次阅读 多人点赞 2018-04-19 15:22:43
    STM32F1xx官方资料: ...STM32的通用定时器分为TIM2、TIM3、TIM4、TIM5,而每个定时器都有独立的4个通道可以用来作为:输入捕获、输出比较、PWM输出、单脉冲模式输出等。 STM32的定时器除了TIM6和TIM7(基本定时器...

    STM32F1xx官方资料:

    《STM32中文参考手册V10》-第14章  通用定时器

     

    通用定时器PWM概述

    STM32定时器输出通道引脚

    这里以TIM3为例来讲解。STM32的通用定时器分为TIM2、TIM3、TIM4、TIM5,而每个定时器都有独立的4个通道可以用来作为:输入捕获、输出比较、PWM输出、单脉冲模式输出等。

    STM32的定时器除了TIM6和TIM7(基本定时器)之外,其他的定时器都可以产生PWM输出。其中,高级定时器TIM1、TIM8可以同时产生7路PWM输出,而通用定时器可以同时产生4路PWM输出,这样STM32最多可以同时产生30路PWM输出!

    从图中的内容可以看出,TIM3的4个通道相对应的各个引脚以及重映射情况下的各个引脚的位置。

    PWM的工作原理

    在通用定时器框图中,主要涉及到最顶上的一部分(计数时钟的选择)、中间部分(时基单元)、右下部分(PWM输出)这三个部分。这里主要讲解一下右下部分(PWM输出),其他两个部分可以参考文章:【STM32】通用定时器的基本原理(实例:定时器中断)

    下面以向上计数为例,简单地讲述一下PWM的工作原理:

    • 在PWM输出模式下,除了CNT(计数器当前值)、ARR(自动重装载值)之外,还多了一个值CCRx(捕获/比较寄存器值)。
    • 当CNT小于CCRx时,TIMx_CHx通道输出低电平;
    • 当CNT等于或大于CCRx时,TIMx_CHx通道输出高电平。

    这个时候就可以对其下一个准确的定义了:所谓脉冲宽度调制模式(PWM模式),就是可以产生一个由TIMx_ARR寄存器确定频率,由TIMx_CCRx寄存器确定占空比的信号。它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。

    PWM的通道概览

    每一个捕获/比较通道都是围绕着一个捕获/比较寄存器(包含影子寄存器),包括捕获的输入部分(数字滤波、多路复用和预分频器),和输出部分(比较器和输出控制)。

    捕获/比较模块由一个预装载寄存器和一个影子寄存器组成。读写过程仅操作预装载寄存器。

    • 在捕获模式下,捕获发生在影子寄存器上,然后再复制到预装载寄存器中。 
    • 在比较模式下,预装载寄存器的内容被复制到影子寄存器中,然后影子寄存器的内容和计数器进行比较。

    • CCR1寄存器:捕获/比较值寄存器:设置比较值;
    • CCMR1寄存器:OC1M[2:0]位:对于PWM方式下,用于设置PWM模式1或者PWM模式2;
    • CCER寄存器:CC1P位:输入/捕获1输出极性。0:高电平有效,1:低电平有效。
    • CCER寄存器:CC1E位:输入/捕获1输出使能。0:关闭,1:打开。

    PWM输出的模式区别

    通过设置寄存器TIMx_CCMR1的OC1M[2:0]位来确定PWM的输出模式

    • PWM模式1:在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。
    • PWM模式2:在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。

    注意:PWM的模式只是区别什么时候是有效电平,但并没有确定是高电平有效还是低电平有效。这需要结合CCER寄存器的CCxP位的值来确定。

    例如:若PWM模式1,且CCER寄存器的CCxP位为0,则当TIMx_CNT<TIMx_CCR1时,输出高电平;同样的,若PWM模式1,且CCER寄存器的CCxP位为2,则当TIMx_CNT<TIMx_CCR1时,输出低电平。

    PWM的计数模式

    向上计数模式

    下面是一个PWM模式1的例子。当TIMx_CNT<TIMx_CCRx时PWM信号参考OCxREF为高,否则为低。如果TIMx_CCRx中的比较值大于自动重装载值(TIMx_ARR),则OCxREF保持为’1’。如果比较值为0,则OCxREF保持为’0’。

    向下计数模式

    在PWM模式1,当TIMx_CNT>TIMx_CCRx时参考信号OCxREF为低,否则为高。如果TIMx_CCRx中的比较值大于TIMx_ARR中的自动重装载值,则OCxREF保持为’1’。该模式下不能产生0%的PWM波形。

    中央对齐模式

    当TIMx_CR1寄存器中的CMS位不为’00’时,为中央对齐模式(所有其他的配置对OCxREF/OCx信号都有相同的作用)。根据不同的CMS位设置,比较标志可以在计数器向上计数时被置’1’、在计数器向下计数时被置’1’、或在计数器向上和向下计数时被置’1’。TIMx_CR1寄存器中的计数方向位(DIR)由硬件更新,不要用软件修改它。

     

    自动加载的预加载寄存器

    在TIMx_CCMRx寄存器中的OCxM位写入’110’(PWM模式1)或’111’(PWM模式2),能够独立地设置每个OCx输出通道产生一路PWM。必须设置TIMx_CCMRx寄存器OCxPE位以使能相应的预装载寄存器,最后还要设置TIMx_CR1寄存器的ARPE位,(在向上计数或中心对称模式中)使能自动重装载的预装载寄存器。

    在TIMx_CRx寄存器的ARPE位,决定着是否使能自动重装载的预加载寄存器。

    根据TIMx_CR1位的APRE位的设置,APRE=0时,预装载寄存器的内容就可以随时传送到影子寄存器,此时两者是互通的;APRE=1时,在每一次更新事件时,才将预装在寄存器的内容传送至影子寄存器。

    简单的说:ARPE=1,ARR立即生效;APRE=0,ARR下个比较周期生效。

     

    PWM相关配置寄存器

    捕获/比较模式寄存器1(TIMx_CCMR1)

    捕获/比较模式寄存器总共2个,TIMx_CCMR1和TIMx_CCMR2。TIMx_CCMR1控制CH1和CH2,TIMx_CCMR2控制CH3和CH4。该寄存器的某些位在不同模式下功能不一样,上面一层对应输出而下面一层对应输入。

    其中模式设置位OCxM位,此位由3位组成,一共可以配置成7种模式,我们使用的是PWM模式,所以这三位必须为110/111。

    作用:在PWM输出模式下,确定PWM的模式、使能相应的预装载寄存器等操作。

    捕获/比较使能寄存器(TIMx_CCER)

    作用:在PWM输出模式下,确定PWM的输出极性和输出使能

    捕获/比较寄存器1(TIMx_CCR1)

    作用:在PWM输出模式下,确定比较的值

     

    PWM相关配置库函数

    • 1个输出初始化函数
    void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
    void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
    void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
    void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

    作用:在四个通道中选择一个,初始化PWM输出模式、比较输出极性、比较输出使能、比较值CCRx的值

    • 1个参数设置函数
    void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
    void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
    void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
    void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);

    作用:在四个通道中选择一个,设置比较值。通常在初始化函数中已经设置了比较值,此函数用于除初始化之外的修改。

    • 2个使能函数
    void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
    void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
    void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
    void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
    void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

    作用:前者在四个通道中选择一个,使能输出比较预装载,后者使能自动重装载的预装载寄存器允许位。

     

    PWM的一般步骤

    实例要求:使用TIM3来产生PWM输出,并使用TIM3的通道2,把通道2重映射到PB5,产生PWM来控制DS0的亮度。

    • 使能定时器和相关IO口时钟。调用函数:RCC_APB1PeriphClockCmd();RCC_APB2PeriphClockCmd();
    • 初始化IO口为复用功能输出。调用函数:GPIO_Init();  
    • 这里我们是要把PB5用作定时器的PWM输出引脚,所以要重映射配置,所以需要开启AFIO时钟。同时设置重映射。调用函数:RCC_APB2PeriphClockCmd();GPIO_PinRemapConfig();
    • 初始化定时器。调用函数:ARR,PSC等:TIM_TimeBaseInit();
    • 初始化输出比较参数。调用函数:TIM_OC2Init();
    • 使能预装载寄存器。调用函数:TIM_OC2PreloadConfig();
    • 使能定时器。调用函数:TIM_Cmd();
    • 不断改变比较值CCRx,达到不同的占空比效果。调用函数:TIM_SetCompare2()。

    下面按照这个一般步骤来进行一个简单的PWM输出程序:

    //TIM3 PWM部分初始化 
    //PWM输出初始化
    //arr:自动重装值
    //psc:时钟预分频数
    void TIM3_PWM_Init(u16 arr,u16 psc)
    {  
    	GPIO_InitTypeDef GPIO_InitStructure;
    	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	TIM_OCInitTypeDef  TIM_OCInitStructure;
    	
    
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);	//使能定时器3时钟
     	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
    	
    	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PB5    
     
       //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形	GPIOB.5
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
     
       //初始化TIM3
    	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
    	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 
    	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
    	
    	//初始化TIM3 Channel2 PWM模式	 
    	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
     	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
    	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
    	TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2
    
    	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器
     
    	TIM_Cmd(TIM3, ENABLE);  //使能TIM3
    	
    
    }
    
     int main(void)
     {		
     	u16 led0pwmval=0;
    	u8 dir=1;	
    	delay_init();	    	 //延时函数初始化	  
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    	uart_init(115200);	 //串口初始化为115200
     	LED_Init();			     //LED端口初始化
     	TIM3_PWM_Init(899,0);	 //不分频。PWM频率=72000000/900=80Khz
       	while(1)
    	{
     		delay_ms(10);	 
    		if(dir)led0pwmval++;
    		else led0pwmval--;
    
     		if(led0pwmval>300)dir=0;
    		if(led0pwmval==0)dir=1;										 
    		TIM_SetCompare2(TIM3,led0pwmval);		   
    	}	 
     }

     

    展开全文
  • PWM

    2008-01-25 11:48:00
    PWM can also be used to drive a LED and thereby get varying light intensities from a signal that is essentially either on or off. PWM can also be used to generate audio. Early desktop computers, such ...
  • STM32 PWM基本知识及配置过程

    万次阅读 多人点赞 2018-11-02 20:37:16
    STM32——PWM基本知识及配置过程 将通用定时器分为四个部分: 1,选择时钟 2,时基电路 3,输入捕获 4,输出比较 本节定时器PWM输出主要涉及到定时器框图右下方部分,即输出比较部分 和上一讲相同,时基时钟来源...
  • PWM模块:边沿对齐PWM和中心对齐PWM

    千次阅读 2019-08-17 10:31:09
    PWM模块:边沿对齐PWM和中心对齐PWMPWM 时基工作在自由运行模式时,模块产生边沿对齐的PWM 信号。给定PWM 通道的输出1. 边沿对齐模式 信号的周期由装入PTPER 的值指定, 其占空比由相应的PDCx 寄存器指定...
  • PWM frequency

    2021-01-07 21:46:34
    Stm32f103 Pwm(Pulse width modulation) signal generation using internal timers, keil MDK-ARMv6 and Stmcubemx Ide PWM INPUT using Input Capture in STM32 setting the frequency of a PWM on a STM32 STM...
  • 一、 PWM输出原理 二、STM32 PWM工作过程 三、定时器PWM功能常用函数 四、PWM输出配置步骤
  • PWM DAC

    2020-06-14 16:19:13
    PWM DAC硬件## PWM DAC 1、PWM DAC原理 PWM本质上其实就是是一种周期一定,而高低电平占空比可调的方波。 其中:T是单片机中计数脉冲的基本周期,也就是STM32定时器的计数频率的倒数。N是PWM波一个周期的计数脉冲个...
  • PWM1与PWM2

    千次阅读 2018-11-17 19:39:54
    好了,言归正传,最近总看到很多朋友对于PWM这个实验有很多的疑惑,看到原子也在极力的回复也挺累的(体谅一下幸苦的原子大神,(*^__^*) ),所以我打算写这么一篇文字来阐述一下我个人对STM32的PWM的理解。...
  • PWM简介

    2020-10-23 22:47:33
    PWM简介概念PWM信号图频率和占空比 概念 PWM 全称是 Pulse WidthModulation,也就是脉冲宽度调制。 PWM信号图 频率和占空比 PWM 信号有两个关键的术语:频率和占空比。 频率:就是开关速度,把一次开关算作一个周期...
  • PWM 简介

    2020-10-10 17:23:19
    PWM 简介1、概念2、PWM信号图3、频率4、占空比 1、概念 PWM 全称是 Pulse WidthModulation,也就是脉冲宽度调制 2、PWM信号图 3、频率 频率就是开关速度,把一次开关算作一个周期,那么频率就是 1 秒内进行了多少次...
  • 80C52输出PWM 80C52输出PWM 80C52输出PWM
  • PWM实验

    千次阅读 2018-10-11 22:18:01
    1.PWM简介 脉冲宽度调制(PWM),是利用微处理器的数字输出来对模拟电路 进行控制的 一种非常有效的技术,即就是对脉冲宽度的控制。 STM32的定时器除了TIM6和7,其他的定时器都可以用来产生PWM输出。其中高级...
  • 在上面一章,我们介绍了pwm子系统的框架以及数据结构等内容,而pwm 子系统中pwm_chip的注册与注销接口也就是实现pwm_chip与pwm_device之间的关联,并将pwm_chip放入系统pwm_chip链表中,而这些接口实现也较简单,就...
  • PWM整流器及其控制

    2020-10-06 22:45:35
    PWM整流器及其控制PWM整流器及其控制PWM整流器及其控制PWM整流器及其控制PWM整流器及其控制PWM整流器及其控制PWM整流器及其控制PWM整流器及其控制PWM整流器及其控制PWM整流器及其控制
  • PWM算法

    千次阅读 2018-05-17 10:13:45
    PWM用于直流斩波,可以用于直流电升压或降压,常见的PWM用于降压。PWM利用占空比来调节单位时间内能量输出的密度,在宏观上体现为输出电压与输入电压不同。 狭义上的PWM只有一种算法,通过线性函数与常量的比较来...
  • Linux PWM接口

    千次阅读 2018-12-23 22:36:23
    脉冲宽度调制(PWM)接口1.识别PWM2.使用PWM3.将PWM与sysfs接口配合使用4.实现PWM驱动程序5.锁6.求助 0.脉冲宽度调制(PWM)接口 这提供了有关Linux PWM接口的概述 PWM通常用于控制手机中的LED,风扇或振动器。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 24,698
精华内容 9,879
关键字:

PWM