STM32F1 PWM輸出(標準庫)

/**
  ************************************* Copyright ******************************   
  *                 (C) Copyright 2020,Wenkic,China, GCU.
  *                            All Rights Reserved
  *                              
  *                     By(Wenkic)
  *                    https://blog.csdn.net/Wekic
  *      
  * FileName     : PWM.h   
  * Version      : v1.0     
  * Author       : Wenkic           
  * Date         : 2020-06-16         
  * Description  :    
  * Function List:  
  ******************************************************************************
 */ 
 /********************************End of Head************************************/
#ifndef _PWM_H
#define _PWM_H

#include "stm32f10x.h"

typedef enum _CH
{
 CH1=0x01,
 CH2=0x02,
 CH3=0x04,
 CH4=0x08
}CH_enum;

typedef struct _PWM
{
    u16 Period;    //裝載值
    u16 Prescaler; //分頻係數
}PWM_TypeDef;

extern PWM_TypeDef PWM1;

void Time1_PWM_Init(void);                                                     //定時器1PWM初始化
void TIM_PWM_GetInitDat(u32 Target_Hz,PWM_TypeDef *PWM_Struct);                //計算分頻初始值  (目標頻率,獲取參數)
void adjuctTIM_Fre(TIM_TypeDef* TIMx,PWM_TypeDef PWM_Struct);                  //調整定時器時鐘基準
void Timer1_PWM_Out(u16 CHx,PWM_TypeDef PWM_Struct,FunctionalState NewState);  //通道輸出  //(通道,參數,新狀態)


#endif
/********************************End of File************************************/
/*
************************************* Copyright ******************************
*
*                 (C) Copyright 2020,Wenkic,China, GCU.
*                            All Rights Reserved
*
*                     By(Wenkic)
*                      https://blog.csdn.net/Wekic
*
* FileName     : PWM.c
* Version      : v1.0
* Author       : Wenkic
* Date         : 2020-06-16
* Description  :
* Function List:
******************************************************************************
*/
/********************************End of Head************************************/
#include "PWM.h"
#include "debug.h"
/*                   |
  *TIM5複用功能重映射|
  *------------------|---------------------------|-----------------------------------------------------------------------------|
  *複用功能          | TIM5CH4_IREMAP = 0        |  TIM5CH4_IREMAP = 1                                                         |
  *------------------|---------------------------|-----------------------------------------------------------------------------|
  *TIM5_CH4          | TIM5的通道4連至PA3        |  LSI內部時鐘連至TIM5_CH4的輸入作爲校準使用                                  |
  *------------------|---------------------------|-----------------------------------------------------------------------------|
  *TIM4複用功能重映射|
  *------------------|---------------------------|-----------------------------------------------------------------------------|
  *複用功能          | TIM4_REMAP = 0            |  TIM4_REMAP = 1                                                             |
  *------------------|---------------------------|-----------------------------------------------------------------------------|
  *TIM4_CH1          | PB6                       |  PD12                                                                       |
  *------------------|---------------------------|-----------------------------------------------------------------------------|
  *TIM4_CH2          | PB7                       |  PD13                                                                       |
  *------------------|---------------------------|-----------------------------------------------------------------------------|
  *TIM4_CH3          | PB8                       |  PD14                                                                       |
  *------------------|---------------------------|-----------------------------------------------------------------------------|
  *TIM4_CH4          | PB9                       |  PD15                                                                       |
  *------------------|---------------------------|-----------------------------------------------------------------------------|
  *TIM3複用功能重映射|
  *------------------|---------------------------|-------------------------|---------------------------------------------------|
  *複用功能          | TIM3_REMAP[1:0] = 00      |  TIM3_REMAP[1:0] = 10   |    TIM3_REMAP[1:0] = 01                           |
  *------------------|---------------------------|-------------------------|---------------------------------------------------|
  *TIM3_CH1          | PA6                       |  PB4                    |    PC6                                            |
  *------------------|---------------------------|-------------------------|---------------------------------------------------|
  *TIM3_CH2          | PA7                       |  PB5                    |    PC7                                            |
  *------------------|---------------------------|-------------------------|---------------------------------------------------|
  *TIM3_CH3          |               PB0                                   |    PC8                                            |
  *------------------|-----------------------------------------------------|---------------------------------------------------|
  *TIM3_CH4          |               PB1                                   |    PC9                                            |
  *------------------|-----------------------------------------------------|---------------------------------------------------|
  *TIM2複用功能重映射|
  *------------------|---------------------------|-------------------------|---------------------------|-----------------------|
  *複用功能          | TIM2_REMAP[1:0] = 00      |  TIM2_REMAP[1:0] =01    |   TIM2_REMAP[1:0] = 10    |  TIM2_REMAP[1:0] = 11 |
  *------------------|---------------------------|-------------------------|---------------------------|-----------------------|
  *TIM2_CH1_ETR(2)   | PA0                       |  PA15                   |   PA0                     |  PA15                 |
  *------------------|---------------------------|-------------------------|---------------------------|-----------------------|
  *TIM2_CH2          | PA1                       |  PB3                    |   PA1                     |  PA3                  |
  *------------------|---------------------------|-------------------------|---------------------------|-----------------------|
  *TIM2_CH3          |                     PA2                             |               PB10                                |
  *------------------|-----------------------------------------------------|---------------------------------------------------|
  *TIM2_CH4          |                     PA3                             |               PB11                                |
  *------------------|-----------------------------------------------------|---------------------------------------------------|
  *TIM1複用功能重映射
  *-------------------|--------------------------|-------------------------|---------------------------------------------------|
  *複用功能           | TIM1_REMAP[1:0] = 00     |   TIM1_REMAP[1:0] = 01  |    TIM1_REMAP[1:0] = 11                           |
  *-------------------|--------------------------|-------------------------|---------------------------------------------------|
  *TIM1_ETR           |                     PA12                           |    PE7                                            |
  *-------------------|----------------------------------------------------|---------------------------------------------------|
  *TIM1_CH1           |                     PA8                            |    PE9                                            |
  *-------------------|----------------------------------------------------|---------------------------------------------------|
  *TIM1_CH2           |                     PA9                            |    PE11                                           |
  *-------------------|----------------------------------------------------|---------------------------------------------------|
  *TIM1_CH3           |                     PA10                           |    PE12                                           |
  *-------------------|----------------------------------------------------|---------------------------------------------------|
  *TIM1_CH4           |                     PA11                           |    PE14                                           |
  *-------------------|--------------------------|-------------------------|---------------------------------------------------|
  *TIM1_BKIN          |  PB12                    |   PA6                   |    PE15                                           |
  *-------------------|--------------------------|-------------------------|---------------------------------------------------|
  *TIM1_CH1N          |  PB13                    |   PA7                   |    PE8                                            |
  *-------------------|--------------------------|-------------------------|---------------------------------------------------|
  *TIM1_CH2N          |  PB14                    |   PB0                   |    PE10                                           |
  *-------------------|--------------------------|-------------------------|---------------------------------------------------|
  *TIM1_CH3N          |  PB15                    |   PB1                   |    PE12                                           |
  *-------------------|--------------------------|-------------------------|---------------------------------------------------|
  *
  *--------------------------------------------------------------------------------------------------------------------------
  *PC6 TIM3_CH1
*/
//typedef enum _CH
//{
// CH1=0x01,
// CH2=0x02,
// CH3=0x04,
// CH4=0x08
//}CH_enum;

//typedef struct _PWM
//{
//    u16 Period;    //裝載值
//    u16 Prescaler; //分頻係數
//}PWM_TypeDef;

void Time1_PWM_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); //打開時鐘    
    
    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_8;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);
      
    //初始化TIM1
    TIM_DeInit ( TIM1 );
    //GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);//改變指定管腳的映射
    //TIMx的時間基準校準
    //(1+TIM_Prescaler )/72M)*(1+TIM_Period )=((1+7199)/72M)*(1+9999)=1秒 = 10000
    //  (1+預分頻數)(1+自動重裝值) /系統時鐘  = 時間
    //  Prescaler = SystemCoreClock / 1000 - 1; //得到1KHz (分頻係數)
    //  Period    = n100us - 1;                 //(裝載值)
    TIM_TimeBaseInitTypeDef  Tim_TimeBaseInitStruct; //初始化TIMx的時間基準校準
    /* 配置輸出頻率 */
    Tim_TimeBaseInitStruct.TIM_Period        = 0x18-1;                //自動裝載值(PWM分辨率)
    Tim_TimeBaseInitStruct.TIM_Prescaler     = 3-1;                 //分頻係數(Prescaler = 4,定時器頻率爲14.4KHz )(Prescaler = 9,定時器頻率爲7.2KHz )
    Tim_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1      ;//時鐘分割
    Tim_TimeBaseInitStruct.TIM_CounterMode   = TIM_CounterMode_Up;//計數方向
    TIM_TimeBaseInit(TIM1,&Tim_TimeBaseInitStruct);
    //初始化定時TIMx外設
    TIM_OCInitTypeDef        TIM_OCInitStruct;                    
    TIM_OCInitStruct.TIM_OCMode       = TIM_OCMode_PWM1;        //脈衝寬度調製模式1
    //輸出極性
    TIM_OCInitStruct.TIM_OCPolarity   = TIM_OCPolarity_Low;        //輸出極性         低  
    TIM_OCInitStruct.TIM_OCNPolarity  = TIM_OCNPolarity_High;      //互補輸出極性     高  
    TIM_OCInitStruct.TIM_OCIdleState  = TIM_OCIdleState_Set;       //在空閒時輸出     高  
    TIM_OCInitStruct.TIM_OCNIdleState = TIM_OCNIdleState_Reset;    //在空閒時互補輸出 低 
    TIM_OCInitStruct.TIM_OutputState  = TIM_OutputState_Enable; //PWM輸出使能
    TIM_OCInitStruct.TIM_Pulse        = 9;                      //捕獲比較的脈衝值
    
    TIM_OC1Init(TIM1,&TIM_OCInitStruct);   
    TIM_OC1PolarityConfig(TIM1, TIM_OCPreload_Enable);
    
    TIM_ARRPreloadConfig(TIM1, ENABLE);  //使能預裝載寄存器
    TIM_Cmd(TIM1, ENABLE);               //使能定時器1
    TIM_CtrlPWMOutputs(TIM1, ENABLE);    //pwm輸出
}


    
//素數判斷
int isPrime(u32 n) {
    for (u32 i = 2; i < n; i++) {
        //可以被別的數整除,不是素數
        if (n % i == 0)
            return 0;
    }
    return 1;
}
//質因數分解,分解素數爲止
int getPrimeFactor(u32 n,u32 *out) {    //可以不返回值,此處返回-1表示出錯,返回1表示正常。
    //1以下都不是素數
    if (n < 2)
        return -1;
    //判斷是否是素數,如果是直接輸出
    if (isPrime(n)) {
          *out = n;
        return 1;
    }
    else {
        //遞歸因式分解
        for (u32 i = 2; i < n; i++) {

            if (n % i == 0) {
                getPrimeFactor(n/i,out); //下一輪求素數
                break;
            }
        }
    }
    return 1;
}

//計算分頻初始值  (目標頻率,獲取參數)
void TIM_PWM_GetInitDat(u32 Target_Hz,PWM_TypeDef *PWM_Struct)
{
    RCC_ClocksTypeDef sys;
    RCC_GetClocksFreq(&sys);
    //PWM_hz = sysFre/[(1+Pre)*(1+Per)]
    u32 sysHZ = sys.SYSCLK_Frequency;
    u32 Period=0;
    u32 Prescaler = 0;
    u32 temp = 0;    
    u32 TargetTemp = sysHZ/Target_Hz; //  
    //TargetTemp = (1+Pre)*(1+Per)
    
    //涉及質因數分解,素數
    if(getPrimeFactor(TargetTemp,&temp)==1)
    {
        Period    = TargetTemp/temp;
        Prescaler = temp;        
    }else{
        pr_err("因式分解輸入錯誤");
        return ;
    }
    while(Period>=0xFFFF) //防止溢出,特別是小頻率時
    {
        if(getPrimeFactor(Period,&temp)==1)
        {
            Prescaler *= temp;
            Period     = TargetTemp/Prescaler;            
        }else{
            pr_err("因式分解輸入錯誤");
            return ;
        }
    }
    //因式分解出的最小素數作爲定時器的分頻係數
    PWM_Struct->Period    = Period;      //預裝載值
    PWM_Struct->Prescaler = Prescaler;   //分頻係數
}

//調整定時器時鐘基準
void adjuctTIM_Fre(TIM_TypeDef* TIMx,PWM_TypeDef PWM_Struct)
{
    TIM_TimeBaseInitTypeDef  Tim_TimeBaseInitStruct; //初始化TIMx的時間基準校準
    /* 配置輸出頻率 */
    Tim_TimeBaseInitStruct.TIM_Period        = PWM_Struct.Period-1;      //自動裝載值(PWM分辨率)
    Tim_TimeBaseInitStruct.TIM_Prescaler     = PWM_Struct.Prescaler-1;   //分頻係數(Prescaler = 4,定時器頻率爲14.4KHz )(Prescaler = 9,定時器頻率爲7.2KHz )
    Tim_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1      ;//時鐘分割
    Tim_TimeBaseInitStruct.TIM_CounterMode   = TIM_CounterMode_Up;//計數方向
    TIM_TimeBaseInit(TIMx,&Tim_TimeBaseInitStruct);
}


PWM_TypeDef PWM1;

//(通道,參數,新狀態)
void Timer1_PWM_Out(u16 CHx,PWM_TypeDef PWM_Struct,FunctionalState NewState)
{
  if(NewState == DISABLE)
  { 
     if(CHx&0x01) TIM_SetCompare1(TIM1,0); 
     if(CHx&0x02) TIM_SetCompare2(TIM1,0); 
     if(CHx&0x04) TIM_SetCompare3(TIM1,0); 
     if(CHx&0x08) TIM_SetCompare4(TIM1,0);       
  }else{
     if(CHx&0x01) TIM_SetCompare1(TIM1,PWM_Struct.Period/2); 
     if(CHx&0x02) TIM_SetCompare2(TIM1,PWM_Struct.Period/2); 
     if(CHx&0x04) TIM_SetCompare3(TIM1,PWM_Struct.Period/2); 
     if(CHx&0x08) TIM_SetCompare4(TIM1,PWM_Struct.Period/2);   
  }
}

#if 0 //測試使用
void Use_PWM_Test(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    Time1_PWM_Init();                   //定時器1PWM初始化
    TIM_PWM_GetInitDat(1000000,&PWM1);  //計算時基1MHz PWM
    adjuctTIM_Fre(TIM1,PWM1);           //更新時基
    Timer1_PWM_Out(CH1,PWM1,ENABLE);    //輸出PWM
}
#endif


/********************************End of File************************************/

 

 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章