STM32输出PWM控制舵机转向

这篇博客详细介绍了如何使用STM32F103微控制器通过TIM3 PWM输出控制SG90舵机进行180°转向。通过部分重映射TIM3通道,设置PWM模式,配置定时器参数,以及延时函数,实现了精确的脉冲宽度控制,以调整舵机的角度。代码中展示了从0.5ms到2.5ms的脉宽变化,模拟了舵机从0°到180°的转动过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最终实现结果:STM32F103发出PWM信号控制舵机SG90进行180°转向

在这里插入图片描述

接线图

在这里插入图片描述

#include "stm32f10x.h"

void delay_us(uint32_t n){
	while(n--){
		SysTick->CTRL = 0;								//Disable SysTick 关闭系统定时器
		SysTick->LOAD = 9;							//Count from 255 to 0 (256 cycles) 配置计数值
		SysTick->VAL = 0;								//CLear current value as well as count flag 清空当前寄存器计数值
		SysTick->CTRL = 1;								//Enable SysTick timer with processor clock 使能系统定时器
		while((SysTick->CTRL & (1<<16)) == 0);			//Wait until count flag is set
	}	
	SysTick->CTRL = 0;									//Disable SysTick 关闭系统定时器
}

void delay_ms(uint32_t n){
	while(n--){
		SysTick->CTRL = 0;								//Disable SysTick 关闭系统定时器
		SysTick->LOAD = 9000;							//Count from 255 to 0 (256 cycles) 配置计数值
		SysTick->VAL = 0;								//CLear current value as well as count flag 清空当前寄存器计数值
		SysTick->CTRL = 1;								//Enable SysTick timer with processor clock 使能系统定时器
		while((SysTick->CTRL & (1<<16)) == 0);			//Wait until count flag is set
	}	
	SysTick->CTRL = 0;									//Disable SysTick 关闭系统定时器
}
/**
* 没有重映射时,TIM3的四个通道CH1, CH2, CH3, CH4分别对应PA6, PA7, PB0, PB1
* 部分重映射时,TIM3的四个通道CH1, CH2, CH3, CH4分别对应PB4, PB5, PB0, PB1
* 完全重映射时,TIM3的四个通道CH1, CH2, CH3, CH4分别对应PC6, PC7, PC8, PC9
* 
* 110:PWM模式1 - 在向上计数时,一旦TIMx_CNT<TIMx_CRRx时,通道x为有效电平,
* 否则为无效电平;在向下计数时,一旦TIMx_CNT>TIMx_CRRx时,通道x为无效电平,
* 否则为有效电平。
*
* 111:PWM模式2 - 在向上计数时,一旦TIMx_CNT<TIMx_CRRx时,通道x为无效电平,
* 否则为有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CRRx时,通道x为有效电平,
* 否则为无效电平。
*/
void TIM3_PWM_Init(uint16_t arr,uint16_t psc,uint16_t time_Pulse){
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	
	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE); //TIM3部分重映射 TIM3_CH2->PB5
	
	TIM_TimeBaseStructure.TIM_Period = arr;	 	 	//设置自动重装载寄存器周期的值 arr=value-1
	TIM_TimeBaseStructure.TIM_Prescaler = psc; 	 	//设置预分频值 psc=value-1
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;	//设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);	//初始化TIMx时间基数
	
	//初始化TIM3 Channel2 PWM模式   
	TIM_OCInitStructure.TIM_Pulse = time_Pulse;						//脉冲值,即输出都是低电平  
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;				//选择定时器模式:TIM脉冲宽度调制模式1
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	//开启关闭脉冲输出
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;		//有效状态为高电平,无效则为低电平
	
	//通道初始化
	TIM_OC2Init(TIM3, &TIM_OCInitStructure);						//根据T指定的参数初始化外设TIM3 OC2
	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);				//通道使能或者失能TIMx在CCR2上的预装载寄存器

	TIM_Cmd(TIM3, ENABLE);											//使能TIMx
}

void GPIO_init_B(void){
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; //配置为复用模式(PWM输出)
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_Init(GPIOB, &GPIO_InitStruct);
}

/**
*  舵机工作需要20ms左右的时基脉冲,脉冲控制角度
*  0.5ms-----------  0度     
*  1.0ms-----------  45度	 
*  1.5ms-----------  90度    
*  2.0ms-----------  135度   
*  2.5ms-----------  180度   
*/

int main(void){
	
	/* 系统时钟初始化 */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);	// 打开功能复用IO时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);	// 使能TIM3的外设时钟
	TIM_CtrlPWMOutputs(TIM3,ENABLE);
	
	GPIO_init_B();
	GPIO_ResetBits(GPIOB, GPIO_Pin_5);
	//计算,假设PWM周期设置为20ms
	//公式为:溢出时间Tout=(arr+1)*(psc+1)/Tclk,Tclk为通用定时器的时钟,如果APB1没有分频,则就为系统时钟,72MHZ
	TIM3_PWM_Init(200 - 1, 7200 - 1, 0);
	
	while(1)
    {
	  TIM_SetCompare2(TIM3, 5); 
	  delay_ms(100);
	  TIM_SetCompare2(TIM3, 10); 
	  delay_ms(100);	
	  TIM_SetCompare2(TIM3, 15); 
	  delay_ms(100);
	  TIM_SetCompare2(TIM3, 20); 
	  delay_ms(100);
	  TIM_SetCompare2(TIM3, 25); 
	  delay_ms(100);
	  TIM_SetCompare2(TIM3, 20); 
	  delay_ms(100);	
	  TIM_SetCompare2(TIM3, 15); 
	  delay_ms(100);
	  TIM_SetCompare2(TIM3, 10); 
	  delay_ms(100);
    }

}

### K210与STM32通讯实现舵机控制 #### 一、K210与STM32的串口通信基础 K210是一款高性能AI芯片,能够完成图像处理任务并将结果通过串口或其他接口传输至外部设备。STM32作为一款广泛使用的微控制器,可以通过配置其USART外设来接收来自K210的数据,并进一步解析这些数据以驱动舵机动作。 在实际应用中,通常采用UART(通用异步收发器)协议进行两者之间的通信[^1]。为了确保双方正常工作,需设置一致的波特率、停止位以及校验方式等参数。例如,在本案例中可以设定9600bps作为默认速率[^2]。 #### 二、数据帧格式设计 对于简单的应用场景来说,定义一种轻量级的数据包结构即可满足需求。这里建议使用如下形式: | 字段名称 | 长度(字节) | 描述 | |----------|------------|------| | 起始标志 | 1 | 表明新消息开始,固定值如'<'字符ASCII码60 | | 数据长度 | 1 | 后续有效载荷总大小 | | 命令ID | 1 | 功能区分符比如转动角度调整对应特定数值X | | 参数列表 | N | 可变数量的具体操作数列 如目标位置角度值Y° | | 结束标志 | 1 | 显示信息结束的标准记号常选为'>'即大于号 | 这种紧凑型布局有助于减少不必要的冗余开销同时保持足够的灵活性适应多种可能的任务要求. #### 三、软件编程实例说明 以下是针对上述理论框架给出的一个具体实现方案: ##### (A). K210端发送逻辑 ```c #include <stdio.h> void send_data(int angle){ char buffer[8]; int length=0; // 构造报文头部 buffer[length++]='<'; buffer[length++]=sizeof(angle)+2; // 计算整个payload size // 添加命令标识符 buffer[length++]='T';// 'T'表示Turn Command // 将角度转换成字符串追加进去 itoa(angle,&buffer[length],10); while(buffer[length]!='\0')length++; // 设置终止符 buffer[length]=’>’ uart_write(UART_PORT_0,(uint8_t *)buffer,length); } ``` ##### (B). STM32端接收与响应机制 ```c #define SERVO_MIN_PULSE_WIDTH ((uint16_t)544) /* Minimum pulse width value */ #define SERVO_MAX_PULSE_WIDTH ((uint16_t)2400) /* Maximum pulse width value */ volatile uint8_t rx_buffer[10]; /* Buffer to store incoming data */ volatile uint8_t index = 0; void USART_IRQHandler(void) { if(RECEIVE_COMPLETE_FLAG_SET()){ rx_buffer[index++]=usart_read_byte(); if(rx_buffer[index-1]=='>'){ parse_command(); /* Once full packet received invoke parser function */ reset_index(); /* Clear counter ready for next message arrival */ } } } void execute_servo_control(uint16_t target_angle){ TIM_OCInitTypeDef sConfigOC ; sConfigOC.OCMode = TIM_OCMODE_PWM1 ; sConfigOC.Pulse = map(target_angle , 0 , 180 ,SERVO_MIN_PULSE_WIDTH,SERVO_MAX_PULSE_WIDTH ); HAL_TIM_PWM_ConfigChannel(&htim3,TIM_CHANNEL_1,&sConfigOC); __HAL_TIM_ENABLE(&htim3); } ``` 以上展示了基本的工作原理和初步代码片段[^1]. 实际项目开发过程中还需要考虑更多细节问题诸如错误检测纠正措施,超时保护策略等等. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值