单片机舵机实验

单片机 :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;
}

测试结果:

相关推荐
移远通信2 小时前
显示器-调试
单片机·嵌入式硬件·计算机外设
Szime10 小时前
全球首创10位40GSPS超宽带ADC选型参考:国产超高速ADC深智微科技选型支持
科技·单片机·嵌入式硬件·fpga开发
(Morgan)11 小时前
51单片机期末复习知识点总结
stm32·单片机·嵌入式硬件
榴莲llll13 小时前
应用于计时器/微波炉等产品的高亮LED数显驱动VK16K33C 数码管屏显驱动芯片
单片机
华一精品Adreamer14 小时前
T606 vs 骁龙662/RK3566:主流安卓+4G定制平板芯片横向测评指南
单片机
Zyed14 小时前
[STM32]Day9-Part1USART+串口接收+串口收发
stm32·单片机·嵌入式硬件
小慧102416 小时前
手动建立工程模板
stm32·单片机
嵌入式ZYXC16 小时前
STM32烧录一次后无法再次烧录的两种原因
stm32·单片机·嵌入式硬件
踏着七彩祥云的小丑18 小时前
嵌入式测试学习第33 天:压力测试、反复开关机、反复插拔接口测试
单片机·嵌入式硬件·学习