stm32中pwm的占空比

stm32中pwm的占空比,第1张

首先,确定TIMx的时钟,除非APB1的时钟分频数设置为1,否则通用定时器TIMx的时钟是APB1时钟的2倍,这时的TIMx时钟为72MHz,用这个TIMx时钟72MHz除以(PSC+1),得到定时器每隔多少秒涨一次,这里给PSC赋7199,计算得定时器每隔00001秒涨一次,即此时频率为10KHz,再把这个值乘以(ARR+1)得出PWM频率。

假如ARR值为0,即00001(0+1),则输出PWM频率为10KHz,再假如输出频率为100Hz的PWM,则将ARR寄存器设置为99即可。如果想调整PWM占空比精度,则只需降低PSC寄存器的值即可。

如果你的预装载值TIM_TimeBaseStructureTIM_Period设为100TIM_SetCompare2(20),就是20%占空比了。

我写的一个 多路PWM模拟   很简单的 希望对有用

#include<reg52h>

unsigned char count;

sbit pwm1=P0^0;

sbit pwm2=P0^1;

sbit pwm3=P0^2;

unsigned char jd1,jd2,m1,m2;

unsigned int   x,y,z,xx,yy,zz;

void delay1(unsigned int ms);

//延时程序

void delay(unsigned int x)

{

   unsigned char i,j;

   for(i=x;i>0;i--)

      for(j=125;j>0;j--);

 

}

//定时01ms,

void Timer0_Init()

{

TMOD |=0x01;

//IE=0x82;

EA=1;            //总中断打开

  ET0=1;           //定时器中断打开

  TR0=1;           //定时器开关打开

TH0=0xff;//10uS

TL0=0xf6;//

TR0=1;

}

void Timer0_Int() interrupt 1//中断程序

{

   TH0=0xff;   //10uS

   TL0=0xf6;

   x++;

   y++;

   z++;

   if(x<3) //30%

   {

pwm1=1;

   }

   else

    pwm1=0;

   if(x>=6    {

    x=0;

   }

   if(y<=2) //20%   

   {

pwm2=1;

   }

   else

    pwm2=0;

   if(y>=10)

   {

y=0;

   }

   if(z<=2) //50%   

   {

pwm3=1;

   }

   else

    pwm3=0;

   if(z>=4)

   {

z=0;

   }

}

哥,占空比的范围是0~1,PWM波还有精度要求的,以下以8为PWM波为例:

8位的PWM波,一个周期有256个时间段,单片机定时器的中断频率为60256=15360 Hz

T=0651ms

以下为伪代码:

ISR_Time();定时器中断服务程序

{ if(i==255)

i=0;

else

i++;

if (i<k) // k=占空比256

PORT=1; //端口输出高电平

else

PORT=0;

定时器计数载入();

}

以标准8051为例(晶振12M),计数脉冲为1us,需计651个脉冲,我们用定时器0,用Keil C编译

#include "reg52h"

unsigned char k=255;//k等于占空比乘以255,可以动态调整

unsigned char i=0;

sbit PORT = P1^0;//P10口输出

void main(void )

{

EA=0;//关总中断

ET0=1; //开定时器中断

TMOD=0x01;//设置定时器为16为定时模式

TH0=0x02; //定时651个周期,0x028B=651

TL0=0x8B;

EA=1;//开中断

TR0=1; //开始定时

while(1);

}

void timer0 (void) interrupt 1 using 0//定时器中断服务程序

{ if(i==255)

i=0;

else

i++;

if (i<k) // k=占空比256

PORT=1; //端口输出高电平

else

PORT=0;

TH0=0x02;

TL0=0x8B;

TR0=1;

}

脉冲输出控制

(JOG控制: 带通道指定)

概述

程序示例

*** 作数

描述

根据参数表的设置,从指定的输出通道(ch0或ch2)输出脉冲。

10

11

ST R 10

F172 (PLSH)

DT 10

K 0

触发器

n

参数表存储区的起始地址 S

指定用于输出脉冲的输出通道Yn(n: K0或K2)

数据寄存器

WX WY WR SV EV DT K H

S N/A N/A N/A N/A N/A A N/A N/A A

n N/A N/A N/A N/A N/A N/A A A N/A

N/A

N/A

*** 作数 索引变址 继电器 定时器/计数器 索引寄存器 常数

I

当相关控制标志为OFF并且执行条件(触发器)变成ON时, 从指定的通道(ch0或者ch2)输出脉冲

在执行条件为ON的状态下持续输出脉冲

CW PLS

CCW SIGN

CW PLS

CCW SIGN

Y3

通道号 输出 输出方式

ch0

ch2

Y0

Y1

Y4

3-443

A: 可以使用

N/A: 不可使用

通过在控制代码中指定加计数或者减计数,可将该指令作为JOG *** 作指令

可以在每个扫描周期内改变脉冲频率, 也可以在不同时间修改目标值 但是在指令执行的过程中, 不能

改变控制代码

如果频率被设置成50kHz或者更高, 应指定占空比为1/4(25%)

数据表设置

(1) 由H常数(16进制)指定控制代码

0: 固定

目标值设置

0: 无目标值模式

1: 到达目标值停止模式

占空比(ON脉冲宽度)

0: 占空比1/2 (50%)

1: 占空比1/4 (25%)

频率范围

0: 15Hz~98kHz

1: 48Hz~100kHz

2: 191Hz~100kHz

动作模式及输出逻辑关系

00: 无计数 CW

01: 无计数 CCW

10: 增计数 CW

12: 增计数 方向输出OFF

13: 增计数 方向输出ON

21: 减计数 CCW

22: 减计数 方向输出OFF

23: 减计数 方向输出ON

(2) 频率范围(Hz) ”K值表示”,

15Hz到98kHz [K1到K9800(单位:Hz)] (最大误差在98kHz时约-09 kHz)

设定”K1”对应15Hz

48Hz到100kHz [K48到K100000(单位: Hz)] (最大误差在100kHz时约-3 kHz)

191Hz到100kHz [K191到K100000(单位: Hz)] (最大误差在100kHz时约-08 kHz)

(3) 目标值(绝对值) (版本20以后)

用于到达目标值停止模式(只使用绝对值)

目标值设置的范围如下表所示 如果指定的数值超出范围, 则实际的输出脉冲数可能

与设定值不同 在无计数模式下, 忽略目标值

控制码H □□□□□□□□

S

S+1

控制代码 (1)

S+2

S+3

频率(Hz) (2)

S+4

S+5

目标值 (3)

S

S+1

控制代码 (1)

S+2

S+3

频率(Hz) (2)

无目标值模式 达到目标值停止模式

增计数

减计数

输出模式 允许指定的目标值。

以上我是在手册查到的,如果需要我可以发给你看看,就非常明白的,望采纳,谢谢!

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

TIM_OCInitTypeDef TIM_OCInitStructure;

//TIM3设置

TIM_DeInit(TIM3);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //clock

//定时器pwm模式

TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); //其它默认值

TIM_TimeBaseStructureTIM_Period = 20000-1; //重载定时器周期,ARPE=1时更新事件时//

TIM_TimeBaseStructureTIM_Prescaler = 0; //定时器时钟分频数,下次更新事件时采用//

TIM_TimeBaseStructureTIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割//

TIM_TimeBaseStructureTIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

TIM_OCStructInit(&TIM_OCInitStructure); //其它默认值

TIM_OCInitStructureTIM_OCMode = TIM_OCMode_PWM1;

TIM_OCInitStructureTIM_OutputState =TIM_OutputState_Enable; //输出禁止

TIM_OCInitStructureTIM_Pulse = 11000; //延时时间

TIM_OC1Init(TIM3, &TIM_OCInitStructure);

//TIM_OC1FastConfig(TIM3, TIM_OCFast_Enable);

//TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable); //通道预装载使能

TIM_Cmd(TIM3, ENABLE);

时钟频率72M,pwm频率=72M/20000=36K

55%=11000/20000

// P2^0和P2^1;接2个按钮,

//P2^0控制频率10HZ到50HZ, 按压改变

//P2^1控制占比10%到90%,按压改变

//假设晶振为12MHz

#include<reg52h>

#define uint unsigned int

#define uchar unsigned char

uint t=0,f=100,w=50;

sbit P10=P1^0; // 输出端

sbit KF=P2^0;  // 改变频率按钮

sbit KW=P2^1;  // 改变占宽按钮

void init()

{

TMOD=0x21;

TH0=(65536-1000)/256;

TL0=(65536-1000)%256;

ET0=1;

TR0=1;

EA=1;

}

void time0() interrupt 1

{

TH0=(65536-1000)/256;

TL0=(65536-1000)%256;

t++;   //t为1ms

if(t>=f) t=0;

}

void main()

{

init();

while(1)

{

if(KF==0) //改变频率

{f=f-10;

if(f<=10)  f=100;

while(KF==0);

w=f/10;

}

if(KW==0) //改变占比

{w=w+f/10;

if(w>=f) w=f/10;

while(KW==0);

}

if(t<w)P10=1;  //单个周期

else P10=0;

}

}

如果看不清,请先“查看大图”,此时另存到你的电脑里,再查看更大的。

后补充:根据你的“问题补充”,需要增加一个AD转换器,常用的并口有ADC0809,串口有ADC0834,单片机扫描AD转换输出的数据,送到上述的频率f和占比w两个变量。就可以改变。幅度改变很简单,用电位器的分压直接输出就可以了。要把整个写出来,需要一定的篇幅,上面给你提供思路,望你自己多动手电脑,得到满意的结果。

第一,你什么电机?第二,步进电机你是几线几向的?你这都没说清楚让人咋写?

其实思想很简单,比如你是用PWM写的,就是控制脉冲占空比。

思想都说了,你要代码?

给你个例子你看看就行了,估计直接用是不可能的,接口不同。

// 左轮驱动

void __leftMotorContr (void)

{

static int8 cStep = 0; / ±£Žæµç»úµ±Ç°Î»Öà /

switch (__GmLeftcDir) {

case __MOTORGOAHEAD: / ÏòÇ°²œœø /

cStep = (cStep + 1) % 8;

break;

case __MOTORGOBACK: / Ïòºó²œœø /

cStep = (cStep + 7) % 8;

break;

default:

break;

}

switch (cStep) {

case 0: / A2B2 /

GPIOPinWrite(GPIO_PORTD_BASE,

__PHLA1 | __PHLA2 | __PHLB1 | __PHLB2,

__PHLA1 | __PHLA2 | __PHLB1 | __PHLB2);

break;

case 1: / B2 /

GPIOPinWrite(GPIO_PORTD_BASE,

__PHLA1 | __PHLA2 | __PHLB1 | __PHLB2,

__PHLB1 | __PHLB2);

break;

case 2: / A1B2 /

GPIOPinWrite(GPIO_PORTD_BASE,

__PHLA1 | __PHLA2 | __PHLB1 | __PHLB2,

__PHLA2 | __PHLB1 | __PHLB2);

break;

case 3: / A1 /

GPIOPinWrite(GPIO_PORTD_BASE,

__PHLA1 | __PHLA2 | __PHLB1 | __PHLB2,

__PHLA2);

break;

case 4: / A1B1 /

GPIOPinWrite(GPIO_PORTD_BASE,

__PHLA1 | __PHLA2 | __PHLB1 | __PHLB2,

__PHLA2 | __PHLB2);

break;

case 5: / B1 /

GPIOPinWrite(GPIO_PORTD_BASE,

__PHLA1 | __PHLA2 | __PHLB1 | __PHLB2,

__PHLB2);

break;

case 6: / A2B1 /

GPIOPinWrite(GPIO_PORTD_BASE,

__PHLA1 | __PHLA2 | __PHLB1 | __PHLB2,

__PHLA1 | __PHLA2 | __PHLB2);

break;

case 7: / A2 /

GPIOPinWrite(GPIO_PORTD_BASE,

__PHLA1 | __PHLA2 | __PHLB1 | __PHLB2,

__PHLA1 | __PHLA2);

break;

default:

break;

}

}

// 右轮驱动同理

首先89C52内部没有硬件PWM发生器,只能通过定时器模拟!你可以通过两个定时器,T0控制周期,T1控制占空比。

例如:实现周期为1000us,占空比为20%的PWM,用P10实现

首先你设置T0为65536-1000 (12M晶振)

T1为65536-200

首先初始化P10=1,两个定时器同时打开,在定时器T1中断时拉低P10,在定时器T0中断时在拉高P10,同时将两定时器初始值初始化T0为65536-1000 ,T1为65536-200

希望对你有用,呵呵!!!

用1个定时器的话也是可以的,但是这就要用一个变量count1 来控制周期和占空比了,比如说你设置1周期为10ms,占空比还是为20%的PWM,你可以设置定时器为每10us产生一次中断,没中断一次使count加1,一开始设置P10为高电平,当count1加到200的时候拉低P10,等count1到1000了在拉高P10,同时复位count1=0,不过这样做的缺点是精度不高,要是PWM所需周期段,精度高的话我还是建议用两个定时器来实现 ,我在这里没有给你具体的代码,我觉得把原理讲清楚猜是最重要的,什么都是才来就上代码,这个对你学习不利,希望对你有用,呵呵!!!!

如果两路同时输出的话只要你设置两个变量,同时进行判断就行了,和一路的原理是一样的。

以上就是关于stm32中pwm的占空比全部的内容,包括:stm32中pwm的占空比、求教单片机PWM发生器,如何实现以下功能:产生2路PWM波,频率10KHz,一路30%占空比,另一路20%占空比、如何让单片机产生 频率为60Hz 占空比在0.5-2.5之间的PWM波等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10643306.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-10
下一篇 2023-05-10

发表评论

登录后才能评论

评论列表(0条)

保存