点击查看代码
/**
******************************************************************************
* @file main.c
* @author
* @version
* @date 2024/06/28
* @brief 实现利用基本定时器TIM3_CH1实现生成20ms的脉冲信号实现控制舵机的角度
信号线 --- PC6(TIM3_CH1)
GND --- GND
VCC --- 5V
******************************************************************************
**/
#include "stm32f4xx.h" //必须包含
//延时微秒 注意:Systick是24bit的递减计数器 约等于798915us,所以参数不可以超过这个值
void delay_us(u32 nus)
{
SysTick->CTRL = 0; // 向控制状态寄存器中写入0,目的关闭系统嘀嗒定时器
SysTick->LOAD = (nus * 21) - 1;// 指的是计数次数,定时时间 = 计数次数 * 计数周期
SysTick->VAL = 0; // 清除当前数值寄存器的值
SysTick->CTRL = 1; // 开启了定时器,并且定时器的时钟源选择了21MHZ--> 计数周期 = 1/21us
while ((SysTick->CTRL & 0x00010000)==0);//等待延时时间到达
SysTick->CTRL = 0; // 向控制状态寄存器中写入0,目的关闭系统嘀嗒定时器
}
//延时毫秒 注意:Systick是24bit的递减计数器 约等于798ms,所以参数不可以超过这个值
void delay_ms(u32 nms)
{
SysTick->CTRL = 0; // 向控制状态寄存器中写入0,目的关闭系统嘀嗒定时器
SysTick->LOAD = (nms * 21*1000) - 1;// 指的是计数次数,定时时间 = 计数次数 * 计数周期
SysTick->VAL = 0; // 清除当前数值寄存器的值
SysTick->CTRL = 1; // 开启了定时器,并且定时器的时钟源选择了21MHZ--> 计数周期 = 1/21us
while ((SysTick->CTRL & 0x00010000)==0);//等待延时时间到达
SysTick->CTRL = 0; // 向控制状态寄存器中写入0,目的关闭系统嘀嗒定时器
}
//舵机SG90的初始化
void SG90_Config()
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
GPIO_InitTypeDef GPIO_InitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
//1.打开TIM3+GPIOC的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM3);
//2.定义结构体变量并对结构体变量的成员进行赋值,必须脉冲周期是20ms
TIM_TimeBaseStructure.TIM_Prescaler = 8400-1; //预分频值,TIM3的时钟是84MHZ,所以可以降低频率 100us计数一次
TIM_TimeBaseStructure.TIM_Period = 200-1; //计数次数,这个值会写入自动重载寄存器 100us * 200 = 20ms
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数模式,定时器TIM3递增计数
//3.对定时器进行初始化
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //PWM模式1 CNT < CCR 通道是有效的
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 5; //20ms中高电平持续0.5ms,舵机角度为0度
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性为高电平,就是通道有效时的电平状态
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM3, ENABLE);
//6.打开定时器TIM3
TIM_Cmd(TIM3, ENABLE);
}
int main()
{
//1.硬件的初始化
SG90_Config();
//打算让舵机角度慢慢从0度变为180度
while(1)
{
//TIM_SetCompare1(TIM3,10);
TIM3->CCR1 = 10; // 高电平持续1.0ms ,对应的是45度
delay_ms(100);
TIM3->CCR1 = 15; // 高电平持续1.5ms ,对应的是90度
delay_ms(100);
TIM3->CCR1 = 20; // 高电平持续2.0ms ,对应的是135度
delay_ms(100);
TIM3->CCR1 = 25; // 高电平持续2.5ms ,对应的是180度
delay_ms(100);
TIM3->CCR1 = 20; // 高电平持续2.0ms ,对应的是135度
delay_ms(100);
TIM3->CCR1 = 15; // 高电平持续1.5ms ,对应的是90度
delay_ms(100);
TIM3->CCR1 = 10; // 高电平持续1.0ms ,对应的是45度
delay_ms(100);
TIM3->CCR1 = 5; // 高电平持续0.5ms ,对应的是0度
delay_ms(100);
}
}