• 検索結果がありません。

プロジェクトの生成とコードの開発

ドキュメント内 Getting Started with the tinyAVR 1-series (ページ 30-39)

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();

} } }

tinyAVR 1 シリーズのトレーニング

ドキュメント内 Getting Started with the tinyAVR 1-series (ページ 30-39)

関連したドキュメント