单片机舵机实验

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

测试结果:

相关推荐
糖糖单片机设计1 小时前
STM32 智能奶茶冲泡系统
stm32·单片机·嵌入式硬件
jianqiang.xue3 小时前
ESP-IDF保姆级入门17|GPIO外部中断全解与工程化设计:分层架构/防抖策略/长按双击/优先级配置,掌握工业级可靠输入处理
stm32·单片机·物联网·架构·esp32
码上上岸8 小时前
基于单片机的老人跌倒监测报警器设计与实现
stm32·嵌入式硬件·物联网·智能硬件·硬件
恒锐丰科技林技术员8 小时前
SS6209 半桥驱动器:小型半桥电源方案的优选器件
经验分享·嵌入式硬件
别催小唐敲代码11 小时前
Pixhawk 6C — Mission Planner 烧录 & 全套校准教程
stm32·单片机·嵌入式硬件
Freak嵌入式13 小时前
Pico UART 数据收发实战:硬件配置、MicroPython 编程
java·开发语言·单片机·嵌入式硬件·生活
Freak嵌入式14 小时前
Pico PIO 汇编语法深度详解:标识符、指令、伪指令全解析
汇编·stm32·单片机·嵌入式硬件·fpga开发·硬件架构
自小吃多15 小时前
PCB Editor软件差分对添加与设置笔记
笔记·嵌入式硬件
逐步前行16 小时前
ESP32-S3-工程管理
单片机
智购科技无人售货机厂家17 小时前
2026自动售货机连接器选型指南:从IP等级到插拔寿命的工程实践~YH
单片机·嵌入式硬件