赞
踩
目录
舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms~2.5ms范围内的角度控制脉冲部分,总间隔为2ms,比如说180度伺服角度,对应的关系如下。
- void main(void)
- {
-
- InitTimer0(); //定时器0初始化
- EA = 1; //开总中断
- while(1) //大循环
- {
- Servo0PwmDuty = 500; //脉冲宽度在500微秒,对应-90°
- DelayMs(1000); //延时1秒
- Servo0PwmDuty = 1000; //脉冲宽度在1000微秒,对应-45°
- DelayMs(1000);
- Servo0PwmDuty = 1500;
- DelayMs(1000);
- Servo0PwmDuty = 2000;
- DelayMs(1000);
- Servo0PwmDuty = 2500;
- DelayMs(1000);
- }
- }
- void main(void)
- {
- uint8 i;
- InitTimer0(); //定时器0初始化
- EA = 1; //开总中断
- while(1) //大循环
- {
- for(i = 0;i<8;i++)
- ServoPwmDuty[i] = 500; //脉冲宽度在500微秒,对应-90°
- DelayMs(1000); //延时1秒
- for(i = 0;i<8;i++)
- ServoPwmDuty[i] = 1000; //脉冲宽度在1000微秒,对应-45°
- DelayMs(1000);
- for(i = 0;i<8;i++)
- ServoPwmDuty[i] = 1500; //脉冲宽度在1500微秒,对应0°
- DelayMs(1000); //延时1秒
- for(i = 0;i<8;i++)
- ServoPwmDuty[i] = 2000; //脉冲宽度在2000微秒,对应45°
- DelayMs(1000);
- for(i = 0;i<8;i++)
- ServoPwmDuty[i] = 2500; //脉冲宽度在2500微秒,对应90°
- DelayMs(1000); //延时1秒
- }
- }
PWM就是脉冲宽度调制,也就是占空比可变的脉冲波形.
pwm的占空比,就是指高电平保持的时间,与该pwm时钟周期时间之比。
在应用中就是通过调节pwm占空比来控制,也就是一个周期中高电平所占的百分比来控制舵机的转角的。
在代码中要特别注意的是时基结构体的TIM_Period(自动重装载寄存器值,简称arr)和TIM_Prescaler(预分频寄存器值,简称psc),因为这两个决定了输出PWM信号的周期。具体的周期计算公式为:周期=(arr+1)*(psc+1)/CLK。其中CLK为计数器的时钟频率,我的是72MHZ,也就是72000000。最后计算结果单位为秒,结果为0.02s,也就是20ms。这样的配置就是为了让输出的PWM信号达到前面说到的舵机要求的20ms周期。
- int main(void)
- {
- int delay_time;
- delay_init(); //延时函数初始化
- TIM_Init(); //定时器初始化
- while(1)
- {
- delay_ms(1000);
- TIM_SetCompare1(TIM1, 175); //对应180度
- delay_ms(1000);
- TIM_SetCompare1(TIM1, 180); //对应135度
- delay_ms(1000);
- TIM_SetCompare1(TIM1, 185); //对应90度
- delay_ms(1000);
- TIM_SetCompare1(TIM1, 190); //对应45度
- delay_ms(1000);
- TIM_SetCompare1(TIM1, 195); //对应0度
- }
- }
stm32驱动程序:
- #include "pca9685.h"
- #include "myiic.h"
- #include "delay.h"
- #include "math.h"
-
- void pca_write(u8 adrr,u8 data)
- {
- IIC_Start();
-
- IIC_Send_Byte(pca_adrr);
- IIC_Wait_Ack();
-
- IIC_Send_Byte(adrr);
- IIC_Wait_Ack();
-
- IIC_Send_Byte(data);
- IIC_Wait_Ack();
-
- IIC_Stop();
- }
-
- u8 pca_read(u8 adrr)
- {
- u8 data;
- IIC_Start();
-
- IIC_Send_Byte(pca_adrr);
- IIC_Wait_Ack();
-
- IIC_Send_Byte(adrr);
- IIC_Wait_Ack();
-
- IIC_Start();
-
- IIC_Send_Byte(pca_adrr|0x01);
- IIC_Wait_Ack();
-
- data=IIC_Read_Byte(0);
- IIC_Stop();
-
- return data;
- }
-
-
- void pca_setfreq(float freq)
- {
- u8 prescale,oldmode,newmode;
- double prescaleval;
- freq *= 0.92;
- prescaleval = 25000000;
- prescaleval /= 4096;
- prescaleval /= freq;
- prescaleval -= 1;
- prescale =floor(prescaleval + 0.5f);
-
- oldmode = pca_read(pca_mode1);
-
- newmode = (oldmode&0x7F) | 0x10; // sleep
-
- pca_write(pca_mode1, newmode); // go to sleep
-
- pca_write(pca_pre, prescale); // set the prescaler
-
- pca_write(pca_mode1, oldmode);
- delay_ms(2);
-
- pca_write(pca_mode1, oldmode | 0xa1);
- }
- void pca_setpwm(u8 num, u32 on, u32 off)
- {
- pca_write(LED0_ON_L+4*num,on);
- pca_write(LED0_ON_H+4*num,on>>8);
- pca_write(LED0_OFF_L+4*num,off);
- pca_write(LED0_OFF_H+4*num,off>>8);
- }
- void Servo_Init(float hz,u8 angle)
- {
- u32 off=0;
- IIC_Init();
- pca_write(pca_mode1,0x0);
- pca_setfreq(hz);
- off=(u32)(145+angle*2.4);
- pca_setpwm(0,0,off);
- pca_setpwm(1,0,off);
- pca_setpwm(2,0,off);
- pca_setpwm(3,0,off);
- pca_setpwm(4,0,off);
- pca_setpwm(5,0,off);
- pca_setpwm(6,0,off);
- pca_setpwm(7,0,off);
- pca_setpwm(8,0,off);
- pca_setpwm(9,0,off);
- pca_setpwm(10,0,off);
- pca_setpwm(11,0,off);
- pca_setpwm(12,0,off);
- pca_setpwm(13,0,off);
- pca_setpwm(14,0,off);
- pca_setpwm(15,0,off);
- delay_ms(500);
- }
- void Servo_angle(u8 num,u8 angle)
- {
- u32 off = 0;
- off = (u32)(158+angle*2.2);
- pca_setpwm(num,0,off);
- }
-
-
stm32主函数:
- int main(void)
- {
- delay_init();//延时函数初始化
- Servo_Init(50,90);//初始化舵机驱动
- delay_ms(1000);
- uart_init(9600);
- Servo_angle(0,90);
- printf("this is a drill");
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。