单片机 :STM32F407
开发板:DMF407电机开发板
平台:keil V5.31
HSE 为8MHZ
HSI为16MHZ
原理图:

按照旋转角度可分为 **180°与360°**的舵机,180 度舵机只能在 0 度到 180 度(±90 度)之
间运动; 360°舵机转动的方式和普通的电机类似,可以连续的转动,不过我们只可以控制
它转动的方向和速度,不能调节转动角度。

主函数
int main(void)
{
uint8_t key,t,id = 1;
char buf[32];
float angle[3] = {0}; /* 初始化角度0° */
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
key_init(); /* 初始化按键 */
lcd_init(); /* 初始化LCD */
atim_timx_pwm_chy_init(20000 - 1, 168 - 1); /* 168 000 000 / 168 = 1000 000 10Khz的计数频率,计数5K次为500ms */
g_point_color = WHITE;
g_back_color = BLACK;
lcd_show_string(10,10,200,16,16,"Servo Test",g_point_color); /* 显示提示信息 */
lcd_show_string(10,30,200,16,16,"KEY0:ID + +",g_point_color);
lcd_show_string(10,50,200,16,16,"KEY1:IAngle + ",g_point_color);
lcd_show_string(10,70,200,16,16,"KEY2:Angle -",g_point_color);
lcd_show_string(10,90,200,16,16,"Servo ID: 1",g_point_color);
printf("KEY0 选择控制的舵机接口\r\n");
printf("KEY1 舵机旋转角度+45°\r\n");
printf("KEY2 舵机旋转角度-45°\r\n");
while (1)
{
if(t % 10 == 1)
{
sprintf(buf,"Servo 1: %.1f",angle[0]);
lcd_show_string(10,110,200,16,16,buf,g_point_color);
sprintf(buf,"Servo 2: %.1f",angle[1]);
lcd_show_string(10,130,200,16,16,buf,g_point_color);
sprintf(buf,"Servo 3: %.1f",angle[2]);
lcd_show_string(10,150,200,16,16,buf,g_point_color);
}
key = key_scan(0);
if(key == KEY0_PRES)
{
id++;
if(id == 4)
{
id = 1;
}
sprintf(buf,"Servo ID: %1d",id); /* 按下KEY0:选择控制哪个舵机,并显示当前ID */
lcd_show_string(10,90,200,16,16,buf,g_point_color);
printf("所选舵机接口为%d\r\n",id);
}
else if(key == KEY1_PRES)
{
angle[id-1] += 45;
if(angle[id-1] > 180)
{
angle[id-1] = 180;
}
servo_angle_set(id,angle[id-1]); /* 控制该ID的舵机,并设置角度值 */
printf("Servo 1: %.1f\r\n",angle[0]);
printf("Servo 2: %.1f\r\n",angle[1]);
printf("Servo 3: %.1f\r\n",angle[2]);
printf("\r\n");
}
else if(key == KEY2_PRES)
{
angle[id-1] -= 45;
if(angle[id-1] < 0)
{
angle[id-1] = 0;
}
servo_angle_set(id,angle[id-1]); /* 控制该ID的舵机,并设置角度值 */
printf("Servo 1: %.1f\r\n",angle[0]);
printf("Servo 2: %.1f\r\n",angle[1]);
printf("Servo 3: %.1f\r\n",angle[2]);
printf("\r\n");
}
t++;
if(t % 20 == 0)
{
LED0_TOGGLE(); /* LED0(红灯) 翻转 */
}
delay_ms(10);
}
}
uint8_t servo_angle_set(uint8_t id,float angle)
{
uint16_t val;
switch(id)
{
case 1:
val = angle_to_tim_val(angle); /* 得到角度转换的比较值 */
if(val != 0)
{
__HAL_TIM_SetCompare(&g_atimx_pwm_chy_handle,TIM_CHANNEL_1,val); /* 设置比较值 */
}
break;
case 2:
val = angle_to_tim_val(angle);
if(val != 0)
{
__HAL_TIM_SetCompare(&g_atimx_pwm_chy_handle,TIM_CHANNEL_2,val);
}
break;
case 3:
val = angle_to_tim_val(angle);
if(val != 0)
{
__HAL_TIM_SetCompare(&g_atimx_pwm_chy_handle,TIM_CHANNEL_3,val);
}
break;
default:
break;
}
return 0;
}
uint16_t angle_to_tim_val(float angle)
{
uint16_t ret;
if((angle < 0)||(angle > 180))
{
ret = 0;
}
else
{
/* 0° -- 500,45° -- 1000,90° -- 1500,135° -- 2000,180° -- 2500 */
ret = 1500 + (int)((float)((angle - 90) * 100 / 9));
if((ret < 500)||(ret > 2500))
{
ret = 0;
}
}
return ret;
}
测试结果:
