//ポートをAFで使用する場合の設定 void Init_af_port(GPIO_TypeDef *port,uint16_t pin,uint8_t af,uint16_t mode){ GPIO_InitTypeDef GPIO_InitStructure; //GPIO初期化のための構造体 // uint8_t pin; RCC_PeriphClock_GPIO(port); GPIO_StructInit(&GPIO_InitStructure); //初期化用構造体にパラメータをセットしていくため、いったん初期値に戻す if((mode&0x0f) == PORT_PP){ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //出力ポートのタイプをプッシュプルに指定する }else if((mode&0x0f )== PORT_OD){ GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //出力ポートのタイプをプッシュプルに指定する } if((mode&0xf0) == PORT_PULL_UP){ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; }else if((mode&0xf0) == PORT_PULL_DOWN){ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; }else if((mode&0xf0) == PORT_PULL_NO){ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; } GPIO_InitStructure.GPIO_Pin = pin; //設定するピンを指定する(スイッチのピン・アクティブハイ) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //指定したピンを出力に指定する GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //GPIOのスピードを100MHz(最高速)にセットする GPIO_Init(port, &GPIO_InitStructure); //PORT設定入力 GPIO_PinAFConfig(port,Pin_select_source(pin),af); }
/****************************************************************************** * タイトル : USART設定 * 関数名 : Init_USART * 引数1 : USART_TypeDef型 *USARTx USART番号 * 引数2 : unsigned int型 baudrate ボーレート * 引数3 : GPIO_TypeDef型 *GPIOx_TX TXポート * 引数4 : uint16_t型 pin_TX TXピン * 引数5 : GPIO_TypeDef型 *GPIOx_RX RXポート * 引数6 : uint16_t型 pin_RX RXピン * 作成者 : 石井岳史 * 作成日 : 2014/11/12 ******************************************************************************/ void Init_USART(USART_TypeDef *USARTx,unsigned int baudrate, GPIO_TypeDef *GPIOx_TX ,uint16_t pin_TX, GPIO_TypeDef *GPIOx_RX, uint16_t pin_RX){ //構造体変数を宣言 USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; //モジュールストップ状態の解除 // RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_PeriphClock_USART(USARTx); //GPIOの設定 Init_port(GPIO_Mode_AF,GPIOx_TX,pin_TX,GPIO_PuPd_NOPULL,GPIO_OType_PP); Init_port(GPIO_Mode_AF,GPIOx_RX,pin_RX,GPIO_PuPd_NOPULL,GPIO_OType_PP); //PINをオルタネィテブファンクションに割り当て GPIO_PinAFConfig(GPIOx_TX, Pin_select_source(pin_TX), GPIO_af_USART_select(USARTx));//USART1 TX/PB6 GPIO_PinAFConfig(GPIOx_RX, Pin_select_source(pin_RX), GPIO_af_USART_select(USARTx));//USART1 RX/PB7 //USART1の設定 USART_InitStructure.USART_BaudRate = baudrate; //ボーレートの設定 USART_InitStructure.USART_WordLength = USART_WordLength_8b; //ビット長 USART_InitStructure.USART_StopBits = USART_StopBits_1; //ストップビットの長さ USART_InitStructure.USART_Parity = USART_Parity_No; //パリティの有無 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //ハードウェアフロー制御の有無 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //送信受信の選択 USART_Init(USARTx, &USART_InitStructure); //USART1の設定 USART_Cmd(USARTx, ENABLE); //USART1周辺回路の有効化 USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE); //USART1周辺回路の割込み有効化 //割り込み設定 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //優先度のビット設定 NVIC_InitStructure.NVIC_IRQChannel = USART_irqn_select(USARTx); //有効化するIRQチャンネルの指定 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //割り込みの優先順位(グループ)の指定。0が最優先 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //割り込みの優先順位(サブ)の指定。0が最優先 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //割り込みの有効化 NVIC_Init(&NVIC_InitStructure); //割り込み設定 }
/****************************************************************************** * タイトル : 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; }
void Init_CAN(int can_num,uint8_t CAN_Mode,GPIO_TypeDef *tx_port,uint16_t tx_pin,GPIO_TypeDef *rx_port,uint16_t rx_pin){ /* Define InitTypeDef ---------------------------------------------------*/ CAN_InitTypeDef CAN_InitStructure; /* initialize InitTypeDef -----------------------------------------------*/ CAN_StructInit(&CAN_InitStructure); /* Supply clock source --------------------------------------------------*/ if(can_num == 1){ CAN_DeInit(CAN1); RCC_APB1PeriphClockCmd( RCC_APB1Periph_CAN1, ENABLE); }else if(can_num == 2){ CAN_DeInit(CAN2); RCC_APB1PeriphClockCmd( RCC_APB1Periph_CAN2, ENABLE); } /* Define gpio_config ---------------------------------------------------*/ Init_port(GPIO_Mode_AF,tx_port,tx_pin,GPIO_PuPd_UP,GPIO_OType_PP); Init_port(GPIO_Mode_AF,rx_port,rx_pin,GPIO_PuPd_UP,GPIO_OType_PP); if(can_num == 1){ GPIO_PinAFConfig(tx_port, Pin_select_source(tx_pin), GPIO_AF_CAN1);//Tx GPIO_PinAFConfig(rx_port, Pin_select_source(rx_pin), GPIO_AF_CAN1);//Rx }else if(can_num == 2){ GPIO_PinAFConfig(tx_port, Pin_select_source(tx_pin), GPIO_AF_CAN2);//Tx GPIO_PinAFConfig(rx_port, Pin_select_source(rx_pin), GPIO_AF_CAN2);//Rx } /* Set up CAN function -------------------------------------------------*/ /* タイムトリガ通信モードの有効化・無効化を設定する */ CAN_InitStructure.CAN_TTCM = ENABLE; /* 自動バスオフ管理(Automatic Bus-Off Management)の有効化・無効化を設定する */ CAN_InitStructure.CAN_ABOM = DISABLE; /* 自動再起動モードの有効化・無効化を設定する */ CAN_InitStructure.CAN_AWUM = DISABLE; /* 自動再送信禁止を有効化・無効化する DISABLE: 自動再送信禁止を無効化(つまり再送信は有効) ENABLE: 自動再送信禁止。正常に送信されなくても送信は1回だけ行われる */ CAN_InitStructure.CAN_NART = DISABLE; /* 受信FIFOロックモードの有効化・無効化を設定する */ CAN_InitStructure.CAN_RFLM = DISABLE; /* 送信FIFOの送信順序を指定する。DISABLE:メッセージIDで送信順序が決定される ENABLE:ソフトウェアで送信要求が発生された順番で送信される */ CAN_InitStructure.CAN_TXFP = DISABLE; /* CANのModeを設定する */ // CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; CAN_InitStructure.CAN_Mode = CAN_Mode; /* 再同期ジャンプ幅(CANハードウェアが再同期を行う際のビット幅)を時間単位の数で設定する */ CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; /* CANビットタイミングレジスタ(CAN_BTR)のTS1[3:0]を設定する。 */ CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq; /* CANビットタイミングレジスタ(CAN_BTR)のTS2[2:0]を設定する */ CAN_InitStructure.CAN_BS2 = CAN_BS2_7tq; /* ボーレートプリスケーラ設定する 1〜1024 APB1=42MHz*/ CAN_InitStructure.CAN_Prescaler = 3; //1Mbps if(can_num == 1){ CAN_Init(CAN1, &CAN_InitStructure); }else if(can_num == 2){ CAN_Init(CAN2, &CAN_InitStructure); } #ifdef USE_INTERRUPT_CAN_RX NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); if(can_num == 1){ NVIC_Configuration(CAN1_RX0_IRQn); CAN_ITConfig(CAN1, CAN_IT_FMP0,ENABLE);//message pending Interrupt /* CAN_ITConfig(CAN1, CAN_IT_EWG, ENABLE);//Error passive Interrupt CAN_ITConfig(CAN1, CAN_IT_EPV, ENABLE);//Error passive Interrupt CAN_ITConfig(CAN1, CAN_IT_BOF, ENABLE);//Bus-off Interrupt CAN_ITConfig(CAN1, CAN_IT_LEC, ENABLE);//tLast error code Interrupt CAN_ITConfig(CAN1, CAN_IT_ERR, ENABLE);//Error Interrupt */ }else if(can_num == 2){ NVIC_Configuration(CAN2_RX0_IRQn); CAN_ITConfig(CAN2, CAN_IT_FMP0,ENABLE);//message pending Interrupt /* CAN_ITConfig(CAN2, CAN_IT_EWG, ENABLE);//Error passive Interrupt CAN_ITConfig(CAN2, CAN_IT_EPV, ENABLE);//Error passive Interrupt CAN_ITConfig(CAN2, CAN_IT_BOF, ENABLE);//Bus-off Interrupt CAN_ITConfig(CAN2, CAN_IT_LEC, ENABLE);//tLast error code Interrupt CAN_ITConfig(CAN2, CAN_IT_ERR, ENABLE);//Error Interrupt */ } #endif #ifdef USE_INTERRUPT_CAN_TX if(can_num == 1){ CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE);//Transmit mailbox empty Interrupt }else if(can_num == 2){ CAN_ITConfig(CAN2, CAN_IT_TME, ENABLE);//Transmit mailbox empty Interrupt } #endif }