Merge branch 'develop',rebase to next generation

This commit is contained in:
NeoZng 2022-12-30 23:49:22 +08:00
commit 08440ce116
5 changed files with 373 additions and 1 deletions

View File

@ -40,6 +40,7 @@ C_SOURCES = \
HAL_N_Middlewares/Src/main.c \ HAL_N_Middlewares/Src/main.c \
HAL_N_Middlewares/Src/gpio.c \ HAL_N_Middlewares/Src/gpio.c \
HAL_N_Middlewares/Src/i2c.c \ HAL_N_Middlewares/Src/i2c.c \
HAL_N_Middlewares/Src/i2c.c \
HAL_N_Middlewares/Src/adc.c \ HAL_N_Middlewares/Src/adc.c \
HAL_N_Middlewares/Src/can.c \ HAL_N_Middlewares/Src/can.c \
HAL_N_Middlewares/Src/dma.c \ HAL_N_Middlewares/Src/dma.c \
@ -67,6 +68,8 @@ HAL_N_Middlewares/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c
HAL_N_Middlewares/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c \ HAL_N_Middlewares/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c \
HAL_N_Middlewares/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c \ HAL_N_Middlewares/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c \
HAL_N_Middlewares/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c \ HAL_N_Middlewares/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c \
HAL_N_Middlewares/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c \
HAL_N_Middlewares/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c \
HAL_N_Middlewares/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c \ HAL_N_Middlewares/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c \
HAL_N_Middlewares/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c \ HAL_N_Middlewares/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c \
HAL_N_Middlewares/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c \ HAL_N_Middlewares/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c \

View File

@ -9,6 +9,9 @@ ADC1.master=1
CAD.formats= CAD.formats=
CAD.pinconfig= CAD.pinconfig=
CAD.provider= CAD.provider=
CAD.formats=
CAD.pinconfig=
CAD.provider=
CAN1.BS1=CAN_BS1_10TQ CAN1.BS1=CAN_BS1_10TQ
CAN1.BS2=CAN_BS2_3TQ CAN1.BS2=CAN_BS2_3TQ
CAN1.CalculateBaudRate=1000000 CAN1.CalculateBaudRate=1000000
@ -21,6 +24,19 @@ CAN2.CalculateBaudRate=1000000
CAN2.CalculateTimeQuantum=71.42857142857143 CAN2.CalculateTimeQuantum=71.42857142857143
CAN2.IPParameters=CalculateTimeQuantum,BS1,BS2,Prescaler,CalculateBaudRate CAN2.IPParameters=CalculateTimeQuantum,BS1,BS2,Prescaler,CalculateBaudRate
CAN2.Prescaler=3 CAN2.Prescaler=3
Dma.MEMTOMEM.5.Direction=DMA_MEMORY_TO_MEMORY
Dma.MEMTOMEM.5.FIFOMode=DMA_FIFOMODE_ENABLE
Dma.MEMTOMEM.5.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL
Dma.MEMTOMEM.5.Instance=DMA2_Stream3
Dma.MEMTOMEM.5.MemBurst=DMA_MBURST_SINGLE
Dma.MEMTOMEM.5.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.MEMTOMEM.5.MemInc=DMA_MINC_ENABLE
Dma.MEMTOMEM.5.Mode=DMA_NORMAL
Dma.MEMTOMEM.5.PeriphBurst=DMA_PBURST_SINGLE
Dma.MEMTOMEM.5.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.MEMTOMEM.5.PeriphInc=DMA_PINC_ENABLE
Dma.MEMTOMEM.5.Priority=DMA_PRIORITY_HIGH
Dma.MEMTOMEM.5.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,FIFOThreshold,MemBurst,PeriphBurst
Dma.ADC1.12.Direction=DMA_PERIPH_TO_MEMORY Dma.ADC1.12.Direction=DMA_PERIPH_TO_MEMORY
Dma.ADC1.12.FIFOMode=DMA_FIFOMODE_DISABLE Dma.ADC1.12.FIFOMode=DMA_FIFOMODE_DISABLE
Dma.ADC1.12.Instance=DMA2_Stream4 Dma.ADC1.12.Instance=DMA2_Stream4
@ -84,6 +100,11 @@ Dma.SPI1_RX.4.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL
Dma.SPI1_RX.4.Instance=DMA2_Stream0 Dma.SPI1_RX.4.Instance=DMA2_Stream0
Dma.SPI1_RX.4.MemBurst=DMA_MBURST_SINGLE Dma.SPI1_RX.4.MemBurst=DMA_MBURST_SINGLE
Dma.SPI1_RX.4.MemDataAlignment=DMA_MDATAALIGN_BYTE Dma.SPI1_RX.4.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.Request5=MEMTOMEM
Dma.Request6=SPI1_RX
Dma.Request7=SPI1_TX
Dma.Request8=SPI2_RX
Dma.Request9=SPI2_TX
Dma.SPI1_RX.4.MemInc=DMA_MINC_ENABLE Dma.SPI1_RX.4.MemInc=DMA_MINC_ENABLE
Dma.SPI1_RX.4.Mode=DMA_NORMAL Dma.SPI1_RX.4.Mode=DMA_NORMAL
Dma.SPI1_RX.4.PeriphBurst=DMA_PBURST_SINGLE Dma.SPI1_RX.4.PeriphBurst=DMA_PBURST_SINGLE
@ -93,8 +114,60 @@ Dma.SPI1_RX.4.Priority=DMA_PRIORITY_LOW
Dma.SPI1_RX.4.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,FIFOThreshold,MemBurst,PeriphBurst Dma.SPI1_RX.4.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,FIFOThreshold,MemBurst,PeriphBurst
Dma.SPI1_TX.5.Direction=DMA_MEMORY_TO_PERIPH Dma.SPI1_TX.5.Direction=DMA_MEMORY_TO_PERIPH
Dma.SPI1_TX.5.FIFOMode=DMA_FIFOMODE_ENABLE Dma.SPI1_TX.5.FIFOMode=DMA_FIFOMODE_ENABLE
Dma.SPI1_TX.5.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL Dma.SPI1_TX.5.FIFOThreshold=10
Dma.SPI1_RX.6.Direction=DMA_PERIPH_TO_MEMORY
Dma.SPI1_RX.6.FIFOMode=DMA_FIFOMODE_ENABLE
Dma.SPI1_RX.6.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL
Dma.SPI1_RX.6.Instance=DMA2_Stream0
Dma.SPI1_RX.6.MemBurst=DMA_MBURST_SINGLE
Dma.SPI1_RX.6.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.SPI1_RX.6.MemInc=DMA_MINC_ENABLE
Dma.SPI1_RX.6.Mode=DMA_NORMAL
Dma.SPI1_RX.6.PeriphBurst=DMA_PBURST_SINGLE
Dma.SPI1_RX.6.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.SPI1_RX.6.PeriphInc=DMA_PINC_DISABLE
Dma.SPI1_RX.6.Priority=DMA_PRIORITY_LOW
Dma.SPI1_RX.6.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,FIFOThreshold,MemBurst,PeriphBurst
Dma.SPI1_TX.7.Direction=DMA_MEMORY_TO_PERIPH
Dma.SPI1_TX.7.FIFOMode=DMA_FIFOMODE_ENABLE
Dma.SPI1_TX.7.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL
Dma.SPI1_TX.7.Instance=DMA2_StreamDMA_FIFO_THRESHOLD_FULL
Dma.SPI1_TX.5.Instance=DMA2_Stream3 Dma.SPI1_TX.5.Instance=DMA2_Stream3
Dma.SPI1_TX.7.MemBurst=DMA_MBURST_SINGLE
Dma.SPI1_TX.7.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.SPI1_TX.7.MemInc=DMA_MINC_ENABLE
Dma.SPI1_TX.7.Mode=DMA_NORMAL
Dma.SPI1_TX.7.PeriphBurst=DMA_PBURST_SINGLE
Dma.SPI1_TX.7.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.SPI1_TX.7.PeriphInc=DMA_PINC_DISABLE
Dma.SPI1_TX.7.Priority=DMA_PRIORITY_LOW
Dma.SPI1_TX.7.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,FIFOThreshold,MemBurst,PeriphBurst
Dma.SPI2_RX.8.Direction=DMA_PERIPH_TO_MEMORY
Dma.SPI2_RX.8.FIFOMode=DMA_FIFOMODE_ENABLE
Dma.SPI2_RX.8.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL
Dma.SPI2_RX.8.Instance=DMA1_Stream3
Dma.SPI2_RX.8.MemBurst=DMA_MBURST_SINGLE
Dma.SPI2_RX.8.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.SPI2_RX.8.MemInc=DMA_MINC_ENABLE
Dma.SPI2_RX.8.Mode=DMA_NORMAL
Dma.SPI2_RX.8.PeriphBurst=DMA_PBURST_SINGLE
Dma.SPI2_RX.8.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.SPI2_RX.8.PeriphInc=DMA_PINC_DISABLE
Dma.SPI2_RX.8.Priority=DMA_PRIORITY_LOW
Dma.SPI2_RX.8.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,FIFOThreshold,MemBurst,PeriphBurst
Dma.SPI2_TX.9.Direction=DMA_MEMORY_TO_PERIPH
Dma.SPI2_TX.9.FIFOMode=DMA_FIFOMODE_ENABLE
Dma.SPI2_TX.9.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL
Dma.SPI2_TX.9.Instance=DMA1_Stream4
Dma.SPI2_TX.9.MemBurst=DMA_MBURST_SINGLE
Dma.SPI2_TX.9.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.SPI2_TX.9.MemInc=DMA_MINC_ENABLE
Dma.SPI2_TX.9.Mode=DMA_NORMAL
Dma.SPI2_TX.9.PeriphBurst=DMA_PBURST_SINGLE
Dma.SPI2_TX.9.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.SPI2_TX.9.PeriphInc=DMA_PINC_DISABLE
Dma.SPI2_TX.9.Priority=DMA_PRIORITY_LOW
Dma.SPI2_TX.9.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,FIFOThreshold,MemBurst,PeriphBurst
Dma.SPI1_TX.5.MemBurst=DMA_MBURST_SINGLE Dma.SPI1_TX.5.MemBurst=DMA_MBURST_SINGLE
Dma.SPI1_TX.5.MemDataAlignment=DMA_MDATAALIGN_BYTE Dma.SPI1_TX.5.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.SPI1_TX.5.MemInc=DMA_MINC_ENABLE Dma.SPI1_TX.5.MemInc=DMA_MINC_ENABLE
@ -192,6 +265,10 @@ I2C2.I2C_Mode=I2C_Fast
I2C2.IPParameters=I2C_Mode I2C2.IPParameters=I2C_Mode
I2C3.I2C_Mode=I2C_Fast I2C3.I2C_Mode=I2C_Fast
I2C3.IPParameters=I2C_Mode I2C3.IPParameters=I2C_Mode
I2C2.I2C_Mode=I2C_Fast
I2C2.IPParameters=I2C_Mode
I2C3.I2C_Mode=I2C_Fast
I2C3.IPParameters=I2C_Mode
KeepUserPlacement=false KeepUserPlacement=false
Mcu.CPN=STM32F407IGH6 Mcu.CPN=STM32F407IGH6
Mcu.Family=STM32F4 Mcu.Family=STM32F4
@ -236,6 +313,8 @@ Mcu.Pin16=PD1
Mcu.Pin17=PA11 Mcu.Pin17=PA11
Mcu.Pin18=PF0 Mcu.Pin18=PF0
Mcu.Pin19=PA9 Mcu.Pin19=PA9
Mcu.Pin18=PF0
Mcu.Pin19=PA9
Mcu.Pin2=PG14 Mcu.Pin2=PG14
Mcu.Pin20=PC9 Mcu.Pin20=PC9
Mcu.Pin21=PA8 Mcu.Pin21=PA8
@ -247,6 +326,16 @@ Mcu.Pin26=PG6
Mcu.Pin27=PH12 Mcu.Pin27=PH12
Mcu.Pin28=PG3 Mcu.Pin28=PG3
Mcu.Pin29=PH11 Mcu.Pin29=PH11
Mcu.Pin20=PC9
Mcu.Pin21=PA8
Mcu.Pin22=PH0-OSC_IN
Mcu.Pin23=PH1-OSC_OUT
Mcu.Pin24=PF1
Mcu.Pin25=PC6
Mcu.Pin26=PG6
Mcu.Pin27=PH12
Mcu.Pin28=PG3
Mcu.Pin29=PH11
Mcu.Pin3=PB4 Mcu.Pin3=PB4
Mcu.Pin30=PH10 Mcu.Pin30=PH10
Mcu.Pin31=PD14 Mcu.Pin31=PD14
@ -323,6 +412,8 @@ NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:false\:false
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.SPI1_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true NVIC.SPI1_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
NVIC.SPI2_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true NVIC.SPI2_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
NVIC.SPI1_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
NVIC.SPI2_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false\:false NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false\:false
NVIC.SavedPendsvIrqHandlerGenerated=true NVIC.SavedPendsvIrqHandlerGenerated=true
NVIC.SavedSvcallIrqHandlerGenerated=true NVIC.SavedSvcallIrqHandlerGenerated=true

View File

@ -0,0 +1,122 @@
#include "servo_motor.h"
extern TIM_HandleTypeDef htim1;
/*第二版*/
static ServoInstance *servo_motor[SERVO_MOTOR_CNT] = {NULL};
static int16_t compare_value[SERVO_MOTOR_CNT]={0};
static uint8_t servo_idx = 0; // register servo_idx,是该文件的全局舵机索引,在注册时使用
// 通过此函数注册一个舵机
ServoInstance *ServoInit(Servo_Init_Config_s *Servo_Init_Config)
{
servo_motor[servo_idx] = (ServoInstance *)malloc(sizeof(ServoInstance));
memset(servo_motor[servo_idx], 0, sizeof(ServoInstance));
servo_motor[servo_idx]->Servo_type = Servo_Init_Config->Servo_type;
servo_motor[servo_idx]->htim = Servo_Init_Config->htim;
servo_motor[servo_idx]->Channel = Servo_Init_Config->Channel;
HAL_TIM_Base_Start(Servo_Init_Config->htim);
HAL_TIM_PWM_Start(Servo_Init_Config->htim, Servo_Init_Config->Channel);
return servo_motor[servo_idx++];
}
/**
* @brief
*
* @param Servo_Motor
* @param S_angle
*/
void Servo_Motor_FreeAngle_Set(ServoInstance *Servo_Motor, int16_t S_angle)
{
switch (Servo_Motor->Servo_type)
{
case Servo180:
if (S_angle > 180)
S_angle = 180;
break;
case Servo270:
if (S_angle > 270)
S_angle = 270;
break;
case Servo360:
if (S_angle > 100)
S_angle = 100;
break;
default:
break;
}
if (S_angle < 0)
S_angle = 0;
Servo_Motor->Servo_Angle.free_angle = S_angle;
}
/**
* @brief
*
* @param Servo_Motor
* @param Start_angle
* @param Final_angle
*/
void Servo_Motor_StartSTOP_Angle_Set(ServoInstance *Servo_Motor, int16_t Start_angle, int16_t Final_angle)
{
Servo_Motor->Servo_Angle.Init_angle = Start_angle;
Servo_Motor->Servo_Angle.Final_angle = Final_angle;
}
/**
* @brief
*
* @param Servo_Motor
* @param mode
*/
void Servo_Motor_Type_Select(ServoInstance *Servo_Motor,int16_t mode)
{
Servo_Motor->Servo_Angle_Type = mode;
}
/**
* @brief
*
*/
void Servo_Motor_Control()
{
static ServoInstance *Servo_Motor;
static Servo_Type_e Servo_type;
for (size_t i = 0; i < servo_idx; i++)
{
if (servo_motor[i])
{
Servo_Motor = servo_motor[i];
Servo_type = Servo_Motor->Servo_type;
switch (Servo_type)
{
case Servo180:
if (Servo_Motor->Servo_type == Start_mode)
compare_value[i] = 0.5 * 20000 / 20 + Servo_Motor->Servo_Angle.Init_angle * 20000 / 20 / 90;
if (Servo_Motor->Servo_type == Final_mode)
compare_value[i] = 0.5 * 20000 / 20 + Servo_Motor->Servo_Angle.Final_angle * 20000 / 20 / 90;
if (Servo_Motor->Servo_type == Free_Angle_mode)
compare_value[i] = 0.5 * 20000 / 20 + Servo_Motor->Servo_Angle.free_angle * 20000 / 20 / 90;
__HAL_TIM_SET_COMPARE(Servo_Motor->htim, Servo_Motor->Channel, compare_value[i]);
break;
case Servo270:
if (Servo_Motor->Servo_type == Start_mode)
compare_value[i] = 0.5 * 20000 / 20 + Servo_Motor->Servo_Angle.Init_angle * 20000 / 20 / 135;
if (Servo_Motor->Servo_type == Final_mode)
compare_value[i] = 0.5 * 20000 / 20 + Servo_Motor->Servo_Angle.Final_angle * 20000 / 20 / 135;
if (Servo_Motor->Servo_type == Free_Angle_mode)
compare_value[i] = 0.5 * 20000 / 20 + Servo_Motor->Servo_Angle.free_angle * 20000 / 20 / 135;
__HAL_TIM_SET_COMPARE(Servo_Motor->htim, Servo_Motor->Channel, compare_value[i]);
break;
case Servo360:
/*500-2500的占空比 500-1500对应正向转速 1500-2500对于反向转速*/
compare_value[i] = 500 + 20 * Servo_Motor->Servo_Angle.servo360speed;
__HAL_TIM_SET_COMPARE(Servo_Motor->htim, Servo_Motor->Channel, compare_value[i]);
break;
default:
break;
}
}
}
}

View File

@ -0,0 +1,90 @@
/**
* @file servo_motor.h
* @author panrui
* @brief
* @version 0.1
* @date 2022-12-12
*
* @copyright Copyright (c) 2022
*
*/
#ifndef SERVO_MOTOR_H
#define SERVO_MOTOR_H
#include "main.h"
#include "tim.h"
#include <stdint-gcc.h>
#define SERVO_MOTOR_CNT 7
/*各种舵机类型*/
typedef enum
{
Servo180 = 0,
Servo270 = 1,
Servo360 = 2,
} Servo_Type_e;
/*舵机模式选择*/
typedef enum
{
Free_Angle_mode, // 任意角度模式
Start_mode, // 起始角度模式
Final_mode, // 终止角度模式
} Servo_Angle_Type_e;
/*角度设置*/
typedef struct
{
/*起止角度模式设置值*/
int16_t Init_angle;
int16_t Final_angle;
/*任意角度模式设置值*/
int16_t free_angle;
/*下述值仅仅适用于360°舵机
*0-100
*0-50
*51-100
*/
int16_t servo360speed;
} Servo_Angle_s;
/* 用于初始化不同舵机的结构体,各类舵机通用 */
typedef struct
{
Servo_Type_e Servo_type;
Servo_Angle_Type_e Servo_Angle_Type;
// 使用的定时器类型及通道
TIM_HandleTypeDef *htim;
/*Channel值设定
*TIM_CHANNEL_1
*TIM_CHANNEL_2
*TIM_CHANNEL_3
*TIM_CHANNEL_4
*TIM_CHANNEL_ALL
*/
uint32_t Channel;
} Servo_Init_Config_s;
typedef struct
{
Servo_Angle_Type_e Servo_Angle_Type;
Servo_Angle_s Servo_Angle;
Servo_Type_e Servo_type;
// 使用的定时器类型及通道
TIM_HandleTypeDef *htim;
/*Channel值设定
*TIM_CHANNEL_1
*TIM_CHANNEL_2
*TIM_CHANNEL_3
*TIM_CHANNEL_4
*TIM_CHANNEL_ALL
*/
uint32_t Channel;
} ServoInstance;
ServoInstance *ServoInit(Servo_Init_Config_s *Servo_Init_Config);
void Servo_Motor_FreeAngle_Set(ServoInstance *Servo_Motor, int16_t S_angle);
void Servo_Motor_Type_Select(ServoInstance *Servo_Motor,int16_t mode);
void Servo_Motor_Control();
#endif // SERVO_MOTOR_H

View File

@ -0,0 +1,66 @@
##舵机的使用
<p align='left' >panrui@hnu.edu.cn</p>
### 舵机基础知识
已最常见的SG90舵机为例SG90舵机要求工作在频率为50HZ——周期为20ms的PWM波且对应信号的高低电平在0.5ms - 2.5ms之间对应的舵机转动角度如下表所示当然也可以按照这个线性的对应关系去达到转动自己想要的角度如想要转动60°则高电平脉宽为大概为1.2ms,具体能不能转到特定的角度还和舵机的精度有关)
>0.5ms-------------0度 2.5%
>1.0ms------------45度 5.0%
>1.5ms------------90度 7.5%
>2.0ms-----------135度 10.0%
>2.5ms-----------180度 12.5%
根据`<font color=black size=3>Tout = (PSC+1)* (ARR+1)/Tclk</font>`公式
则我们需要产生50Hz的PWM波则预分频的系数为 Prescaler = 168-1自动重装载值 Counter Period = 20000-1此时定时器产生的频率为 168Mhz/168/20000 = 50Hz。 当然这个值也可以自己设置只要满足产生的频率为50Hz即可.
`__HAL_TIM_SET_COMPARE(htim, Channel, compare_value);`
这是设置占空比的函数
eg当初始占空比为1200/20000则为6%根据20*6%=1.2ms 1.2-0.5/(2.5-0.5)*180=63° 故舵机会转动63°
为了方便通过上述eg我们将所需要的角度与PWM计数值对应关系封装成函数。需要在初始化的時候输入我们所需要的角度和相关定时器参数即可。这样我们就可以设置SG90为参数范围内(0~180°)任意度数。
---
## 如何注册一个舵机实例
!!!
**注意由于舵机为开环控制无论选择舵机为何种类型舵机都能够正常运行但是运行的角度可能会与设定不同请务必正确选择舵机型号且最多添加7个舵机**
我们可以像这样注册一个舵机实例
```c
static ServoInstance *leftservomoto;
//初始化参数
Servo_Init_Config_s config={
//舵机安装选择的定时器及通道
//C板有常用的7路PWM输出:TIM1-1,2,3,4 TIM8-1,2,3
.htim=&htim1,
.Channel=TIM_CHANNEL_1,
//舵机的初始化模式和类型
.Servo_Angle_Type=Start_mode,
.Servo_type=Servo180,
};
// 设置好参数后进行初始化并保留返回的指针
leftservomoto = ServoInit(&config);
```
>要控制一个舵机 我们提供了以下三个接口
```c
//自由模式下,写入自由角度数值
void Servo_Motor_FreeAngle_Set(ServoInstance *Servo_Motor, int16_t S_angle);
//起止模式下,写入起始,终止角度数值(防止反复写入起始和终止角度)
void Servo_Motor_StartSTOP_Angle_Set(ServoInstance *Servo_Motor, int16_t Start_angle, int16_t Final_angle);
/*
Free_Angle_mode, // 任意角度模式
Start_mode, // 起始角度模式
Final_mode, // 终止角度模式
*/
void Servo_Motor_Type_Select(ServoInstance *Servo_Motor,int16_t mode);
//比如我们要使用舵机,并更改一个舵机的模式
void ServoTask()
{
//更改leftservomoto为Free_Angle_mode模式
Servo_Motor_Type_Select(leftservomoto,Free_Angle_mode);
//设置转到0角度
Servo_Motor_FreeAngle_Set(leftservomoto, 0);
//调用函数,控制电机
Servo_Motor_Control();
}
```