3. 課題 2: PWM 信号を生成し、デューティサイクルと周波数を計測する
3.6. プロジェクトの生成とコードの開発
以上で、必要な全てのドライバが追加されました。次にプロジェクトを生成し、以下を実行するための コードを追加します。
• RTC ISR内でPWMのデューティサイクルを変更する
• 与えられたPWM信号のデューティサイクルと周波数を計算する
• 計算したデューティサイクルと周波数をUSART経由で送信する
To do: プロジェクトを生成します。
1. ウィンドウの最下段にある ボックスをクリックします。
Info: [Project Summary] ウィンドウには、変更されたファイルと、この再構成されたプ
ロジェクトに追加されたファイルの一覧が表示されます。ここには、新しいドライバフ ァイルと設定済みドライバファイルが全て表示されます。
tinyAVR 1 シリーズのトレーニング
Info: main.c ファイルを選択すると、新しい空白の main.c ファイルが生成されます。
3. 生成されたプロジェクト内の全ての設定済みドライバが system_init() 関数によって初期化され る事を確認します。
Tip: src → driver_init.c → system_init()
Result: 設定済みドライバを使ってプロジェクトが生成されます。
To do: TCAによって生成される PWM信号のデューティサイクルを変更するためのコードを
RTC ISR内に追加します。
1. driver_isr.c ファイルを開きます。
2. ISR より前でデューティサイクル変数を定義します。この変数は 10 に初期化され(初期デューティ
サイクル = 10%)、ISR内で変更されます。
3. 以下のコードを ISRの中に追加します。このコードは、ISR内でデューティサイクルを10%ずつ変 更します(100%に達した後は10%にロールオーバーします)。
Info: CMP0レジスタは、TCA PWMのデューティサイクルを決定します。
4. <F7>を押してプロジェクトをビルドします(ビルドは、エラーが発生する事なく正常に完了する必 要があります)。
5. <Ctrl + Alt + F5>を押す事により、更新したコードをデバイスにプログラミングします。
6. 下図の通り、ATtiny Xplained Pro上のPB0とPB4の間をケーブルで接続します。
change_duty_cycle+=10;
if (change_duty_cycle >100) {
change_duty_cycle =10;
}
TCA0.SINGLE.CMP0 = change_duty_cycle;
volatile uint8_t change_duty_cycle=10;
tinyAVR 1 シリーズのトレーニング
図3-11. ハードウェア接続
Note: EXT1コネクタでは、「1」のピン列(上面)が左側のピンラベル列に対応し、「2」のピン列
(下面)が右側のピンラベル列に対応します。従って PB0 は「1」のピン列(上面)にあり、PB4 は
「2」のピン列(下面)にあります。
Info: TCA PWM出力はPB0ピンで生成され、LEDはATtiny Xplained Proボード上の PB4 ピンに接続しています。従って、PB0と PB4を接続する事で、生成された PWM信 号のデューティサイクルに応じてLEDの輝度が変化します。
Result: PWMデューティサイクルを変更するとLEDの輝度が変化する事を観察します。
To do: 与えられたPWMのデューティサイクルと周波数を計算するためのコードを追加します。
tinyAVR 1 シリーズのトレーニング
キャプチャ レジスタが読み出されるか割り込みフラグがクリアされた時点で、次のキャプチャ シーケン スに備えてTCの準備が完了します。
1. main.c ファイルを開きます。
2. 以下の通り、main() の前で、タイマレジスタを読み出すための変数と、計算したデューティサイ クルと周波数を保存するための変数を定義します。
3. デューティサイクルと周波数を計算するために、以下のコードを while(1) ループの中に追加しま す。
Info: TCB0.INTFLAGS は、キャプチャした値が利用可能になった時にセットされます。
このフラグは、フラグに「1」を書き込む事によってクリアします。周期は TCB0.CNT レ ジスタを介して読み出され、パルス幅は TCB0.CCMP レジスタを介して読み出されます。
デューティサイクルは「%」を単位として計算されます。キャプチャした周波数の単位は
「Hz」です。
To do: 与えられたPWM信号のデューティサイクルと周波数の計算値をUSART経由で送信す
るためのコードを追加します。
500 ms周期でRTC割り込みが生成されてデューティサイクルが変更されるため、デューティサイクルと
周波数の計算値を各周期後に送信するためのコードを追加します。
1. main.c ファイルを開きます。
2. 以下に示す通り、main() の前で、フラグを 500 ms 周期でセットするための変数と送信バッファ 文字列を定義します。
3. driver_isr.c を開きます。driver_isr.c 内のISRより前で rtc_500ms_flg を extern として定義し ます。
4. driver_isr.c 内のRTC ISRの中で rtc_500ms_flg をセットします。
rtc_500ms_flg=1;
extern uint8_t rtc_500ms_flg;
volatile uint8_t rtc_500ms_flg=0;
const char tx_buf[]={"\ncaptured data:"};
if(TCB0.INTFLAGS) {
TCB0.INTFLAGS=1;
period_after_capture = TCB0.CNT;
pulse_width_after_capture = TCB0.CCMP;
capture_duty = ((pulse_width_after_capture * 100 )/period_after_capture);
if (capture_duty>100) {
capture_duty=0;
}
capture_frequency = F_CPU /period_after_capture;
}
volatile uint16_t period_after_capture = 0;
volatile uint16_t pulse_width_after_capture = 0;
volatile uint8_t capture_duty = 0;
volatile uint16_t capture_frequency = 0;
tinyAVR 1 シリーズのトレーニング
5. 以下に示す通り、main.c ファイル内の main() より前で関数 send_data() を定義します。この 関数は、計算したデューティサイクルと周波数を文字列に変換し、USARTを介して送信します。
6. ファイルの先頭で string.h ファイルをインクルードします。
Info: string.h 内で定義された itoa および ltoa 関数は、デューティサイクルと周波数
を ASCII 文字列に変換します。strcat 関数は、tx_buf とデューティサイクル文字列
および周波数文字列を連結します。その結果得られた tx_data 文字列がターミナルへ送 信されます。USART_0_putc 関数は、データを TXDATA USART レジスタに書き込み ます。
TXDATA は、データレジスタ エンプティフラグ(USART.STATUS 内の DREIF)がセット
されている時にのみ書き込み可能です。このフラグは、レジスタがエンプティであり新 しいデータの書き込みが可能である事を示します。
7. 各500 ms周期の後に send_data() 関数を呼び出すためのコードを while(1) ループの中に追 加します。
8. <F7>を押してプロジェクトをビルドします(ビルドは、エラーが発生する事なく正常に完了する必 要があります)。
9. [Debug] → [Start without Debugging] を選択するか、<Ctrl + Alt + F5>を押す事により、更新し たコードをデバイスにプログラミングします。
10. 下図の通り、ATtiny Xplained Proボード上のPB0とPA5の間をケーブルで接続します。
if (rtc_500ms_flg==1) {
rtc_500ms_flg=0;
send_data();
}
#include <string.h>
void send_data() {
uint8_t i=0;
char duty str[4]={0},freq str[10]={0},tx data[30]={0};
itoa(capture duty, duty str, 10); //duty cycle to ASCII ltoa(capture frequency, freq str, 10); //frequency to ASCII strcat(tx_data,tx_buf);
strcat(tx_data,duty_str);
strcat(tx_data,"% ");
strcat(tx_data,freq_str);
strcat(tx_data,"Hz");
//tx data=tx buf+duty cycle string+frequency string
while(tx_data[i] !=0) {
//check for null character USART_0_write(tx_data[i]); // send data
i++;
} }
tinyAVR 1 シリーズのトレーニング
図3-12. ハードウェア接続(PB0 - PA5)
Info: TCBはPA5でPWM信号をキャプチャするよう設定されており、TCA PWMは
PB0で生成されます。
11. Atmel Studio 7内で、メニューから[Tools] → [Data Visualizer] を選択します。
tinyAVR 1 シリーズのトレーニング
12. [Data Visualizer] ウィンドウ内で、[Configuration] タブをクリックしてから[Serial Port]をダブル クリックします。
13. [Serial Port Control Panel] 内で[EDBG Virtual COM Port] 番号をリストの中から選択し、[Baud rate] を「9600」に設定します。[Open Terminal] ボタンをクリックしてから[Connect] をクリッ クします。
Tip: 接続している ATtiny Xplained Pro ボードの EDBG 仮想 COM ポート番号は、
Windowsの[スタート] → [コントロール パネル] → [デバイス マネージャ] → [ポート]を 選択する事で確認できます。
Result: 与えられた PWM 信号でキャプチャされたデューティサイクルと周波数は、ターミ
ナル ウィンドウに表示されます。
tinyAVR 1 シリーズのトレーニング
最終的なコードを以下に示します。
#include <string.h>
#include <atmel_start.h>
volatile uint16_t period_after_capture = 0;
volatile uint16_t pulse_width_after_capture = 0;
volatile uint8_t capture_duty = 0;
volatile uint16_t capture_frequency = 0;
volatile uint8_t rtc_500ms_flg=0;
const char tx_buf[]={"\ncaptured data:"};
void send_data() {
uint8_t i=0;
char duty_str[4]={0},freq_str[10]={0},tx_data[30]={0};
itoa(capture_duty, duty_str, 10); //duty cycle to ASCII ltoa(capture_frequency, freq_str, 10); //frequency to ASCII
strcat(tx_data,tx_buf); //tx_data=tx_buf+duty cycle string+frequency string strcat(tx_data,duty_str);
strcat(tx_data,"% ");
strcat(tx_data,freq_str);
strcat(tx_data,"Hz");
while(tx_data[i] !=0) //check for null character {
USART_0_write(tx_data[i]); // send data i++;
} }
int main(void) {
/* Initializes MCU, drivers and middleware */
atmel_start_init();
/* Replace with your application code */
while (1) {
if(TCB0.INTFLAGS) {
TCB0.INTFLAGS=1;
period_after_capture = TCB0.CNT;
pulse_width_after_capture = TCB0.CCMP;
capture_duty = ((pulse_width_after_capture * 100 )/period_after_capture);
if (capture_duty>100) {
capture_duty=0;
}
capture_frequency = F_CPU /period_after_capture;
}
if (rtc_500ms_flg==1) {
rtc_500ms_flg=0;
tinyAVR 1 シリーズのトレーニング
send_data();
} } }