« OSBDMで使うデバッグ・モード導入装置 (5) | メイン | OSBDMで使うデバッグ・モード導入装置 (6) »

STM8Sマイコンを使った最初のアプリケーション (5)


STM8S-Discovery アプリケーションの方針を決めよう

  プロジェクトができました.このプロジェクト上に,可能な限り簡単に LED を点滅させるアプリケーションを作成します.まずは,設計方針から決めましょう.

デフォルト状態でのクロック周波数

  このアプリケーションでは, LED を所望の周期で点滅させます.そのため,点滅周期の基本となるクロックの状態を調べておきます.

  STM8S マイコン内部のペリフェラルに供給されるクロックは,マスタ・クロック(Master clock)と呼ばれ,いくつかのクロック源から選択することができます.

リセット直後のクロック供給状態

  リセット直後は,高速内部 RC 発振器(High Speed Internal RC oscillator: HSI)が選択されます. HSI の発振周波数(fHSI)は, 16MHz とされています. HSI には,専用分周器があり,リセット後は 8 分周に設定されています.このため,リセット後のマスタ・クロック周波数(fMASTER)は, fHSI ÷ 8 = 2MHz となります.

タイマの分周比を決めよう

  LED の点滅には, TIM3 の PWM(Pulse Width Modulation)出力機能をそのまま使います.すると, TIM3 のチャネル2に接続されている LED は,タイマ周期にしたがって点滅します.

PWM波形とLEDの点滅の関係

  点滅周期,すなわちタイマの周期は,1秒とします. fMASTER が 2MHz でしたから,タイマで必要な分周比は, 200万 ということになります.16ビットのタイマ・カウンタを目一杯使うため,タイマ・カウンタの周期を62500とし,プリスケーラを32分周に設定して,全体の分周比を 200万 としました.

TIM3の分周機能 ソース・コードを書こう

 アプリケーションの方針で決めたように,タイマ TIM3 のチャネル2から, PWM 波形を出力させるだけで,アプリケーションはできそうです.そこで,マイコンのレジスタにひたすら値を書き込むプログラムを作成しました.

//**************************************
//
// main.c : 
//  
// Copyright (c) 2010 noritan.org
//
//**************************************

//======================================
// Type declaration
//======================================
typedef unsigned char byte;
typedef unsigned int  word;

//======================================
// Register map definition.
//======================================
volatile byte TIM3_CR1   @ 0x005320;
volatile byte TIM3_CCMR2 @ 0x005326;
volatile byte TIM3_CCER1 @ 0x005327;
volatile byte TIM3_PSCR  @ 0x00532A;
volatile byte TIM3_ARRH  @ 0x00532B;
volatile byte TIM3_ARRL  @ 0x00532C;
volatile byte TIM3_CCR2H @ 0x00532F;
volatile byte TIM3_CCR2L @ 0x005330;

//======================================
// Constant declaration
//======================================
#define PERIOD  (62500)         // timer counter period
#define DUTY    (PERIOD/2)      // PWM duty value

//======================================
// Main procedure
//======================================
main()
{
  TIM3_PSCR = 5;                // 1/32 prescaler
  TIM3_ARRH = (PERIOD-1) >> 8;  // set period MSB
  TIM3_ARRL = (PERIOD-1);       // set period LSB
  
  TIM3_CCMR2 = 0b01100000;      // Set TIM3CH2 as PWM
  TIM3_CCER1 = 0b00110000;      // Enable TIM3CH2 output
  TIM3_CCR2H = DUTY >> 8;       // Set PWM duty MSB
  TIM3_CCR2L = DUTY;            // Set PWM duty MSB
  
  TIM3_CR1   = 0b00000001;      // Start timer
  
  while (1);                    // loop forever
}

 まあ,これでも動作することはするのですが,まったくエレガントではありません.レジスタの宣言ぐらいは,再利用できるようにヘッダ・ファイルにまとめて欲しいものです.というわけで,ほかの方法を探します.

このプログラムは,最初の頃, TIM3_CCRH / TIM3_CCRL レジスタを単なる16ビットのレジスタとして定義し,16ビットの変数で書き込んでいました.ところが,どうもうまく働きませんでした.

原因は,16ビットのレジスタをアクセスする場合,MSBバイトをアクセスしてからLSBバイトをアクセスするという順にアクセスしなくてはならないという制約によるものです.16ビットのレジスタとして宣言した場合,16ビットのXレジスタによるアクセスを行うプログラムが生成されましたが,これでは,順序が保証されなかったようです.

しかたがないので,8ビットずつのアクセスを行うプログラムを書きました.こういった経緯から,冗長なプログラムになってしまいましたが,これもエレガントではない理由のひとつになっています.

次回は,エレガントなプログラムを作成するための準備をします.

田中範明(noritan.org)

カテゴリ:

トラックバック

このエントリーのトラックバックURL:
http://www.eleki-jack.com/mt/mt-tb.cgi/3817





カテゴリ

会社案内
情報セキュリティおよび個人情報の取り扱いについて

コメントとトラックバックは、spamを予防するために、編集担当が公開の作業をするまで非公開になっています。
コメントはそれぞれ投稿した人のものです。

Powered by
Movable Type 4.1
/*yahoo remove*/