フォト
2021年6月
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30      
無料ブログはココログ

STM32

2021年3月26日 (金)

「Arduino STM32 リファレンス 日本語版」が2万アクセス突破!

何気に自分用にまとめていた「Arduino STM32 リファレンス 日本語版」が2万アクセス突破!
ScrapBox、ページ参照数のカウンター機能があるんですね~ 気付きませんでした)
微妙に閲覧されているんですね。内容的に中途で放置している状況、申し訳ないです。

01_20210326112601

豊四季タイニーBASIC for Arduino STM32」の開発のためのArduino STM32の解析メモ、
ついでにScrapBoxの使い具合を知るために作成したのですが、労力が活用されるのは嬉しいです。

ただし、かつてのNAVERのように、内容を理解していない人が小銭稼ぎで、丸写し転用・公開はノーサンキュです。
NAVERといえば、一次ソース公開者に利益分配するとか言ってましたが曖昧にしたまま、結局は何もせず終了

関連会社のLINEについても、ここにきてやっと以前からエンジニアの間での常識だった問題が
やっと一般にも知られてきましたね~
常識のあるエンジニアさんは、何年も前から「私はLINEは使わない」っていってましたよね~
こういう情報が中々伝わらないのも、日本のマスゴミが、顧客スポンサーの批判報道には消極的だからでしょうね..

2020年5月13日 (水)

SPI接続フラッシュメモリモジュールを入手しました

Aliexpressにて、SPI 接続で利用するフラッシュメモリ W25Q64を見つけ、入手しました。
容量的には64Mビット(8Mバイト)です。3.3Vでの利用します。

 W25Q64 64Mbit 8mbyte Flash Storage Module SPI Interface
01_20200513113001




DIP版は以前から、Arduino用の漢字フォントの格納用に利用していたのですが、

W25q64

ブレッドボード上で使う場合、こんな感じで配線が必要なんですよね。

Demo

今回入手したも―ジュールを使うこと、改善できると思います。


届いた製品


Dscn2645

ちゃんと、梱包されていていい感じです。

Dscn2646

基板に乗っているICは、W25Q64FVでした。使ったことがあるICで、これなら問題なしです。
基板やはんだ付け具合は問題なさそうです。


動作確認

早速、はんだ付けして、3.3V対応の Arduino Uno互換機で動作しました。

Dscn2693

この 3.3V対応のArduino Uno、なかなか重宝しています。

Dscn2694

モジュールには通電が確認出来るLEDが乗っています。

動作確認には、自作のW25Q64ライブラリのサンプルプログラムを利用しました。

  ■ 利用したライブラリ
     Arduino用 SPI接続フラッシュメモリW25Q64ライブラリ
     https://github.com/Tamakichi/Arduino-W25Q64

   03_20200513115801    
   ライブラリにUnique ID取得の際、バイト長にミスがることをあり、修正しました。
  (nopnop2002さん、不具合のご指摘、ありがとうございました)

スケッチを書き込んで、サンプルプログラムにて
フラッシュメモリの種別、ユニークIDの取得、データの読み書き等を行ってみました。

02_20200513120101      
 
正常に認識し、問題無く動作しているようです。

念のため、STM32マイコンでも試して見ましたが、問題なく動作しました。

Dscn2696

3.3V利用には注意が必要ですが、お手軽に大容量(8Mバイト)のメモリが利用出来るようになりました。


2019年6月 1日 (土)

Arduino STM32でキャラクタ液晶ディスプレイを使う

現在ちびちびと Arduino STM32 リファレンス 日本語版 を整備しているにですが、
今回、標準ライブラリの LiquidCrystalライブラリの部分を追記しました。

このライブラリはHD44780コントローラ(互換品含む)を使った
キャラクタ液晶ディスプレイ用のライブラリです。

動作確認として、実際にBluePillボードで制御してみました。

02_5  

利用したキャラクタ液晶ディスプレイ
1602A-V2aitendoでも販売されています)
   表示文字数 16桁×2行 、バックライト付きSTN液晶ディスプレイ
   Aliexpressでは、2ドル以下で購入出来ます。

久しぶりに、パラレル接続のキャラクタ液晶ディスプレイを使いました。
色々と忘れていて、コントラスト調整に戸惑ってしまいました。

今回はとりあえず、4ビットモードで利用しました。
動作電源が5Vのため、BluePillボードの5Vで利用可能なピンを利用しました。
下記がその結線です。

結線表

1602A-V2端子 接続先 備考
VSS BluePill - GND  
VDD BluePill - 5V  
V0 20kΩ半固定抵抗(GND接続) コントラスト調整用
RS BluePill - PA8 5Vトレラントピン利用
RW BluePill - GND LOW(GND)でWモード固定
E BluePill - PA9 5Vトレラントピン利用
D0 (未接続)  
D1 (未接続)  
D2 (未接続)  
D3 (未接続)  
D4 BluePill - PB6 5Vトレラントピン利用
D5 BluePill - PB7 5Vトレラントピン利用
D6 BluePill - PB8 5Vトレラントピン利用
D7 BluePill - PB9 5Vトレラントピン利用
A BluePill - 5V バックライトLED用
K BluePill - GND バックライトLED用


動作確認に利用したスケッチ

#include <LiquidCrystal.h>
#define LCD_RS  PA8
#define LCD_E   PA9
#define LCD_D4  PB6
#define LCD_D5  PB7
#define LCD_D6  PB8
#define LCD_D7  PB9
uint8_t font[]= {
  0b00001010,
  0b00001110,
  0b00011111,
  0b00010101,
  0b00011111,
  0b00011111,
  0b00001110,
 0b00000000,
};
LiquidCrystal lcd(LCD_RS,LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
void setup() {
  lcd.begin(16, 2);
  lcd.createChar(1,font);
  lcd.clear();
  lcd.cursor();
  lcd.blink();
  lcd.setCursor(0, 0);
  lcd.print("Hello, world!");
  lcd.setCursor(0, 1);
  lcd.print("\xc8\xba\x20\xc6\x20\xba\xdd\xca\xde\xdd\xdc\x01");
}
void loop() { }

スケッチは、LiquidCrystalクラスのインスタンス lcd をピン割り付けを指定して生成し、
begin()にて利用開始します。

4ビットモードだと結線数も少なく、割と簡単に制御出来ます。

LiquidCrystalライブラリ は、Printクラスの派生クラスのため、
Serialオブジェクトのような感じで、print()関数が利用出来ます。
数値等の出力も簡単に出来ます。

写真の 「ネコ ニ ホンバンワ」の半角カタカナ表示の部分は、
Arduino IDE環境の文字コードUTF-8コードのため、文字列をそのまま記述することはできません。
UTF-8で半角カタカナ1文字は、3バイトに置き換えられてしまい文字化けします。
ですので、文字コードを16進数表記で記述しています。

また、猫っぽいアイコンは、CGRAM領域にフォントデータを登録して表示しています。
CGRAM領域には、最大8文字(5x8ドット)登録することが出来ます。
lcd.createChar(1,font)にてその登録を行っています。
登録した文字は文字コード0~7にて指定出来ます。
(ただし、文字コード0は文字列終端子と被るのでwrite()で書く必要あり)

登録するフォントデータは8バイトですが、横5ドットは下位5ビットにて定義します。
縦は実際は7ドットのため、最後の8列目は0を設定します。

参考文献
 ・Adafruit Explore & Learn - Wiring a Character LCD
 ・HD44780U (LCD-II)

2019年5月29日 (水)

Arduino STM32のWS2812Bライブラリ(NeoPixel制御ライブラリ) その1

Arduino STM32には、WS2812Bライブラリ(NeoPixel制御ライブラリ)が、
標準で(最初から)用意されています。

このライブラリを使いたいと思い、ドキュメントが無いので
プログラムソースから日本語ドキュメントを作成しました。

Arduino STM32 リファレンス 日本語版
 ┗  WS2812Bライブラリ(NeoPixel制御ライブラリ)

ドキュメントを作成し、ライブラリの仕様を理解した上で
さっそく、BluePillボードで動作確認してみました。

ダメです。このライブラリ、まともに動作しません。
LEDが全く点灯出来ません。
色々とソースを修正して現時点で、やっとLED点灯するももの、
意図したとおりに制御出来ません。

01_8

このライブラリはSPIを使ってパルスを生成しています。
システムクロック72MHzを1/32に分周した2.25MHzのパルス幅 0.444μSを使っています。
  パルス幅 0.444μSは許容範囲、
  1ビットのデータは3パルス幅、
  1つのLEDのRGBデータが24ビット、
  1つのLEDは3×24=72パルス、
   SPIは8パルス(8ビット)なので9バイト分、

これなら1個のLED単位でなんとか制御出来そうなのですが、リセット信号のがマズいようです。
ソースを見た限り、リセット信号の送信がされていないみたいなのですが..

更新
1ビット分の3パルスが0.444μS×3= 1.332 μS、
1.25 μS を超えているのがマズいようです。仕様では±0.6μSは許容範囲なのですが駄目っぽい。
24ビット分のデータの前半と後半部分がちゃんと受信されていないようです。
データはGRB(緑、赤、青)の順番で送信するのですが、
1点ルーレット表示は赤しかちゃんと点灯しません。

現在、ライブラリ修正中です。

2019年5月25日 (土)

Arduino STM32のADC(アナログ・デジタル コンバータ)周辺の調査(2)

前回の続きです。

Arduino STM32で手っ取り早くADCを使うには、analogRead()を利用します。
このanalogRead()を利用した場合、変換に要する時間はどれ程なのでしょうか?

疑問に思い、調べてみました。

STM32F1xでは、次のパラメタの設定値が変換時間を決定します。
1)ADCCLK
      ADCのベースとなるクロックです。次の設定が可能です。
      ・システムクロックの1/2
      ・システムクロックの1/4
      ・システムクロックの1/6
      ・システムクロックの1/8

      Arduino STM32では、デフォルトではシステムクロックを1/6 に分周したクロックが設定されています。

 2)サンプリングタイム 
      サンプリングタイムはADCCLKサイクルを単位として、次の設定が可能です。
      ・1.5 × ADCCLK サイクル
      ・7.5 × ADCCLK サイクル
      ・13.5 × ADCCLK サイクル
      ・28.5 × ADCCLK サイクル
      ・41.5 × ADCCLK サイクル
      ・55.5 × ADCCLK サイクル
      ・71.5 × ADCCLK サイクル
      ・239.5 × ADCCLK サイクル

 
変換に要する時間は次の式で求めることが出来ます。
   Tconv = サンプリングタイム + 12.5 サイクル (サイクル)

デフォルトでは 55.5 × ADCCLK サイクル が設定されています。 

Blue Pillボードをシステムクロック 72MHzで利用した場合、
   ADCCLK  = 72MHz / 6 = 12MHz
   Tconv(サイクル)  =  12.5 + 55.5 = 68 サイクル 
   Tconv(μ秒)         =  1/12e6 × 68 × 1e6 =  5.67 μ(マイクロ)秒

となります。

実際にBluePillボードで測定してみました。

テスト用スケッチ

void setup() {
  Serial.begin(115200);
  pinMode(PA0,INPUT_ANALOG);
}
void loop() {
  uint32_t t1,t2;
  uint16_t v;  
 t1 = micros();  
 v = analogRead(PA0);  t2 = micros();  Serial.print("v=");Serial.print(v);  Serial.print(" t=");Serial.println(t2-t1);  delay(1000); }

実行結果

01_7

測定結果としては、おおよそ7~8μ秒 でした。
呼び出しのオーバーヘッド等もあるので妥当な値でしょう。

次に、変換時間が最短になるよう、ADCCLKとサンプリングタイムを変更してみました。
次の設定に変更します。
  ADCCLK                : システムクロックの1/2
  サンプリングタイム  : 1.5 × ADCCLK サイクル

この設定の場合、変換に要する時間は、
   ADCCLK  = 72MHz / 2 = 36MHz
   Tconv(サイクル)  =  12.5 + 1.5 = 14 サイクル 
   Tconv(μ秒)         =  1/36e6 × 14 × 1e6 =  0.38 μ(マイクロ)秒

変更したスケッチ

#include <libmaple/adc.h>
void setup() {
  Serial.begin(115200);
  adc_set_prescaler(ADC_PRE_PCLK2_DIV_2);
  adc_set_sample_rate(PIN_MAP[PA0].adc_device,ADC_SMPR_1_5);
  pinMode(PA0,INPUT_ANALOG);
}
void loop() {
  uint32_t t1,t2;
  uint16_t v;  
 t1 = micros();  
 v = analogRead(PA0);  t2 = micros();  Serial.print("v=");Serial.print(v);  Serial.print(" t=");Serial.println(t2-t1);  delay(1000); }

実行結果

02_4

測定結果としては、おおよそ2~3μ秒 でした。
デフォルト設定の実測値 7~8μ秒より、約5μ秒短縮出来ました。
計算値上でも5.3μ秒の短縮(5.67⇒0.38)ですので、オーバヘッドが2μ秒程度であることがわかります。
ですので、高速化時の測定結果 2~3μ秒(うちオーバヘッドが2μ程度)は妥当な値でしょう。

高速化のスケッチのADCCLK、サンプリングタイムの変更は、前回 ちょっこと触れた
 ・アナログ - デジタル変換(ADC)のサポート Analog to Digital Conversion (ADC) support(adc.h)
のAPI関数を利用しています。

analogRead() を使って、簡単なADCを行う分においては、
デフォルト設定と高速化でそれほど大きな差はないので、デフォルトのまま利用して問題ないと思います。
ただし、DMAを使って多チャンネルのADCを行う場合は、このパラメタの変更はかなり有効になってきます。

2019年5月24日 (金)

Arduino STM32のADC(アナログ・デジタル コンバータ)周辺の調査(1)

BluePillボード(STM32F103C8T6搭載) + Arduino STM32 の環境で、
ADC(アナログ・デジタル コンバータ)を使うためのライブラリを調べています。

STM32のADC機能はArduino Unoと比べるとかなり高機能・高性能なのですがその分、複雑です。
下図は「中容量及び大容量 STM32F101xx 及び STM32F103xx 高性能 ARM ベース32bit MCU(RM0008)」
の「10.3 ADC の機能詳細」からの引用です。雰囲気的に高機能だとわかると思います。

01_6
図を簡単に解説すると、
  ・最大16チャンネルをグループ化して不定期 or 周期的サンプリングが出来る(レギュラー・グループ)
     ADCx_IN0~ADCx_IN15(ただし、ADCコンバータは2機or3機なので同時にではなく各チャンネルを順次変換)
  ・上記のグループに割り込んでADCして最大4つのデータが別途保持できる(インジェクト・グループ)
  ・AD変換開始の様々なトリガーの設定が出来る
  ・サンプルレートの設定が出来る(ADCCLK×選択サイクル数、ADCCLKはシステムクロックの分周選択)
  ・AD変換完了の割り込みが利用可能(レギュラー・グループ 変換完了、インジェクト・グループ完了、アナログ閾値監視ウオッチドック)
  ・DMAを使って、CPUが介在しないマルチチャンネルサンプリングが出来る
  ・マルチチャンネルサンプリング において、各チャンネルに異なるサンプリング周期の指定が出来る 

ADCを使うにあたり、次のライブラリ or APIが用意されています。
1)analogRead()関数       ・・・  Arduino互換関数(ただし分解能は12ビット)
2)STM32ADCライブラリ  ・・・  多チャンネルサンプリング、DMA利用等の機能が利用できる
3)Analog to Digital Conversion (ADC) support(adc.h)  ・・・下位ライブラリ

これらは下記にてリファレンスマニュアルとまとめ中です。

 Arduino STM32 リファレンス 日本語版
    ┣ 1) analogRead()関数
    ┣ 2) STM32ADC 高機能アナログ - デジタル変換(ADC)ライブラリ
    ┗ 3) Analog to Digital Conversion (ADC) support(adc.h) アナログ - デジタル変換(ADC)のサポート

現在、2)STM32ADCライブラリを詳しく調査しています。
このライブラリは、ADCブログ図のかなりの部分をカバーしているライブラリで、
DMAを利用した高速多チャンネルサンプリング等をサポートしています。
中々、強力なライブラリです。

ただし、調査そ進めていくと、いくつかの不具合を見つけました。

現時点で見つけた不具合
 (1)コンパイル時、一部の関数のリンクに失敗する。
     その関数を呼び出すと、暴走(フリーズ?)する。
 (2)readVcc()、readTemp()で取得する値が正しくない。

このライブラリの実装、イージーミスが多く、テスト不十分のようです。

Blue PillボードではADCは2個、ADC接続端子は外部端子として10チャンネル、
内部端子は2チャンネル(内部温度センサ用、内部基準電圧測定用)があります。
このあたりの機能について、上記のライブラリと合わせてもう少し調べてまとめて行きたいと思います。


2019年4月 9日 (火)

豊四季Tiny BASIC for Arduino STM32用基板を頂きました

Facebookのお友達から、豊四季Tiny BASIC for Arduino STM32用の基板を頂きました (^_^)

Dscn9939

早速、手持ちのパーツをかき集めて組み立てみました。

Dscn9940

完成しました。
やはり専用基板があると、組み立てが楽ちんです。

Dscn9956

GROVE端子にてCardKeyBoard(PS/2インタフェース改造版)が直接接続可能です。
まずは、NTSC版のファームウェアを書き込んでの動作確認。
問題なく動作しました。

Dscn9951

次に、TFT版のファームウェアを書き込んでの動作確認。

裏面には3.2インチのTFT液晶の取り付けが可能です。
ひっくり返して、TFT版として利用出来ます。

Dscn9963

こちらも問題なく動作く動作しました。
TFTモジュール側のSDカードスロットでのSDカードの利用も可能です。
漢字フォントを読み込んで、日本語表示も問題無しです。

だだしこのキーボード、やはりちょっと入力しにくいです。
そこで以前製作した USB・PS/2 変換モジュール を思い出し、試しに使ってみました。

Dscn9959

Bluetoothドングルを使ってポケモンキーボードを接続して利用、
いい感じで文字入力出来ました。
USB・PS/2 変換モジュール  を活用することにします。
このケースを3Dプリンターで作ればもう少し小型化も出来ると思います。

う~ん、やはり自分で基板を製作したいですね。
いずれ、チャレンジしたいと思います。
頂いた基板、レイアウトやマルチに使える機能、大変参考になりました^^

2019年4月 1日 (月)

Arduino用 MML文演奏ライブラリの作成 その1

Arduino および Arduino STM32環境で利用できる
MML(Music Macro :ミュージック・マクロ・ランゲージ) 演奏ライブラリを作成中です。
ゲームなんかでも利用できるよう、バックグラウンド演奏にも対応予定です。

01

ハードウェア依存部分を切り離して利用できるようにと、
音を出す処理(実際は関数)をアタッチして利用する形式にしています。
これにより、Arduino、Arduino STM32やMIDI出力等に柔軟に対応できると思います。
02_1

ほぼ完成で、マニュアル作成および動作確認を残すのみです。
ArduinoTVoutとの併用も出来るか等、動作確認をやろうと思っています。

サンプルプログラム
Arduino STM32環境にてBluePillボードを使った単音演奏のサンプルプログラムです。

とりあえず、こんな感じです。
ココログのシステムリニューアルで、不具合が続出で<pre>での
プログラムソースの表示がおかしくなります。

<pre></pre>の中に<br>が追加されたりと、分断されたりと
<pre></pre>ブロックを認識出来ないようです。
システム不具合が改善されてから、改めて修正します。

直接挿入は諦めて、GitHubのgistを使ったソース挿入に変更しました。

2019年3月21日 (木)

BluePillボードで4桁7セグLEDの制御

先日のArduino STM32用タイマー割り込みライブラリを使って、
BluePillボードを使って、4桁7セグLEDをダイナミック点灯にて制御してみました。

Dscn9818

動いている様子



以前、秋月電子で入手して放置していた 4桁7セグLEDはOSL40562-IG を利用しました。
このOSL40562-IGアノードコモンでVFが3.3Vと高く 少々使いにくです。

  ダイナミック接続4桁高輝度緑色7セグメントLED表示器 アノードコモン アノード共通接続 OSL40562-IG

  01


03

とりあえず、次のような回路で駆動させてみました。

02

BluePillボードの5Vトレラント対応のピンを使って駆動させます。
各LEDに流れる電流は5mA程度にしています。
I = (5[V] - Vf[V] ) / 330[Ω]  = (5 - 3.3) /330 = 0.00515[A] ≒ 5[mA]

各桁セグメントDIG1 ~ DIG4は、LED8個分の40mAが流れます。 
BluePillボードでは20mAまでしか流せないため、PNPトランジスタ 2SA1015を使って
駆動させるようにしました。

スケッチ
//
// 4桁高輝度緑色7セグメントLED表示器(アノードコモン) OSL40562-IG の制御
// 2019/03/17 たま吉さん 
// 利用パーツ
//  BluePillボード
//  4桁7セグメントLED  OSL40562-IG x 1
//  桁制御用トランジスタ    2SA1015L-GR x 4
//  LED電流制御用抵抗       330Ω x 8
//  トランジスタベース抵抗  10kΩ x 4
//

#include "TimerEvent.h"

// タイマー割り込み管理
TimerEvent ticker;     
#define REFTIME 4

// デジタルピンの定義
#define DIG1  PB12
#define DIG2  PB13
#define DIG3  PB14
#define DIG4  PB15
#define SEGA  PB3
#define SEGB  PB4
#define SEGC  PB6
#define SEGD  PB7
#define SEGE  PB8
#define SEGF  PB9
#define SEGG  PB10
#define SEGP  PB11

// 桁表示ON・OFF
#define DIG_ON   0
#define DIG_OFF  1

// セグメント表示ON・OFF
#define SEG_ON   0
#define SEG_OFF  1

// セグメントビット定義
#define BIT_A 0b10000000
#define BIT_B 0b01000000
#define BIT_C 0b00100000
#define BIT_D 0b00010000
#define BIT_E 0b00001000
#define BIT_F 0b00000100
#define BIT_G 0b00000010
#define BIT_P 0b00000001

// フォントの定義
const uint8_t font[12] = {
  BIT_A|BIT_B|BIT_C|BIT_D|BIT_E|BIT_F,       // 0
  BIT_B|BIT_C,                               // 1
  BIT_A|BIT_B|BIT_G|BIT_E|BIT_D,             // 2
  BIT_A|BIT_B|BIT_G|BIT_C|BIT_D,             // 3
  BIT_F|BIT_B|BIT_G|BIT_C,                   // 4
  BIT_A|BIT_F|BIT_G|BIT_C|BIT_D,             // 5
  BIT_A|BIT_F|BIT_E|BIT_D|BIT_C|BIT_G,       // 6
  BIT_A|BIT_B|BIT_C,                         // 7
  BIT_A|BIT_B|BIT_C|BIT_D|BIT_E|BIT_F|BIT_G, // 8
  BIT_A|BIT_B|BIT_C|BIT_D|BIT_F|BIT_G,       // 9
  0,                                         // ブランク
  BIT_G,                                     // -
};

// 桁制御ピン
const uint8_t pin_dig[4] = {
  DIG1, DIG2, DIG3, DIG4,
};

// セグメント制御ピン
const uint8_t pin_seg[8] = {
  SEGA, SEGB, SEGC, SEGD, SEGE, SEGF, SEGG, SEGP,
};

// 表示用データ
volatile uint8_t digit[4];

// タイマー割り込み呼び出し関数
void dinamic_update() {
  static uint8_t cnt = 0;
  for (uint8_t i = 0; i < 4; i++)
    digitalWrite(pin_dig[i], DIG_OFF); 
  for (uint8_t i = 0; i < 8; i++)  
     digitalWrite(pin_seg[i], digit[cnt] & (0x80>>i) ? SEG_ON:SEG_OFF);
  digitalWrite(pin_dig[cnt], DIG_ON); 
  cnt++; if (cnt == 4) cnt = 0;
}

// データのクリア
void cls() {
  digit[0] = 0; digit[1] = 0; digit[2] = 0; digit[3] = 0;
}

// 数値の設定
void setNumber(uint16_t n, uint8_t dt = 0) {
  if (n>9999)
    return;

  cls();
  uint8_t dec = 0;
  // 4桁目
  if (n >= 1000) {
    digit[0] =font[ n / 1000]; n = n % 1000; dec = 1;
  }
  // 3桁目
  if (n >= 100) {
    digit[1] = font[n / 100]; n = n % 100; dec = 1;
  } else if (dec) {
    digit[1] = font[0];
  }
  // 2桁目
  if (n >= 10) {
    digit[2] = font[n / 10]; n = n % 10; dec = 1;
  } else if(dec) {
    digit[2] = font[0];
  }
  // 1桁目
  digit[3] = font[n];

  // 小数点
  if(dt && dt <=4) {
    digit[4-dt] |= BIT_P;
  }
}

void setup() { 
  //  桁ピンの初期化
  for (uint8_t i = 0; i < 4; i++) {
    pinMode(pin_dig[i], OUTPUT_OPEN_DRAIN);
    digitalWrite(pin_dig[i], DIG_OFF);
  }

  //  セグメントピンの初期化
  for (uint8_t i = 0; i < 8; i++) {
    pinMode(pin_seg[i], OUTPUT_OPEN_DRAIN);
    digitalWrite(pin_seg[i], SEG_OFF);
  }

  // 表示データの初期化
  for (uint8_t i = 0; i < 4; i++) {
    digit[i] = 0;
  }

  // LEDダイナミック点灯用割り込み設定
  ticker.set(REFTIME, dinamic_update);  // REFTIME間隔で dinamic_update()を呼び出す
  ticker.start();                       // タイマー割り込み実行開始
}

void loop() {
  static uint16_t n = 0;
  setNumber (n,millis()%1000>500?1:0);
  delay(100);
  n++; if (n>9999) n = 0;
}

タイマー割り込みは4m秒間隔で実行させています。
一回の割り込みで4桁のうちの1つを表示させています。
全桁更新周期は 4m秒 x 4 = 16m秒 ≒ 1/60秒 です。
これは、人間の目がちらつきを感じない周期です。
これ以上遅くすると、ちらついて見えます。

電圧を5Vではなく、3.3Vにしても問題なく点灯出来ました。
VF 3.3Vとありますが、実際はもっと低い値のようです。

2019年3月17日 (日)

Arduino STM32用タイマー割り込みライブラリを作成しました

Arduino STM32用のタイマー割り込みライブラリを作成しました。

・Arduino STM32用 簡易タイマー割り込みライブラリ (Tamakichi/STM32_TimerEvent)
  https://github.com/Tamakichi/STM32_TimerEvent

Arduino STM32では、最初から強力なタイマー割り込みライブラリがあるのですが、
少々設定が面倒なので、もう少しお手軽に使えるライブラリを作成しました。
(正確には、ラッパークラスライブラリですね)

次のような感じで使います。
BluePillボード上にあるLEDを0.5秒間隔で点滅するスケッチです。
#include "TimerEvent.h"

#define LED_PIN  PC13 // LEDピン

// タイマー割り込み管理
TimerEvent ticker;     

// タイマー割り込み呼び出し関数
void handle_timer() {
  static uint8_t sw = LOW;
  sw = !sw;
  digitalWrite(LED_PIN, sw);      // LEDの制御
}
 
void setup() {
  pinMode(LED_PIN, OUTPUT);
  ticker.set(500, handle_timer);  // 0.5秒間隔で handle_timer()を呼び出す
  ticker.start();                 // タイマー割り込み実行開始
}

void loop() {

}
 

設定できる割り込み間隔は 1ミリ秒 ~ としています。
利用するハードウェアタイマを明示的に指定することが出来ます。

次のような感じで複数のタイマー割り込みを同時実装することも出来ます。
また、割り込み優先度を指定することが出来ます。

// タイマー割り込み管理
TimerEvent ticker1(Timer1);
TimerEvent ticker2(Timer2);
TimerEvent ticker3(Timer3);
TimerEvent ticker4(Timer4);
・・・

ticker1.set(100, handle_timer1); ticker1.setPriority(14);
ticker2.set(200, handle_timer2);
ticker3.set(400, handle_timer3);
ticker4.set(800, handle_timer4);
・・・

ticker1.start();
ticker2.start();
ticker3.start();
ticker4.start();

上記では、ticker1の優先度をticker2 ~ ticker4 よりも上げています。
ticker1は、ticker2 ~ ticker4の割り込み処理実行中に更に割り込んで実行できます。
ticker1の割り込み実行中は、ticker2 ~ ticker4の割り込み実行は保留されます。

割り込み優先度の設定については、シリアル通信、I2C、ピン変化等の割り込み優先度も
考慮して設定する必要があります。

割り込み優先度は0~15の16レベルがあり、
デフォルトでは、すべての割り込み優先度は最低の15が設定(0が最優先)されています。
ただし、同一の優先度の場合は、割り込みベクター番号が小さいほど優先度が高いです。

このたりの詳細については、Arduino STM32の低レベルAPI nvic.h が参考になると思います。
Nested Vector Interrupt Controller (NVIC) support(nvic.h)


元祖 AVR版Arduinoでも割り込み機能はあるのですが、
優先度が固定のため、特定の割り込み処理中でI2C通信が出来ない等、
(I2Cの割り込み優先度は最低レベルに近い)
多重割り込みを使う場合、場合によっては色々と難儀しました。

その点、ARM cortex M3 の割り込み機構 NVIC はかなり強力で自由度があり
使いやすいです。

より以前の記事一覧