基于stm32的平衡小车直立,转动,调速过程


编码器用于电机测速。在电机转动一圈时编码器可以输出固定的脉冲数,通过读取编码器
脉冲可以获取当前电机转动状态。
一般处理编码器脉冲有两种方法:
1. T法:计算一定量的脉冲数所用的时间
2. M法:计算一段固定时间内所捕获的脉冲数。
3.转速计算方法:用捕获值(一秒内输出的脉冲数)/编码器线数(转速一圈输出脉冲数)/电机减数比(内部电机转动圈数与电机输出轴转动圈数比,即减速齿轮比)
实现直流电机转动
    直流电机包含减速器、编码器,
        通过调节施加在电机上面的直流电压大小可以 调速, 调节施加在电机上面的直流电压极性可以换向
利用pwm可以实现电机的转动,驱动:TB6612FNG,电机与驱动相应引脚相连,设置对应输出IO口即可实现
        
,基于STM32利用串口实时显示电机转速
  • 电机转动与速度的改变需要pwm,pwm占空比越大,电机转速越快;(可参考一)
  • 需要计算电机的转速;
  • 串口显示转速;
  • 具体分析:需要两个定时器,一个实现pwm的占空比调节来控制电机转速,一个在计数器模式下通过记脉冲的个数来计算转速(即M法测速)
    M法测速:电机每转一圈,传感器输出的脉冲数一定,随着电动机转速和输出脉冲频率的不同,频率与转速成正比,能测量其频率,通过软件计算就能得到速度。
利用串口显示pwm占空比

(全局变量在其定义后所有函数都能用,但是静态局部变量只能在一个函数里面用。

1、 全局变量的作用用这个程序块,而局部变量作用于当前函数
2、前者在内存中分配在全局数据区,后者分配在栈区
3、 生命周期不同:全局变量随主程序创建和创建,随主程序销毁而销毁,局部变量在局部函数内部,甚至局部循环体等内部存在,退出就不存在
4、 使用方式不同:通过声明后全局变量程序的各个部分都可以用到,局部变量只能在局部使用
操作系统和编译器通过内存分配的位置来知道的全局变量分配在全局数据段,并且在程序被运行的时候就被加载。)
程序如下:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "pwm.h"


//ALIENTEK 探索者STM32F407开发板 实验9
//PWM输出实验-库函数版本
//技术支持:www.openedv.com
//淘宝店铺:http://eboard.taobao.com  
//广州市星翼电子科技有限公司  
//作者:正点原子 @ALIENTEK
	float m=0;
float zkb()
{
	m=((float)TIM14->CCR1/499)*100;
	return m;
}

int main(void)
{ 
	u16 led0pwmval=0;    
	u8 dir=1;
//		float m=0;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	uart_init(115200);//初始化串口波特率为115200
 	TIM14_PWM_Init(500-1,84-1);	//84M/84=1Mhz的计数频率,重装载值500,所以PWM频率为 1M/500=2Khz.       

	while(1) //实现比较值从0-300递增,到300后从300-0递减,循环
	{
		
//		GPIO_SetBits(GPIOA,GPIO_Pin_0);
//		GPIO_SetBits(GPIOA,GPIO_Pin_1);
//		GPIO_ResetBits(GPIOA,GPIO_Pin_2);
		
 		delay_ms(10);	
zkb();		
		if(dir)led0pwmval++;//dir==1 led0pwmval递增
		else led0pwmval--;	//dir==0 led0pwmval递减 
 		if(led0pwmval>300)dir=0;//led0pwmval到达300后,方向为递减
		if(led0pwmval==0)dir=1;	//led0pwmval递减到0后,方向改为递增
 	/*       8    不断改变比较值CCRX,达到不同的占空比效果   */
		TIM_SetCompare1(TIM14,led0pwmval);	//修改比较值,修改占空比
		printf("\r\n 占空比为:%.3f %%\r\n",m);
	}
}

2、 两个电机转起来
利用TIM14输出两路pwm波,复用PF9和PA7作为PWM输出引脚,PF10/PF11为PWMA的输入IO口,PF3/PF4为PWB的输出IO口。(我的血泪史,搞了几天电机都转不起来,就是因为我随便设置的IO口,没有考虑到32板子是和51板子不一样的,IO口不能随便用,要去查一下芯片手册 )
led .c程序
void LED_Init(void)
{    	 
  GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能GPIOF时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
  //GPIOF9,F10初始化设置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10|GPIO_Pin_3 |GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化
	
	  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
	
	GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10| GPIO_Pin_4);//GPIOF9,F10设置高,灯灭
	GPIO_ResetBits(GPIOF,GPIO_Pin_3 | GPIO_Pin_11);
}
pwm.c程序:
void TIM14_PWM_Init(u32 arr,u32 psc)
{		 					 
	//此部分需手动修改IO口设置
	
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE);  	//TIM14时钟使能    
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); 	//使能PORTF时钟	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
	
	GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); //GPIOF9复用为定时器14
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_TIM14);
	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;           //GPIOF9
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
	GPIO_Init(GPIOF,&GPIO_InitStructure);              //初始化PF9
	  
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;           //GPIOF9
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
	GPIO_Init(GPIOA,&GPIO_InitStructure); 
		
	TIM_TimeBaseStructure.TIM_Prescaler=psc;  //定时器分频
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseStructure.TIM_Period=arr;   //自动重装载值
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
	
	TIM_TimeBaseInit(TIM14,&TIM_TimeBaseStructure);//初始化定时器14
	
	//初始化TIM14 Channel1 PWM模式	 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
	TIM_OC1Init(TIM14, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1 4OC1

	TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);  //使能TIM14在CCR1上的预装载寄存器
 
  TIM_ARRPreloadConfig(TIM14,ENABLE);//ARPE使能 
	
	TIM_Cmd(TIM14, ENABLE);  //使能TIM14
 	  
}  
主程序:
int main(void)
{ 
	u16 led0pwmval=0;    
	u8 dir=1;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	uart_init(115200);//初始化串口波特率为115200
	LED_Init();
 	TIM14_PWM_Init(500-1,84-1);	//84M/84=1Mhz的计数频率,重装载值500,所以PWM频率为 1M/500=2Khz.     
   while(1) //实现比较值从0-300递增,到300后从300-0递减,循环
	{
 		delay_ms(10);	 
		if(dir)led0pwmval++;//dir==1 led0pwmval递增
		else led0pwmval--;	//dir==0 led0pwmval递减 
 		if(led0pwmval>300)dir=0;//led0pwmval到达300后,方向为递减
		if(led0pwmval==0)dir=1;	//led0pwmval递减到0后,方向改为递增
		TIM_SetCompare1(TIM14,led0pwmval);	//修改比较值,修改占空比
	}
}


3 两个电机转动,利用串口实时改变pwm占空比,改变电机转速



你可能感兴趣的:(基于stm32的平衡小车直立,转动,调速过程)