定时器同时输出好几路pwm,一个定时器不是共用的一个计数器吗?同时输出好几路pwm,它是如何实现的
user3917511:
MSP430系列单片机的TimerA结构复杂,功能强大,当PWM 不需要修改占空比和时间时,TimerA 能自动输出PWM,而不需利用中断维持PWM输出。单片机内部均含有两个定时器,TA和TB;TA有三个模块,CCR0-CCR2;TB含有CCR0-CCR67个模块;其中CCR0模块不能完整的输出PWM波形(只有三种输出模式可用);TA可以输出完整的2路PWM波形;TB可以输出6路完整的PWM波形。
定时器的PWM输出有有8种模式:
输出模式0 输出模式:输出信号OUTx由每个捕获/比较模块的控制寄存器CCTLx中的OUTx位定义,并在写入该寄存器后立即更新。最终位OUTx直通。 输出模式1 置位模式:输出信号在TAR等于CCRx时置位,并保持置位到定时器复位或选择另一种输出模式为止。 输出模式2 PWM翻转/复位模式:输出在TAR的值等于CCRx时翻转,当TAR的值等于CCR0时复位。 输出模式3 PWM置位/复位模式:输出在TAR的值等于CCRx时置位,当TAR的值等于CCR0时复位。 输出模式4 翻转模式:输出电平在TAR的值等于CCRx时翻转,输出周期是定时器周期的2倍。 输出模式5复位模式:输出在TAR的值等于CCRx时复位,并保持低电平直到选择另一种输出模式。 输出模式6PWM翻转/置位模式:输出电平在TAR的值等于CCRx时翻转,当TAR值等于CCR0时置位。 输出模式7PWM复位/置位模式:输出电平在TAR的值等于CCRx时复位,当TAR的值等于CCR0时置位。
1. 计数模式:
增计数模式 捕获/比较寄存器CCR0用作Timer_A增计数模式的周期寄存器,因为CCR0为16位寄存器,所以该模式适用于定时周期小于65 536的连续计数情况。计数器TAR可以增计数到CCR0的值,当计数值与CCR0的值相等(或定时器值大于CCR0的值)时,定时器复位并从0开始重新计数。
连续计数模式 在需要65 536个时钟周期的定时应用场合常用连续计数模式。定时器从当前值计数到0FFFFH后,又从0开始重新计数
增/减计数模式 需要对称波形的情况经常可以使用增/减计数模式,该模式下,定时器先增计数到CCR0的值,然后反向减计数到0。计数周期仍由CCR0定义,它是CCR0计数器数值的2倍。
1. TA定时器有比较、捕获两种工作方式;比较可以产生PWM波形等,捕获可以精确的测量时间;这里用的是比较输出。
硬件介绍就这么多了,其他的可以参考msp430g2553—users_guide(用户指南)。
2. 程序实现:
下面就给大家介绍msp430g2553生成pwm波。并控制舵机的转动,如果只需要生成pwm波的程序可以自行修改,其中主函数前一部分就是生成pwm波的部分。
#include "msp430g2553.h"
#define MCU_CLOCK 1000000
#define PWM_FREQUENCY 44 // 当为44时,频率刚好50hz.
#define SERVO_STEPS 180 // 设置一度步进
#define SERVO_MIN 650 // 最小值0°
#define SERVO_MAX 2700 // 大概转动180°
unsigned int PWM_P =(MCU_CLOCK / PWM_FREQUENCY);// PWM 的频率
void main (void)
{
unsigned int servo_stepval, servo_stepnow;
unsigned int servo_lut[200];
unsigned int i;
// 计算步长值和当前步骤,默认定义为最小
servo_stepval =((SERVO_MAX – SERVO_MIN)/ SERVO_STEPS );
servo_stepnow = SERVO_MIN;
// 赋值LUT
for(i =0;i<200; i++)
{
servo_stepnow += servo_stepval;
servo_lut[i]= servo_stepnow;
}
// 设置PWM波的输出
WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗
TACCTL1 = OUTMOD_7; // TACCR1 复位/设置
TACTL = TASSEL_2 + MC_1; // SMCLK, upmode
TACCR0 = PWM_P; // PWM 频率
TACCR1 = servo_lut[0]; // TACCR1 PWM 占空比设置
P1DIR |= BIT2; // 设置P1.2为普通IO口
P1SEL |= BIT2; // 设置P1.2为TA1输出
//转动角度设置
while(1){
// Go to 0°;+duty 3.0%。
TACCR1 = servo_lut[0];
__delay_cycles(1000000);
// Go to 45°;+duty 4.8%。
TACCR1 = servo_lut[45];
__delay_cycles(1000000);
// Go to 90°; +duty 7.4%.
TACCR1 = servo_lut[90];
__delay_cycles(1000000);
// Go to 135°; +duty 9.8%.
TACCR1 = servo_lut[146];
__delay_cycles(1000000);
// Go to 180°; +duty 12.3%.
TACCR1 = servo_lut[190];
__delay_cycles(1000000);
// Go to 0°;+duty 3.0%。
TACCR1 = servo_lut[0];
__delay_cycles(1000000);
}
}
user4091353:
回复 user3917511:
几时到 servo_lut[0]; 不产生中断吗?怎么没定时器A的中断函数。