stm32的TIM和PWM学习笔记

文章目录

TIM定时器与中断

参考视频

c 复制代码
/*定时器配置,先不用*/
void My_Timer1_Init(void)
{
	//1.初始化时钟配置
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	//2.初始化时基单元,调用的时内部时钟,定时器上电后默认使用内部时钟,不写也是调用内部时钟,可以不写,但是调用外部时钟必须写
	TIM_InternalClockConfig(TIM2);
	
	//3.配置时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//1分频
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
	/*时基单元里每个关键寄存器的参数,没有CNT计数器的参数可以用setCounter和getCounter函数操作计数器
	计数器溢出频率:CK_CNT_OV=CK_CNT/(ARR+1)=CK_PSC/(PSC+1)/(ARR+1)
	定时频率=72M/(PSC+1)/(ARR+1)
	72MHZ=72,000,000HZ,下设置的时1HZ*/
	TIM_TimeBaseInitStruct.TIM_Period = 10000 - 1;							周期,ARR重装器的值,取值范围:0~65535
	TIM_TimeBaseInitStruct.TIM_Prescaler = 7200 - 1;					PSC预分频器的值,取值范围:0~65535
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;	//重复计数器的值,高级定时器才有,不用时直接给0
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
	
	//中断,我这里又RTOS所以注释了
	//TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//开启更新中断与NVIC的通路
	
	//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//分组2
	
	//NVIC_InitTypeDef NVIC_InitStruct;
	//NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
	//NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    //NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级
	//NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;//响应优先级
	//NVIC_Init(&NVIC_InitStruct);
	
	//启动定时器
	TIM_Cmd(TIM2,ENABLE);
}

/*定时中断而言,中断函数就是为别的文件服务的,所以可以在想用的文件里调用*/
//void TIM2_IRQHandler(void){
	//if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET){
		//中断内容
		//清除标志位
		//TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	//}
//}

TIM输出比较(占空比信号概念)

参考视频

模式 描述
冻结 CNT=CCR时,REF保持原状态
匹配时置有效电平 CNT=CCR时,REF置有效电平(高电平)
匹配时置无效电平 CNT=CCR时,REF置无效电平(低电平)
匹配时电平翻转 CNT=CCR时,REF电平翻转
强制为无效电平 CMT与CCR无效,REF强制为无效电平
强制为有效电平 CMT与CCR无效,REF强制为有效电平
PWM模式1 向上计数:CNT<CCR时,REF置有效电平,CNT>=CCR时,REF置无效电平
PWM模式1 向下计数:CNT>CCR时,REF置无效电平,CNT<=CCR时,REF置有效电平
PWM模式2 向上计数:CNT<CCR时,REF置无效电平,CNT>=CCR时,REF置有效电平
PWM模式2 向下计数:CNT>CCR时,REF置有效电平,CNT<=CCR时,REF置无效电平
c 复制代码
/*
比较器
当CNT>CCR和CNT<CCR时输出TIM_OC1就会对应的置1置0
每个高级定时器和通用定时器都拥有4个输出比较通道;并且高级定时器的三个通道额外拥有死区生成和互补输出的功能
输出比较模式
|      模式      |             								 描述   						         |
|----------------|---------------------------------------------------------|
|      冻结      |CNT=CCR时,REF保持原状态       													 |
|匹配时置有效电平|CNT=CCR时,REF置有效电平(高电平)  												 |
|匹配时置无效电平|CNT=CCR时,REF置无效电平(低电平)    											 |
| 匹配时电平翻转 |CNT=CCR时,REF电平翻转          													 |
| 强制为无效电平 |CMT与CCR无效,REF强制为无效电平													 |
| 强制为有效电平 |CMT与CCR无效,REF强制为有效电平													 |
|----------------|---------------------------------------------------------|
|      PWM       |向上计数:CNT<CCR时,REF置有效电平,CNT>=CCR时,REF置无效电平|
|     模式1      |向下计数:CNT>CCR时,REF置无效电平,CNT<=CCR时,REF置有效电平|
|----------------|---------------------------------------------------------|
|      PWM       |向上计数:CNT<CCR时,REF置无效电平,CNT>=CCR时,REF置有效电平|
|     模式2      |向下计数:CNT>CCR时,REF置有效电平,CNT<=CCR时,REF置无效电平|
|----------------|---------------------------------------------------------|
冻结模式:正在输出PWM波想要暂停,可以使用这个模式.设置后高低电平维持为暂停时刻的状态
匹配时置有效电平(置高电平),匹配时置无效电平(置低电平),匹配时电平翻转:都是高级定时器里的说法.是和关断、刹车这些功能配合表述的.
强制为无效电平,强制为有效电平:与冻结模式差不多.
PWM模式1和PWM模式2:它们可以输出频率和占空比都可调的PWM波形
PWM基本结构
时基单元:->PSC预分频器->CNT计数器->ARR自动重装器
		^					 ^
		|			         |
    运行控制			        v
      输出比较单元(*4):CRR捕获/比较器->CNT<CCR时,REF置有效电平	-REF->极性->GPIO
																			 CNT>=CCR时,REF置无效电平	-REF->选择->GPIO

PWM频率: 		Freq=CK_PSC/(PSC+1)/(ARR+1)
PWM占空比:		Duty=CCR/(ARR+1)
PWM分辨率:		Reso= 1/(ARR+1)
*/

PWM(占空比信号代码)

参考视频

c 复制代码
void My_TIM2_Init(void)
{
	My_TIM2_Init_GPIO();
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//1分频
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
	/*时基单元里每个关键寄存器的参数,没有CNT计数器的参数可以用setCounter和getCounter函数操作计数器
	计数器溢出频率:CK_CNT_OV=CK_CNT/(ARR+1)=CK_PSC/(PSC+1)/(ARR+1)
	定时频率=72M/(PSC+1)/(ARR+1)
	72MHZ=72,000,000HZ,下设置的时1HZ*/
	TIM_TimeBaseInitStruct.TIM_Period = 100 - 1;							//周期,ARR重装器的值,取值范围:0~65535
	TIM_TimeBaseInitStruct.TIM_Prescaler = 720 - 1;					//PSC预分频器的值,取值范围:0~65535
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;	//重复计数器的值,高级定时器才有,不用时直接给0
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
	
	//启动定时器
	TIM_Cmd(TIM2,ENABLE);
	//初始化输出比较单元
	//PA0->OC1输出通道(OC1)
	/*对结构体而言现在它时局部变量,如果不给它的成员赋初始值,它成员的值是不确定的,可能会导致比如高级定时器做通用定时器输出PWM时,
	TIM2改成TIM1这样结构体原来用不到的成员现在用到了,而那些成员没给赋值,那就会导致高级定时器输出PWM出现一些奇怪的问题
	为了避免程序中出现不确定因素,有没有用到都把结构体的值全部配置一下,之后在修改个别的值*/
	TIM_OCInitTypeDef TIM_OCInitStruct;
	TIM_OCStructInit(&TIM_OCInitStruct);//给结构体赋初始值
	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//设置输出比较模式
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//设置输出比较的极性
	TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//设置输出使能
	TIM_OCInitStruct.TIM_Pulse = 50;//设置CCR
	TIM_OC1Init(TIM2,&TIM_OCInitStruct);
}

呼吸灯

c 复制代码
uint8_t i;
void PWM_Task(void *param){
	My_TIM2_Init();
	while(1){
		for(i=0;i<=100;i++){
		//单独修改CCR寄存器值
			TIM_SetCompare1(TIM2,i);
			vTaskDelay(10);
		}
		for(i=0;i<=100;i++){
			TIM_SetCompare1(TIM2,100-i);
			vTaskDelay(10);
		}
	}
}
相关推荐
AI_零食1 小时前
HarmonyOS ArkTS 数据格式化技术深度解析
学习·华为·harmonyos·鸿蒙
暗夜猎手-大魔王1 小时前
hermes源码学习7--会话存储
人工智能·学习
上海观智网络1 小时前
健身房瑜伽馆想开发小程序,上海靠谱服务商怎么选?
经验分享·笔记
leo_yu_yty1 小时前
Go语言分布式计算(并发Debug)
开发语言·笔记·后端·golang
嵌入式小站1 小时前
STM32 可移植教程 01:VSCode 环境搭建 + 点亮 LED(实战篇)
vscode·stm32·嵌入式硬件
Dovis(誓平步青云)1 小时前
《QT学习第五篇:QSS美化界面与API绘图》
开发语言·数据库·qt·学习·时序数据库·开源智能体
guygg881 小时前
STM32正交编码器接口指南
stm32·单片机·嵌入式硬件
San813_LDD1 小时前
[深度学习]量化研究_ML_Lesson2
笔记
数智工坊1 小时前
周志华《Machine Learning》学习笔记--第十六章--强化学习
笔记·学习·机器学习