通用定时器输出比较模式,寄存器配置,从零开始全解析:TIM输出比较模式,四通道输出,同频率,占空比、相位可调,高电平时间要求大于Arr-相位,

输入捕获和输出比较很像,其实就是在CCMR1寄存器的1:0位设置不同的通道模式,包括后面的PWM工作模式也是。
依据前面这两种工作模式的设计,总结出的一个固定模式。--------------------------------------

1、开定时器时钟

RCC->APB1ENR|=1<<x;


2、设定输入输出引脚的工作模式

RCC->APB2ENR|=1<<2;    	//使能PORTA时钟	
GPIOA->CRL&=0X00FFFFFF;	//PA6 PA7输出
GPIOA->CRL|=0XBB000000;	//复用功能输出

3、设定定时器的时基单元

● 计数器寄存器(TIMx_CNT)
● 预分频器寄存器 (TIMx_PSC)
● 自动装载寄存器 (TIMx_ARR)

4、逐个通道设置输出比较的设置 CCMR1寄存器

每个通道有8位5个设定点,输出比较快速使能只在PWM模式下起作用,也就是共计7位4个设定点
从低位开始
1)1:0 CCxS[1:0]:捕获/比较x 选择
该位定义通道的方向(输入/输出),及输入脚的选择:
00:CC2通道被配置为输出;
01:CC2通道被配置为输入,IC2映射在TI2上;
10:CC2通道被配置为输入,IC2映射在TI1上;
11:CC2通道被配置为输入,IC2映射在TRC上。此模式仅工作在内部触发器输入被选中时(由TIMx_SMCR寄存器的TS位选择)。
注:CC2S仅在通道关闭时(TIMx_CCER寄存器的CC2E=’0’)才是可写的。
2)3 OCxPE: :输出比较x预装载使能
0:禁止TIMx_CCR1寄存器的预装载功能,可随时写入TIMx_CCR1寄存器,并且新写入的数值立即起作用。
1:开启TIMx_CCR1寄存器的预装载功能,读写操作仅对预装载寄存器操作,TIMx_CCR1的预装载值在更新事件到来时被传送至当前寄存器中。
3)6:4 OCxM[2:0]:输出比较x模式
该3位定义了输出参考信号OC1REF的动作,而OC1REF决定了OC1的值。OC1REF是高电平有效,而OC1的有效电平取决于CC1P位
000:冻结。输出比较寄存器TIMx_CCR1与计数器TIMx_CNT间的比较对OC1REF不起作用;
001:匹配时设置通道1为有效电平。当计数器TIMx_CNT的值与捕获/比较寄存器1(TIMx_CCR1)相同时,强制OC1REF为高。
010:匹配时设置通道1为无效电平。当计数器TIMx_CNT的值与捕获/比较寄存器1(TIMx_CCR1)相同时,强制OC1REF为低。
011:翻转。当TIMx_CCR1=TIMx_CNT时,翻转OC1REF的电平。
100:强制为无效电平。强制OC1REF为低。
101:强制为有效电平。强制OC1REF为高。
剩下的是PWM模式:
4)7 OC1CE:输出比较1清0使能
0:OC1REF 不受ETRF输入的影响;
1:一旦检测到ETRF输入高电平,清除OC1REF=0。

5、CCER控制输出使能和极性

四个通道一个寄存器控制,每个通道两个位,分四份,每4位一组,两位有效,两位保留,
位0 C1E:输入/捕获1输出使能
CC1 通道配置为输出时:
0: 关闭- OC1禁止输出。
1: 开启- OC1信号输出到对应的输出引脚

位1 CC1P:输入/捕获1输出极性
CC1 通道配置为输出:
0:OC1高电平有效
1:OC1低电平有效

6、开中断

此处如需调节占空比就开个溢出中断,不然不需要中断
TIM3->DIER=0;
TIM3->DIER|=1<<0; //UIF:允许更新中断,其实是计数器溢出,

7、开定时器

TIM3->CR1|=1<<0; //使能定时器3
MY_NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2

关于中断服务函数
只有一个溢出中断是自己想要的,其他通道中断无用,中断最后清除所有标志位
工作机制:
通道开始输出低,至CNT=CCRx,电平翻转为高。
至CNT=ARR,触发溢出中断,为CRR写入新值,电平保持高。
至CNT=CRRx,电平翻转为低,注意次翻转的CNT值与上次不同了。
至CNT=ARR,再次写入CRRx最初的值,开始循环,
贴个草图看一下 草图
在这里插入图片描述

以下是完整的配置和中断函数

/**************************************
文件名:TIM_Output_Compare
-------------------------------------------------------------
使用说明:
1、设定定时器3输出比较模式,四通道输出,同频率,占空比、相位可调,高电平时间要求大于Arr-相位,
2、相位与占空比调节工作在中断服务函数中进行
3、不用中断服务函数则输出频率可调,相位可调占空比固定50%的方波
4、IO口不映射   CH1-PA6 CH2-PA7 CH3-PB0 CH4-PB1
5、有效电平为高
6、默认只开溢出中断,无DMA。
7、TIM3_Output_Compare_CH1_Data可随时设置定时器3输出比较波形参数,包括周期、占空比、相位
8、中断服务函数运行机制参考中断服务函数
------------------------------------------------------------
-------------------------------------------------------------
运行环境:#include "sys.h"
------------------------------------------------------------
版本:1.0  
作者:GPY
时间:2018-4-22
描述: 
1、设定定时器3输出比较模式,四通道输出,同频率,占空比、相位可调,高电平时间要求大于Arr-相位,
2、相位与占空比调节工作在中断服务函数中进行
3、不用中断服务函数则输出频率可调,相位可调占空比固定50%的方波
4、IO口不映射   CH1-PA6 CH2-PA7 CH3-PB0 CH4-PB1
5、有效电平为高
6、默认只开溢出中断,无DMA。
7、TIM3_Output_Compare_CH1_Data可随时设置定时器3输出比较波形参数,包括周期、占空比、相位
8、中断服务函数运行机制参考中断服务函数
全局变量:无 
内部函数:
外部函数:
void TIM3_Output_Compare(u16 Arr,u16 Duty);//设定定时器3输出比较模式,四通道输出,同频率,占空比、相位可调,高电平时间要求大于Arr-相位,
u8 TIM3_Output_Compare_CHx_Data(u8 CHx,u16 Duty_Htime,u16 Phase);//设置定时器3输出比较波形参数,包括周期、占空比、相位
**************************************/
#include "TIM_Output_Compare.h"
/*-------------------------------------------
//函数名:TIM3_Output_Compare
//描述:
1、设定定时器3输出比较模式,四通道输出,同频率,占空比、相位可调,高电平时间要求大于Arr-相位,
2、相位与占空比调节工作在中断服务函数中进行
3、不用中断服务函数则输出频率可调,相位可调占空比固定50%的方波
4、IO口不映射   CH1-PA6 CH2-PA7 CH3-PB0 CH4-PB1
5、有效电平为高
6、默认只开溢出中断,无DMA。
//参数:
u16 Arr     周期的二分之一
u16 Duty    翻转时间
//返回值:无
//函数调用列表:u8 TIM3_Output_Compare_CHx_Data(u8 CHx,u16 Duty_Htime,u16 Phase);//设置定时器3输出比较波形参数,包括周期、占空比、相位
---------------------------------------------*/
//初始电平应该是无效    预分频器设为35,即CNT加一时间0.5US,最小时间分辨率0.5us
void TIM3_Output_Compare(u16 Arr,u16 Duty)
{
	/*开时钟*/
	RCC->APB1ENR|=1<<1;	//定时器3时钟使能	
  /*CH1 CH2IO口设置,不重映射   CH1-PA6   CH2-PA7*/
	RCC->APB2ENR|=1<<2;    	//使能PORTA时钟	
	GPIOA->CRL&=0X00FFFFFF;	//PA6 PA7输出
	GPIOA->CRL|=0XBB000000;	//复用功能输出 	  
  /*CH3 CH4IO口设置,不重映射   CH3-PB0   CH4-PB1*/
	RCC->APB2ENR|=1<<3;    	//使能PORTB时钟	
	GPIOB->CRL&=0XFFFFFF00;	//PB0 PB1输出
	GPIOB->CRL|=0X000000BB;	//复用功能输出 	  

//	RCC->APB2ENR|=1<<0;     //开启辅助时钟	   
//	AFIO->MAPR&=0XFFFFF3FF; //清除MAPR的[11:10]
//	AFIO->MAPR|=1<<11;      //部分重映像,TIM3_CH2->PB4
/*设定比较寄存器和计数器溢出值*/
	TIM3->ARR=Arr;			//设定计数器自动重装值,周期
	TIM3->CCR1=Duty;    //高电平时间
	TIM3->CCR2=Duty;    //高电平时间
	TIM3->CCR3=Duty;    //高电平时间
	TIM3->CCR4=Duty;    //高电平时间
/*预分频,72MHz/PSC作为CNT累积时钟*/
 	TIM3->PSC=71;			//预分频器   
/*CH1输出比较设置*/
	TIM3->CCMR1|=0<<0;   //CC1S[1:0]:捕获/比较1 选择,00:CC1通道配置为输出
	TIM3->CCMR1|=0<<3;   //OC1PE:输出比较1预装载使能   0禁止预装载,可随时写入TIM3->CCRx,并写入的数立即生效
	TIM3->CCMR1|=3<<4;   //OC1M[2:0]:输出比较1模式 011:翻转。当TIMx_CCR1=TIMx_CNT时,翻转OC1REF的电平。
	TIM3->CCMR1|=0<<7;   //OC1CE:输出比较1清0使能 0:OC1REF 不受ETRF输入的影响;1:一旦检测到ETRF输入高电平,清除OC1REF=0。
/*CH2输出比较设置*/
	TIM3->CCMR1|=0<<8;   //CC2S[1:0]:捕获/比较1 选择,00:CC2通道配置为输出
	TIM3->CCMR1|=0<<11;   //OC2PE:输出比较1预装载使能   0禁止预装载,可随时写入TIM3->CCRx,并写入的数立即生效
	TIM3->CCMR1|=3<<12;   //OC2M[2:0]:输出比较1模式 011:翻转。当TIMx_CCR2=TIMx_CNT时,翻转OC2REF的电平。
	TIM3->CCMR1|=0<<15;   //OC2CE:输出比较1清0使能 0:OC1REF 不受ETRF输入的影响;1:一旦检测到ETRF输入高电平,清除OC2REF=0。
/*CH3输出比较设置*/
	TIM3->CCMR2|=0<<0;   //CC3S[1:0]:捕获/比较1 选择,00:CC3通道配置为输出
	TIM3->CCMR2|=0<<3;   //OC3PE:输出比较1预装载使能   0禁止预装载,可随时写入TIM3->CCRx,并写入的数立即生效
	TIM3->CCMR2|=3<<4;   //OC3M[2:0]:输出比较1模式 011:翻转。当TIMx_CCR3=TIMx_CNT时,翻转OC1REF的电平。
	TIM3->CCMR2|=0<<7;   //OC3CE:输出比较1清0使能 0:OC3REF 不受ETRF输入的影响;1:一旦检测到ETRF输入高电平,清除OC3REF=0。
/*CH4输出比较设置*/
	TIM3->CCMR2|=0<<8;   //CC4S[1:0]:捕获/比较1 选择,00:CC2通道配置为输出
	TIM3->CCMR2|=0<<11;   //OC4PE:输出比较1预装载使能   0禁止预装载,可随时写入TIM3->CCRx,并写入的数立即生效
	TIM3->CCMR2|=3<<12;   //OC4M[2:0]:输出比较1模式 011:翻转。当TIMx_CCR4=TIMx_CNT时,翻转OC4REF的电平。
	TIM3->CCMR2|=0<<15;   //OC4CE:输出比较1清0使能 0:OC1REF 不受ETRF输入的影响;1:一旦检测到ETRF输入高电平,清除OC4REF=0。

/*CH1 CCER控制输出使能和极性*/	
	TIM3->CCER|=1<<0;   	//OC1 输出使能	
  TIM3->CCER|=0<<1;    //CC1P:输入/捕获1输出极性	0:OC1高电平有效
/*CH2 CCER控制输出使能和极性*/	
	TIM3->CCER|=1<<4;   	//OC2 输出使能	
  TIM3->CCER|=0<<5;    //CC2P:输入/捕获1输出极性	0:OC2高电平有效
/*CH3 CCER控制输出使能和极性*/	
	TIM3->CCER|=1<<8;   	//OC3 输出使能	
  TIM3->CCER|=0<<9;    //CC3P:输入/捕获1输出极性	0:OC3高电平有效
/*CH4 CCER控制输出使能和极性*/	
	TIM3->CCER|=1<<12;   	//OC4 输出使能	
  TIM3->CCER|=0<<13;    //CC4P:输入/捕获1输出极性	0:OC4高电平有效

//	TIM3->CR1=0x0080;   	//ARPE使能        自动重装载
  TIM3->DIER=0;
  TIM3->DIER|=1<<0;   //UIF:允许更新中断,其实是计数器溢出,
	
	TIM3->CR1|=1<<0;     //使能定时器3
  MY_NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2
	
  TIM3_Output_Compare_CHx_Data(1,40,90);    //输出通道1的占空比相位设置,可以不在这里加
 	TIM3_Output_Compare_CHx_Data(2,50,90);    //输出通道2的占空比相位设置,可以不在这里加
 	TIM3_Output_Compare_CHx_Data(3,60,90);    //输出通道3的占空比相位设置,可以不在这里加
 	TIM3_Output_Compare_CHx_Data(4,70,90);    //输出通道4的占空比相位设置,可以不在这里加
}

/*-------------------------------------------
//函数名:TIM3_Output_Compare_CH1_Data
//描述:设置定时器3输出比较波形参数,包括周期、占空比、相位
//参数:
u8 CHx         设置通道 1-4
u16 Duty       占空比,此处直接定为高电平时间,注意必须大于 T/2-Phase
u16 Phase      相位
//返回值:
0:设定成功
1:设定失败,高电平时间不合适
//函数调用列表:
---------------------------------------------*/
u16 T3_OutC_CHx_DU[5][2]={55,40,55,40,55,40,55,40,55,40,};    //DU[1]  初始相位 DU[1]/2arr    占空比=(arr-DU[1]+DU[0])/2*arr 
u8 TIM3_Output_Compare_CHx_Data(u8 CHx,u16 Duty_Htime,u16 Phase)
{
	u16 ARR;
	ARR=TIM3->ARR;
	if(Duty_Htime<ARR-Phase)    //占空比数值过小
	{return 1;}
	T3_OutC_CHx_DU[CHx][1]=Phase;
	T3_OutC_CHx_DU[CHx][0]=Duty_Htime+Phase-ARR;	
	return 0;
}

/*-------------------------------------------
//函数名:TIM3_IRQHandler
//描述:定时器3输出比较中断服务函数,设置输出占空比和相位
工作机制:
    通道开始输出低,至CNT=CCRx,电平翻转为高。
    至CNT=ARR,触发溢出中断,为CRR写入新值,电平保持高。
    至CNT=CRRx,电平翻转为低,注意次翻转的CNT值与上次不同了。
    至CNT=ARR,再次写入CRRx最初的值,开始循环,
//参数:
//返回值:无
//函数调用列表:
---------------------------------------------*/
u8 TIM3_Out_T=0;//定时器3溢出次数,主要用来取奇偶数
void TIM3_IRQHandler(void) 
{			
	if(TIM3->SR&1<<0)      //计数器溢出中断
	{
			if(TIM3_Out_T&0x01)      //0 1 交替   进一次溢出中断改变一次CCR的值
			{//通道1
				TIM3->CCR1=T3_OutC_CHx_DU[1][1];        
			}else{TIM3->CCR1=T3_OutC_CHx_DU[1][0];}	
			if(TIM3_Out_T&0x01)      //0 1 交替   进一次溢出中断改变一次CCR的值
			{//通道2
				TIM3->CCR2=T3_OutC_CHx_DU[2][1];        
			}else{TIM3->CCR2=T3_OutC_CHx_DU[2][0];}	
			if(TIM3_Out_T&0x01)      //0 1 交替   进一次溢出中断改变一次CCR的值
			{//通道3
				TIM3->CCR3=T3_OutC_CHx_DU[3][1];        
			}else{TIM3->CCR3=T3_OutC_CHx_DU[3][0];}	
			if(TIM3_Out_T&0x01)      //0 1 交替   进一次溢出中断改变一次CCR的值
			{//通道4
				TIM3->CCR4=T3_OutC_CHx_DU[4][1];        
			}else{TIM3->CCR4=T3_OutC_CHx_DU[4][0];}	
      TIM3_Out_T++;		    //标记溢出次数
	}
	TIM3->SR=0;     //清除所有中断
}





猜你喜欢

转载自blog.csdn.net/qq_27620407/article/details/84429344