1. Timer1的PWM控制舵机
S3C2440的Timer0、Timer1、Timer2和Timer3具有PWM功能,以前的blog已经叙述过,详见:
TQ2440开发板的Timer0的TOUT0输出连接了Beep,所以,这次利用Timer1的TOUT1输出来连接舵机的控制信号。
舵机的内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基准信号,将获得的直流偏置电压与电位器的电压比较,获得电压差输出。通过调整控制信号的高电平宽度,即可实现舵机不同转角的控制。
舵机控制原理详见:舵机的原理和控制
程序思路很简单:
- 设置GPB1为TOUT1的输出格式;
- Timer1初始化,设置周期为20ms;
- 默认情况TOUT1输出的脉宽是低电平,需要将TCON第10位设置为1,即Inverter on for TOUT1
- 主程序检测串口输入,加号则增大脉宽,减号则减小脉宽。
2. Timer1的中断控制舵机
模仿舵机C51测试程序,用Timer1计时,周期0.5ms。在Timer1的中断控制程序中控制PWM的脉宽输出。
查看TQ2440的底板原理图,可知系统总线接口上有GPA0,就利用它作为PWM的输出了。
程序思路:
a.设置Timer1初始化
void Timer1_Init(void)
{
rTCFG0 &= ~(0xff) ; // Prescaler0 determine prescale value for Timer 0 and 1.
rTCFG0 |= 49 ; // Prescaler0 [7:0]
rTCFG1 &= ~(0xf0) ; // TCFG1[7:4] -- Select MUX input for PWM Timer1.
rTCFG1 |= 0x0<<4 ; // MUX1: 0-1/2, 1-1/4, 2-1/8, 3-1/16
// 50M/50/2=500K 500,000 = 1sec
rTCNTB1 = 250 ; // 500K/50 = 10000 ==> 20ms cycles
// 10000/40 <=> 20/0.5 , so 250 is 0.5ms
rTCON |= (1 << 9) ; //manual update for Timer 1.
rTCON = 0x09<<8; //D=1001,clear manual update; auto reload
}
b.设置Timer1中断
extern unsigned char count; //0.5ms次数标识
extern unsigned char jd; //角度标识
void Isr_Init(void)
{
pISR_TIMER1 = (U32)Timer1_Isr ;
}
void __irq Timer1_Isr(void)
{
if(count<jd) //判断0.5ms次数是否小于角度标识
rGPADAT |= 0x01; //确实小于,PWM输出高电平
else
rGPADAT &= (~(0x01)); //大于则输出低电平
count=(count+1); //0.5ms次数加1
count=count%40; //次数始终保持为40 即保持周期为20ms
rSRCPND |= 1 << 11 ;
rINTPND |= 1 << 11 ;
}
void Timer1_Interrupt_Init(void)
{
rINTMSK &= ~(1 << 11) ;
}
c.主程序查询串口按键输入(还有GPA0,Timer1,中断等的初始化)
int Main()
{
unsigned char key;
jd=2;
count=0;
rGPACON &= (~(0x01)); // set GPA0 output
rGPADAT &= (~(0x01)); // GPA0=0
Timer1_Interrupt_Init();
Isr_Init();
Timer1_Init();
Uart0_Init(115200);
Uart_Printf( "\nPWM TEST ( Key Control )\n" );
Uart_Printf( "Press +/- to increase/reduce the frequency of PWM \n" ) ;
Uart_Printf( "Press 'ESC' key to Exi \n\n" );
while(1)
{
key = Uart0_Getc();
if( (key == '=')||(key == '+')) //tq-zql:添加对小键盘的+的支持
{
jd++; //角度标识加1
count=0; //按键按下 则20ms周期从新开始
if(jd==6)
jd=5;
}
if( key == '-' )
{
jd--; //角度标识减1
count=0;
if(jd==0)
jd=1;
}
Uart_Printf( "\tFreq = %d\n", jd ) ;
if( key == ESC_KEY )
{
return 1;
}
}
return 0;
}
上述程序的完整代码:点击打开链接