当前位置: 首页 > java >正文

STM32核心机制解析:重映射、时间片与系统定时器实战——从理论到呼吸灯开发

知识点1【重映射的概念】

1、引入

默认:

**定义:**系统或硬件在未经用户修改时的预设配置或行为

STM32的引脚功能、外设配置、中断向量表等默认由芯片设计或库函数预设。

部分重映射

**定义:**仅修改部分资源或地址的映射关系,其余保留默认配置

通过AFIO(Alternate Function I/O)或外设寄存器,仅修改部分外设的引脚映射,其他功能保持默认。

完全重映射

**定义:**彻底替换原有映射关系,重新分配所有资源或地址的映射规则。

彻底改变外设或系统资源的全局映射关系,通常需要重新配置硬件或系统级寄存器

注意:影响全局功能,谨慎操作。

2、定时器的映射关系图

知识点2【GPIO和AFIO】

1、GPIO

主要用于最基础的数字信号输入/输出

输入模式:浮空,上拉,下拉,模拟

输出模式:推挽,开漏或复用功能

2、AFIO

专门管理”外设功能“如何映射到特定引脚。

比如USART1,SPI1,I2C1,定时器PWM,外部中断线(EXTI)等外设,都有多个候选引脚,AFIO通过重映射(Remap)寄存器决定最终用哪个引脚。

知识点3【复用推挽/开漏 与 推挽/开漏】

注意:

用到重映射想到 对应端口需要 复用

用到外设要想到 对应端口需要 复用

用到外部中断想到 对应端口需要 复用

知识点4【时间片】

**时间片(Time Slice)**是操作系统中 CPU时间分配的最小单元

**核心思想:**将CPU的执行时间划分称多个固定长度的时间片段,每个任务(或线程/进程)在一个时间片内独占CPU,时间片用完后强制切换其他任务。

调度流程:

  • 步骤 1:任务 A 获得 CPU 使用权,开始执行。
  • 步骤 2:系统时钟中断触发,检查已用时间片。
  • 步骤 3:若时间片耗尽,将任务 A 挂起,切换到任务 B。
  • 步骤 4:任务 A 重新等待调度,进入就绪队列。

时间片主要是为了实现非阻塞

知识点5【系统定时器】

系统定时器又称 嘀嗒定时器,属于内核部分。

系统定时器中采用向下计数没有预分频器,有计数器,与 重装载计数器

计数器:计数范围0-FFFFFF,24位

重装载计数器:计数范围0-FFFFFF,24位

系统定时器一般用于实现延时,下面我写一段延时代码,主要看逻辑,函数无需刻意记忆,用多了自然会记住,记不住可以看手册。

函数介绍 SysTick_Config

static __INLINE uint32_t SysTick_Config(uint32_t ticks)

函数功能:

是ARM Cortex-M内核中SysTick定时器的初始化函数,用来配置SysTick定时器的 中断周期

主要是设置SysTick定时器的重装载值(Reload Value),并启动定时器和中断、

参数:

ticks:SysTick定时器的重装载值,决定中断触发周期

返回值:

0:配置成功

-1:配置失败(ticks超出SysTick寄存器的最大范围)

触发中断对应的中断服务函数

void SysTick_Handler(void)

代码演示

#include "stm32f10x.h" 
#include "stm32f10x_conf.h"void Systick_Init(u32 ticks);
void Delay_ms(u32 ms);
void SysTick_Handler(void);
void LED_Init(void);
void LED0_Blink(u32 ms);
void LED1_Blink(u32 ms);u32 delay_ms = 0;//这里我们实现一个两个灯独立闪烁,互不影响
//LED0:闪烁周期0.4s  PB5
//LED1:闪烁周期0.6s  PE5u32 LED0[2] = {0,0};
u32 LED1[2] = {0,0};int main(void)
{//打开系统定时器Systick_Init(72000);//每隔1ms delay_ms + 1LED_Init();while(1){LED0_Blink(400);LED1_Blink(600);}}//系统定时器初始化函数
void Systick_Init(u32 ticks)
{SysTick_Config(ticks);
}void LED_Init(void)
{
//	GPIO_InitTypeDef GPIOB_InitStruct;GPIO_InitTypeDef GPIOE_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);//	GPIOB_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
//	GPIOB_InitStruct.GPIO_Pin = GPIO_Pin_5;
//	GPIOB_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIOE_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIOE_InitStruct.GPIO_Pin = GPIO_Pin_5;GPIOE_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIOE_InitStruct);GPIO_Init(GPIOE,&GPIOE_InitStruct);GPIO_SetBits(GPIOB,GPIO_Pin_5);GPIO_SetBits(GPIOE,GPIO_Pin_5);
}//延时函数
void Delay_ms(u32 ms)
{u32 ticks = delay_ms + ms;while(ticks > delay_ms);
}void LED0_Blink(u32 ms)
{LED0[1] = ms;if(LED0[0] >= LED0[1]){GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1 - GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5)));LED0[0] = 0;}
}
void LED1_Blink(u32 ms)
{LED1[1] = ms;if(LED1[0] >= LED1[1]){GPIO_WriteBit(GPIOE,GPIO_Pin_5,(BitAction)(1 - GPIO_ReadOutputDataBit(GPIOE,GPIO_Pin_5)));LED1[0] = 0;}
}//系统定时器中断服务函数
void SysTick_Handler(void)
{delay_ms++;LED1[0]++;LED0[0]++;
}

代码遇到的问题

SysTick_Handler重定义

解决方法

屏蔽掉即可

知识点6【定时器常用标准库函数】

详细函数使用看手册

注意事项:

TIM_GetITStatus与TIM_ClearITPendingBit配套使用

TIM_GetFlagStatus 与TIM_ClearFlag 配套使用

代码演示

这里我们使用标准库 实现了使用 OC(输出比较)的中断,来控制CCR寄存器中的值,进而 实现呼吸灯

#include "stm32f10x.h" 
#include <stm32f10x_tim.h>
#include <stm32f10x_conf.h>
#include "delay.h"
//定时器的OC(PA1  定时器2通道2)中断实现LED(PB5)呼吸灯
void LED_Init(void);
void TIM3_CH2_Init(void);int dirction = 1;
int num_ccr = 0;int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//开启AFIO  重映射之前需要开启RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//重映射GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);LED_Init();TIM3_CH2_Init();while(1){}
}
//LED初始化 PB5
void LED_Init(void)
{GPIO_InitTypeDef GPIOB_InitStruct;//时钟配置RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//管脚输出模式配置GPIO_DeInit(GPIOB);GPIOB_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIOB_InitStruct.GPIO_Pin = GPIO_Pin_5;GPIOB_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIOB_InitStruct);//熄灭GPIO_SetBits(GPIOB,GPIO_Pin_5);
}//TIM3初始化 通道2 PA2
void TIM3_CH2_Init(void)
{TIM_TimeBaseInitTypeDef TIM3_TimeBaseInitStruct;TIM_OCInitTypeDef TIM3_OC2InitStruct;NVIC_InitTypeDef NVIC_InitStruct_TIM3_CH2;//时钟配置RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//定时器 时基单元 配置TIM_TimeBaseStructInit(&TIM3_TimeBaseInitStruct);TIM3_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM3_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM3_TimeBaseInitStruct.TIM_Period = 1000 - 1;TIM3_TimeBaseInitStruct.TIM_Prescaler = 72 - 1;TIM_TimeBaseInit(TIM3,&TIM3_TimeBaseInitStruct);//OC配置TIM_OCStructInit(&TIM3_OC2InitStruct);TIM3_OC2InitStruct.TIM_OCMode = TIM_OCMode_PWM1;TIM3_OC2InitStruct.TIM_Pulse = 0;	TIM3_OC2InitStruct.TIM_OCPolarity = TIM_OCPolarity_Low;TIM3_OC2InitStruct.TIM_OutputState = TIM_OutputState_Enable;TIM_OC2Init(TIM3,&TIM3_OC2InitStruct);//输出比较使能//TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);//中断使能TIM_ITConfig(TIM3,TIM_IT_CC2,ENABLE);//NVIC配置NVIC_InitStruct_TIM3_CH2.NVIC_IRQChannel = TIM3_IRQn;NVIC_InitStruct_TIM3_CH2.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct_TIM3_CH2.NVIC_IRQChannelPreemptionPriority = 0x01;NVIC_InitStruct_TIM3_CH2.NVIC_IRQChannelSubPriority = 0x01;NVIC_Init(&NVIC_InitStruct_TIM3_CH2);//启动定时器TIM_Cmd(TIM3,ENABLE);
}//中断服务函数
void TIM3_IRQHandler(void)
{if(TIM_GetITStatus(TIM3,TIM_IT_CC2) == SET){//条件判断 //CCR == 1000-》DIR = -1;//CCR == 0-》DIR = 1;if(num_ccr <= 0){num_ccr = 0;dirction = 1;}else if(num_ccr >= 1000 - 1){num_ccr = 1000 - 1;dirction = -1;}num_ccr += dirction;TIM_SetCompare2(TIM3,num_ccr);//清除中断标志位TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);}
}

代码犯错:

1、输出比较寄存器需要使能,在对应的结构体内使能

TIM3_OC2InitStruct.TIM_OutputState = TIM_OutputState_Enable;

2、使用了 重映射PB5,输出模式要用AF_PP(复用推挽输出)

结束

代码重在练习!

代码重在练习!

代码重在练习!

今天的分享就到此结束了,希望对你有所帮助。如果你喜欢我的分享,请点赞收藏加关注,谢谢大家!!!

http://www.xdnf.cn/news/5577.html

相关文章:

  • fiddler 配置ios手机代理调试
  • 保持Word中插入图片的清晰度
  • ✅ TensorRT Python 安装精简流程(适用于 Ubuntu 20.04+)
  • CVPR2025 | Prompt-CAM: 让视觉 Transformer 可解释以进行细粒度分析
  • 如何应对网站被爬虫和采集?综合防护策略与实用方案
  • 5.12第四次作业
  • spring常用注解
  • 从海洋生物找灵感:造个机器人RoboPteropod,它能在水下干啥?
  • 【C++贪心】P11044 [蓝桥杯 2024 省 Java B] 食堂|普及
  • 华为FAT AP配置 真机
  • Java学习手册:服务网关与路由
  • 《Effective Python》第1章 Pythonic 思维详解——深入理解流程控制中的解构利器match
  • Bravery靶机通关笔记
  • 机器学习管道 pipeline
  • OpenCV中Canny、Sobel和Laplacian边界检测算法原理和使用示例
  • django之视图
  • OpenCV图像金字塔详解:原理、实现与应用
  • 医院保洁智能化管理新范式:诺怀云医院后勤解决方案的实践探索
  • edge设置位IE模式打开网页
  • Java设计模式之装饰器模式:从基础到高级的全面解析(万字解析)
  • 【速写】KV-cache与解码的再探讨(以束搜索实现为例)
  • C 语言_可变参数宏详解
  • 硅基计划2.0 学习总结 壹 Java初阶
  • pytorch模型画质增强简单实现
  • STM32入门教程——GPIO输出
  • Java设计模式之代理模式:从入门到精通(保姆级教程)
  • http和https的区别
  • 键盘RGB矩阵与LED指示灯(理论部分)
  • 外出充电不发愁,倍思便携式移动电源成出行新宠
  • 数据治理域——数据治理体系建设