【STC8A8K64D4开发板】第3-10讲:SG90舵机驱动

第3-10讲:SG90舵机驱动

    1. 学习目的
  1. 了解SG90舵机的相关参数、控制方式。
  2. 编程用PWM驱动SG90舵机,通过按键改变舵机旋转角度。
    1. 舵机简介
      1. 规格参数

“舵机”这个名号其实是一个俗称,是那些玩航模、船模的人起的名字,因为这种电机常被用于舵面控制。舵机是一种位置(角度)伺服的驱动器,适用于那些需要角度不断变化并可以保持的闭环控制执行模块。

舵机是一个闭环控制系统。控制电路板接收来自信号线的控制信号,控制电机转动,电机带动一系列齿轮组,减速后传动至输出舵盘。舵机的输出轴与位置反馈电位计相连,舵盘转动的同时带动位置反馈电位计,电位计将输出一个电压信号到控制电路板进行反馈,然后控制电路板根据所在位置决定电机转动的方向和速度,从而达到目标停止。

我们学习舵机时,通常以经典款模拟舵机SG90入门,SG90是一种微型舵机,具有便宜、小巧的特点,常用于小型模型、玩具或智能小车等。

SG90舵机规格参数如下图所示。

图1:SG90规格参数

      1. 接口信号

图2:SG90舵机接口信号

      1. 驱动方式

SG90舵机通常使用PWM驱动:用单片机的定时器或者PWM外设生成一个周期为20ms的PWM波,按照下图的占空比即可驱动舵机旋转到相应的角度。

图3:SG90舵机旋转角度和脉冲宽度关系

  • 注意事项:驱动舵机时,不同的占空比(高电平持续时间)是驱动舵机旋转到对应的角度,而不是旋转对应的角度。如2.5%的占空比(高电平持续时间0.5ms),舵机会旋转到0度,之后,一直保持该占空比输出,舵机是不会继续旋转的。
    1. 软件设计
      1. SG90舵机驱动实验
  • 注:本节的实验是在“实验2-15-1:PWM输出波形”的基础上修改,本节对应的实验源码是:“实验3-10-1:SG90舵机驱动(按键改变旋转角度)”。
        1. 实验内容

使用STC8A8K64D4单片机的PWM通道6的P1.6引脚输出频率为50Hz(周期20ms)的波形,通过开发板上的按键修改PWM输出波形的占空比,实现控制SG90旋转。

  •  按键KEY1:舵机旋转到45度。
  • 按键KEY2:舵机旋转到90度。
  • 按键KEY3:舵机旋转到135度。
  • 按键KEY4:舵机旋转到180度。
        1. 代码编写
  1. 配置PWM

本例中,通道6,选择P1.6为通道6的输出引脚,频率:50Hz,占空比2.5%(让舵机初始化旋转到0度),代码清单如下。

代码清单:初始化PWM

  1. /********************************************************************************** 
  2. 功能描述:初始化PWM模块。 
  3.         :使用通道6,选择P1.6为通道6的输出引脚,频率:50Hz,占空比2.5% 
  4. 参    数:无 
  5. 返 回 值:无 
  6. ***********************************************************************************/  
  7. void pwm_config(void)  
  8. {  
  9.     PWMSET |= 0x01;              //使能PWM模块,必须先使能后面的配置才能生效  
  10.       
  11.     /*---------------------PWMCFG----------------------------------- 
  12.     位7  位6  位5  位4    位3      位2      位1     位0    
  13.     --   --   --   --   PWMCBIF  EPWMCBI  EPWMTA  PWMCEN 
  14.     x    x    x     x      0        0        0       0 
  15.     PWMCBIF:PWM计数器归零中断标志位,需软件清零 
  16.     PEPWMCBI=0:使能PWM计数器归零中断 
  17.     EPWMTA = 0:PWM与ADC不关联 
  18.     PWMCEN = 0:PWM停止计数 
  19.     ---------------------------------------------------------------*/  
  20.     PWMCFG = 0x00;                 
  21.   
  22.     P_SW2 |= 0x80;               //将EAXFR位置1,允许访问扩展RAM区特殊功能寄存器(XFR)  
  23.     /*---------------------PWMCKS----------------------------------- 
  24.     位7  位6  位5   位4     位3~0    
  25.     --   --   --   SELT2  PWM_PS[3:0] 
  26.     1    0    x     0        1011 
  27.  
  28.     SELT2=0:PWM 时钟源为系统时钟经分频器分频之后的时钟  
  29.     PWM_PS[3:0]=1111:系统时钟的1/16,(24/16)MHz = 1.5MHz 
  30.     ---------------------------------------------------------------*/  
  31.     PWMCKS = 0x0F;        
  32.       
  33.     /*---------------------PWM6CR----------------------------------- 
  34.     位7  位6  位5  位4~3     位2   位1    位0 
  35.     ENO  INI  --  C0_S[1:0]  ENI  ENT2I  ENT1I 
  36.      1    1    x     00       0     0      0 
  37.      
  38.     ENO = 1:PWM的通道6相应PWM端口为 PWM 输出口 
  39.     INI = 0:PWM的通道6初始电平为低电平 
  40.     C0_S[1:0] =01:选择P1.6为PWM通道6输出脚 
  41.     ENI = 0:使能PWM通道6的PWM中断 
  42.     ENT2I = 0:关闭PWM的通道6在第2个触发点中断 
  43.     ENT1I = 0:关闭PWM的通道6在第1个触发点中断 
  44.     ---------------------------------------------------------------*/  
  45.     PWM6CR = 0x88;    
  46.     PWMC   = 29999;            //设置 PWM 周期为 20ms  
  47.     PWM6T1 = 0;                //第1触发点设置为0  
  48.     PWM6T2 = SG90_90D_PWM_VAL; //设置第2触发点,让舵机旋转到0度
  49.     P_SW2 &= 0x7F;             //将EAXFR位置0,禁止访问XFR  
  50.     PWMCFG |= 0x01;            //将PWMCEN位置1,使能PWM波形发生器,PWM计数器开始计数  
  1. 修改PWM占空比

为了方便控制舵机旋转角度,我们编写一个根据角度修改PWM占空比的函数以便于应用程序调用。首先,定义出舵机旋转角度对应的PWM第2触发点的值,如下所示。

代码清单:定义舵机旋转角度对应的PWM第2触发点的值

  1. #define  SG90_0D_PWM_VAL      29250  //旋转到0度时PWM第2触发点的值  
  2. #define  SG90_45D_PWM_VAL     28500  //旋转到45度时PWM第2触发点的值  
  3. #define  SG90_90D_PWM_VAL     27750  //旋转到90度时PWM第2触发点的值  
  4. #define  SG90_135D_PWM_VAL    27000  //旋转到135度时PWM第2触发点的值  
  5. #define  SG90_180D_PWM_VAL    26250  //旋转到180度时PWM第2触发点的值  

驱动舵机旋转到某个角度,也就是将PWM占空比修改为角度对应的值,即修改PWM第2触发点的值,代码清单如下。

代码清单:驱动舵机旋转到指定的角度

  1. /********************************************************************************** 
  2. 功能描述:驱动舵机旋转到指定的角度。 
  3. 参    数:angle[in]:角度的编号 
  4. 返 回 值:无 
  5. ***********************************************************************************/  
  6. void set_angle(u8 angle)  
  7. {  
  8.     P_SW2 |= 0x80;               //将EAXFR位置1,允许访问扩展RAM区特殊功能寄存器(XFR)  
  9.     switch (angle)  
  10.     {  
  11.        case SG90_0_DEGREE:  
  12.           PWM6T2=SG90_0D_PWM_VAL;  //第2触发点设置为29250,对应占空比为2.5%,即高电平持续时间0.5ms
  13.           break;  
  14.           
  15.        case SG90_45_DEGREE:  
  16.           PWM6T2=SG90_45D_PWM_VAL; //第2触发点设置为28500,对应占空比为2.5%,即高电平持续时间0.5ms
  17.           break;  
  18.           
  19.        case SG90_90_DEGREE:  
  20.           PWM6T2=SG90_90D_PWM_VAL; //第2触发点设置为27750,对应占空比为2.5%,即高电平持续时间0.5ms
  21.           break;  
  22.           
  23.        case SG90_135_DEGREE:  
  24.           PWM6T2=SG90_135D_PWM_VAL;//第2触发点设置为27000,对应占空比为2.5%,即高电平持续时间0.5ms
  25.           break;  
  26.           
  27.        case SG90_180_DEGREE:  
  28.           PWM6T2=SG90_180D_PWM_VAL;//第2触发点设置为26250,对应占空比为2.5%,即高电平持续时间0.5ms
  29.           break;  
  30.     }  
  31.     P_SW2 &= 0x7F;           //将EAXFR位置0,禁止访问XFR  
  32. }  
  1. 主函数

主函数中完成相关的初始化,之后,在主循环中扫描按键状态,根据扫描到的键值驱动舵机旋转到对应的角度,代码清单如下。

代码清单:主函数

  1. /********************************************************************************** 
  2. 功能描述:主函数 
  3. 参    数:无 
  4. 返 回 值:int类型 
  5. ***********************************************************************************/  
  6. int main(void)  
  7. {  
  8.     u8  button_num;  
  9.       
  10.     P2M1 &= 0xBF;   P2M0 &= 0xBF;     //设置P2.6为准双向口(指示灯D1)  
  11.     P1M1 &= 0xBF;   P1M0 |= 0x40;     //设置P1.6为推挽  
  12.     P3M1 &= 0x3F;   P3M0 &= 0x3F;     //设置P3.6~P3.7为准双向口(按键KEY2和KEY1)  
  13.     P0M1 &= 0x5F;   P0M0 &= 0x5F;     //设置P0.5,P0.7为准双向口(按键KEY4和KEY3)  
  14.   
  15.     pwm_config();                     //初始化PWM  
  16.     while(1)  
  17.     {  
  18.         button_num = buttons_scan(0);          //获取开发板用户按键检测值,不支持连按  
  19.         if(button_num == BUTTON1_PRESSED)      //按键KEY1按下  
  20.         {   
  21.             set_angle(SG90_45_DEGREE);         //舵机旋转到45度  
  22.         }  
  23.         else if(button_num == BUTTON2_PRESSED) //按键KEY2按下  
  24.         {  
  25.             set_angle(SG90_90_DEGREE);         //舵机旋转到90度  
  26.         }  
  27.         else if(button_num == BUTTON3_PRESSED) //按键KEY3按下  
  28.         {  
  29.             set_angle(SG90_135_DEGREE);        //舵机旋转到135度  
  30.         }  
  31.         else if(button_num == BUTTON4_PRESSED) //按键KEY4按下  
  32.         {  
  33.             set_angle(SG90_180_DEGREE);        //舵机旋转到180度  
  34.         }  
  35.         delay_ms(100);             
  36.     }  
  37. }  
        1. 硬件连接

如下图所示,将SG90舵机安装到开发板上。

图4:硬件连接

        1. 实验步骤
  1. 解压“…\第3部分:配套例程源码”目录下的压缩文件“实验3-10-1:SG90舵机驱动(按键改变旋转角度)”,将解压后得到的文件夹拷贝到合适的目录,如“D\STC8”(这样做的目的是为了防止中文路径或者工程存放的路径过深导致打开工程出现问题)。
  2. 双击“…\sg90_pwm\project”目录下的工程文件“sg90_pwm.uvproj”。
  3. 点击编译按钮编译工程,编译成功后生成的HEX文件“sg90_pwm.hex”位于工程的“…\sg90_pwm\Project\Object”目录下。
  4. 打开STC-ISP软件下载程序,下载使用内部IRC时钟,IRC频率选择:24MHz。
  5. 程序运行后,分别按下KEY1~ KEY4,可以观察到:
  • 按下按键KEY1:舵机旋转到45度。
  • 按下按键KEY2:舵机旋转到90度。
  • 按下按键KEY3:舵机旋转到135度。
  • 按下按键KEY4:舵机旋转到180度。

好的,以下是STC8A8K64D4单片机与JDY-31蓝牙模块进行通信的基本代码: ```c #include <STC8.H> #include <intrins.h> #define FOSC 24000000L //系统时钟频率 #define BAUD 9600 //串口波特率 #define MD0 P3_0 //定义STC8A8K64D4 P3.0引脚作为蓝牙模块的模式选择引脚 bit busy; //串口忙标志位 unsigned char RcvBuff; //串口接收缓冲区 void InitUART() //初始化串口 { SCON = 0x50; //8位数据,可变波特率 TMOD &= 0x0F; //清除原来的定时器设置 TMOD |= 0x20; //设定定时器1为8位自动重装方式 TH1 = TL1 = -(FOSC/12/32/BAUD);//设定波特率 TR1 = 1; //启动定时器1 ES = 1; //串口中断允许 EA = 1; //总中断允许 } void UART_SendByte(unsigned char dat) //串口发送一个字符 { while(busy); //等待前面的数据发送完成 busy = 1; SBUF = dat; //写数据到UART数据寄存器 } void main() { InitUART(); //初始化串口 while(1) { MD0 = 0; //将P3.0引脚置为低电平,使蓝牙模块进入AT指令模式 UART_SendByte('A'); //向蓝牙模块发送AT指令 MD0 = 1; //将P3.0引脚置为高电平,使蓝牙模块退出AT指令模式 } } void UART_Isr() interrupt 4 using 1 //串口中断服务程序 { if(RI) { RI = 0; RcvBuff = SBUF; } if(TI) { TI = 0; busy = 0; } } ``` 以上代码实现了串口初始化、发送一个字符的函数以及主函数中对蓝牙模块的AT指令操作。其中,P3.0引脚作为蓝牙模块的模式选择引脚,当该引脚为低电平时,蓝牙模块进入AT指令模式;当该引脚为高电平时,蓝牙模块退出AT指令模式。此外,还需要注意将STC8A8K64D4单片机的串口接口连接到JDY-31蓝牙模块的TX和RX引脚上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

电子友人张

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值