[Bicicleta de autoequilibrio de rueda Momentum] STM32_PID (código abierto, incluidos datos de hardware)

Bicicleta autoequilibrante Momentum Wheel STM32

¿Cómo hacer una bicicleta autoequilibrada? Los siguientes compartirán el contenido de producción con todos, bienvenidos a discutir e intercambiar~.

contenido

1. Hardware (con el enlace de Taobao, la tienda es incierta, también puede buscar y comprar usted mismo)

1. Sistema mínimo STM32F103C8T6 (tablero azul pequeño)

2. Sensor de actitud MPU6050 (fuente de alimentación de 3,3 V)

3. Pantalla OLED de 0,96 pulgadas (cuatro pines, comunicación IIC, fuente de alimentación de 3,3 V)

4. Módulo Bluetooth HC-05

5. Módulo de alcance ultrasónico

6. Motor y accionamiento N20 (selección de motor: tipo DC 12V A12)

7. Módulo de rueda de impulso de motor sin escobillas

8. servos

9. Batería de avión modelo 3S (preste atención al tamaño de la batería)

10. Módulo regulador de voltaje e interruptor

11. Ruedas y Cojinetes

12. Bastidor y estructura de dirección (impresión 3D)

13. PCB del circuito

2. Artículos de software

1.principal.c

2. Algoritmo de control PID

3. Interrupción TIM2

4. Detección de voltaje de la batería

5. Pantalla OLED

6. Notas sobre la lectura de códigos

3. Enlaces


1. Hardware (con el enlace de Taobao, la tienda es incierta, también puede buscar y comprar usted mismo)

1. Sistema mínimo STM32F103C8T6 (tablero azul pequeño)

marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16

2. Sensor de actitud MPU6050 (fuente de alimentación de 3,3 V)

marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16

3. Pantalla OLED de 0,96 pulgadas (cuatro pines, comunicación IIC, fuente de alimentación de 3,3 V)

marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16

4. Módulo Bluetooth HC-05

(Comunicación en serie, utilizada para recibir comandos de movimiento del carro)

Use el enlace del tutorial: https://blog.csdn.net/weixin_44325419/article/details/110727911

marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16

5. Módulo de alcance ultrasónico

marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16

6. Motor y accionamiento N20 (selección de motor: tipo DC 12V A12)

marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16

7. Módulo de rueda de impulso de motor sin escobillas

El motor tiene su propio accionamiento y codificador fotoeléctrico.

marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16

 En esta bicicleta autoequilibrada, utilizamos un servomotor sin escobillas Mabuchi, un accionamiento integrado, soporte de rotación hacia adelante y hacia atrás, regulación de velocidad PWM y salida de señal de doble canal de fase AB con codificador de 100 líneas.

marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16

El diagrama de cableado del motor se muestra en la figura anterior. El color del cable en el automóvil real puede no coincidir con la figura anterior. Debe juzgarlo según la posición en lugar del color del cable.

1.) La fase A y la fase B de la señal son terminales de salida de pulsos del codificador;

2.) La línea para la conmutación hacia adelante y hacia atrás está controlada directamente por el nivel de 3,3 V del pin de la microcomputadora de un solo chip, y no hay ningún problema;

3.) La fuente de alimentación del codificador está conectada a 3,3 V;

4.) PWM está conectado a la salida PWM de la microcomputadora de un solo chip.Para iniciar la operación, conectamos el puerto IO de la microcomputadora de un solo chip y lo configuramos en un nivel alto cuando se inicializa el motor;

5.) El polo negativo de la fuente de alimentación está conectado a GND y el polo positivo de la fuente de alimentación está conectado a 12V.

8. servos

Los que se usan en el video son un poco caros, puedes comprar unos baratos.

marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16

9. Batería de avión modelo 3S (preste atención al tamaño de la batería)

marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16

marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16

10. Módulo regulador de voltaje e interruptor

Reduzca el voltaje de la batería del modelo de avión a 5 V para suministrar energía al microcontrolador, mecanismo de dirección, Bluetooth, ultrasonido y codificador de motor.

11. Ruedas y Cojinetes

Dado que la rueda trasera del carro es accionada por una correa, para reducir la fricción y hacer que la rueda trasera gire más suavemente, es necesario instalar un cojinete en miniatura en la rueda trasera. (Los rodamientos se compran según el tamaño del eje)

marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16

    Las dimensiones son las siguientes:

12. Bastidor y estructura de dirección (impresión 3D)

Haga clic en el enlace de la estación B al final del artículo para seguir y dejar un mensaje (o correo electrónico) para obtener el archivo del modelo de impresión 3D del marco y la estructura de dirección

marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16

13. PCB del circuito

Los módulos funcionales anteriores están integrados en una placa de circuito impreso (6,5 x 7,8 cm), para facilitar la soldadura, los condensadores, las resistencias y los triodos son todos componentes en línea. El nivel del autor es limitado, el PCB es para su referencia y usted mismo puede ajustar y cambiar las deficiencias.

Haga clic en el enlace de la estación B al final del artículo para seguir y dejar un mensaje (o correo electrónico) para obtener el archivo del proyecto PCB marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16

2. Artículos de software

Haga clic en el enlace de la estación B al final del artículo para seguir y dejar un mensaje (o correo electrónico) para obtener el archivo del código fuente de Keil

1.principal.c

#include "sys.h"

float AdcValue;                                    //电池电压数字量
float Pitch,Roll,Yaw;						      //角度
short aacx,aacy,aacz;		                        //加速度传感器原始数据
short gyrox,gyroy,gyroz;	                        //陀螺仪原始数据
int PWM1;
int PWM_MAX=6500,PWM_MIN=-6500;	//PWM限幅变量
int Encoder_Motor;	//编码器数据(速度)

int main(void)
{  
	NVIC_Config();
   	delay_init();
    Led_Init();
    Beep_Init();
    Wave_SRD_Init();
   	uart3_init(9600);
    OLED_Init();			//初始化OLED  
    OLED_Clear();
	adc_Init();
    MOTOR_1_Init();
    MOTOR_2_Init();
    PWM_Init_TIM3(7199,0);//定时器3初始化PWM 10KHZ,用于驱动动量轮电机 
    PWM_Init_TIM2(9999, 143);//定时器2初始化PWM 50HZ,用于驱动舵机
    TIM_SetCompare1(TIM2, 790);//舵机复位
    Init_TIM1(9998,7199);
    Encoder_Init_TIM4(65535,0);
    OLED_ShowString(25,4,"MPU6050...",16);
    MPU_Init();            //MPU6050初始化  
    while(mpu_dmp_init())
 	{
		OLED_ShowString(25,4,"MPU6050 Error",16);
	}  
    OLED_ShowString(25,4,"MPU6050 OK!",16); 
    Beep=1;
    delay_ms(400);
    Beep=0;
    MPU6050_EXTI_Init();
    OLED_Clear();
 	OLED_ShowString(0,0,"Roll :         C",16);
    OLED_ShowString(0,3,"Speed:         R ",16);
    OLED_ShowString(0,6,"Power:        V ",16);    
    

    while(1)
    {	        
        Wave_SRD_Strat();        
        AdcValue=11.09*(3.3*Get_adc_Average(ADC_Channel_4,10)/0x0fff); //ADC值范围为从0-2^12=4095(111111111111)一般情况下对应电压为0-3.3V
        OLED_Showdecimal(55,0,Roll,9,16);  
        OLED_Showdecimal(55,3,Encoder_Motor*0.25,9,16);         
        OLED_Showdecimal(50,6,AdcValue,9,16);       
	}
}

2. Algoritmo de control PID

Haga clic en el enlace de la estación B al final del artículo para seguir y dejar un mensaje (o correo electrónico) para obtener materiales tutoriales relacionados con PID

El automóvil es más capaz de lograr el equilibrio vertical y necesita usar dos controles de bucle cerrado, a saber, bucle vertical (control PD, retroalimentación negativa), bucle de velocidad (control PI, retroalimentación positiva). El principio del código y el proceso de depuración son básicamente los mismos. como el coche de equilibrio de dos ruedas.

En cuanto al aprendizaje del algoritmo de control PID, hay muchos contenidos, y no es fácil de ampliar en detalle, hay abundantes recursos en línea, y puedes aprender por ti mismo. Aquí hay un artículo recomendado: https://zhuanlan.zhihu.com/p/39573490

3. Interrupción TIM2

Para evitar que el automóvil sea interferido por la función de evitación de obstáculos ultrasónicos durante la operación y la depuración, la función de evitación de obstáculos ultrasónicos se puede apagar primero.La función de evitación de obstáculos ultrasónicos se implementa en la función de servicio de interrupción del temporizador 2, por lo que la interrupción TIM2 habilitar se puede desactivar.

//TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //使能TIM2中断,中断模式为更新中断:TIM_IT_Update
void TIM2_IRQHandler()
{   
    static int count=0;
    if(TIM_GetITStatus(TIM2, TIM_IT_Update)==1) //当发生中断时状态寄存器(TIMx_SR)的bit0会被硬件置1
	{
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //状态寄存器(TIMx_SR)的bit0置0
        count++;      
        if(Distance<8)              //与障碍物距离小于8cm时,蜂鸣器发出警报病后退
        {
            Beep=1,Led1=0,Led2=0;
            Backward();
            TIM_SetCompare1(TIM2, 790);//舵机复位
        }
        else Beep=0;
        if(count==25)        //TIM2溢出时间为20ms,20x25=500ms,即后退500ms后停止
        {
            Stopped();count=0;           
        }            
	}
}

4. Detección de voltaje de la batería

En general, la potencia de la batería del modelo de avión está relacionada con el voltaje. La descarga excesiva conducirá inevitablemente a una descarga excesiva permanente de la batería y al daño de la batería. Por lo tanto, es necesario que controlemos el cambio de voltaje de la batería. para aproximar la potencia de la batería.Cuando la energía de la batería es relativamente baja, recuerde que cargamos, el tiempo de carga no supera las 2 horas y media, para no sobrecargar la batería. Para el almacenamiento a largo plazo, asegúrese de que el voltaje de una sola celda sea de aproximadamente 3,8 V y cárguelo una vez al mes.

Cuando está completamente cargado para 3S, es de 12,6 V y el voltaje es inferior a 9,6 V cuando se descarga en exceso.
Cuando está completamente cargado durante 2S, es de 8,4 V y el voltaje es inferior a 7,4 V cuando se descarga en exceso.

marca de agua, tipo_d3F5LXplbmhlaQ, sombra_50, texto_Q1NETiBAX-aXuuS7lOWwj-iPoOiQnQ==, tamaño_20, color_FFFFFF, t_70, g_se, x_16

Use el ADC incorporado de STM32 para medir el voltaje de la batería. El rango de valor de ADC es de 0-2 ^ 12 = 4095 (111111111111). Generalmente, el voltaje correspondiente es 0-3.3V, mientras que el voltaje de la batería del avión modelo 3S es 12 V. La medición directa quemará el microcontrolador, por lo que es necesario dividir el voltaje de la batería, el diagrama esquemático es el siguiente:

20191128115903985.png

Un análisis simple muestra que después de que el voltaje de la batería se divide por la resistencia y se agota a 1/11 del valor original, se envía al ADC de un solo chip para su detección, y luego el valor de voltaje recopilado se multiplica por 11 para obtener el valor real. voltaje de la batería. (aquí se multiplica por 11,09, que se puede ajustar según la situación real)

#include "adc.h"
#include "delay.h"

//ADC初始化函数
void adc_Init()
{
  GPIO_InitTypeDef GPIO_InitStructure; //定义一个引脚初始化的结构体  
  ADC_InitTypeDef ADC_InitStructure; //定义一个ADC初始化的结构体 
  
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能CPIOB时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使能TIM4时钟
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4; //引脚0
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; //引脚输入输出模式为模拟输入模式
	GPIO_Init(GPIOA, &GPIO_InitStructure); //根据上面设置好的GPIO_InitStructure参数,初始化引脚GPIOA_PIN0

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
	ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
	
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC工作模式:ADC1和ADC2工作在独立模式
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;	//是否为扫描(一组)模式:否:单通道模式
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	//是否为连续转换模式,否:单次转换模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//转换由软件而不是外部触发启动
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//ADC数据对齐模式:右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 1;	//顺序进行规则转换的ADC通道的数目
	ADC_Init(ADC1, &ADC_InitStructure);	//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器  
	
	ADC_Cmd(ADC1, ENABLE);
	
	ADC_ResetCalibration(ADC1);	//使能复位校准   
	while(ADC_GetResetCalibrationStatus(ADC1));	//等待复位校准结束
	
	ADC_StartCalibration(ADC1);	 //开启AD校准
	while(ADC_GetCalibrationStatus(ADC1));	 //等待校准结束
	
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能
}

//采集ADC值函数,输入参数为ADC通道
u16 Get_adc(u8 chn)
{
	ADC_RegularChannelConfig(ADC1, chn, 1, ADC_SampleTime_239Cycles5 );	//ADC1,chn:ADC通道,第3个参数设置该通道的转换顺序(多通道模式下)
	                                                                  //采样时间为239.5周期=239.5/ADCCLOK,ADCCLOK=72/6MHZ(6代表ADC初始化时的分频系数)		    
  
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能	
	 
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
	return ADC_GetConversionValue(ADC1);	//返回最近一次ADC1规则组的转换结果
}

//采集多次ADC值求平均值函数,输入参数为ADC通道和采集次数
u16 Get_adc_Average(u8 chn, u8 times)
{
  u32 temp_val=0;
	u8 t;
	for(t=0;t<times;t++)
	{
		temp_val+=Get_adc(chn);
		delay_ms(5);
	}
	return temp_val/times;
}
AdcValue=11.09*(3.3*Get_adc_Average(ADC_Channel_4,10)/0x0fff); //ADC值范围为从0-2^12=4095(111111111111)一般情况下对应电压为0-3.3V

5. Pantalla OLED

En general, en los datos del módulo de pantalla OLED adquirido por Taobao, no hay funciones decimales ni positivas y negativas en la función de visualización. Por lo tanto, las siguientes funciones se agregan a la función de visualización original, de modo que el ángulo del automóvil, la velocidad de la rueda de impulso y el voltaje de la batería se pueden mostrar convenientemente en tiempo real.

//显示9位字符,最高位正负,三位整数,第五位小数点,后四位小数部分
//x,y :起点坐标	 
//len :数字的位数
//size:字体大小	 		  
void OLED_Showdecimal(u8 x,u8 y,float num,u8 len,u8 size2)
{         	
	u8 t,temp,len1,temp1;
	float temp2;
	u8 enshow=0;
    if(num < 0)
	{
        OLED_ShowChar(x,y,'0'- 3,size2);
		num =fabs(num);
	}
    else
	OLED_ShowChar(x,y,' ',size2);//第一位显示符号
	temp1 = (int)temp;
	temp2 = num - temp1;
	len1 = len - 6;//len1为整数部分位数,若显示数位需要扩展,修改该行
	OLED_ShowChar(x + size2/2*4,y,'0'- 2,size2);//浮点数的第5位显示小数点
	x = x + size2/2;
	for(t=0;t<len1;t++)//整数部分的显示
	{
		temp=(int)((num/oled_pow(10,len1-t-1)))%10;
		if(enshow==0&&t<(len1-1))
		{
			if(temp==0)
			{
				OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
				continue;
			}else enshow=1; 
		 	 
		}
	 	OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2); 
	}
	OLED_ShowChar(x+(size2/2)*4,y,((int)(temp2*10)%10) + '0',size2); //小数第一位
	OLED_ShowChar(x+(size2/2)*5,y,((int)(temp2*100)%10) + '0',size2); //小数第2位
//	OLED_ShowChar(x+(size2/2)*6,y,((int)(temp2*1000)%10) + '0',size2); //小数第3位
//	OLED_ShowChar(x+(size2/2)*7,y,((int)(temp2*10000)%10) + '0',size2); //小数第4位
} 

6. Notas sobre la lectura de códigos

1.) Todos los archivos de encabezado están incluidos en sys.h, y cada archivo .h incluye sys.h para llamadas de función convenientes.

#ifndef __SYS_H
#define __SYS_H	
#include "stm32f10x.h"
#include "adc.h"
#include "oled.h"
#include "led.h" 
#include "beep.h"
#include "wave.h"
#include "control.h" 
#include "exti.h" 
#include "mpu6050.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h" 
#include "motor.h"
#include "pwm.h"
#include "encoder.h"
#include "usart.h"   				
#include "delay.h"

#include <math.h>
#include <stdlib.h>

2.) La agrupación de prioridad de interrupción está configurada en el archivo sys.c

#include "sys.h"

/*
  ============================================================================================================================
    NVIC_PriorityGroup   | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority  | Description
  ============================================================================================================================
   NVIC_PriorityGroup_0  |                0                  |            0-15             |   0 bits for pre-emption priority
                         |                                   |                             |   4 bits for subpriority
  ----------------------------------------------------------------------------------------------------------------------------
   NVIC_PriorityGroup_1  |                0-1                |            0-7              |   1 bits for pre-emption priority
                         |                                   |                             |   3 bits for subpriority
  ----------------------------------------------------------------------------------------------------------------------------    
   NVIC_PriorityGroup_2  |                0-3                |            0-3              |   2 bits for pre-emption priority
                         |                                   |                             |   2 bits for subpriority
  ----------------------------------------------------------------------------------------------------------------------------    
   NVIC_PriorityGroup_3  |                0-7                |            0-1              |   3 bits for pre-emption priority
                         |                                   |                             |   1 bits for subpriority
  ----------------------------------------------------------------------------------------------------------------------------    
   NVIC_PriorityGroup_4  |                0-15               |            0                |   4 bits for pre-emption priority
                         |                                   |                             |   0 bits for subpriority                       
  ============================================================================================================================
*/
void NVIC_Config(void)
{
	NVIC_InitTypeDef NVIC_InitStruct_extiB5;
    NVIC_InitTypeDef NVIC_InitStruct_extiA10;
	NVIC_InitTypeDef NVIC_InitStruct_usart3;
    NVIC_InitTypeDef NVIC_InitStruct_tim2;
    NVIC_InitTypeDef NVIC_InitStruct_tim1;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//4级抢占,4级响应。
	
	//外部中断PB5
	NVIC_InitStruct_extiB5.NVIC_IRQChannel=EXTI9_5_IRQn;
	NVIC_InitStruct_extiB5.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct_extiB5.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStruct_extiB5.NVIC_IRQChannelSubPriority=0;
	NVIC_Init(&NVIC_InitStruct_extiB5);
	
    //USART3 NVIC 配置
    NVIC_InitStruct_usart3.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStruct_usart3.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
	NVIC_InitStruct_usart3.NVIC_IRQChannelSubPriority = 0;		//子优先级3
	NVIC_InitStruct_usart3.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStruct_usart3);	//根据指定的参数初始化VIC寄存器
    
    // 定时器2中断
    NVIC_InitStruct_tim2.NVIC_IRQChannel=TIM2_IRQn; //属于TIM2中断
	NVIC_InitStruct_tim2.NVIC_IRQChannelCmd=ENABLE; //中断使能
	NVIC_InitStruct_tim2.NVIC_IRQChannelPreemptionPriority=1; //抢占优先级为1级,值越小优先级越高,0级优先级最高
	NVIC_InitStruct_tim2.NVIC_IRQChannelSubPriority=1; //响应优先级为1级,值越小优先级越高,0级优先级最高
	NVIC_Init(&NVIC_InitStruct_tim2); //根据NVIC_InitStruct_tim1的参数初始化VIC寄存器,设置TIM2中断
    
    //外部中断PA10
	NVIC_InitStruct_extiA10.NVIC_IRQChannel=EXTI15_10_IRQn;
	NVIC_InitStruct_extiA10.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct_extiA10.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStruct_extiA10.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStruct_extiA10);
    
    // 定时器1中断
    NVIC_InitStruct_tim1.NVIC_IRQChannel=TIM1_UP_IRQn; //属于TIM1中断
	NVIC_InitStruct_tim1.NVIC_IRQChannelCmd=ENABLE; //中断使能
	NVIC_InitStruct_tim1.NVIC_IRQChannelPreemptionPriority=2; //抢占优先级为1级,值越小优先级越高,0级优先级最高
	NVIC_InitStruct_tim1.NVIC_IRQChannelSubPriority=2; //响应优先级为1级,值越小优先级越高,0级优先级最高
	NVIC_Init(&NVIC_InitStruct_tim1); //根据NVIC_InitStruct_tim1的参数初始化VIC寄存器,设置TIM2中断
}

3.) Después de reiniciar la MCU de la serie STM32F10x, PA13/14/15 y PB3/4 se configuran como función JTAG de forma predeterminada. A veces configuramos estos puertos como puertos de E/S normales para aprovechar al máximo los recursos de los puertos de E/S de la MCU.

Cuando use JLINK para programar STM32, necesita usar 6 pines de chip (tome STM32F103C8T6 como ejemplo), a saber, PB4/JNTRST, PB3/JTDO, PA13/JTMS, PA14/JTCK, PA15/JTDI, NRST. Cuando los recursos del puerto IO del chip son relativamente ajustados, puede elegir el modo SW para grabar el programa. SWD solo necesita usar dos líneas PA13 / JTMS, PA14 / JTCK, NREST se puede conectar o no, los PB4 / JNTRST, PB3 / JTDO y PA15 / JTDI restantes se pueden usar como IO ordinario, pero estos tres puertos son, por supuesto, ordinarios Al usar IO, primero debe configurar lo siguiente. (Aquí el módulo MPU6050 usa pines PB3 y PB4)

mpuiic.c

//初始化IIC
void MPU_IIC_Init(void)
{					     
  GPIO_InitTypeDef  GPIO_InitStructure;
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB,ENABLE); //打开PB口时钟和AFIO复用时钟
  GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //重映射
		
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;	 // 端口配置
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
  GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIO 
	
  GPIO_SetBits(GPIOB,GPIO_Pin_3|GPIO_Pin_4);						 //PB3,PB4 输出高	
 
}

3. Enlaces

bilibili_[Momentum Wheel Self-Balancing Bike] STM32_PID (código abierto, incluida información de hardware) https://www.bilibili.com/video/BV1M3411J77m?share_source=copy_web

Supongo que te gusta

Origin blog.csdn.net/weixin_47820462/article/details/122797752
Recomendado
Clasificación