单片机舵机实验

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

测试结果:

相关推荐
hsjiasb8 小时前
FreeRTOS学习(二十六)——动态内存管理heap_1到heap_5
stm32·单片机·学习·学习笔记·freertos
周洲083012 小时前
STM32 GPIO 外部中断深度解析:边沿触发 / 电平触发、NVIC 优先级配置、中断嵌套实战
stm32·单片机·嵌入式硬件
LCG元13 小时前
STM32F103 CAN 总线通信实战:标准库双机通信与过滤器配置精讲
stm32·单片机·嵌入式硬件
zlinear数据采集卡13 小时前
D223的PWM电机控制:6路独立脉冲+加减速算法深度解析
arm开发·stm32·嵌入式硬件·算法·fpga开发·架构
Kuakewei88814 小时前
平芯微42V热拔插OVP过压保护芯片:PW1600
嵌入式硬件
ACP广源盛1392462567314 小时前
WAIC2026 国产超节点算力浪潮下@ACP#IX9104 在算力矩阵中的定位与落地场景
大数据·数据库·人工智能·嵌入式硬件·线性代数·矩阵
z203483152014 小时前
STM32单片机控制无源蜂鸣器播放《晴天》
stm32·单片机·嵌入式硬件
国科安芯16 小时前
详解ADC 规则组外部触发:CH2、CH3 与 TRGO2
运维·网络·单片机·嵌入式硬件·mcu·系统架构
ACP广源盛1392462567316 小时前
WAIC2026 国产算力浪潮@ACP#YLB3118 在算力矩阵中的存储定位与落地场景
大数据·人工智能·分布式·单片机·嵌入式硬件
ACP广源盛1392462567316 小时前
WAIC2026 国产算力浪潮下@ACP#IX8024 在算力矩阵中的定位与落地场景
大数据·数据库·人工智能·嵌入式硬件·线性代数·矩阵