STM32 输出比较模式

  cheney

    输出比较模式用来控制输出一段波形或者指示一段时间的到来。如果定时器不用来波形输出,使用输出比较模式一个定时器完全可以作为4个小定时器单独使用。测试中发现通道无法直接关闭,去掉时能都还能触发,只能配置为输入通道才能关闭,时间还是不够准,有漂移现象,也就是说,只能当成一个循环定时器来使用,而且精度不是很高,必须采用向下计数模式,不然精度更低,原因不明。

    ##效果
    1. 这4个定时器公用一个计数器。【不能对计数器直接操作】
    2. 独立的使能开关。
    3. 单独的定时时间。
    4. 独立的中断信号。【优先级不能独立配置】
    5. 独立的DMA请求信号产生。

    ##配置
    1. 引脚配置为普通IO口防止误输出。
    2. 选择合适的计数时钟(内部、外部、预分频)。
    3. TIMx_ARR 决定了整个定时器的更新事件时间,限定了4个小定时器单次最长定时时间。
    4. TIMx_CCMR1 和 TIMx_CCMR2 中 CCxS 的两位都为 0 ,使用定时器的输出比较模式。
    5. TIMx_CCER 中 CCxE 单独使能和关闭每个定时器。
    6. TIMx_CCRx 决定了4个小定时器的定时时间。
    7. TIMx_DIER 中 CCxIE 单独的配置每个定时器的中断开关。
    8. TIMx_SR 中 CCxIF 位对应中断源。

    ##函数

    	// 如果需要连续的中断
    	// 需要全局变量传递每个通道的时间
    	u16 gCCMR1Cnt;
    	u16 gCCMR2Cnt;
    	u16 gCCMR3Cnt;
    	u16 gCCMR4Cnt;
    	
    	// 函数: TIM1 初始化函数
    	//		配置为4个小定时器
    	// 参数: 无
    	// 返回: 无 
    	void TIM1_Init(void)
    	{
    		// TIM1时钟使能
    	    RCC->APB2ENR |= APB2_TIM1_EN;
    	
    	    // 设置计数和分频
    		// 1us 的计数周期
    	    TIM1->PSC = 71;
    		// 最长时间为 50ms
    	    TIM1->ARR = 50000;
    		// 清空计数
    		TIM1->CNT = 0;
    	
    	    // 设置通道为输出比较模式 
    		// 根据需要开关注释 
    		// CCM1
    		TIM1->CCMR1 &= ~0x3;
    		// CCM2
    		TIM1->CCMR1 &= ~(0x3<<8);
    		// CCM3
    		//TIM1->CCMR2 &= ~0x3;
    		// CCM4
    		//TIM1->CCMR2 &= ~(0x3<<8);
    	
    		
    		// 设置中断
    		// 根据需要选用
    		// 允许更新中断
    	    //TIM1->DIER |= 1 << 0;	
    		TIM1->DIER |= 1 << 1;
    		TIM1->DIER |= 1 << 2;
    		//TIM1->DIER |= 1 << 3;
    		//TIM1->DIER |= 1 << 4;
    		
    		// 允许触发中断
    	    TIM1->DIER |= 1 << 6;                                                           
    	
    	    // TIM1使能
    	    TIM1->CR1 |= 0x1;
            // 必须使用向下计数模式
            TIM1->CR1 |= 0x1<<4
    	
    	    // 设置中断优先级
    	    //NVIC_SetPriority(TIM1_UP_IRQn, 1);
    	    //NVIC_EnableIRQ(TIM1_UP_IRQn);
    		
    		NVIC_SetPriority(TIM1_CC_IRQn, 1);
    	    NVIC_EnableIRQ(TIM1_CC_IRQn);
    	}
    		
    	// 函数:设置 CCM1 时间
    	// 参数:us -- 微妙时间
    	// 返回:无
    	void Set_TIM1_CCM1(u16 us)
    	{
    		gCCMR1Cnt = us;
    		TIM1->CCR1 = TIM1->CNT - us;
    		TIM1->CCER |= 1<<0;
    	}
    	
    	// 函数:设置 CCM2 时间
    	// 参数:us -- 微妙时间
    	// 返回:无
    	void Set_TIM1_CCM2(u16 us)
    	{
    		gCCMR2Cnt = us;
    		TIM1->CCR2 = TIM1->CNT - us;
    		TIM1->CCER |= 1<<4;
    	}
    	
    	// 函数:设置 CCM3 时间
    	// 参数:us -- 微妙时间
    	// 返回:无
    	void Set_TIM1_CCM3(u16 us)
    	{
    		gCCMR3Cnt = us;
    		TIM1->CCR3 = TIM1->CNT - us;
    		TIM1->CCER |= 1<<8;
    	}
    	
    	// 函数:设置 CCM4 时间
    	// 参数:us -- 微妙时间
    	// 返回:无
    	void Set_TIM1_CCM4(u16 us)
    	{
    		gCCMR4Cnt = us;
    		TIM1->CCR4 = TIM1->CNT - us;
    		TIM1->CCER |= 1<<12;
    	}
    	
    	
    	
    	void TIM1_CC_IRQHandler(void)
    	{
    		if(TIM1->SR & 1 <<1)
    		{
    			TIM1->SR &= ~(1<<1);
    			Set_TIM1_CCM1(gCCMR1Cnt);
    			// do
    			
    		}
    		if(TIM1->SR & 1 <<2)
    		{
    			TIM1->SR &= ~(1<<2);
    			Set_TIM1_CCM2(gCCMR2Cnt);
    			// do
    			
    		}
    		if(TIM1->SR & 1 <<3)
    		{
    			TIM1->SR &= ~(1<<3);
    			Set_TIM1_CCM3(gCCMR3Cnt);
    			// do
    			
    		}
    		if(TIM1->SR & 1 <<4)
    		{
    			TIM1->SR &= ~(1<<4);
    			Set_TIM1_CCM4(gCCMR4Cnt);
    			// do
    			
    		}
    	}