#蓝桥杯嵌入式#PWM模式

参考资料:
      蓝桥杯嵌入式备赛手册
      蓝桥杯嵌入式开发经验分享(9.PWM模式配置)
      蓝桥杯嵌入式开发经验分享(11.输入捕获模式讲解)
      STM32F1 定时器 PWM输入捕获两路
总目录:目录

文章目录

    • PWM简介
    • OC之固定频率、可变占空比
      • pwm.c的编写
      • main.c的编写
    • OC之可变频率、可变占空比
      • 输出两路PWM
      • 按键调节占空比或频率
    • IC之一路PWM的频率和占空比
    • IC之两路PWM的频率和占空比

PWM简介

  • 脉冲宽度调制(Pulse width modulation)
  • 脉冲宽度调制是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的改变
  • 基本原理:控制方式就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替正弦波或所需要的波形。也就是在输出波形的半个周期中产生多个脉冲,使各脉冲的等值电压为正弦波形,所获得的输出平滑且低次谐波少。按一定的规则对各脉冲的宽度进行调制,既可改变逆变电路输出电压的大小,也可改变输出频率

中文STM32手册中8.3.7 定时器复用功能重映射
#蓝桥杯嵌入式#PWM模式_第1张图片
TIM2,TIM3是一样的,都是通用定时器,掌握其中一个,那么另外一个也是相同的配置,只不过是对应的复用引脚不同
#蓝桥杯嵌入式#PWM模式_第2张图片

OC之固定频率、可变占空比

pwm.c的编写

  • 我们首先要捋清楚,PWM都用了什么,那么初始化里面就要有哪些模块的东西
  • 首先是上面说的定时器,TIM2和TIM3都可以
  • 回顾之前的TIM的配置,我们主要用其基础配置
  • 其参考例程在Project ->STM32F10x_StdPeriph_Examples->TIM->TimeBase
  • 为了灵活改变其占空比,我们需要改变时钟的计数值和分频系数,其中arr=1000000/freq - 1
  • 这个频率是用户要求的,因此在初始化函数的参数中加上u32 freq
    #蓝桥杯嵌入式#PWM模式_第3张图片
    #蓝桥杯嵌入式#PWM模式_第4张图片
  • 关于设置arr的原理
    #蓝桥杯嵌入式#PWM模式_第5张图片
  • 以及,TIM中还需要配置NVIC,直接复制过来修改一下优先级即可
    在这里插入图片描述
  • 因为现在没什么能看PWM,所以借助TIM的操作函数进行点灯,同一目录下stm32f10x_it.c中有void TIM2_IRQHandler(void)
  • 在此函数中,直接写管脚
    u8 status = 0;
    u16 cnt = 0;
    void TIM2_IRQHandler(void)
    {
           
      if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
      {
           
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    		if(cnt++ == 500)
    		{
           
    			cnt = 0;
    			led_Control(LED_ALL, status);
    			status = !status;
    		}
      }
    }
    
  • 同时,在初始化函数中,也要加上GPIO的初始化
  • 具体配置可以参考之前的博客(链接),和其中led.c中初始化函数一致
  • 最后,就是本次的PWM的配置
  • 参考例程:Project->STM32F10x_StdPeriph_Examples->TIM->PWM_Output
    #蓝桥杯嵌入式#PWM模式_第6张图片
  • 这里,我们要把脉冲设置为我们的计算值(arr+1)*duty/100
  • 综上,pwm.c为
    #include "pwm.h"
    #include "led.h"
    
    void PWM_OC_Init(u32 freq,u8 duty)
    {
           
    	GPIO_InitTypeDef GPIO_InitStructure;
    	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	TIM_OCInitTypeDef  TIM_OCInitStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    	
    	u32 arr = 1000000 / freq - 1;
    	
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC, ENABLE);
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    	
    	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0 | GPIO_Pin_2;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOC, &GPIO_InitStructure);
    	
    	TIM_TimeBaseStructure.TIM_Period = arr;
    	TIM_TimeBaseStructure.TIM_Prescaler = 71;
    	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE );
    	
    	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    	TIM_OCInitStructure.TIM_Pulse = (arr+1)*duty/100;
    	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    	TIM_OC2Init(TIM2, &TIM_OCInitStructure);
    	TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
    	TIM_ARRPreloadConfig(TIM2, ENABLE);
    	TIM_Cmd(TIM2, ENABLE);
    	
    	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    	NVIC_Init(&NVIC_InitStructure);
    }
    
    u8 status = 0;
    u16 cnt = 0;
    void TIM2_IRQHandler(void)
    {
           
      if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
      {
           
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    		//if(cnt++ == 500)
    		//{
           
    			//cnt = 0;
    			//led_Control(LED_ALL, status);
    			//status = !status;
    		//}
    	GPIO_SetBits(GPIOD, GPIO_Pin_2);
    	GPIO_ResetBits(GPIOD, GPIO_Pin_2);
      }
    }
    

main.c的编写

  • 用TIM_SetCompareX(TIMX,Pulse)改变占空比
  • 这里原本是想通过PWM改变灯的亮度,然而并不明显……
  • 因此,主函数为:
    int main(void)
    {
           
    	u16 LedPWMVal = 0, dir = 1;
    	SysTick_Config(SystemCoreClock/1000);
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    	led_Init();
    	PWM_OC_Init(500, 60);
    	
    	while(1)
    	{
           
    		if(dir)
    			LedPWMVal++;
    		else
    			LedPWMVal--;
    		if(LedPWMVal>665)
    			dir = 0;
    		if(LedPWMVal == 0)
    			dir = 1;
    		TIM_SetCompare3(TIM2, LedPWMVal);
    		Delay_Ms(10);
    	}
    }
    

别忘了吧stm32f10x_tim.c加到工程中再编译

OC之可变频率、可变占空比

输出两路PWM

这里我们设PA6频率为10KHz,占空比为10%,PA7频率为1KHz,占空比为20%

  • 参考例程:Project->STM32F10x_StdPeriph_Examples->TIM->OCTogglemain.c

  • 包含:

  • 全局变量定义
    #蓝桥杯嵌入式#PWM模式_第7张图片

  • TIM和TIMOC初始化#蓝桥杯嵌入式#PWM模式_第8张图片

  • 时钟使能#蓝桥杯嵌入式#PWM模式_第9张图片

  • GPIO初始化#蓝桥杯嵌入式#PWM模式_第10张图片

  • 中断初始化
    #蓝桥杯嵌入式#PWM模式_第11张图片

  • PWM的初始化完成

  • 下面是中断服务函数,在同一目录下打开stm32f10x_it.c
    #蓝桥杯嵌入式#PWM模式_第12张图片

  • 自己定义占空比变量分别执行下列函数

    TIM_SetCompare1(TIM3, capture + (u16)CCR1_Val *zhankong1 );
    TIM_SetCompare1(TIM3, capture + (u16)CCR1_Val *(1-zhankong1));
    
  • 其中,CCRx_Val=频率为72M/72/频率

  • 综上,pwm.c如下

    #include "pwm.h"
    
    __IO uint16_t CCR1_Val = 100;//72000000/72/10000
    __IO uint16_t CCR2_Val = 1000;//72000000/72/1000
    float zhankong1=0.1;
    float zhankong2=1;
    
    void PWM_OC_Init()
    {
           
    	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	TIM_OCInitTypeDef  TIM_OCInitStructure;
    	GPIO_InitTypeDef GPIO_InitStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    	
    	/* TIM3 clock enable */
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    
      /* GPIOA clock enable */
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);
    	
    	TIM_TimeBaseStructure.TIM_Period = 65535;
      TIM_TimeBaseStructure.TIM_Prescaler = 71;
      TIM_TimeBaseStructure.TIM_ClockDivision = 0;
      TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
      TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
    
      TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
      TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
      TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
      TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
      TIM_OC1Init(TIM3, &TIM_OCInitStructure);
    
      TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);
      TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
      TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
      TIM_OC2Init(TIM3, &TIM_OCInitStructure);
      TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable);
    	
    	TIM_Cmd(TIM3, ENABLE);
    
      TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2, ENABLE);
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_Init(GPIOA, &GPIO_InitStructure);
    	
    	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);
    }
    
    uint16_t capture = 0;
    u8 pa6_state=0,pa7_state=0;
    void TIM3_IRQHandler(void)
    {
           
      if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
      {
           
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC1 );
        capture = TIM_GetCapture1(TIM3);
    		if(pa6_state == 0)
    		{
           
    			TIM_SetCompare1(TIM3, capture + (u16)CCR1_Val * zhankong1 );
    			pa6_state = 1;
    		}
    		else
    		{
           
    			TIM_SetCompare1(TIM3, capture + (u16)CCR1_Val * (1 - zhankong1));
    			pa6_state = 0;
    		}
      }
    	if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
      {
           
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
        capture = TIM_GetCapture2(TIM3);
        if(pa7_state == 0)
    		{
           
    			TIM_SetCompare2(TIM3, capture + (u16)CCR2_Val * zhankong2 );
    			pa7_state = 1;
    		}
    		else
    		{
           
    			TIM_SetCompare2(TIM3, capture + (u16)CCR2_Val * (1 - zhankong2));
    			pa7_state = 0;
    		}
      }
    }
    

按键调节占空比或频率

假设KEY1使PA6的占空比增加10%,KEY2使PA7的频率增加1KHz

  • 我们只需增加按键中断处理函数即可,其参考例程在:Project->STM32F10x_StdPeriph_Examples->EXTI->EXTI_Config下的是stmf10x_it.c
    #蓝桥杯嵌入式#PWM模式_第13张图片
  • 在操作函数中修改zhankongxCCRx_Val即可
    void EXTI0_IRQHandler(void)
    {
           
    	Delay_Ms(10);
      if(EXTI_GetITStatus(EXTI_Line0) != RESET)
      {
           
        zhankong1 += 0.1;
        EXTI_ClearITPendingBit(EXTI_Line0);
      }
    }
    u16 pinlv2=1000;
    void EXTI9_5_IRQHandler(void)
    {
           
    	Delay_Ms(10);
      if(EXTI_GetITStatus(EXTI_Line8) != RESET)
      {
           
        pinlv2+=1000;
        CCR2_Val=(u16)(1000000/pinlv2);//72MHz/72
        EXTI_ClearITPendingBit(EXTI_Line8);
      }
    }
    

IC之一路PWM的频率和占空比

  • 关于PWM输入模式的介绍
    #蓝桥杯嵌入式#PWM模式_第14张图片
  • 参考例程:Project->STM32F10x_StdPeriph_Examples->TIM->PWM_Inputmain.c
  • 首先是TIM_IC的初始化:
    #蓝桥杯嵌入式#PWM模式_第15张图片
  • 时钟使能
    #蓝桥杯嵌入式#PWM模式_第16张图片
  • GPIO初始化
    #蓝桥杯嵌入式#PWM模式_第17张图片
  • 中断NVIC初始化
    #蓝桥杯嵌入式#PWM模式_第18张图片
  • 同目录下stm32f10x_it.c
  • 全局变量的定义,其中DutuCycle为占空比,Frequency为频率
    在这里插入图片描述
  • 中断处理函数
    #蓝桥杯嵌入式#PWM模式_第19张图片
  • 根据题目要求灵活改变引脚和时钟通道即可
  • 综上,pwm.c为:
    #include "pwm.h"
    
    void PWM_IC_Init()
    {
           
    	TIM_ICInitTypeDef  TIM_ICInitStructure;
    	GPIO_InitTypeDef GPIO_InitStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    	
    	/* TIM3 clock enable */
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
      /* GPIOA clock enable */
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    	
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_Init(GPIOA, &GPIO_InitStructure);
    	
      NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);
    	
      TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
      TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
      TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
      TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
      TIM_ICInitStructure.TIM_ICFilter = 0x0;
    
      TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);
    
      /* Select the TIM3 Input Trigger: TI2FP2 */
      TIM_SelectInputTrigger(TIM3, TIM_TS_TI2FP2);
    
      /* Select the slave Mode: Reset Mode */
      TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
    
      /* Enable the Master/Slave Mode */
      TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);
    
      /* TIM enable counter */
      TIM_Cmd(TIM3, ENABLE);
    
      /* Enable the CC2 Interrupt Request */
      TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);
    }
    
    __IO uint16_t IC2Value = 0;
    __IO uint16_t DutyCycle = 0;
    __IO uint32_t Frequency = 0;
    
    void TIM3_IRQHandler(void)
    {
           
      /* Clear TIM3 Capture compare interrupt pending bit */
      TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
    
      /* Get the Input Capture value */
      IC2Value = TIM_GetCapture2(TIM3);
    
      if (IC2Value != 0)
      {
           
        /* Duty cycle computation */
        DutyCycle = (TIM_GetCapture1(TIM3) * 100) / IC2Value;
    
        /* Frequency computation */
        Frequency = SystemCoreClock / IC2Value;
      }
      else
      {
           
        DutyCycle = 0;
        Frequency = 0;
      }
    }
    
  • 为了直观显示,我们在LCD屏上直接显示占空比和频率,main.c代码如下:
    #include "stm32f10x.h"
    #include "lcd.h"
    #include "pwm.h"
    #include "stdio.h"
    
    u32 TimingDelay = 0;
    
    extern __IO uint16_t IC2Value;
    extern __IO uint16_t DutyCycle;
    extern __IO uint32_t Frequency;
    
    void Delay_Ms(u32 nTime);
    
    //Main Body
    int main(void)
    {
           
    	u8 pwm[20];
    	SysTick_Config(SystemCoreClock/1000);
    	STM3210B_LCD_Init();
    	PWM_IC_Init();
    	LCD_Clear(Blue);
    	LCD_SetTextColor(Black);
    	LCD_SetBackColor(White);
    	
    	
    	while(1)
    	{
           
    		sprintf((char*)pwm, "DutyCycle : %d", DutyCycle);
    		LCD_DisplayStringLine(Line0,pwm);
    		sprintf((char*)pwm, "Frequency : %d", Frequency);
    		LCD_DisplayStringLine(Line2,pwm);
    		Delay_Ms(10);
    	}
    }
    
    //
    void Delay_Ms(u32 nTime)
    {
           
    	TimingDelay = nTime;
    	while(TimingDelay != 0);	
    }
    

IC之两路PWM的频率和占空比

  • 原理图如下:(来自蓝桥杯嵌入式备赛手册)
    #蓝桥杯嵌入式#PWM模式_第20张图片
  • 参考例程:Project->STM32F10x_StdPeriph_Examples->TIM->InputCapturemain.c
  • 时钟捕获初始化,这里由于是要捕获两路PWM,因此需要加上通道1以及中断(即TIM_ICInitStructure.TIM_Channel = TIM_Channel_1|TIM_Channel_2;)以及(TIM_ITConfig(TIM3, TIM_IT_CC1|TIM_IT_CC2, ENABLE);
    #蓝桥杯嵌入式#PWM模式_第21张图片
  • 时钟信号
    #蓝桥杯嵌入式#PWM模式_第22张图片
  • GPIO初始化
    #蓝桥杯嵌入式#PWM模式_第23张图片
  • NVIC初始化
    #蓝桥杯嵌入式#PWM模式_第24张图片
  • 同目录下stm32f10x_it.c
  • 全局变量定义
    在这里插入图片描述
  • 中断处理函数,若没要求占空比的话,例程可以直接用
    #蓝桥杯嵌入式#PWM模式_第25张图片
  • 若是考虑占空比的计算以及两路PWM,那这里的例程和全局变量仅能做一个参考,需要我们自己完善
__IO uint16_t IC3ReadValue1 = 0, IC3ReadValue2 = 0;//
__IO uint16_t DutyCycleValue1 = 0,DutyCycleValue2 = 0;
__IO uint16_t CaptureNumber = 0,CaptureNumber_DC = 0;//捕获计数
__IO uint32_t Capture = 0,Capture_DC = 0;//捕获时间,DC表示下降沿捕获时间
__IO uint32_t TIM3Freq = 0,TIM3DutyCycle = 0;//频率和占空比

__IO uint16_t _IC3ReadValue1 = 0, _IC3ReadValue2 = 0;
__IO uint16_t _DutyCycleValue1 = 0,_DutyCycleValue2 = 0;
__IO uint16_t _CaptureNumber = 0,_CaptureNumber_DC = 0;
__IO uint32_t _Capture = 0,_Capture_DC = 0;
__IO uint32_t _TIM3Freq = 0,_TIM3DutyCycle = 0;
void TIM3_IRQHandler(void)
{
      
	//采用定时器溢出中断,不管定时器频率如何变化,总是会出现定时器溢出中断更新不及时的情况,即计数值已重新技术到比0大的值,但定时器溢出中断未产生
	if(TIM_GetITStatus(TIM3, TIM_IT_CC1) == SET) //捕获1发生捕获事件
	{
     
    	TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);//清楚中断标志位
		if(_CaptureNumber_DC == 0)
		{
     
			//捕获到上升沿,计算时间
			_DutyCycleValue1 = TIM_GetCapture1(TIM3);
			if(_CaptureNumber == 0)
			{
     
				_IC3ReadValue1 = _DutyCycleValue1;
				_CaptureNumber = 1;
			}
			else if(_CaptureNumber == 1)
			{
     
				_IC3ReadValue2 = _DutyCycleValue1; 
				if (_IC3ReadValue2 > _IC3ReadValue1)
					_Capture = (_IC3ReadValue2 - _IC3ReadValue1); 
				else
					_Capture = ((0xFFFF - _IC3ReadValue1) + _IC3ReadValue2); 
				_TIM3Freq = (uint32_t) SystemCoreClock / _Capture;
				_CaptureNumber = 0;
			}
			TIM_OC1PolarityConfig(TIM3, TIM_ICPolarity_Falling);
			_CaptureNumber_DC = 1;
		}
		else if(_CaptureNumber_DC==1)
		{
     
			_DutyCycleValue2 = TIM_GetCapture1(TIM3);
			if (_DutyCycleValue2 > _DutyCycleValue1)
				_Capture_DC = (_DutyCycleValue2 - _DutyCycleValue1); 
			else
				_Capture_DC = ((0xFFFF - _DutyCycleValue1) + _DutyCycleValue2); 
			//计算占空比=下降沿捕获时间/总捕获时间
			_TIM3DutyCycle = _Capture_DC/_Capture;
			//设置为上升沿捕获
			TIM_OC1PolarityConfig(TIM3, TIM_ICPolarity_Rising);
			_CaptureNumber_DC = 0;
		}
  }
	/*Initialize TIM3 CC2 IT*/
	if(TIM_GetITStatus(TIM3, TIM_IT_CC2) == SET) 
	{
     
  		TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
		if(CaptureNumber_DC == 0)
		{
     
			DutyCycleValue1 = TIM_GetCapture2(TIM3);
			if(CaptureNumber == 0)
			{
     
				IC3ReadValue1 = DutyCycleValue1;
				CaptureNumber = 1;
			}
			else if(CaptureNumber == 1)
			{
     
				IC3ReadValue2 = DutyCycleValue1; 
				if (IC3ReadValue2 > IC3ReadValue1)
					Capture = (IC3ReadValue2 - IC3ReadValue1); 
				else
					Capture = ((0xFFFF - IC3ReadValue1) + IC3ReadValue2); 
				TIM3Freq = (uint32_t) SystemCoreClock / Capture;
				CaptureNumber = 0;
			}
			TIM_OC2PolarityConfig(TIM3, TIM_ICPolarity_Falling);
			CaptureNumber_DC = 1;
		}
		else if(CaptureNumber_DC==1)
		{
     
			DutyCycleValue2 = TIM_GetCapture2(TIM3);
			if (DutyCycleValue2 > DutyCycleValue1)
				Capture_DC = (DutyCycleValue2 - DutyCycleValue1); 
			else
				Capture_DC = ((0xFFFF - DutyCycleValue1) + DutyCycleValue2); 
			TIM3DutyCycle = Capture_DC/Capture;
			TIM_OC2PolarityConfig(TIM3, TIM_ICPolarity_Rising);
			CaptureNumber_DC = 0;
		}
	}
}
  • main.c如下:
int main(void)
{
     
	u8 pwm[20];
	SysTick_Config(SystemCoreClock/1000);

	STM3210B_LCD_Init();
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	
	Pwm_Ic_Init();

	while(1)
	{
     
		LCD_DisplayStringLine(Line1,pwm);
		LCD_DisplayStringLine(Line3,pwm);
		Delay_Ms(10);	
	}
}

单路输出利用主从模式,占用另一个通道的CCRX获得高电平时间。
双路输出不能用主从模式,且需要调节上升/下降沿触发。注意要配置TIM_TimeBaseStructure;

你可能感兴趣的:(嵌入式(蓝桥杯))