// set the output enable - this is only required for TIM1 | TIM8 void pwmBDTRInit(const TIM_TypeDef *tim) { TIM_BDTRInitTypeDef TIM_BDTRInitStruct; TIM_BDTRStructInit(&TIM_BDTRInitStruct); TIM_BDTRInitStruct.TIM_LOCKLevel = TIM_LOCKLevel_OFF; TIM_BDTRInitStruct.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; TIM_BDTRInitStruct.TIM_OSSIState = TIM_OSSIState_Enable; TIM_BDTRConfig((TIM_TypeDef *)tim, &TIM_BDTRInitStruct); }
static void config_tim1( void ) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_BDTRInitTypeDef TIM_BDTRInitStructure; uint16_t TimerPeriod = 0; uint16_t Channel1Pulse = 0, Channel2Pulse = 0, Channel3Pulse = 0, Channel4Pulse = 0; /* Compute the value to be set in ARR register to generate signal frequency at 16 Khz */ //TimerPeriod = (SystemCoreClock / 16000) - 1; // In center aligned mode, counts up and down, so * 2. // TimerPeriod = (84000000 / ( 2 * 14000 )) - 1; TimerPeriod = 1000; /* Compute CCR1 value to generate a duty cycle at 50% for channel 1 */ //Channel1Pulse = (uint16_t) (((uint32_t) 5 * (TimerPeriod - 1)) / 10); Channel1Pulse = 500; /* Compute CCR2 value to generate a duty cycle at 25% for channel 2 */ //Channel2Pulse = (uint16_t) (((uint32_t) 25 * (TimerPeriod - 1)) / 100); Channel2Pulse = 250; /* Compute CCR3 value to generate a duty cycle at 12.5% for channel 3 */ //Channel3Pulse = (uint16_t) (((uint32_t) 125 * (TimerPeriod - 1)) / 1000); Channel3Pulse = 125; // pulse sent to other timer to trigger ADC; // 97 steps from 999 -> 999-97 = 902 Channel4Pulse = 902; /* Time Base configuration */ TIM_TimeBaseStructInit( &TIM_TimeBaseStructure ); // 14 MHz / 1000 steps == 14 kHz TIM_TimeBaseStructure.TIM_Prescaler = PRESCALER; //TIM_TimeBaseStructure.TIM_Prescaler = 65535; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned2; TIM_TimeBaseStructure.TIM_Period = TimerPeriod; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); /* Channel 1, 2 and 3 Configuration in PWM mode */ TIM_OCStructInit( &TIM_OCInitStructure ); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; TIM_OCInitStructure.TIM_Pulse = Channel1Pulse; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Set; TIM_OC1Init(TIM1, &TIM_OCInitStructure); TIM_OCInitStructure.TIM_Pulse = Channel2Pulse; TIM_OC2Init(TIM1, &TIM_OCInitStructure); TIM_OCInitStructure.TIM_Pulse = Channel3Pulse; TIM_OC3Init(TIM1, &TIM_OCInitStructure); TIM_OCStructInit( &TIM_OCInitStructure ); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; TIM_OCInitStructure.TIM_Pulse = Channel4Pulse; TIM_OC4Init(TIM1, &TIM_OCInitStructure); /* Automatic Output enable, Break, dead time and lock configuration*/ TIM_BDTRStructInit( &TIM_BDTRInitStructure ); TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; TIM_BDTRInitStructure.TIM_DeadTime = 11; TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable; TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low; TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure); TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable); TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable); /* Master Mode selection and TRGO update output */ TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_OC4Ref); TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable); /* TIM1 counter enable */ TIM_Cmd(TIM1, ENABLE); /* Main Output Enable */ TIM_CtrlPWMOutputs(TIM1, ENABLE); }
/** * @brief Configures TIM1: channels in PWM mode * @param None * @retval None */ void TIM_Config(void) { TIM_BDTRInitTypeDef TIM_BDTRInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; GPIO_InitTypeDef GPIO_InitStructure; /* GPIOA clock enable */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); /* TIM1 channels pin configuration: TIM1_CH1 -> PA8 */ GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Enable Alternate function on PA8 to be controlled by TIM1 */ GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_2); /* TIM1 clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); /* Time Base configuration */ TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = 100; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); /* Channel 1 Configuration in PWM mode */ TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; TIM_OCInitStructure.TIM_Pulse = 50; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; TIM_OC1Init(TIM1, &TIM_OCInitStructure); /* Automatic Output enable, Break, dead time and lock configuration*/ TIM_BDTRStructInit(&TIM_BDTRInitStructure); TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; TIM_BDTRInitStructure.TIM_DeadTime = 11; TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable; TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High; TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure); /* Main Output Enable */ TIM_CtrlPWMOutputs(TIM1, ENABLE); /* TIM1 counter enable */ TIM_Cmd(TIM1, ENABLE); }
/****************************************************************************** * タイトル : PWM初期設定 * 関数名 : Init_PWM * 戻り値 : int型 0:設定できた 1:設定できない * 引数1 : TIM_TypeDef *型 TIMx TIMx TIMのポインタ * 引数2 : GPIO_TypeDef型 *GPIOx GPIOx GPIOのポインタ * 引数3 : uint16_t型 pin GPIO_Pin_x PINの設定 * 引数4 : int型 frequency PWM周波数[Hz](整数) * 作成者 : 永谷 智貴 * 作成日 : 2014/11/10 ******************************************************************************/ int Init_PWM(TIM_TypeDef * TIMx,GPIO_TypeDef *GPIOx,uint16_t pin,int frequency)//エラーがあれば1、なければ0をreturnする { long TIM_clock=0; int prescaler=0; int period=0; int calc_retry_flag=1; //float error_ratio=0; unsigned short i = 0; Pin_t pin_state;// //システムクロックをRCC_Clocksで取得 SystemCoreClockUpdate(); RCC_ClocksTypeDef RCC_Clocks; RCC_GetClocksFreq(&RCC_Clocks); //TIMのクロックの取得 if((TIM2<=TIMx&&TIMx<=TIM7)||(TIM12<=TIMx&&TIMx<=TIM14)){ TIM_clock=RCC_Clocks.PCLK1_Frequency*((RCC_TIMPRE+1)*2); //PCLK1のTIMプリスケーラ倍したらTIM2-7,12-14のクロックが出てくる }else{ TIM_clock=RCC_Clocks.PCLK2_Frequency*((RCC_TIMPRE+1)*2); //PCLK2のTIMプリスケーラ倍したら上のやつ以外のクロックが出てくる } #ifdef PRINTF_AVAILABLE printf("Init_PWM() start.\nTIM_clock:%d,\n",TIM_clock); #endif //上下の設定可能な周波数の中に納まっているか確認 if(frequency<FREQUENCY_UNDER_LIMIT || frequency>TIM_clock/PRESCALER_UNDER_LIMIT/PERIOD_UNDER_LIMIT) { #ifdef PRINTF_AVAILABLE printf("Error. Frequency value out of range. '%d' - '%d' Requested frequency '%d'\n",FREQUENCY_UNDER_LIMIT,TIM_clock/PRESCALER_UNDER_LIMIT/PERIOD_UNDER_LIMIT,frequency); #endif return 1; //おかしければエラー返して終了 } //prescaler,periodを計算 while(calc_retry_flag) //periodが制限内の最大になるまでprescalerを上げているだけ。計算でも出せるけど、見た目だけはこっちのほうがきれい。 { prescaler++; period=TIM_clock/prescaler/frequency; if(period<=PERIOD_LIMIT) calc_retry_flag=0; if(prescaler>=PRESCALER_LIMIT){ //prescalerが上の制限を超しちゃったらエラーを履くけどそうはならない。 #ifdef PRINTF_AVAILABLE printf("Error. Prescaler value out of range. '%d'-'%d' \n",PRESCALER_UNDER_LIMIT,PRESCALER_LIMIT); #endif return 1; //おかしければエラー返して終了 } } // error_ratio=fabs(((float)TIM_clock/prescaler/period-(float)frequency)/(float)frequency)*100;//周波数の誤差をパーセントで計算。1%以内には納まる。 frequency=TIM_clock/prescaler/period; //設定した数値から算出される周波数 大体同じ。 #ifdef PRINTF_AVAILABLE printf("Result: \n period:%d,\n prescaler:%d,\n frequency:%d,\n\n",period,prescaler,frequency); #endif //ここから普通のPWM設定 //設定に使用する構造体の宣言 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //TIM設定用構造体宣言 TIM_OCInitTypeDef TIM_OCInitStructure; //OC設定用構造体宣言 TIM_BDTRInitTypeDef TIM_BDTRInitStructure; //クロック供給 RCC_PeriphClock_TIM(TIMx);//TIMクロック供給 //クロック供給とGPIO設定 Init_port(GPIO_Mode_AF,GPIOx,pin,GPIO_PuPd_NOPULL,GPIO_OType_PP); //TIM設定 TIM_TimeBaseStructure.TIM_Period = period-1; //計算したperiod-1 TIM_TimeBaseStructure.TIM_Prescaler = prescaler-1; //計算したprescaler-1 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //なんかここ変えても周波数変わらなかったんだよね ナニコレ TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //カウンターモードアップ設定 TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //高機能タイマー用 基本0 TIM_TimeBaseInit(TIMx,&TIM_TimeBaseStructure); //設定書き込み TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //PWMモード1 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //アクティブレベル時の極性をHighレベルにセット TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //タイマ出力を有効化 TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set; TIM_OC1Init(TIMx,&TIM_OCInitStructure); //初期化 TIM_OC1PreloadConfig(TIMx,TIM_OCPreload_Disable); //プリロード不許可 TIM_OC2Init(TIMx,&TIM_OCInitStructure); //初期化 TIM_OC2PreloadConfig(TIMx,TIM_OCPreload_Disable); //プリロード不許可 TIM_OC3Init(TIMx,&TIM_OCInitStructure); //初期化 TIM_OC3PreloadConfig(TIMx,TIM_OCPreload_Disable); //プリロード不許可 TIM_OC4Init(TIMx,&TIM_OCInitStructure); //初期化 TIM_OC4PreloadConfig(TIMx,TIM_OCPreload_Disable); //プリロード不許可 //使用するピンをTIMの出力として設定 // GPIO_PinAFConfig(GPIOx,Pin_select_source(pin),Tim_select_af(TIMx));//AF設定 /*TIM1とTIM8はSTM32の中でも高機能タイマに分類され、 モータ制御用に使用されるBREAK入力機能がついている このBREAK機能の中でoutputの有効化という機能があり、デフォルトの設定で タイマー出力ごとにoutputが無効に設定されているためPWM信号が止まる。 そのため、 タイマの更新イベントごとにoutputが自動的に再有効になるように設定する。*/ if(TIMx == TIM1 || TIMx == TIM8){ TIM_BDTRStructInit(&TIM_BDTRInitStructure); TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; TIM_BDTRConfig(TIMx, &TIM_BDTRInitStructure); TIM_CtrlPWMOutputs(TIMx, ENABLE); } Analysis_GPIO_Pin(pin, &pin_state); for (i = 0; i < 16; i++){ if (pin_state.user_pin[i] == 1){ GPIO_PinAFConfig(GPIOx, Pin_select_source(pin_state.pin_address[i]), Tim_select_af(TIMx));//AF設定 } } //ミニMDではしない方が良さげ TIMx->CCR1=0;TIMx->CCR2=0;TIMx->CCR3=0;TIMx->CCR4=0; //一応duty全部0%にしておく TIM_ARRPreloadConfig(TIMx,ENABLE);//プリロード設定の適用 TIM_Cmd(TIMx,ENABLE);//タイマー有効化 return 0; }
/* Инициализация таймера и ШИМ */ extern "C" void hal_TIM2_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure; TIM_OCInitTypeDef TIM_OC_InitStructure; TIM_BDTRInitTypeDef TIM_BDTRInitStructure; //Initialize clocks for TIM2 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //Initialize clocks for GPIOA, AFIO RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* //Configure pin TIM2 CH1 = PA0 as alternative function push-pull GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; */ //GPIO_Init(GPIOA, &GPIO_InitStructure); //Configure TIM2 time base TIM_DeInit(TIM2); TIM_TimeBaseStructInit( &TIM_TimeBase_InitStructure ); TIM_TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBase_InitStructure.TIM_Period = 65000; TIM_TimeBase_InitStructure.TIM_Prescaler = 0; TIM_TimeBaseInit(TIM2, &TIM_TimeBase_InitStructure); TIM_OCStructInit( &TIM_OC_InitStructure ); TIM_OC_InitStructure.TIM_Pulse = 130; TIM_OC_InitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OC_InitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OC_InitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //TIM_OC1Init(TIM2, &TIM_OC_InitStructure); // Automatic Output enable, Break, dead time and lock configuration TIM_BDTRStructInit(&TIM_BDTRInitStructure); TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; //TIM_BDTRConfig(TIM2, &TIM_BDTRInitStructure); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); /* Enable the TIM Update Interrupt */ /* 1 bit for pre-emption priority, 3 bits for subpriority */ NVIC_SetPriorityGrouping(1); /* Enable the TIM2 Interrupt */ NVIC_SetPriority(TIM2_IRQn, 0x01); /* 0x00 = 0x01 << 3 | (0x00 & 0x7*/ NVIC_EnableIRQ(TIM2_IRQn); /* Enable TIM2 interrupt */ TIM_Cmd(TIM2, ENABLE); /* TIM counter enable */ return; }