MC9S12XS128单片机,PWM模块速览

来源:互联网 发布:java udp编程 编辑:程序博客网 时间:2024/06/18 18:54

工作机理,在左对齐输出模式时,8位通道计数器PWMCENTx只做加法计数;当PWMCNTx计数器加法计数到通道占空比寄存器PWMDTYx中设置的数值时,PWM通道输出波形改变;当PWMCENTx加法计数到通道周期计数器PWMDTYx寄存器中设置的数值时,PWMCENTx清零,输出波形再次发生变化。<



一般地,在实际使用中,较常使用到的是,PWMPER(通道周期寄存器)和PWMDTY(通道占空比寄存器)。<
~ PWME是PWM的使能寄存器,用于控制,某一口是否输出波形,一般地,在初始化时,都需要将其关闭,1开 0闭;

~ PWMPOL是极性寄存器,用于确定一开始输出的波形是高开还是低走,其中,如果PPOLx位为1,周期脉冲输出高电平,反之,输出低电平,这里会在之后的PWMCNT中产生影响。

~ PWMCLK是时钟选择寄存器,用于选择,PWM的时钟源,CLOCK A和CLOCKB有总线时钟分频得到,其中,SA由clocka分频得到,SB同样,

~ PWMPRCLK预分频时钟选择寄存器, PWMPRCLK 寄存器包括ClockA预分频和ClockB预分频的控制位。ClockA、ClockB的值为总线时钟的1/2n
(0≤n≤7),PCKB0~PCKB2 是对ClockB进行预分频。 PCKA0~PCKA2 是对ClockA进行预分频。

~ PWM分频寄存器PWMSCLA、PWMSCLB ,lock SA 是通过对 PWMSCLA 寄存器的设置来对ClockA 进行分频而产生的。其计算公式为:
Clock SA=Clock A /(2*PWMSCLA)
PWMSCLB 寄存器与PWMSCLA 寄存器相似,Clock SB 就是通过对PWMSCLB 寄存器的设置来对 ClockB 进行分频而产生的。其计算公式为:
Clock SB=Clock B /(2*PWMSCLB)
~ PWMCAE居中对齐使能器,1表示居中对齐,0表示左对齐,控制PWM波以中心对齐输出或左对齐输出。

左对齐输出,8位通道计数器PWMCENTx只做加法计数;当PWMCNTx计数器加法计数到通道占空比寄存器PWMDTYx中设置的数值时,PWM通道输出波形改变;当PWMCENTx加法计数到通道周期计数器PWMDTYx寄存器中设置的数值时,PWMCENTx清零,输出波形再次发生变化,然后读取PWMDTYx寄存器和PWMPERx寄存器中的数值作为下一次PWMCNTx加法计数参考使用。(并不知道具体是如何使用的过程)。

左对齐输出PWM


居中输出,当使用居中对齐方式进行输出的时,8位计数器PWMCNTx既做加法计数器也能做减法计数器;当PWMCNTx加法计数器加法到PWMDTYx寄存器中设置的数值时,PWM波形发生变化;当PWMCNTx计数器开始减法计数到PWMPERx寄存器中的数值的时,PWMCNTx会从加法计数器变为减法计数器;当PWMCNTx计数器开始减法计数到PWMDTYx寄存器中的数值时,PWM通道输出波形在此发生变化;当PWMCNTx计数器中数值减到0时,PWMCNTx重新变为加法计数器,然后读取PWMDTYx寄存器和PWMPERx寄存器中的数值作为下一次PWMCNTx计数参考使用。<
PWM居中对齐波形

~ PWMCTL PWM控制寄存器,用于PWM模块的各种控制,包括4个级联(CON67、CON45、CON23、CON01),将一个8位通道变成16位,用于提升PWM的精度

PWMCTL_CON67=1 — 通道6、7 级联成一个16位的PWM通道。此时只有7 通道的控制字起作用,原通道7的使能位、PWM输出极性选择位、时钟选择控制位以及对齐方式选择位用来设置级联后的PWM输出特性<

PWMCTL_CON67=0 — 通道6,7 通道不级联

CON45、CON23、CON01的用法同CON67相似。设置此控制字的意义在于扩大了PWM 对外输出脉冲的频率范围。

PSWAI=1— MCU 一旦处于等待状态,就会停止时钟的输入。这样就不会因时钟在空操作而费电;当它置为0,则MCU就是处于等待状态,也允许时钟的输入。

PFRZ=1— MCU 一旦处于冻结状态,就会停止计数器工作。<

~ PWMSCLA 比例因子A寄存器 ,是可编程的分频寄存器,用于将ClockA分频,产生ClockSA。计算公式:

ClockSA=Clock/(2PWMSCLA)

(PWMSCLA默认值为256)

~ PWMSCLB 比例因子B寄存器,与PWMSCLB作用相同,计算公式:

ClockSB=Clock/(2PWMSCLB)

(PWMSCLB默认值为256)

~ PWMCNT PWM通道计数器,,在不同模式中有不同的技术方法,实际上PWM模块的工作原理就是基于计数器的加减法计数。

一般地,比如在左对齐模式中,当PWMCNT中的计数值达到,PWMDTYx中设置的数值,则输出的PWM波形就会发生反转,之后的,从PWMDTYx到PWMPER之间的就一直维持相反的,电平信号,PWMDTYx之前的,与,这一段所构成的周期里就产生了一个矩形波,这个矩形波中的,两段波所占的比例就构成了占空比。<

~ PWMPER 通道周期寄存器,用于确定一段矩形波的波长,同时,也确定了,在占空比参数中所能给到的最大占空比。

~ PWMDTY 通道占空比寄存器,用于控制PWM波形,设置占空比,其数值含义,根据PPOLx不同而不同,有占空比计算公式如下:

PPOLx = 0时,(周期脉冲首先输出低电平)

=1(PWMPERxPWMDTYx)/PWMPERx100

PPOLx = 1时,(周期脉冲首先输出高电平)

=(PWMPERxPWMDTYx)/PWMPERx100
<

~ PWMSDN 关闭寄存器,在紧急情况下立即关闭PWM通道输出。

例程:

PWM对LED进行控制

#include <hidef.h>      /* common defines and macros */#include "derivative.h"      /* derivative-specific definitions *//**  PWME是PWM的使能寄存器,用于控制,某一口是否输出波形,一般地,在初始化时,都需要将其关闭,1开 0闭*  PWMPOL是极性寄存器,用于确定一开始输出的波形是高开还是低走,其中,如果PPOLx位为1,周期脉冲输出高电平,*  反之,输出低电平,这里会在之后的PWMCNT中产生影响。*  ******/void PWM_Init(void){  PWME = 0x00;        //禁止PWM模块  PWMPRCLK = 0x06;    //CLOCKA的预分频设置6  PWMSCLA = 125;      //SA的分频因子设置125  PWMCLK = 0x01;      //通道0选择SA作为PWM时钟  PWMPER0 = 200;      //通道0周期寄存器设置200  PWMDTY0 = 0;        //通道0占空比设置  PWMPOL = 0X01;      //PWM输出先位高电平,后为低电平,急性选择寄存器  PWMCAE = 0X00;      //左对齐输出  PWMCTL = 0X00;      //不联级  PWME = 0X01;        //使能PWM通道0}//延时函数void delay(unsigned int delay_time) {  unsigned int loop_i,loop_j;  for(loop_i=0;loop_i<delay_time;loop_i++) {    for(loop_j=0;loop_j<5000;loop_j++) {      ;    }  }}void main(void) {  /* put your own code here */  unsigned char loop_index;  PWM_Init();  while(1) {    for(loop_index=0;loop_index<200;loop_index++) {      PWMDTY0=loop_index;   //设置占空比,在这里作用是,使小灯亮的时间越来越久      delay(5000);    }    for(loop_index = 200;loop_index>0;loop_index--) {      PWMDTY0 = loop_index;  //设置占空比,在这里作用是,使小灯亮的时间越来越短      delay(5000);    }  }}

PWM控制直流电机

#include <hidef.h>      /* common defines and macros */#include "derivative.h"      /* derivative-specific definitions */#define BUS_FREQ 32000000#define PWM_PRCLK 0x32#define CH_A_FREQ 8000000#define CH_B_FREQ 8000000#define CH_SA_FREQ 1000000#define CH_SB_FREQ 1000000#define CH_SA_DIV (CH_A_FREQ / (CH_SA_FREQ * 2))#define CH_SB_DIV (CH_B_FREQ / (CH_SB_FREQ * 2))#define STEER_FREQ 100#define MOTOR_FREQ 5000void Pwm_init(void) {  PWMPRCLK = PWM_PRCLK;  PWMSCLA = CH_SA_DIV;  PWMSCLB = CH_SB_DIV;  PWMCTL_CON45 = 1;  PWMCTL_CON67 = 1;  PWMCTL_CON23 = 1;  PWMCLK_PCLK5 = 1;  PWMCLK_PCLK3 = 1;  PWMCLK_PCLK7 = 1;  PWMPER45 = (CH_SA_FREQ / STEER_FREQ);  PWMPER23 = (CH_SB_FREQ / MOTOR_FREQ);  PWMPER67 = (CH_SB_FREQ / MOTOR_FREQ);  PWMPOL_PPOL5 = 1;  PWMPOL_PPOL3 = 0;  PWMPOL_PPOL7 = 0;  PWMCAE = 0X00;  PWME_PWME5 = 1;}void Motor_forward (unsigned int duty) {  PWME_PWME7 = 1;  PWME_PWME3 = 0;  DDRP_DDRP3 = 0;  PWMDTY67 = duty;}void Motor_back (unsigned int duty) {  PWME_PWME3 = 1;  PWME_PWME7 = 0;  DDRP_DDRP7 = 0;  PWMDTY23 = duty;}void Motor_brake (void) {  PWME_PWME3 = 0;  PWME_PWME7 = 0;  DDRP_DDRP3 = 1;  DDRP_DDRP7 = 1;  PTP_PTP3 = 0;  PTP_PTP7 = 0;}void main(void) {  /* put your own code here */    EnableInterrupts;}
0 0
原创粉丝点击