記事のミス等のお問い合わせはTwitterにてお願いします。その2カテゴリ:工作の基礎マイコン前回は任意の周波数のPWMを生成するためのパラメータを決定しました。今回はその決定したパラメータを実際にプログラムに落とし込む方法を紹介します。レジスタの設定いままでの計算で目的の周波数のPWMを出力する設定は見つかりました。今度は実際にその設定をレジスタに入力していきます。タイマー0のレジスタ設定はP76~78、タイマー1のレジスタ設定はP94~96、タイマー2のレジスタ設定はP112~114に書かれています。8ビットタイマーの「タイマー0,1」と16ビットタイマーの「タイマー1」は分けて紹介したいと思います。8ビットタイマー8ビットタイマーは「タイマー0」と「タイマー2」に搭載されていますがほぼ設定内容は同一なので「タイマー0」を基準に紹介していきます。(分周のところだけ違うのでそこだけ別途説明します)タイマー0における、PWM出力の設定レジスタは「TCCR0A」と「TCCR0B」です。可変周波数PWMを行う場合の波の高さは「OCR0A」レジスタに、duty比を設定する閾値は「OCR0B」レジスタに入力します。それでは、各レジスタの中身を見ていきましょう。PWMを生成するのに使用するレジスタはこの4つですが、下の2つのレジスタは数値を入力するだけなので、詳細な説明は省略します。上の2つのレジスタは各ビットの状態を使ってさまざまな、設定を行っています。それぞれの設定項目別に紹介をしていきます。OC0Aの端子の出力設定(比較A出力選択)「TCCR0Aの第6,7ビット」この項目で確認する必要があるのは、図の赤で囲んだところです。PWMの動作種別(波の形)によって「高速PWM比較A出力選択」か「位相基準PWM動作比較A出力選択」を確認して下さい。波の高さを可変する可変周波数PWMを出力する場合は、ここで出力設定をする「OC0A」端子に対応する、比較レジスタ(PWM生成の閾値)が波の高さを設定するレジスタそのものであるため、この端子からPWMを出力することはできません。そのため、可変周波数PWMを使用する場合は図の赤で示した「標準ポート動作(OC0A切断)」を選択します。COM0A1,COM0A0ともに0となります。可変周波数PWMを使わず、限られた周波数のPWMのみを出力する場合は「OC0A」端子もPWM出力が可能となり、その場合は図の青←で示した「比較一致でLow...」「上昇計数時の比較一致でLow...」の設定を選択します。「TCCR0Aの第4,5ビット」この項目の中身自体は先ほどの設定と大差なく、確認する箇所も同じですが、可変周波数PWMを使用する場合は設定する内容が違うことに注意が必要です。ここで設定を行う「OC0B」端子は、可変周波数PWMを行う場合ではPWMが出力される端子です。COM0B2:0」を選択しなければなりません。(データシートのレジスタの項目名は間違いです)この設定をしないとPWMが正しく出力されないので注意が必要です。(なお、COM0A1,2:11を選ぶと出力波形が反転します)タイマー波形選択「TCCR0Aの第0,1ビット、TCCR0Bの第4ビット」ここの項目ではタイマーで生成される波形の種類を選択します。可変周波数のPWMを生成する場合は波の高さを変更できるようにする必要があるため、TOP値をレジスタで設定できる項目を選ばなければなりません。そのため、図の赤の←で示したTOP値が「OCR0A」で定義できる設定を選択します。WGM00:1)を選択します。WGM00:1)を選択します。可変周波数のPWMを使用しない場合は図の青←で示したTOP値が「$FF(255)」の項目を選択します。この設定項目を保存するレジスタはWGM01とWGM00が「TCCR0A」、WGM02が「TCCR0B」と2つに分かれていることに注意しなければなりません。分周選択この項目では、タイマーに使う分周の値を選択します。必要な分周に応じた項目を選択してください。この項目は同じ8ビットタイマーでも「タイマー0」と「タイマー2」で選択肢が異なるので注意してください。上の画像は「タイマー0」の設定です。「タイマー2」の場合は以下のような選択肢に変わります。このように、同じ分周数でもレジスタに設定する値が変わってくるので注意が必要です。レジスタの設定例これまでに説明した、手順で実際に任意の周波数のPWMを出力する設定を紹介します。今回はシステムクロック16Mhzで出力PWMを1kHzとし、タイマーの波形は位相基準PWMとした場合です。duty比は0.5としておきます。初めに、分周値とTOP値を選定します。(分周は64として代入)計算結果より、TOP値は125となり使用可能範囲であるため、設定パラメータは分周64、TOP値125とします。各レジスタに設定した値を入力していくと以下のようなパラメータとなります。赤字は関係ないor設定できない項目なので0にしています。TOP値を定義する「OCR0A」とduty比を設定する閾値を定義する「OCR0B」には以下のように値をそのまま入力させます。OCR0A=125OCR0B=OCR0A*0.5=62このように設定することで任意の周波数のPWMを生成することができます。16ビットタイマー16ビットタイマー(タイマー1)の場合も8ビットタイマーと同様に設定を行っていきます。データシートのP94~96より、PWMの設定レジスタは「TCCR1A」と「TCCR0B」となっています。可変周波数PWMを使う場合の波の最大値は「OCR1A」or「ICR1」、PWM生成の閾値は「OCR1B」となっています。後者の3つのレジスタは値を設定するレジスタです。16ビットタイマーなので設定できる値は16ビットとなりますが、あくまでAtmega328Pは8ビットマイコンなので8ビットのレジスタを2つ使う形となっています。8ビットタイマーとシステムが近いので違いがある点を絞って紹介をしていきたいと思います。設定レジスタである「TCCR1A」と「TCCR1B」の中身を見てみます。設定レジスタの中身はこのようになっており、タイマーの波形選択である「WGMn」以外の設定は8ビットタイマーと同じ設定です。今回は8ビットタイマーと設定が異なる波形の形の設定を見てみましょう。TCCR1Bの第3,4ビット」8ビットタイマーに比べて設定項目が非常に多くなっています。8ビットタイマーとの違いは主にTOP値の選択項目が多くなっているということで、「0x00FF」「0x01FF」「0x3FF」「OCR1A」「ICR1」と5種類のなかから選ぶことが可能になります。1)を選択すると良いでしょう。1)を選択すると良いでしょう。16ビットタイマーでもほかの設定は8ビットタイマーと同じなので省略します。次に波の高さ(TOP値)やPWMを生成する閾値を設定するレジスタを見てみます。Atmega328Pはあくまで8ビットマイコンなので16ビットの値を1つのレジスタとして扱うことができません。Studioではこれら2つをまとめて「OCR1A」として扱うことが可能になっています。そのため、ほかの8ビットタイマーなどと同様の感覚で使うことが可能です。(この書き方ができない環境の場合はビット演算とビットシフトを使って、それぞれのレジスタに書き込みをする必要があります)レジスタの設定は、8ビットタイマーの時と同様に行います。サンプルプログラム今回は、ある変数に入力された周波数のPWMを生成するプログラムをサンプルとして紹介したいと思います。今回はタイマー0を使用しDuty比は31%に固定としています。(1){}プログラムとしては、TOP値が8ビットに収まる範囲で場合分けをして分周を区切っています。プログラム実行中の周波数を変更も視野に入れたため、念のためPWM周波数を変更する処理を行うときはPWM出力を一旦停止させています。TOP値の計算は前回紹介したものをあらかじめ計算可能な場所のみ計算したものを使用しています。以上で任意の周波数のPWMを出力する方法の紹介は終わりです。次はタイマー割り込みのお話を予定しています。