/**
************************************* 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************************************/