📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

ページの作成:「== 概要 == PWM (Pulse Width Modulation, パルス幅変調) は、電力を制御するための技術である。<br> PWMMは、ON / OFFを高速で切り替えることにより、平均電力を制御したり、パルスのデューティ比 (ON時間とOFF時間の比率) を変えることで出力を調整することができる。<br> <br> DCモータの速度制御、LEDの調光制御、ヒータ等の温度制御、オーディオ信号の増幅 (Class…」
 
文字列「__FORCETOC__」を「{{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{…
 
(同じ利用者による、間の8版が非表示)
25行目: 25行目:
用途に応じて最適な値を選択することが重要である。<br>
用途に応じて最適な値を選択することが重要である。<br>
<br>
<br>
==== PWMの周波数 ===
==== PWMの周波数 ====
PWMの周波数は、1秒間のパルスの数を表す。 (単位は[Hz])<br>
PWMの周波数は、1秒間のパルスの数を表す。 (単位は[Hz])<br>
<br>
<br>
56行目: 56行目:
* 周波数が高すぎると、スイッチング損失が増加して、効率が低下する場合がある。
* 周波数が高すぎると、スイッチング損失が増加して、効率が低下する場合がある。
* デューティ比が0%や100%に近づくと、制御の分解能が低下する。
* デューティ比が0%や100%に近づくと、制御の分解能が低下する。
<br><br>
== デューティ比の計算 ==
クロックが1.1[MHz]の場合、TA0CCR0レジスタの値を999、TA0CCR1レジスタの値を100に設定することにより、デューティ比を10%に設定することができる。<br>
<math>\mbox{ PWM 周 期 } = (\mbox{TA0CCR0} + 1) \times \frac{1}{\mbox{ 分 周 比 }} = 1000 \times 1 = 1000</math><br>
<br>
<math>\mbox{ PWM 周 波 数 } = \frac{\mbox{ ク ロ ッ ク 周 波 数 }}{\mbox{ PWM 周 期 }} = \frac{1.1 \mbox{[MHz]}}{1000} = 1.1 \mbox{[kHz]}</math><br>
<br>
<math>\mbox{ デ ュ ー テ ィ 比 } = \frac{\mbox{TA0CCR1}}{\big( \mbox{TA0CCR0} + 1 \big)} = \frac{100}{1000} = 0.1 = 10[\%]</math><br>
<br>
ただし、クロックが16[MHz]の場合、TA0CCR0レジスタに15999999を代入することはできない。<br>
MSP430G2553のタイマA0は、16ビットタイマであり、最大値は65535 (0xFFFF) だからである。<br>
<br>
したがって、16[MHz]のクロックを使用する場合、以下に示すようにTA0CCR0レジスタとTA0CCR1レジスタの値を設定することができる。<br>
<syntaxhighlight lang="c">
// タイマA0の設定
TA0CTL  = TASSEL_2 | MC_1 | ID_3;  // SMCLK (16[MHz]), アップモード, 分周 1/8 = 2[MHz]のクロックを生成
TA0CCR0 = 20000 - 1;              // PWM周期を1[mS] (1[kHz]) に設定
TA0CCR1 = 2000;                    // デューティ比を10%に設定
</syntaxhighlight>
<br>
上記の設定では、以下のように計算される。<br>
<math>\mbox{ PWM 周 期 } = (\mbox{TA0CCR0} + 1)  \times \frac{1}{\mbox{ 分 周 比 }} = 20000 \times \dfrac{1}{\dfrac{1}{8}} = 20000 \times 8 = 160000</math><br>
<br>
<math>\mbox{ PWM 周 波 数 } = \frac{\mbox{ ク ロ ッ ク 周 波 数 }}{\mbox{ PWM 周 期 }} = \frac{16 \mbox{[MHz]}}{160000} = 1 \mbox{[kHz]}</math><br>
<br>
<math>\mbox{ デ ュ ー テ ィ 比 } = \frac{\mbox{TA0CCR1}}{\big( \mbox{TA0CCR0} + 1 \big)} = \frac{16000}{160000} = 0.1 = 10 [\%]</math><br>
<br>
このように、クロックが16[MHz]の場合は、分周器を使用してクロックを分周して、適切なTA0CCR0とTA0CCR1の値を設定することにより、目的のPWM周期とデューティ比を達成することができる。<br>
<br>
また、上記のサンプルコードでは、、タイマA0のクロックソースとしてSMCLK (Sub-Main Clock) を選択している。<br>
SMCLKは、DCOを分周して生成されるクロックであり、タイマや周辺機器のクロックとして使用されるクロックである。<br>
<syntaxhighlight lang="c">
TA0CTL = TASSEL_2 | MC_1 | ID_0;  // SMCLK (1MHz), アップモード, 分周なし
</syntaxhighlight>
<br>
ここで、TASSEL_2レジスタはクロックソース選択ビットであり、以下のように定義されている。<br>
* TASSEL_0
*: TAxCLK (外部クロック)
* TASSEL_1
*: ACLK (補助クロック、32.768[kHz])
* TASSEL_2
*: SMCLK (サブメインクロック、DCOを分周)
* TASSEL_3
*: INCLK (外部クロック)
<br>
一方、MCLK (Main Clock) は、CPUやその他の一部の周辺機器のクロックとして使用される。<br>
MCLKは、DCOを直接使用する、または、DCOを分周して生成される。<br>
<br>
デフォルトではDCOが1.1[MHz]に設定されており、SMCLKとMCLKはこの周波数で動作する。<br>
ただし、DCOの周波数を変更することにより、SMCLKとMCLKの周波数を変更することができる。<br>
<br><br>
<br><br>


91行目: 142行目:
     P1DIR |= LED_PIN;          // LEDピンを出力に設定
     P1DIR |= LED_PIN;          // LEDピンを出力に設定
   
   
     // タイマーA0の設定
     // タイマA0の設定
     TA0CTL  = TASSEL_2 | MC_1 | ID_0;  // SMCLK (1[MHz]), アップモード, 分周なし
     TA0CTL  = TASSEL_2 | MC_1 | ID_0;  // SMCLK (1[MHz]), アップモード, 分周なし
     TA0CCR0  = 1000 - 1;                // PWM周期を1[mS] (1[kHz]) に設定
     TA0CCR0  = 1000 - 1;                // PWM周期を1[mS] (1[kHz]) に設定
                                        // タイマA0のカウント値が0から999までカウントアップするのに1[mS]掛かるため、-1減算している
     TA0CCR1  = 500;                    // デューティ比を50%に設定
     TA0CCR1  = 500;                    // デューティ比を50%に設定
                                        // デューティ比を10%に設定する場合は、100を指定する
     TA0CCTL1 = OUTMOD_7;                // リセット / セットモード
     TA0CCTL1 = OUTMOD_7;                // リセット / セットモード
   
   
115行目: 168行目:
  </syntaxhighlight>
  </syntaxhighlight>
<br>
<br>
PWM信号の生成は、タイマーA0のハードウェア機能により自動的に行われる。<br>
PWM信号の生成は、タイマA0のハードウェア機能により自動的に行われる。<br>
1度設定されたPWM信号は、割り込みを使用しなくても継続的に出力される。<br>
1度設定されたPWM信号は、割り込みを使用しなくても継続的に出力される。<br>
<br>
<br>
129行目: 182行目:
<br><br>
<br><br>


== サンプルコード : LEDの調光制御 (割り込み処理) ==
以下の例では、PWMのLED調光制御を割り込みを使用して並列に実行して、メイン処理では他の処理を実行している。<br>
<br>
メイン処理で変数duty_cycleの値を変更することにより、割り込み処理でPWMのデューティ比が更新されて、LEDの超高制御を動的に調整できる。<br>
<br>
# タイマA0の設定を行う。
# TA0CCR1の値を設定する。
# グローバル割り込みを有効化する。
# 以下の例では、必要に応じて、変数duty_cycleの値を変更することにより、LEDの調光制御が調整できる。
# タイマA0 CCR1割り込み内で、TA0IVレジスタ (タイマA0の割り込みベクタレジスタ) の値に応じて処理を行う。<br>以下の例では、TA0CCR1レジスタの割り込みが発生した場合に、変数duty_cycleの値でTA0CCR1レジスタを更新する。
<br>
<u>※注意</u><br>
<u><code>volatile</code>を付加して変数duty_cycleを宣言しているが、これは割り込み処理とメイン処理の両方からアクセスされるためである。</u><br>
これにより、最適化によって問題が発生することを防ぐ。</u><br>
<br>
<syntaxhighlight lang="c">
#include <msp430.h>
#define LED_PIN BIT6                    // P1.6ピンにLEDを接続
volatile unsigned int duty_cycle = 100;  // デューティ比の初期値を10%に設定
void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;        // ウォッチドッグタイマを停止
    P1DIR |= LED_PIN;  // LEDピンを出力に設定
    // タイマA0の設定
    TA0CTL = TASSEL_2 | MC_1 | ID_0;  // SMCLK (1MHz), アップモード, 分周なし
    TA0CCR0 = 1000 - 1;              // PWM周期を1[mS] (1[kHz]) に設定
    TA0CCR1 = duty_cycle;            // デューティ比を設定
    TA0CCTL1 = OUTMOD_7;              // リセット / セットモード
    P1SEL |= LED_PIN;                // LEDピンをタイマA0の出力に設定
    __enable_interrupt();  // グローバル割り込みを有効化
    while (1) {
        // ...略
        // 例: 変数duty_cycleの値を変更することにより、LEDの調光制御が調整可能
        // duty_cycle = 500;  // デューティ比を50%に変更する場合
    }
}
// タイマA0 CCR1割り込み
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A1(void)
{
    switch (TA0IV) {
      case 0x02:  // タイマA0のカウンタが、TA0CCR1レジスタの値に達した場合に発生する割り込みがある時、TA0IVレジスタの値は0x02となる
                  // TA0IVレジスタの値が0x02になる場合は、PWM周期ごとにTA0CCR1に関連する割り込みが発生していること
          TA0CCR1 = duty_cycle;  // デューティ比を更新
          break;
    }
}
</syntaxhighlight>
<br><br>
{{#seo:
|title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki
|keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,電気回路,電子回路,基板,プリント基板
|description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux
|image=/resources/assets/MochiuLogo_Single_Blue.png
}}


__FORCETOC__
__FORCETOC__
[[カテゴリ:MSP430]]
[[カテゴリ:MSP430]]