单片机舵机实验

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

测试结果:

相关推荐
FreakStudio11 天前
W55MH32L-EVB 上手测评:硬件 TCP/IP 加持的以太网单片机,MicroPython 零门槛开发
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
✎ ﹏梦醒͜ღ҉繁华落℘16 天前
单片机基础知识---stm32单片机的优先级
stm32·单片机·mongodb
u1521096484916 天前
S.S.Audio PRO A2音频隔离器
嵌入式硬件·音视频·实时音视频·视频编解码·视频
zd84510150016 天前
RS485 总线详解
单片机·嵌入式硬件
半条-咸鱼16 天前
【STM32】I2C协议原理、HAL读写与OLED显示操作
嵌入式硬件·c·信息与通信
wohoo_wangzi16 天前
苏州晟雅泰电子:关于W25Q128JVSIQ这个芯片物料的参数,规格及应用领域
嵌入式硬件
✎ ﹏梦醒͜ღ҉繁华落℘16 天前
编程基础 --高内聚,低耦合
c语言·单片机
科芯创展16 天前
1A,1MHz,30VIN,XZ4115,降压恒流LED驱动芯片
单片机·嵌入式硬件
集芯微电科技有限公司16 天前
四通道2A输出集成功率电感降压模块专为紧凑型方案设计
人工智能·单片机·嵌入式硬件·生成对抗网络·计算机外设
踏着七彩祥云的小丑16 天前
嵌入式测试学习第 37 天:异常场景测试:断电、拔插、干扰、非法指令
单片机·嵌入式硬件·学习