【stm32最小系统板】基础入门与实战(学习笔记)


前言

stm32F103c8t6 最小系统板(基础入门)

片上资源/外设

在这里插入图片描述

一、 使用GPIO 口

在这里插入图片描述
首先,从APB2总线 引出,RCC_APB2PeriphClockCmd(GPIO口的名字,状态)
如GPIOA 使能

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 

其次, 我们看一下,GPIO 初始化函数

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)

第一个参数 GPIO口的名字 如GPIOA
第二个参数 GPIO的结构体地址 如&GPIO_InitStructure

stuuct 关键字 定义结构体变量 用途:数据打包,不同类型的变量打包,如
在这里插入图片描述在这里插入图片描述

因为结构体变量类型较长,所以通常用typedef更改变量类型名
typedef 关键字 用途:将一个比较长的变量类型名换个名字
比如:
在这里插入图片描述
将 结构体变量struct{} 换一个别名叫GPIO_InitTypeDef
于是 ,我们用

GPIO_InitTypeDef GPIO_InitStructure;

来定义了一个名为GPIO_InitStructure的结构体变量
我们将其地址存入

GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure 有三个参数

GPIO_InitStructure.GPIO_Mode
GPIO_InitStructure.GPIO_Pin
GPIO_InitStructure.GPIO_Speed

第一个Mode有8种模式
在这里插入图片描述

GPIO_Mode_AIN(Analog IN)//模拟输入 
GPIO_Mode_IN_FLOATING  //浮空输入
GPIO_Mode_IPD (In Pull Down) //下拉输入
GPIO_Mode_IPU (In Pull Up) //上拉输入
GPIO_Mode_OUT_OD(Out Open Drain) //开漏输出
GPIO_Mode_PP_OD(Out Push Pull) //推挽输出
GPIO_Mode_AF_OD(Atl Open Drain) //复用开漏
GPIO_Mode_AF_PP(Atl Push Pull) //复用推挽

在这里插入图片描述

第二个GPIO_InitStructure.GPIO_Pin 的选择
在这里插入图片描述
第三个GPIO_InitStructure.GPIO_Speed的选择
在这里插入图片描述
我们一般选50MHz
整个步骤如下

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

这样我们就把GPIOA 上所有引脚都初始化好了。

关于GPIO口的常用函数

将GPIO口置 1 和 置零 操作

		GPIO_ResetBits(GPIOA, GPIO_Pin_0); //将PA0口置0
		Delay_ms(500);
		GPIO_SetBits(GPIOA, GPIO_Pin_0);//将PA0口置1
		Delay_ms(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);//Bit_RESET设置低电平
		Delay_ms(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
		Delay_ms(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0);//强制转换BitAction类型 0 1
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);
		Delay_ms(500);

读取GPIO上 电平操作

GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);//读取PB13上引脚输入 一般是接一个按键 读它的输入 即是否按下
GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1)//读取PA1上引脚输出 一般接光敏传感器 读它的AO口输出  即是否被遮挡

流水灯例程

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);////6923个
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	
	//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//开漏模式 高电平没有驱动能力
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	while (1)
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_0);
		Delay_ms(500);
	
		GPIO_SetBits(GPIOA, GPIO_Pin_0);
		Delay_ms(500);
		
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);//Bit_RESET设置低电平
		Delay_ms(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
		Delay_ms(500);
		
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0);//强制转换BitAction类型 0 1
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);
		Delay_ms(500);
	}
}

其中Delay.c

#include "stm32f10x.h"
/**
  * @brief  微秒级延时
  * @param  xus 延时时长,范围:0~233015
  * @retval 无
  */
void Delay_us(uint32_t xus)
{
	SysTick->LOAD = 72 * xus;				//设置定时器重装值
	SysTick->VAL = 0x00;					//清空当前计数值
	SysTick->CTRL = 0x00000005;				//设置时钟源为HCLK,启动定时器
	while(!(SysTick->CTRL & 0x00010000));	//等待计数到0
	SysTick->CTRL = 0x00000004;				//关闭定时器
}
/**
  * @brief  毫秒级延时
  * @param  xms 延时时长,范围:0~4294967295
  * @retval 无
  */
void Delay_ms(uint32_t xms)
{
	while(xms--)
	{
		Delay_us(1000);
	}
}
/**
  * @brief  秒级延时
  * @param  xs 延时时长,范围:0~4294967295
  * @retval 无
  */
void Delay_s(uint32_t xs)
{
	while(xs--)
	{
		Delay_ms(1000);
	}
} 

Delay.h

#ifndef __DELAY_H
#define __DELAY_H

void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
void Delay_s(uint32_t s);

#endif

封装函数操作

//灯的打开
void LED1_ON(void)
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}
//灯的熄灭
void LED1_OFF(void)
{
	GPIO_SetBits(GPIOA, GPIO_Pin_1);
}
//灯的翻转
void LED1_Turn(void)
{
	if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1) == 0)
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_1);
	}
	else
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_1);
	}
}

二、使用AFIO外部中断引脚选择

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

使能APB2总线上的AFIO时钟

比如 : 我们将PB12设为中断引脚
首先,使能APB2总线上的AFIO时钟和初始化PB12 引脚

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能gpio时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//使能afio时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入  exit 上拉 下拉 都行
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);  //配置gpio

中断初始化

其次,选择中断引脚

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource11);//AFIO 中断引脚选择

然后中断初始化

void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)

类似于GPIO初始化

EXTI_InitTypeDef EXTI_InitStructure;
//有四个参数
EXTI_InitStructure.EXTI_Line   //EXIT_Line0 ~19  其中line16 ~line19 是 PVD(电压检测器) RTC(实时时钟) USB ETH(以太网)
EXTI_InitStructure.EXTI_LineCmd //ENABLE FALSE 开启关闭
EXTI_InitStructure.EXTI_Mode //   EXTI_Trigger_Rising  上边沿触发 EXTI_Trigger_Falling  下边沿触发 EXTI_Trigger_Rising_Falling 双边沿触发
EXTI_InitStructure.EXTI_Trigger // EXTI_Mode_Interrupt  中断触发 EXTI_Mode_Event 事件触发

NVIC初始化

然后选择NVIC优先级分组
在这里插入图片描述

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//分组2 2抢占 2 响应

抢占 相当于 重症直接进icu
响应 相当于 插队到下一个
5-9 中断线 共用一个中断通道 EXTI9_5_IRQn
10-15中断线 共用一个中断通道 EXIT15_10IRQn

	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;  //指定中断通道来开启或关闭  //每个f1型号不一样,c8是MD中等型号  10-15 都在EXTI15_10_IRQn里 //EXTI0_IRQn
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级  20-3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //响应优先级  0-3
	NVIC_Init(&NVIC_InitStructure);//

中断函数

最后写中断函数

//中断函数里查看清除状态
EXTI_GetITStatus(EXTI_Line11)
EXTI_ClearITPendingBit(EXTI_Line11)
//主程序里查看清除状态
EXTI_GetFlagStatus()
EXTI_ClearFlag()
void EXTI15_10_IRQHandler(void)///EXTI0_IRQHandler //中断函数不需要申明,因为自动执行
{
	if (EXTI_GetITStatus(EXTI_Line11) == SET) //判断中断线是否是1
	{
		CountSensor_Count ++;
		EXTI_ClearITPendingBit(EXTI_Line11);//不清楚中断标志位 ,就一直置1
	}
}

以下为全代码

void CountSensor_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能gpio时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//使能afio时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入  exit 上拉 下拉 都行
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);  //配置gpio
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource11);//AFIO 中断引脚选择
	
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = EXTI_Line11; //PB11  中断线
	EXTI_InitStructure.EXTI_LineCmd = ENABLE; //开启中断
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;  //中断模式
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
	EXTI_Init(&EXTI_InitStructure);//配置中断
	
	//nvic在misc.h里
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//分组2 2抢占 2 响应
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;  //指定中断通道来开启或关闭  //每个f1型号不一样,c8是MD中等型号  10-15 都在EXTI15_10_IRQn里 //EXTI0_IRQn
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级  20-3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //响应优先级  0-3
	NVIC_Init(&NVIC_InitStructure);//
}

void EXTI15_10_IRQHandler(void)///EXTI0_IRQHandler //中断函数不需要申明,因为自动执行
{
	if (EXTI_GetITStatus(EXTI_Line11) == SET) //判断中断线是否是11
	{
		CountSensor_Count ++;
		EXTI_ClearITPendingBit(EXTI_Line11);//不清楚中断标志位 ,就一直置1
	}
}

三、使用定时器/计数器

在这里插入图片描述

选择时钟

内部时钟和外部时钟

//选择内部时钟
TIM_InternalClockConfig(TIM2); 
//通过ETR引脚的外部时钟模式2配置
TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00);
//TIM_ExtTRGPSC_OFF 不需要分频   TIM_ExtTRGPolarity_NonInverted极性,高电平或上升沿有效 

内部时钟当定时器用

ARR 自动重装的值
PSC 预分频器的值

1MHz=1000 000Hz

//计数器计数频率 CK_CNT = CK_PSC/(PSC+1)
//计数器溢出频率 CK_CNT_OV = CK_PSC/(PSC+1)/(ARR+1)
//预分频给少点 自动重装给多点 以一个比较高的频率计比较多的数
//预分频给多点 自动重装给少点 以一个低的频率计比较少的数
//计数器计数频率 CK_CNT = CK_PSC/(PSC+1)

10k的计数频率 计10000的数 即 1s 加1

TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1; //周期 ARR自动重装器的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;  //PSC预分频器的值 10k的计数频率 计10000的数

计数方式

TIM_TimeBaseInitStructure.TIM_CounterMode 
TIM_CounterMode_Up   //向上计数     从零计到到目标值之后变零       
TIM_CounterMode_Down//向下计数   从目标值计到目标值之后回到目标值    
TIM_CounterMode_CenterAligned1    //自动对齐 到目标值 到零 均更新中断
TIM_CounterMode_CenterAligned2    
TIM_CounterMode_CenterAligned3     
一般选用向上计数

初始化时基单元

//初始化时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //配置时基单元
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //指定时钟分频 /1分频 影响不大
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1; //周期 ARR自动重装器的值
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;  //PSC预分频器的值 10k的计数频率 计10000的数
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器的值   //高级定时器才有 这里通用计时器 不用
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);

中断方式选择 更新中断

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //使能中断 update 更新中断

以下为全部代码

#include "stm32f10x.h"                  // Device header

//extern uint16_t Num; //引用其他文件(主函数)的Num变量

void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//TIM2 APB1总线上的外设
	
	TIM_InternalClockConfig(TIM2); //选择内部时钟
	//初始化时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //配置时基单元
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //指定时钟分频 /1分频 影响不大
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1; //周期 ARR自动重装器的值
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;  //PSC预分频器的值 10k的计数频率 计10000的数
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器的值   //高级定时器才有 这里通用计时器 不用
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);//手动把更新中断标志位清除一下 防止 reset直接到1
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //使能中断 update 更新中断
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //优先级分组
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM2, ENABLE); //启动定时器
}

/*
void TIM2_IRQHandler(void) //定时器2 的中断函数
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)//看更新中断标志位
	{
		Num++;
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}
*/

外部时钟当计数器用

#include "stm32f10x.h"                  // Device header

//PA0 TIM2的ETR引脚
void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00);//通过ETR引脚的外部时钟模式2配置
	//TIM_ExtTRGPSC_OFF 不需要分频   TIM_ExtTRGPolarity_NonInverted极性,高电平或上升沿有效      0x00不用滤波器
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 10 - 1; //0计到9
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;//不需要分频  //如果有预分频了 就是遮挡几次加一次
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM2, ENABLE);
}

uint16_t Timer_GetCounter(void)
{
	return TIM_GetCounter(TIM2);
}

/*
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
	{
		
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}
*/

TIM函数

中断函数里
//看更新中断标志位  清除标志位
TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
TIM_ClearITPendingBit(TIM2, TIM_IT_Update)
主程序里
TIM_GetFlagStatus()
TIM_ClearFlag(TIM2, TIM_FLAG_Update);

四、OC输出比较器(PWM)

OC (output compare) 输出比较 比较CNT 和 CCR 寄存器的关系
IC (input compare) 输入捕获
CC (capture compare)输入捕获 和输出比较单元

在这里插入图片描述

	TIM_OCInitTypeDef TIM_OCInitStructure;//初始化输出比较单元
	TIM_OCStructInit(&TIM_OCInitStructure); //给结构体赋初始值 里面定义默认给的初始值,防止高级定时器出错
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //PWM1模式
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出比较极性 高级性 极性不翻转 有效电平为高电平
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 0;		//CCR寄存器的值
	TIM_OC1Init(TIM2, &TIM_OCInitStructure);//PA0口对应第一个输出比较通道
void PWM_SetCompare1(uint16_t Compare) 
{
	TIM_SetCompare1(TIM2, Compare);//单独更改通道1的CCR的值的
}

五、使用AFIO复用功能引脚重映射

重映射方式和引脚对应关系 ,选择重映射方式 查看参考手册
在这里插入图片描述
gpio.c 选择重映射方式

GPIO_PartialRemap1_TIM2 //部分重映射1
GPIO_PartialRemap2_TIM2//部分重映射2
GPIO_FullRemap_TIM2//完全重映射

在这里插入图片描述
最小系统板引脚定义 最后一列为重映射
在这里插入图片描述
GPIO_PinRemapConfig()重映射函数
方式1

//  解除JTACK调试端口复用 PA15 PB3 PB14 变回GPIO
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //打开AFIO时钟
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
	

方式2

// 重映射定时器 或者其他外设的复用引脚
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);  //引脚重映射 选择部分重映射1 方式

方式3

//重映射引脚正好是调试端口的引脚 那都加上
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);  //引脚重映射 选择部分重映射1 方式
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//解除JTACK调试端口复用 PA15 PB3 PB14 变回GPIO

有了这三句 我们定时器的通道1 , 就从PA0 挪到PA15了
那么我们初始化的是GPIO口是应该是PA15 了

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定时器2
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);  
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
	                                    
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出 想用定时器来控制引脚 复用 引脚控制权才能交给片上外设  //不然是输出数据寄存器控制
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//PA15
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

最后附上引脚定义图
在这里插入图片描述

六、tb6612 的使用

在这里插入图片描述
VM 接5v
STBY 待机控制脚 ,不需要待机 直接接逻辑电源正3.3V
A01 A02 接两个电机 接线不分正反 对调两根线 电机旋转的方向就会反过来
AIN1 AIN2 是方向控制 任意接两个GPIO 就行了
PWMA 是速度控制 需要接PWM的输出脚 这里接的是PA2 PA2 对应的是TIM2的通道3 ,到时候初始化通道3就行了

  • 9
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值