tmpm330...
TRANSCRIPT
Rev 2.0
2010 年 5 月
SP-03-301J
TMPM330
アプリケーションノート
製品取り扱い上のお願い
本資料に掲載されているハードウェア、ソフトウェアおよびシステム(以下、本製品という)に関する情報等、本資料の掲載内容は、技術の進歩などにより予告なしに変更されることがあります。
文書による当社の事前の承諾なしに本資料の転載複製を禁じます。また、文書による当社の事前の承諾を得て本資料を転載複製する場合でも、記載内容に一切変更を加えたり、削除したりしないでください。
当社は品質、信頼性の向上に努めていますが、半導体製品は一般に誤作動または故障する場合があります。本製品をご使用頂く場合は、本製品の誤作動や故障により生命・身体・財産が侵害されることのないように、お客様の責任において、お客様のハードウェア・ソフトウェア・システムに必要な安全設計を行うことをお願いします。なお、設計および使用に際しては、本製品に関する 新の情報(本資料、仕様書、データシート、アプリケーションノート、半導体信頼性ハンドブックなど)および本製品が使用される機器の取扱説明書、操作説明書などをご確認の上、これに従ってください。また、上記資料などに記載の製品データ、図、表などに示す技術的な内容、プログラム、アルゴリズムその他応用回路例などの情報を使用する場合は、お客様の製品単独およびシステム全体で十分に評価し、お客様の責任において適用可否を判断してください。
本製品は、一般的電子機器(コンピュータ、パーソナル機器、事務機器、計測機器、産業用ロボット、家電機器など)または本資料に個別に記載されている用途に使用されることが意図されています。本製品は、特別に高い品質・信頼性が要求され、またはその故障や誤作動が生命・身体に危害を及ぼす恐れ、膨大な財産損害を引き起こす恐れ、もしくは社会に深刻な影響を及ぼす恐れのある機器(以下“特定用途”という)に使用されることは意図されていませんし、保証もされていません。特定用途には原子力関連機器、航空・宇宙機器、医療機器、車載・輸送機器、列車・船舶機器、交通信号機器、燃焼・爆発制御機器、各種安全関連機器、昇降機器、電力機器、金融関連機器などが含まれます。本資料に個別に記載されている場合を除き、本製品を特定用途に使用しないでください。
本製品を分解、解析、リバースエンジニアリング、改造、改変、翻案、複製等しないでください。
本製品を、国内外の法令、規則及び命令により、製造、使用、販売を禁止されている製品に使用することはできません。
本資料に掲載してある技術情報は、製品の代表的動作・応用を説明するためのもので、その使用に際して当社及び第三者の知的財産権その他の権利に対する保証または実施権の許諾を行うものではありません。
別途、書面による契約またはお客様と当社が合意した仕様書がない限り、当社は、本製品および技術情報に関して、明示的にも黙示的にも一切の保証(機能動作の保証、商品性の保証、特定目的への合致の保証、情報の正確性の保証、第三者の権利の非侵害保証を含むがこれに限らない。)をしておりません。
本製品、または本資料に掲載されている技術情報を、大量破壊兵器の開発等の目的、軍事利用の目的、あるいはその他軍事用途の目的で使用しないでください。また、輸出に際しては、「外国為替及び外国貿易法」、「米国輸出管理規則」等、適用ある輸出関連法令を遵守し、それらの定めるところにより必要な手続を行ってください。
本製品の RoHS 適合性など、詳細につきましては製品個別に必ず弊社営業窓口までお問合せください。本製品のご使用に際しては、特定の物質の含有・使用を規制する RoHS 指令等、適用ある環境関連法令を十分調査の上、かかる法令に適合するようご使用ください。お客様がかかる法令を遵守しないことにより生じた損害に関して、当社は一切の責任を負いかねます。
1
TMPM330 アプリケーションノート
目 次
1 概要 .........................................................................................................................................................................1 2 使用する機能.......................................................................................................................................................1 3 端子用途................................................................................................................................................................3 4 開発環境................................................................................................................................................................6 5 機能 .........................................................................................................................................................................7 5-1 動作モード選択 ........................................................................................................7 5-2 ウォッチドッグタイマ(WDT) ......................................................................................7 5-3 スタートアップ(STARTUP) ......................................................................................8 5-4 シリアルチャネル(SIO) .............................................................................................9 5-4-1 UART0 からUART2 へ送信..............................................................................9 5-4-2 リターゲットRetarget .......................................................................................10
5-5 シリアルバスインタフェース(SBI) ...........................................................................11 5-5-1 I2Cマスタ(EEPROMアクセス)........................................................................11 5-5-2 I2C スレーブ...................................................................................................12
5-6 CEC(Consumer Electronics Control) ...................................................................13 5-7 リモコン(RMC) .......................................................................................................14 5-8 タイマ(TMRB) ........................................................................................................15 5-8-1 インタバルタイマ .............................................................................................15 5-8-2 PPG(プログラマブル矩形波)出力 ................................................................15 5-8-3 周波数測定.....................................................................................................15
5-9 リアルタイムクロック(RTC)....................................................................................16 5-10 A/D変換(ADC) ......................................................................................................16 5-11 フラッシュ(FLASH).................................................................................................17
6 ソフトウェア......................................................................................................................................................... 18 6-1 スタートアップ(STARTUP) ....................................................................................20 6-1-1 メインプログラム : [main.c] ............................................................................20
6-2 シリアルチャネル(SIO) ...........................................................................................21 6-2-1 TMPM330 SIO デモ : [main.c] ......................................................................21
6-2-1-1 メインプログラム .............................................................................21 6-2-1-2 クリアバッファ ..................................................................................22
6-2-2 SIO 制御関数 : [uart.c] ................................................................................22 6-2-2-1 UART初期化 (SIO) ........................................................................22 6-2-2-2 文字送信.........................................................................................23
6-2-3 Retarget : [retarget.c] ....................................................................................24 6-2-3-1 文字出力.........................................................................................24
6-2-4 割り込み処理 : [system_it.c] .........................................................................24 6-2-4-1 UART0 (SIO0) 送信割り込み処理 ................................................24 6-2-4-2 UART2 (SIO2) 受信割り込み処理 ................................................24
6-3 シリアルバスインタフェース(SBI) ...........................................................................25 6-3-1 TMPM330 SBI デモ : [main.c] ......................................................................25 6-3-1-1 メインプログラム .............................................................................25
TMPM330 アプリケーションノート
6-3-1-2 クリアバッファ ..................................................................................28 6-3-2 SBI 制御関数 : [sbi.c]...................................................................................28 6-3-2-1 SBI初期化 .......................................................................................28 6-3-2-2 EEPROM読み取り...........................................................................29 6-3-2-3 EEPROM書き込み ..........................................................................31 6-3-2-4 SBIマスタ書き込み .........................................................................32 6-3-2-5 SBIスレーブ設定.............................................................................34 6-3-2-6 バスフリーチェック ..........................................................................34 6-3-2-7 バスビジーチェック..........................................................................34 6-3-2-8 承認チェック ....................................................................................35 6-3-2-9 SBI送信完了チェック ......................................................................35
6-3-3 割り込み処理 : [system_it.c] .........................................................................36 6-3-3-1 SBI2 割り込み処理 .........................................................................36 6-3-3-2 SBI0 割り込み処理 .........................................................................36
6-4 CEC(Consumer Electronics Control) ...................................................................38 6-4-1 TMPM330 CEC デモ : [main.c].....................................................................38 6-4-1-1 メインプログラム .............................................................................38
6-4-2 CEC 制御関数 : [cec.c]................................................................................41 6-4-2-1 CEC初期化 .....................................................................................41 6-4-2-2 待機命令送信 .................................................................................42 6-4-2-3 CECリモコンパススルー .................................................................43 6-4-2-4 CECコマンドタスク ..........................................................................43 6-4-2-5 CEC受信 .........................................................................................45
6-4-3 割り込み関数 : [system_it.c] .........................................................................46 6-4-3-1 CEC受信割り込み処理 ..................................................................46 6-4-3-2 CEC送信割り込み処理 ..................................................................46
6-5 リモコン(RMC) .......................................................................................................48 6-5-1 TMPM330 RMC デモ : [main.c] ....................................................................48 6-5-1-1 メインプログラム .............................................................................48 6-5-1-2 コード出力 .......................................................................................50
6-5-2 RMC 制御関数 : [rmc.c] ...............................................................................50 6-5-2-1 RMC I/O設定..................................................................................50 6-5-2-2 RMC初期化.....................................................................................51 6-5-2-3 RMC受信処理.................................................................................51
6-5-3 割り込み処理 : [system_it.c] .........................................................................53 6-5-3-1 RMC受信割り込み処理..................................................................53 6-5-3-2 タイマ割り込み 0 .............................................................................55
6-6 タイマ(TMRB) ........................................................................................................57 6-6-1 TMPM330 TMRB デモ: [main.c] ....................................................................57
6-6-1-1 メインプログラム .............................................................................57 6-6-1-2 平均周波数の計算 .........................................................................60
6-6-2 タイマ制御関数 : [timer.c].............................................................................60 6-6-2-1 タイマ初期化 ...................................................................................60
TMPM330 アプリケーションノート
6-6-3 文字列変換処理: [tmrb_tostring.c]................................................................61 6-6-3-1 デューティレート文字列変換 ..........................................................61 6-6-3-2 周波数文字列変換 .........................................................................61
6-6-4 割り込み処理: [system_it.c] ...........................................................................62 6-6-4-1 タイマ 5 割り込み (インタバルタイマ) ...........................................62 6-6-4-2 タイマ 8 割り込み (周波数測定)...................................................62
6-7 リアルタイマクロック(RTC) ....................................................................................64 6-7-1 TMPM330 RTC デモ: [main.c].......................................................................64
6-7-1-1 メインプログラム .............................................................................64 6-7-1-2 RTC表示 .........................................................................................64
6-7-2 RTC 制御関数 : [rtc.c] .................................................................................66 6-7-2-1 RTC初期化 .....................................................................................66
6-7-3 割り込み処理 : [system_it.c] .........................................................................66 6-8 A/D変換(ADC) ......................................................................................................67 6-8-1 TMPM330 ADC デモ: [main.c] ......................................................................67 6-8-1-1 メインプログラム .............................................................................67 6-8-1-2 A/D変換表示..................................................................................68
6-8-2 ADC 制御関数 : [adc.c]................................................................................70 6-8-2-1 ADC初期化 .....................................................................................70 6-8-2-2 A/D変換値読み取り.......................................................................70
6-8-3 割り込み処理: [system_it.c] ...........................................................................71 6-8-3-1 A/D変換割り込み処理...................................................................71
6-9 フラッシュ(FLASH).................................................................................................72 6-9-1 TMPM330 Flash デモ: [main.c] .....................................................................72 6-9-1-1 メインプログラム .............................................................................72 6-9-1-2 デモ .................................................................................................73 6-9-1-3 フラッシュ書き込みエントリ.............................................................73 6-9-1-4 フラッシュコピー ..............................................................................75
6-9-2 Flash 制御関数 : [flash.c].............................................................................76 6-9-2-1 フラッシュ書き込み(切り替え).......................................................76 6-9-2-2 フラッシュ書き込み .........................................................................78 6-9-2-3 フラッシュブロック消去....................................................................78 6-9-2-4 フラッシュページ書き込み ..............................................................80 6-9-2-5 ページブロックチェック....................................................................82 6-9-2-6 アドレスブロック番号変換 ..............................................................82 6-9-2-7 RAMコピー ......................................................................................83
6-10 低消費電力(Low Power) ......................................................................................84 6-10-1 Low Power 制御関数 : [power_mode.c]...............................................84 6-10-1-1 パワーモード変更 ...........................................................................84 6-10-1-2 要因設定クリア ...............................................................................85
1
TMPM330 アプリケーションノート
はしがき
このアプリケーションノート(サンプルソフトウェア)は、あなたが東芝製マイクロコントロ
ーラを使用して製品を開発する際の、プログラム開発を習得する手助けとなるもので
す。
1 概要
本アプリケーションノートのサンプルプログラムは、ARM Cortex™-M3コアの東芝製マイコン
TMPM330 用です。各サンプルプログラムは、主なMCU内蔵機能を単独で実行するように出来
ています。サンプルプログラム内の一部を取り出して再利用することで、希望する機能を動作さ
せることができます。
※ARMおよびARM CortexはARM LimitedのEUおよびその他の国における商標および登録商標です。
2 使用する機能
機 能 チャネル 使用/未使用
クロックギア 未使用 クロック/モード制御
(CG) PLL PLL なし/4逓倍
スタンバイモード
SLEEP モードのみ使用
SysTick
未使用
ウォッチドッグタイマ
(WDT)
使用
割り込みコントローラ
(NVIC)
使用
INT0 未使用
INT1 未使用
INT2 未使用
INT3 未使用
INT4 未使用
INT5 未使用
INT6 未使用
外部割り込み
(INT)
INT7 未使用
SIO0 UART0,2 で通信制御(送信)
SIO1 未使用 シリアルチャネル
(SIO) SIO2 UART0,2 で通信制御(受信)
シリアルバスインタフェース SBI0 使用
2
TMPM330 アプリケーションノート
機 能 チャネル 使用/未使用
SBI1 未使用 (SBI)
SBI2 使用
CEC
CEC 受信、送信機能
RMC0 未使用 リモコンプロセッサ
(RMC) RMC1 リモコン受信
TMRB0 使用
TMRB1 未使用
TMRB2 未使用
TMRB3 使用 (周波数測定)
TMRB4 未使用
TMRB5 使用 (インタバルタイマ)
TMRB6 未使用
TMRB7 未使用
TMRB8 使用 (周波数測定)
16 ビットタイマ
TMRB9 未使用
リアルタイムクロック
(RTC)
RTC の秒カウントを年月日時分秒で表示
AIN0 使用
AIN1 未使用
AIN2 未使用
AIN3 未使用
AIN4 未使用
AIN5 未使用
AIN6 未使用
AIN7 未使用
AIN8 未使用
AIN9 未使用
AIN10 未使用
10ビット A/D コンバータ
(ADC)
AIN11 使用
3
TMPM330 アプリケーションノート
3 端子用途
本アプリケーションノートのサンプルプログラムは、開発環境にIAR社 TMPM330-SK評価キット
において設計・実装・評価されています。以下に、端子用途を説明します。
No 端子名称 用途
1 PD6, AN10 未使用
2 PD7, AN11 MIC 入力
3 AVSS GND
4 VREFH +3.3V
5 AVCC +3.3V
6 PG3, INT4 LED4
7 PK2, TB9OUT 未使用
8 PJ5, TB7OUT 未使用
9 PH4, TB2IN0 未使用
10 PH5, TB2IN1 未使用
11 PG7, TB8OUT 未使用
12 TEST2 未使用
13 DVSS GND
14 DVCC +3.3V
15 PG4, SO2, SDA2 SDA2
16 PG5, SI2, SCL2 SCL2
17 PG6, SCK2 未使用
18 TEST1 未使用
19 PF7, INT5 LCD DB7
20 PE0, TXD0 SIO0 TX
21 PE1, RXD0 SIO0 RX
22 PE2, SCLK0, CTS0 未使用
23 PE4, TXD1 未使用
24 PE5, RXD1 未使用
25 PE6, SCLK1, CTS1 未使用
26 PG0, SO0, SDA0 SDA0/LED1
27 PG1, SI0, SCL0 SCL0/LED2
28 PG2, SCK0 LED3
29 PB3 未使用
30 PH0, TB0IN0, BOOT 未使用
31 PH1, TB0IN1 LCD_E
32 PH2, TB1IN0 LCD_RW
33 PF0, TXD2 SIO2 TX
34 PF1, RXD2 SIO2 RX
4
TMPM330 アプリケーションノート
No 端子名称 用途
35 PF2, SCLK2, CTS2 LCD_BL
36 PH3, TB1IN1 LCD_RS
37 PB4 KEY1
38 PI0, TB0OUT PPG(プログラマブル矩形波) 出力
39 PJ6, INT6 未使用
40 PI1, TB1OUT 未使用
41 PB5 KEY2
42 PI2, TB2OUT 未使用
43 PB6 KEY3
44 PF4, SO1, SDA1 LCD_DB4
45 PF5, SI1, SCL1 LCD_DB5
46 PF6, SCK1 LCD_DB6
47 PB7 KEY4
48 PI3, TB3OUT 未使用
49 PJ1, INT1 LED6
50 PK0, CEC 未使用
51 PK1, SCOUT, ALARM 未使用
52 PI4, TB4OUT 未使用
53 PI5, TB5OUT 未使用
54 PB0, TDO, SWV TDO
55 PA0, TMS, SWDIO TMS
56 PA1, TCK, SWCLK TCK
57 TEST3 未使用
58 PJ7, INT7 未使用
59 PB1, TDI TDI
60 PB2, TRST TRST
61 PF3, RXIN1 未使用
62 DVCC +3.3V
63 DVSS GND
64 PA2, TRACECLK 未使用
65 PA3, TRACEDATA0 未使用
66 PA4, TRACEDATA1 未使用
67 PA5, TRACEDATA2 未使用
68 PA6, TRACEDATA3 未使用
69 PA7 未使用
70 PJ0, INT0 LED5
71 CVCC +3.3V
72 X2 10MHz 発振子接続
73 CVSS GND
74 X1 10MHz 発振子接続
5
TMPM330 アプリケーションノート
No 端子名称 用途
75 REGVSS GND
76 REGVCC +3.3V
77 XT1 32.768kHz 発振子接続
78 XT2 32.768kHz 発振子接続
79 PI6, TB4IN0 未使用
80 NMI 未使用
81 MODE GND
82 RESET RESET
83 PI7, TB4IN1 未使用
84 PH6, TB3IN0 周波数測定用の入力
85 PH7, TB3IN1 未使用
86 PJ2, INT2 LED7
87 PJ3, INT3 LED8
88 PJ4, TB6OUT 未使用
89 PE3, RXIN0 未使用
90 TEST4 未使用
91 PC0, AN0 AN0
92 PC1, AN1 未使用
93 PC2, AN2 未使用
94 PC3, AN3 未使用
95 PD0, AN4, TB5IN0 未使用
96 PD1, AN5, TB5IN1 未使用
97 PD2, AN6, TB6IN0 未使用
98 PD3, AN7, TB6IN1 未使用
99 PD4, AN8 未使用
100 PD5, AN9 未使用
6
TMPM330 アプリケーションノート
4 開発環境
下記に開発環境の構成を示します。
1. ハードウェア:
1) IAR 社 TMPM330-SK 評価キット
2. 開発ツール:
1) J-Link:IAR 社 J-Link-ARM 7.0 / J-Link 6.0
2) IDE: IAR 社 Embedded workbench 5.4
SDA/SCL I2C
ADC
RMC
CG
CEC
UART0/2RTC
PC (Terminal Software)
WD
TMPM330
IO LCD, LED
リモコン信号
受信機
マイク
EEPROM
TX/RX
HDMI DVD with CEC
FLASH
7
TMPM330 アプリケーションノート
5 機能
5-1 動作モード選択
NORMAL モード:
システムクロックに高速発振器(fc)を使用します。
SLEEP モードへ移行するには、システムコントロールレジスタ STBYCR0<STBY2:0>にて
SLEEP モードを選択し、WFI(Wait For Interrupt)命令を実行します。
SLEEP モード:
内部低速発振器(fs), RTC, CEC 機能,リモコン判定機能のブロックが動作します。
SLEEP モードの解除要因には、RTC 割り込み、CEC 割り込み、リモコン割り込み、外部割
り込みが選択できます。
SLEEP モードが解除されると、SLEEP モードへ移行する直前の動作モードへ復帰し、動
作を開始します。
動作モードの設定は、RMC と CEC のサンプルプログラムに組み込まれています。
5-2 ウォッチドッグタイマ(WDT)
ウォッチドッグタイマは、NORMAL モードで動作します。NORMAL モードでは、ウォッチドッグタ
イマモードレジスタ WDMOD<WDTP6:4>で設定した、WDT 検出時間内に、ウォッチドッグタイマコ
ントロールレジスタ WDCRへWDT クリアコード(4EH)を書き込むことでウォッチドッグタイマをクリ
アします。
STARTUP のサンプルプログラム以外のウォッチドッグタイマは、初期設定により禁止にしてい
ます。
命令/sleep on exit
割り込み要因
Reset
NORMAL
モード
SLEEP
モード
8
TMPM330 アプリケーションノート
5-3 スタートアップ(STARTUP)
スタートアップは、リセット解除からメイン関数までの処理です。東芝オリジナルコンパイラでは、
初期化処理(スタックポインタの設定、変数初期化)を全てユーザーで記述する必要がありまし
た。
ARM 社、IAR 社、KEIL 社のコンパイラでは、変数初期化等はライブラリで準備されています。
変数初期化では、静的変数(アドレスが割当てられた変数)に対して、初期値付き変数の場合、
初期値(ROMに配置)を設定します。初期値なし変数の場合は、リンクファイルの指定により 0 ク
リアします。
リセット
startup.asm
スタックポインタ初期化
変数初期化
H/W 初期化(ポート設定等)
メイン関数へ
Main.c
Main()
リセット
C ライブラリ
変数初期化
ユーザーアプリケーション
Main()
H/W 初期化(ポート設定等)
スタックポインタ初期化
9
TMPM330 アプリケーションノート
5-4 シリアルチャネル(SIO)
5-4-1 UART0 からUART2 へ送信
SIO サンプルプログラムでは、UART0 を送信、 UART2 を受信として使用します。
UART0 から文字列“TMPM330” を送信します。
UART2 は、データを受信すると、LCD に受信データを表示します。
送信するには K1 を押します。送信完了後、K1 を押すことで(送信)再開します。
LCD 表示形式
(リセット時)
K1を押す
K1 を押す
K1 を押す
UART0 to UART2 :
Press K1:start
UART0 to UART2 :
TMPM330
UART0 to UART2 :
Press K1:start
UART 設定:
データ長 : 8 bits
パリティ : None
ストップビット : 1 bit
ボーレート : 115200bps
フロー制御 : None
10
TMPM330 アプリケーションノート
5-4-2 リターゲットRetarget
C 言語の標準入出力ライブラリの標準入力(stdin)、標準出力(stdout)をターゲットのハードウ
ェアに合わせて変更することをリターゲットと呼びます。
サンプルプログラムでは、標準入力 と 標準出力を、共に UART0 に設定します。
アプリケーションから、printf()関数、getchar()関数 を用いて、UART0 から入出力を行います。
ユーザーアプリケーション
Cライブラリ
ANSI C標準関数(printf()など)
デバイスドライバ層
(ターゲットに合わせて変更します)
ターゲット(ハードウェア、デバッガ等)
UART 設定:
データ長 : 8 bits
パリティ : None
ストップビット : 1 bit
ボーレート : 115200bps
フロー制御 : None
11
TMPM330 アプリケーションノート
5-5 シリアルバスインタフェース(SBI)
5-5-1 I2Cマスタ(EEPROMアクセス)
ボード内蔵の EEPROM よりデータを読み取り又は書き込みます。
データを読み出し、PC上のターミナルソフトにて表示します。
K1 を押すと、EEPROM データ読み取りを開始します。
PC 上のターミナルソフトに以下のメッセージを出力します。
PC 表示形式
TMPM330-SK 評価ボード上の LCD に次のメッセージを出力します。
LCD 表示形式
読み取り終了後、TMPM330-SK 評価ボード上の LCD に次のメッセージを出力します。
LCD 表示形式
K2 を押すと、PC 上のターミナルソフトからのキー入力待ちになります。
LCD 表示形式
PC 上のターミナルソフトからによる単語 (最大8文字) を入力し、Enter を押します。
この単語は、EEPROM に書き込まれ、K1 の入力待ちになります。
LCD 表示形式
例として“TOSHIBA”と入力します。
K1 を押すと、EEPROM を読み取り、TMPM330-SK評価ボード上の LCDにターミナルソフトで入
力したメッセージを表示します。
LCD 表示形式
TMPM330
EEPROM READ
Read Over
Press K2 to Write
Write Over
Press K1 to Read
Type a word
TOSHIBA
TMPM330 I2C Demo
0x0000: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
0x0010: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
……
Finish
12
TMPM330 アプリケーションノート
5-5-2 I2C スレーブ
EEPROMの読み取り/書き込み操作に続いて、K2 を押すと、I2Cスレーブのデモの開始表示に
切り替わります。
TMPM330-SK評価ボード上のSBI0 と SBI2 を I2Cバスで接続します。SBI2 をマスタで、SBI0 を
スレーブとして使用します。
SBI2(マスタ)から文字列を送信します。SBI0(スレーブ)は、受け取った文字列を LCD に表示しま
す。このデモでは、SBI 割り込みを使用しています。
I2C スレーブアドレスは、B0H としています。
LCD 表示形式
K3 を押すと、SBI2(マスタ)から SBI0(スレーブ)に文字列「TOSHIBA」を送信します。
LCD 表示形式
K1 を押すと、SBI0(スレーブ)の受信バッファから取得した文字列「TOSHIBA」を表示します。
LCD 表示形式
K3:SBI2 to SBI0
Write Over
K1:Show SBI0
TOSHIBA
SBI2 to SBI0 OK
(注)
このサンプルソフトの実行には、IAR TMPM330-SK 評価ボードの改造が必要です。
・ 端子 15(PG4/SDA2)と端子 26(PG0/SDA0)を接続してください。
・ 端子 16(PG5/SCL2)と端子 27(PG1/SCL0)を接続してください。
・ LED1、LED2 と接続されている JP8 のショートピンを外してください。
13
TMPM330 アプリケーションノート
5-6 CEC(Consumer Electronics Control)
このアプリケーションは、TMPM330 と DVD 間の CEC ラインによる通信機能のデモです。ヘッ
ダ/オペコード/オペランドの上位8ビットをPC上のターミナルソフトに送信し、Hexフォーマットで
表示します。
PC 表示形式
CEC メッセージを受信する際に動作モードが SLEEP モードの場合、NORMAL モードに復帰して
から、CEC メッセージを処理します。
この CEC メッセージは、論理アドレス14(自由使用)を使用しています。
PC 表示形式
PC上のターミナルソフトによるPCキーボード又はリモコンキーでCECメッセージを送信します。
以下にサポートされている CEC メッセージとそのトリガキーを示します。
PC キー リモコンキー CEC メッセージ
1 [1] Power (Pass Through)
2 [2] System standby
3 [3] Play (Pass Through)
4 [4] Stop (Pass Through)
リモコンキーにより動作モードの切り替えを行います。
NORMAL モード中に[POWER]キーを押すことで、SLEEP モードへ移行します。
SLEEP モード中に CEC メッセージを受信することで、NORMAL モードへ復帰します。
TMPM330 CEC Demo
CEC_Recv: XX XX XX
CEC_Recv: YY YY
TMPM330 CEC Demo
CEC_ Send: XX XX XX
CEC_ Send: YY YY
14
TMPM330 アプリケーションノート
5-7 リモコン(RMC)
このアプリケーションは、赤外線リモコンの信号を受信し、デコードします。デコードされたデータ
は、PC 上のターミナルソフトに表示します。カスタマコード/アドレスコード/コマンドコードは、
Hex フォーマットで表示します。
PC 表示形式
リモコンキーにより動作モードの切り換えを行います。
NORMAL モード中に、[9]キーを押すことで、SLEEP モードへ移行します。
SLEEP モード中に[7]キーを押すことで、NORMAL モードへ復帰します。
TMPM330 RMC Demo
RMC_1: XX XX
RMC_1: YY YY
15
TMPM330 アプリケーションノート
5-8 タイマ(TMRB)
5-8-1 インタバルタイマ
この機能は、MCUのタイマを使ってインタバルタイマを実現します。
タイマ設定は、1ms 周期です。
このタイマを使い、1s 間隔で LED 点滅を実現します。
LCD 表示形式
5-8-2 PPG(プログラマブル矩形波)出力
MCU タイマを使い、デューティ可変の PPG(プログラマブル矩形波)の波形を出力します。
デューティは、5 段階(10%, 25%, 50%, 75%, 90%)に変更できます。
K1 を押すと、タイマを PPG モードに設定し、PPG 出力処理を開始します。
LCD 表示形式
K2 を押すことで、デューティを変更します(10% → 25% → 50% → 75% → 90% → 10%)。
LCD 表示形式
5-8-3 周波数測定
MCUのタイマを使い、入力信号の周波数を測定します。
K3 を押すことで、タイマを周波数測定モードに設定します。
LCD 表示形式
* 端子 84(PH6/TB3IN0)が、周波数測定用の入力端子となります。パルスジェネレータ等
で任意の周波数を入力してください。
General Timer
PPG Output
Duty: 50%
K2: Change Duty
K3: Measure Freq
Freq measure
f=99999Hz
16
TMPM330 アプリケーションノート
5-9 リアルタイムクロック(RTC)
MCU内蔵の RTC を利用し、時刻及び日付を LCD に表示します。
初期設定は、2009/7/1 00:00:00, 24 時間形式です。
更新間隔: 1s
LCD 表示形式
5-10 A/D変換(ADC)
ボリュームとマイクの音量を読み取り、LCD に表示します。
A/D 変換終了は、割り込みで通知します。
A/D 変換データを LCD に表示します。
LCD 表示形式
K1 を押すことでボリュームの値を読み取り、LCD に表示します。
LCD 表示形式
第1行では、ボリュームのパーセンテージ値を表示します。
第2行では、ボリューム値のバーを表示します。
K2 を押すことでマイクの音量を読み取り、LCD に表示します。
LCD 表示形式
第1行では、マイクの音量を表示します。
第2行では、マイク音量のバーを表示します。
2009/07/01
12:50:55
Mic Value : 25
*********
Press K1 to ADC
then K2 to MIC
ADC Value : 25
*********
17
TMPM330 アプリケーションノート
5-11 フラッシュ(FLASH)
このアプリケーションは、プログラムを内蔵 RAM 上で実行し、内蔵フラッシュメモリの消去及び
再書き込み操作を行います。
プログラムは、ユーザーブートモードで実行します。
プログラムの再書き込みは、データ消去を行い、書き込みブロックを指定します。
プログラム A とプログラム Bが書き換えられたことは、LED の点滅で判断します。
プログラム Aの時は、TMPM330-SK 評価ボード上の LED1-4 が点滅します。
プログラム Bの時は、TMPM330-SK 評価ボード上の LED5-8 が点滅します。
動作手順:
- 初期保存のプログラムを実行し、キー入力を待ちます。
- キー入力により、指定ブロックにデータの消去と再書き込みを行います。
・RAM へ、消去/再書き込みプログラムとプログラム A(または B)を転送します。
・プログラム Aが保存された場合は、プログラム Bを RAMへ、
プログラム Bが保存された場合は、プログラム A を RAMへ転送します。
- 再書き込み終了後、キー入力を待ちます。
flash flash
B program RAM A program
A
Key press
A programcurrent executing program B program current executing program
RAM 転送、フラッシュ消去又は再書き込み中に、LCD にて関連メッセージを表示します。
LCD 表示形式
(プログラム RAM転送中)
(消去中)
(再書き込み中)
(再書き込み完了)
RAM transferring
……
Erasing……
Rewriting……
Finished
18
TMPM330 アプリケーションノート
6 ソフトウェア
本アプリケーションノートのサンプルプログラムでは、機能毎にプロジェクトを分割しています。
一部のプログラムは、IAR社 TMPM330-SK評価キットに付属のサンプルプログラムを利用して
います。
ワークスペース構造とプロジェクト名は、以下に示します。
TMPM330 Sample Program
├─IAR
│ ├─STARTUP
│ │ ├─common (CMSIS ファイル)
│ │ ├─application
│ │ │ ├─include (ヘッダファイル)
│ │ │ └─sourcecode (ソースファイル)
│ │ └─driver
│ │ ├─incclude
│ │ └─sourcecode
│ ├─ADC
│ │ └─(同上)
│ ├─CEC
│ │ └─(同上)
│ ├─FLASH
│ │ └─(同上)
│ ├─RMC
│ │ └─(同上)
│ ├─RTC
│ │ └─(同上)
│ ├─SBI
│ │ └─(同上)
│ ├─SIO
│ │ └─(同上)
│ └─TMRB
└─(同上)
19
TMPM330 アプリケーションノート
次に A/D変換プロジェクトを例に説明します。
備考: IAR 社 TMPM330-SK 評価ボードでは CEC と RMC のインターフェースがありま
せん。ソフトウェアのみ掲載いたします。
アプリケーションレイヤ:
ファイル名: adc.c
関数名: ADC_Init(), ADC_Get_Value()
ドライバレイヤ:
ファイル名: m330_adc.c
関数名: API_ADC_ChSet()
20
TMPM330 アプリケーションノート
6-1 スタートアップ(STARTUP)
6-1-1 メインプログラム : [main.c]
メイン処理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int main(void)
{
/* Initial Setting */
__disable_irq();
API_CG_Init();
API_CG_IO_ClkSel(IP_CG_FPE_2);
API_CG_ScoutSel(IP_CG_FSYS);
API_CG_PLL_ON(CG_OSCILLATION);
API_CG_PLL_Sel(CG_PLL);
API_WDT_Set_WdtMode(IO_WDT_MOD_INIT | IP_WDT_FSYS_220);
API_WDT_Set_WdtCtrl(IP_WDT_CLEARCODE);
/* Port Setting */
/* Special Function Register Setting */
/* Interrupt Setting */
__enable_irq();
/* Main routine */
for (;;) {
API_WDT_Set_WdtCtrl(IP_WDT_CLEARCODE);
}
}
[6 行目: CG レジスタ初期化]
[7 行目: プリスケーラクロック選択(fperi/2)]
[8 行目: SCOUT 出力選択(fsys)]
[9 行目: PLL 動作許可]
[10 行目: PLL 選択(PLL ON)]
[12 行目: WDT 許可、周期設定(26.21ms@40MHz)]
[13,21 行目: WDT クリアコード ]
21
TMPM330 アプリケーションノート
6-2 シリアルチャネル(SIO)
6-2-1 TMPM330 SIO デモ : [main.c]
6-2-1-1 メインプログラム
SIO デモにおけるメイン処理
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
31
32
33
34
35
36
37
38
int main(void)
{
char m330[] = "TMPM330";
uint8_t key_info;
/* Initialize system */
Set_System();
LCD_Configuration();
LCD_Light(ON);
UART_Init();
/* enable SIO0 trx int, SIO2 trx int */
NVIC_EnableIRQ(INTRX0_IRQn);
NVIC_EnableIRQ(INTTX0_IRQn);
NVIC_EnableIRQ(INTRX2_IRQn);
NVIC_EnableIRQ(INTTX2_IRQn);
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text("UART0 to UART2");
for (;;) {
ClearBuffer(gSIORxBuffer);
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text("Press K1: start");
do {
key_info = API_PORT_BitIn(KEY_PORT, KEY1);
} while (key_info == SET);
do {
key_info = API_PORT_Read(KEY_PORT) & KEYRELEASE;
} while (key_info != KEYRELEASE);
printf("%s\r\n", m330);
while(fSIORxOK == NO) {
/* do nothing */
}
fSIORxOK = NO;
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text(gSIORxBuffer);
do {
key_info = API_PORT_BitIn(KEY_PORT, KEY1);
} while (key_info == SET);
do {
22
TMPM330 アプリケーションノート
39
40
41
42
key_info = API_PORT_Read(KEY_PORT) & KEYRELEASE;
} while (key_info != KEYRELEASE);
}
}
[7 行目: システムクロック、I/O ポート設定]
[8 行目: LCD 初期設定]
[9 行目: LCD バックライトライト ON]
[10 行目: UART 初期化]
[12,13 行目: SIO0 送受信割り込み許可]
[14,15 行目: SIO2 送受信割り込み許可]
[16,20,33 行目: LCD にコマンドを送信]
[17,21,34 行目: LCD に表示データを送信]
[19 行目: 受信用バッファをクリア]
[23,36 行目: キーが押された情報を取得]
[26,39 行目: キーが放された情報を取得]
6-2-1-2 クリアバッファ
1
2
3
4
5
6
7
8
void ClearBuffer(char * buf)
{
u_int8 i;
for(i = 0; i < BUFFER_SIZE; i++) {
*(buf+i) = 0x00;
}
}
6-2-2 SIO 制御関数 : [uart.c]
6-2-2-1 UART 初期化 (SIO)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void UART_Init(void)
{
/* configure SIO0 for transmit */
API_SIO_Init(SC0);
API_SIO_IP_Enable(SC0, ENABLE);
API_SIO_CR_Set(SC0,IO_SIO_CR_INIT);
API_SIO_MOD0_Set(SC0,IP_SIO_UARTBIT8MODE | IP_SIO_CLK_BAUDRATE);
API_SIO_MOD1_Set(SC0,SIO_I2SO | IP_SIO_HALFDOUBLE_TRS);
API_SIO_MOD2_Set(SC0,SIO_WBUF);
API_SIO_FCNF_Set(SC0,IO_SIO_FCNF_INIT);
API_SIO_BR_Set(SC0,(SIO_BRxADDE | IP_SIO_BRN_5),IP_SIO_BR16K_9);
API_SIO_SndEnable(SC0,ENABLE);
/* configure SIO2 for reception */
API_SIO_Init(SC2);
API_SIO_IP_Enable(SC2, ENABLE);
23
TMPM330 アプリケーションノート
16
17
18
19
20
21
22
23
API_SIO_CR_Set(SC2,IO_SIO_CR_INIT);
API_SIO_MOD0_Set(SC2,IP_SIO_UARTBIT8MODE | IP_SIO_CLK_BAUDRATE);
API_SIO_MOD1_Set(SC2,IP_SIO_HALFDOUBLE_RCV);
API_SIO_MOD2_Set(SC2,SIO_WBUF);
API_SIO_FCNF_Set(SC2,IO_SIO_FCNF_INIT);
API_SIO_BR_Set(SC2,(SIO_BRxADDE | IP_SIO_BRN_5),IP_SIO_BR16K_9);
API_SIO_RcvEnable(SC2,ENABLE);
}
[4,14 行目: SIO 初期化]
[5,15 行目: SIO 動作許可]
[6,16 行目: SIO コントロールレジスタ設定]
[7,17 行目: SIO モードコントロールレジスタ 0 設定]
[8,18 行目: SIO モードコントロールレジスタ 1 設定]
[9,19 行目: SIO モードコントロールレジスタ 2 設定]
[10,20 行目: SIO FIFO コンフィグレジスタ設定]
[11,21 行目: SIO ボーレートコントロールレジスタ設定]
[14 行目: SIO 送信許可]
[27 行目: SIO 受信許可]
6-2-2-2 文字送信
SIO0 に一つの文字を送信します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
uint8_t send_char(uint8_t ch)
{
while (gSIORdIndex != gSIOWrIndex) {
/* do nothing */
}
gSIOTxBuffer[gSIOWrIndex++] = ch;
if (fSIO0_INT == CLEAR) {
fSIO0_INT = SET;
API_SIO_SndDataSet(SC0, gSIOTxBuffer[gSIORdIndex++]);
NVIC_EnableIRQ(INTRX0_IRQn);
NVIC_EnableIRQ(INTTX0_IRQn);
}
return ch;
}
[9 行目: SIO 送信データセット]
[10,11 行目: SIO0 送受信割り込み許可]
24
TMPM330 アプリケーションノート
6-2-3 Retarget : [retarget.c]
6-2-3-1 文字出力
printf() から受け取った一文字を SIO に送信します。 1
2
3
4
int putchar(int ch)
{
return (send_char(ch));
}
[3 行目: SIO0 に1文字を送信]
6-2-4 割り込み処理 : [system_it.c]
6-2-4-1 UART0 (SIO0) 送信割り込み処理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void INTTX0_IRQHandler(void)
{
if (gSIORdIndex < gSIOWrIndex) {
API_SIO_SndDataSet(SC0, gSIOTxBuffer[gSIORdIndex++]);
fSIO0_INT = SET;
}
else {
/* disable SIO0 INT */
fSIO0_INT = CLEAR;
NVIC_EnableIRQ(INTRX0_IRQn);
NVIC_EnableIRQ(INTTX0_IRQn);
}
if(gSIORdIndex >= gSIOWrIndex) {
gSIOWrIndex = CLEAR;
gSIORdIndex = CLEAR;
}
}
[4 行目: SIO 送信データセット]
[10,11 行目: SIO0 送受信割り込み禁止]
6-2-4-2 UART2 (SIO2) 受信割り込み処理
1
2
3
4
5
6
7
8
void INTRX2_IRQHandler(void)
{
static uint8_t i = 0;
uint8_t tmpchar = 0;
tmpchar = API_SIO_RcvDataRead(SC2);
if(tmpchar == 0x0A) {
fSIORxOK = YES;
25
TMPM330 アプリケーションノート
9
10
11
12
13
14
i = CLEAR;
}
else if(tmpchar != 0x0D) {
gSIORxBuffer[i++] = tmpchar;
}
}
[6 行目: 受信データ取得]
6-3 シリアルバスインタフェース(SBI)
6-3-1 TMPM330 SBI デモ : [main.c]
6-3-1-1 メインプログラム
SBI デモメイン処理
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
31
32
int32_t main(void)
{
uint8_t i, j;
uint8_t key_info;
uint8_t rtn;
char str[] = "TOSHIBA";
/* Initialize System */
Set_System();
LCD_Configuration();
LCD_Light(ON);
SIO_ChInit();
if((SBI_ChInit(SBI0) == SBIERROR) || (SBI_ChInit(SBI2) == SBIERROR)) {
Send_LCD_Text("Fail to Initial");
return 0;
}
printf("TMPM330 SBI DEMO\r\n");
for (;;) {
/******************* Master Part *********************/
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text("Press K1 to");
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text("Read EEPROM");
NVIC_EnableIRQ(INTSBI2_IRQn);
do {
key_info = API_PORT_BitIn(KEY_PORT, KEY1);
} while (key_info == SET);
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text(" TMPM330 ");
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text(" EEPROM READ ");
for(i=0; i<(TWOKB); i++) {
26
TMPM330 アプリケーションノート
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/* Master read from EEPROM, SBI2 <- EEPROM(24C02) */
if(EEPROM_Read(SBI2, gSBIRxBuffer, i*SIZE, EEPROMAddr, SIZE)) {
printf("0x%04x: ", i*SIZE);
for(j=0; j<SIZE; j++) {
printf("0x%02x ", gSBIRxBuffer[j]);
}
printf("\r\n");
}
else {
printf("READ ERROR: %d\r\n", i);
}
}
printf("Finish\r\n");
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text("Read Over Press");
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text("K2 to Write");
do {
key_info = API_PORT_BitIn(KEY_PORT, KEY2);
} while (key_info == SET);
NVIC_EnableIRQ(INTRX0_IRQn);
NVIC_EnableIRQ(INTTX0_IRQn);
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text(" Type a word ");
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text(" ");
while (fSIORxOK == READY) {
/* do nothing */
}
fSIORxOK = READY;
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
/* Master write to EEPROM, SBI2 -> EEPROM(24C02) */
rtn = EEPROM_Write(SBI2,gSIORxBuffer,0x0000,
EEPROMAddr,strlen(gSIORxBuffer));
if(rtn == SBIGOOD) {
Send_LCD_Text("Write Over");
}
else {
Send_LCD_Text("Write ERROR");
return 0;
}
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text("Press K1 to Read");
do {
key_info = API_PORT_BitIn(KEY_PORT, KEY1);
} while (key_info == SET);
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text(" ");
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
ClearBuffer(gSBIRxBuffer, SBI_BUFFER_SIZE);
/* Master read from EEPROM, SBI2 <- EEPROM(24C02) */
rtn = EEPROM_Read(SBI2,gSBIRxBuffer,0x0000,
27
TMPM330 アプリケーションノート
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
EEPROMAddr,strlen(gSIORxBuffer));
if(rtn == SBIGOOD) {
Send_LCD_Text(gSBIRxBuffer);
}
else {
Send_LCD_Text("Read Error");
return 0;
}
ClearBuffer(gSBIRxBuffer, SBI_BUFFER_SIZE);
ClearBuffer(gSIORxBuffer, strlen(gSIORxBuffer));
/******************* Slave Part *******************/
do {
key_info = API_PORT_BitIn(KEY_PORT, KEY2);
} while (key_info == SET);
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text("K3: SBI2 to SBI0");
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text(" ");
NVIC_EnableIRQ(INTSBI0_IRQn);
SBI_Slave_Set(SBI0, SELFSLVAddr);
do {
key_info = API_PORT_BitIn(KEY_PORT, KEY3);
} while (key_info == SET);
/* Master write to Slave, SBI2 -> SBI0 */
rtn = SBI_Master_Write(SBI2, str, strlen(str), SELFSLVAddr);
if(rtn == SBIGOOD) {
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text("Write Over");
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text("K1: Show SBI0");
}
else {
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text("Write ERROR");
}
while (fSBIRxOK == READY) {
/* do nothing */
}
fSBIRxOK = READY;
do {
key_info = API_PORT_BitIn(KEY_PORT, KEY1);
} while (key_info == SET);
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text(gSBIRxBuffer);
ClearBuffer(gSBIRxBuffer, SBI_BUFFER_SIZE);
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text("SBI2 to SBI0 OK");
do {
key_info = API_PORT_BitIn(KEY_PORT, KEY4);
} while (key_info == SET);
}
}
28
TMPM330 アプリケーションノート
[9 行目: CG レジスタ設定、WDT 禁止、ボタン、LCD、I/O 設定]
[10 行目: LCD 初期化]
[11 行目: LCD バックライトオン]
[12 行目: SIO チャネル初期化]
[13 行目: SBI0 と SBI2 を初期化]
[14,21,23,29,31,47, 49,56,58,68,71,75,80,87, 90,100,
102,112,114,118,128,131行目: LCD にて文字列を表示]
[20,22,28,30,46,48,55,57,63,74,79,81,99,101,111,
113,117,127,130行目: LCD コマンド実行-出力行の指定]
[24 行目: SBI2 割り込み許可]
[25,76,124 行目: KEY1の入力待ち]
[34,84 行目: EEPROMへマスタ読み取りを実行]
[50,96 行目: KEY2 の入力待ち]
[53,54 行目: SIO0送信割り込み許可]
[59 行目: UART 受信待ち]
[65 行目: EEPROMへマスタ書き込みを実行]
[82,93,94,129 行目: バッファをクリア]
[102 行目: SBI0割り込み許可]
[104 行目: SBI0をスレーブ及びそのアドレスを設定する]
[105 行目: KEY3 の入力待ち]
[109 行目: マスタよりスレーブに書き込みを実行]
[120 行目: スレーブ(SBI0)の受信完了待ち]
[132 行目: KEY4 の入力待ち]
6-3-1-2 クリアバッファ
1
2
3
4
5
6
7
8
void ClearBuffer(char * buf, uint8_t length)
{
uint8_t cnt;
for(cnt=0; cnt<length; cnt++)
{
buf[cnt] = 0x00;
}
}
6-3-2 SBI 制御関数 : [sbi.c]
6-3-2-1 SBI 初期化
1
2
3
4
uint8_t SBI_ChInit(SBI_TypeDef * SbiChSel)
{
API_SBI_Init(SbiChSel);
API_SBI_IP_Enable(SbiChSel,ENABLE);
29
TMPM330 アプリケーションノート
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
API_SBI_CR1_Set(SbiChSel,0x09);
API_SBIi_SlvAddressSet(SbiChSel,0xA0);
/* wait the bus is free */
ret = BusFreeChk(SbiChSel);
if (ret == BUSY) {
return (SBIERROR);
}
else {
/* do nothing */
}
/* Configures the SBI as a I2C slave receiver */
API_SBI_CR2_Set(SbiChSel,0x18);
API_SBI_Idle(SbiChSel,ENABLE);
return (SBIGOOD);
}
[3 行目: SBI 初期化]
[4 行目: SBI レジスタ設定許可]
[5 行目: SBI レジスタ値設定]
[6 行目: SBI のアドレス設定]
[9 行目: バスフリー待ち]
[16 行目: SBI を I2C スレーブとして設定する]
[17 行目: SBI を有効に設定する]
6-3-2-2 EEPROM読み取り
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
uint8_t EEPROM_Read(SBI_TypeDef * Chl,char* Buf,uint16_t RAd,uint8_t SAd,uint8_t RSz)
{
fSBISTAT = READY;
gRcvSize = RSz - 1;
/* wait for bus free */
ret = BusFreeChk(Chl);
if (ret == BUSY) {
return (SBIERROR);
}
else {
/* do nothing */
}
/* send slave address+wr & start condition */
API_SBI_CR1_Set(Chl,0x1C);
API_SBI_SndDataSet(Chl, SAd);
API_SBI_CR2_Set(Chl,0xF8);
ret = AckChk();
if (ret == NOACK) {
return (SBIERROR);
}
else {
/* do nothing */
}
30
TMPM330 アプリケーションノート
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
fSBISTAT = (READY);
/* send read address to slave */
API_SBI_SndDataSet(Chl,RAd);
ret = AckChk();
if (ret == NOACK) {
return (SBIERROR);
}
else {
/* do nothing */
}
fSBISTAT = READY;
/* send stop condition */
ret = BusBusyChk(Chl);
if (ret == FREE) {
return (SBIERROR);
}
else {
/* do nothing */
}
API_SBI_CR2_Set(Chl,0xD8);
WaitForStop(WAIT_TIME);
/* send slave address+rd & start condition */
ret = BusFreeChk(Chl);
if (ret == BUSY) {
return (SBIERROR);
}
else {
/* do nothing */
}
API_SBI_SndDataSet(Chl,(SAd|SBI_READ));
API_SBI_CR2_Set(Chl,0xF8);
ret = AckChk();
if (ret == NOACK) {
return SBIERROR;
}
else {
/* do nothing */
}
fSBISTAT = (READY);
/* read dummy to send SCK */
fSBITrxGo = GO;
*Buf = SBI2->DBR;
/* check whether tx finish or not */
ret = SBITrxChk();
if (ret == SBINOTFIN) {
return SBIERROR;
}
else {
/* do nothing */
}
/* Send STOP condition */
31
TMPM330 アプリケーションノート
77
78
79
80
81
82
83
84
85
86
87
ret = BusBusyChk(Chl);
if (ret == FREE) {
return (SBIERROR);
}
else {
/* do nothing */
}
WaitForStop(WAIT_TIME);
API_SBI_CR2_Set(Chl,0xD8);
return (SBIGOOD);
}
[7,48 行目: バスフリー待ち]
[15,16,17 行目: スレーブアドレス及び書き込み・開始条件を設定]
[18,28,57 行目: 応答チェック]
[27 行目: 読み取りアドレスを設定する]
[38,77 行目: バスビジーチェック]
[46,84 行目: スレーブ終了待ち]
[69 行目: 送信完了チェック]
6-3-2-3 EEPROM書き込み
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
uint8_t EEPROM_Write(SBI_TypeDef*Ch,char* pBuf,uint16_t WAdd,uint8_t SAdd,uint8_t Sz)
{
long i;
fSBISTAT = READY;
gSndSize = Sz;
/* save the data into tx buffer */
for(i=0; i<Sz; i++) {
gSBITxBuffer[i] = *(pBuf+i);
}
/* wait for bus free */
ret = BusFreeChk(Ch);
if (ret == BUSY) {
return (SBIERROR);
}
else {
/* do nothing */
}
/* send slave address+wr and start condition */
API_SBI_CR1_Set(Ch,0x1C);
API_SBI_SndDataSet(Ch,SAdd);
API_SBI_CR2_Set(Ch,0xF8);
ret = AckChk();
if (ret == NOACK) {
return (SBIERROR);
}
else {
/* do nothing */
32
TMPM330 アプリケーションノート
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
}
fSBISTAT = READY;
/* send write address to slave and start data tx */
fSBITrxGo = GO;
API_SBI_SndDataSet(Ch,WAdd);
/* check whether tx finish or not */
ret = SBITrxChk();
if (ret == SBINOTFIN) {
return (SBIERROR);
}
else {
/* do nothing */
}
/* Send STOP condition */
ret = BusBusyChk(Ch);
if (ret == FREE) {
return (SBIERROR);
}
else {
/* do nothing */
}
WaitForStop(WAIT_TIME);
API_SBI_CR2_Set(Ch,0xD8);
return (SBIGOOD);
}
[12 行目: バスフリー待ち]
[20,21,22 行目: スレーブアドレスと書き込み・開始条件を設定]
[23 行目: 応答チェック]
[33 行目: スレーブ書込みアドレスを設定し、データ転送開始]
[35 行目: 転送終了チェック]
[43 行目: バスビジーチェック]
[50 行目: スレーブ終了待ち]
6-3-2-4 SBI マスタ書き込み
SBIマスタ書き込み (スレーブモード用)
1
2
3
4
5
6
7
8
9
10
11
12
13
uint8_t SBI_Master_Write(SBI_TypeDef* Chl,char* pBuf,uint8_t size,uint8_t SlvAddr)
{
long i;
fSBISTAT = READY;
gSndSize = size;
/* save the data into tx buffer */
for(i=0; i<size; i++) {
gSBITxBuffer[i] = *(pBuf+i);
}
/* wait for bus free */
ret = BusFreeChk(Chl);
if (ret == BUSY) {
33
TMPM330 アプリケーションノート
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
return (SBIERROR);
}
else {
/* do nothing */
}
/* send slave address+wr and start condition */
API_SBI_CR1_Set(Chl,0x1C);
API_SBI_SndDataSet(Chl,SlvAddr);
API_SBI_CR2_Set(Chl,0xF8);
ret = AckChk();
if (ret == NOACK) {
return (SBIERROR);
}
else {
/* do nothing */
}
fSBISTAT = READY;
/* send size to slave and start data tx */
fSBITrxGo = GO;
API_SBI_SndDataSet(Chl,size);
/* check whether tx finish or not */
ret = SBITrxChk();
if (ret == SBINOTFIN) {
return (SBIERROR);
}
else {
/* do nothing */
}
/* Send STOP condition */
ret = BusBusyChk(Chl);
if (ret == FREE) {
return (SBIERROR);
}
else {
/* do nothing */
}
WaitForStop(WAIT_TIME);
API_SBI_CR2_Set(Chl,0xD8);
return (SBIGOOD);
}
[12行目: バスフリー待ち]
[20,21,22行目: スレーブアドレス及び書き込み・開始条件を設定]
[22行目: 応答チェック]
[33行目: サイズの設定とデータ転送開始]
[35行目: 転送終了チェック]
[43行目: バスビジーチェック]
[50行目: スレーブ終了待ち]
34
TMPM330 アプリケーションノート
6-3-2-5 SBI スレーブ設定
1
2
3
4
5
6
void SBI_Slave_Set(SFR_SBIx_t * SbiChSel, uint8_t SlvAddr)
{
API_SBIi_SlvAddressSet(SbiChSel, SlvAddr);
API_SBI_CR1_Set(SbiChSel, 0x1C);
API_SBI_CR2_Set(SbiChSel, 0x18);
}
[3 行目: I2C バスアドレスレジスタ設定]
[4 行目: シリアルバスコントロールレジスタ1設定]
[5 行目: シリアルバスコントロールレジスタ2設定]
6-3-2-6 バスフリーチェック
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
uint8_t BusFreeChk(SBI_TypeDef * SbiChSel)
{
long i;
for(i=0; i<=TIMEOUT; i++) {
ret = API_SBI_StatusRead(SbiChSel) & 0x20;
if(ret != 0x20) {
return (FREE);
}
else {
/* do nothing */
}
}
return (BUSY);
}
[6 行目: I2C バス状態モニタビット情報取得]
6-3-2-7 バスビジーチェック
1
2
3
4
5
6
7
8
9
10
11
12
13
14
uint8_t BusBusyChk(SBI_TypeDef * SbiChSel)
{
long i;
for(i=0; i<=TIMEOUT; i++) {
ret = API_SBI_StatusRead(SbiChSel) & 0x20;
if(ret == 0x20) {
return (BUSY);
}
else {
/* do nothing */
}
}
return (FREE);
35
TMPM330 アプリケーションノート
15 }
[6 行目: I2C バス状態モニタビット情報取得]
6-3-2-8 承認チェック
アクノリッジ(ACK)チェック
1
2
3
4
5
6
7
8
9
10
11
12
13
14
uint8_t AckChk(void)
{
long i;
for(i=0; i<=TIMEOUT; i++) {
if(fSBISTAT == YES) {
return (ACK);
}
else {
/* do nothing */
}
}
return (NOACK);
}
6-3-2-9 SBI 送信完了チェック
送信完了チェック
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
uint8_t SBITrxChk(void)
{
long i,j;
for (i=0; i<=TIMEOUT; i++) {
for (j=0; j<=TIMEOUT; j++) {
if (fSBITrxGo == HALT) {
return (SBIFIN);
}
else {
/* do nothing */
}
}
}
return (SBINOTFIN);
[7行目: 送信完了チェック]
36
TMPM330 アプリケーションノート
6-3-3 割り込み処理 : [system_it.c]
6-3-3-1 SBI2 割り込み処理
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
31
32
void INTSBI2_IRQHandler(void)
{
static uint8_t i = 0;
uint8_t sbistatus;
fSBISTAT = YES;
sbistatus = API_SBI_StatusRead(SBI2) & SBITXMODE;
if ((sbistatus == SBITXMODE) && (fSBITrxGo == GO)) {
if(gSndSize) {
gSndSize--;
API_SBI_SndDataSet(SBI2, (uint8_t)(gSBITxBuffer[i++]));
}
else {
i = 0;
fSBITrxGo = HALT;
}
}
if((sbistatus != SBITXMODE) && (fSBITrxGo == GO)) {
if (gRcvSize > 0) {
gRcvSize--;
gSBIRxBuffer[i++] = (char)(API_SBI_RcvDataRead(SBI2));
}
else {
if (fSBITrxGo != HALT) {
API_SBI_CR1_Set(SBI2,0x0C);
gSBIRxBuffer[i++] = (char)(API_SBI_RcvDataRead(SBI2));
fSBITrxGo = HALT;
i = 0;
}
}
}
}
[7 行目: 送信/受信選択モニタビット情報取得]
[8 行目: 送信モードチェック]
[11 行目: シリアルバスインターフェースデータバッファレジスタへ送信データ設定]
[18 行目: 受信モードチェック]
[25 行目: シリアルバスコントロールレジスタ1設定]
[26 行目: シリアルバスインターフェースデータバッファレジスタから受信データ読み込み]
6-3-3-2 SBI0 割り込み処理
1
2
void INTSBI0_IRQHandler(void)
{
37
TMPM330 アプリケーションノート
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
31
32
33
34
35
36
37
38
39
static uint8_t i = 0;
static uint8_t downcnt = 0;
uint8_t intStat;
intStat = API_SBI_StatusRead(SBI0);
if ((intStat & SBIAAS) == SBIAAS) {
intStat = API_SBI_RcvDataRead(SBI0);
}
else {
if ((intStat & SBILRB) == SBILRB) {
if (i == 0x00) {
downcnt = API_SBI_RcvDataRead(SBI0);
i++;
}
else {
if (downcnt != 0x00) {
downcnt--;
API_SBI_CR1_Set(SBI0, SBICR1SET);
gSBIRxBuffer[(i++)-1] = (char)(API_SBI_RcvDataRead(SBI0));
if (downcnt == 0x00) {
i = 0;
fSBIRxOK = YES;
}
else {
/* do nothing */
}
}
else {
/* do nothing */
}
}
}
else {
/* do nothing */
}
}
}
[7 行目: シリアルバスインターフェースステータスレジスタ情報取得]
[20 行目: シリアルバスコントロールレジスタ1設定]
[21 行目: シリアルバスインターフェースデータバッファレジスタから受信データ読み込み]
38
TMPM330 アプリケーションノート
6-4 CEC(Consumer Electronics Control)
6-4-1 TMPM330 CEC デモ : [main.c]
6-4-1-1 メインプログラム
この機能は、初期化終了後 RMC 及び PC のキー入力を確認し、キー入力があった場合に入
力キーに該当する CEC コマンドを送信します。NORMAL モードではリモコンのパワーキーのみ
で動作モードは、SLEEP モードへ遷移します。SLEEP モードでは、CEC データの受信のみで動
作モードは、NORMAL モードに復帰します。CEC の受信データは、UART にて PC へ送信しま
す。
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
31
32
33
uint32_t main(void)
{
uint8_t tmpCMD;
uint8_t tmp_i;
IO_SFR16_u RMCcmd;
int char_PC2board;
Set_System();
NVIC->ICER[0] = 0xFFFFFFFF;
NVIC->ICER[1] = 0xFFFFFFFF;
NVIC->ICER[2] = 0xFFFFFFFF;
NVIC->ICER[3] = 0xFFFFFFFF;
/*************** TIMER init *****************/
Timer_Init(TB0, 0x06, 0x00, 0xC3);
API_TMRB_RG1_Write(TB0, 0x09C0);
Timer_Init(TB1, 0x06, 0x00, 0xC3);
API_TMRB_RG1_Write(TB1, 0x09C0);
/************* UART init **************/
Uart_IO_Configuration();
UART_Init();
/************* RMC init **************/
RMC_IO_Configuration(RMC1);
RMC_ChInit(RMC1);
/************* CEC Port: PortK set **************/
API_PORT_CrRegSet(PORTK,0x01);
API_PORT_Fr1RegSet(PORTK,0x01);
API_PORT_IeRegSet(PORTK,0x01);
CEC_Init();
/*************** int init *****************/
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGB,20))) = 1;
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGB,21))) = 1;
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGB,22))) = 0;
39
TMPM330 アプリケーションノート
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGC,28))) = 1;
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGC,29))) = 1;
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGC,30))) = 0;
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGD,4))) = 1;
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGD,5))) = 1;
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGD,6))) = 0;
CG_IMCGB_INT6EN = ENABLE;
CG_IMCGC_INTBEN = ENABLE;
CG_IMCGD_INTCEN = ENABLE;
NVIC_EnableIRQ(INTRX0_IRQn);
NVIC_EnableIRQ(INTTX0_IRQn);
NVIC_EnableIRQ(INTRX1_IRQn);
NVIC_EnableIRQ(INTCECRX_IRQn);
NVIC_EnableIRQ(INTCECTX_IRQn);
NVIC_EnableIRQ(INTTB1_IRQn);
NVIC_EnableIRQ(INTRMCRX1_IRQn)
API_TMRB_RunSet(TB1, TMRB_RUN, TMRB_RUN);
/*************** Setting CECRx to release Sleep mode *****************/
PowerMode_SetClearFactor(CF_CECRX, CF_ENABLE, CF_RISING);
printf("TMPM330 CEC DEMO\r\n");
for (;;) {
if (fRMCDone && (CMD_Buffer.WrIdx < CMD_BUFFER_SIZE)) {
API_RMC_RcvEnable(RMC1, DISABLE);
RMCcmd.reg = RMCRcv(RMC1);
#ifdef RMC_1
tmpCMD = RMCcmd.byte[0];
#endif
#ifdef RMC_2
tmpCMD = RMCcmd.byte[0]&0x3F;
#endif
#ifdef RMC_3
tmpCMD = RMCcmd.byte[0];
#endif
#ifdef RMC_4
tmpCMD = RMCcmd.byte[0];
#endif
#ifdef RMC_5
tmpCMD = RMCcmd.byte[0];
#endif
switch (tmpCMD) {
case REMO_CTRL_1: /* [1] */
CMD_Buffer.Data[CMD_Buffer.WrIdx++] = KEY_POWER;
break;
case REMO_CTRL_2: /* [2] */
CMD_Buffer.Data[CMD_Buffer.WrIdx++] = KEY_STANDBY;
break;
case REMO_CTRL_3: /* [3] */
CMD_Buffer.Data[CMD_Buffer.WrIdx++] = KEY_PLAY;
break;
case REMO_CTRL_4: /* [4] */
CMD_Buffer.Data[CMD_Buffer.WrIdx++] = KEY_STOP;
break;
40
TMPM330 アプリケーションノート
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
case REMO_CTRL_POWER: /* [POWER] */
PowerMode_N2Sleep();
break;
default:
/* do nothing */
break;
}
API_RMC_RcvEnable(RMC1, ENABLE);
}
else {
/* do nothing */
}
if (fSIORxOK == YES){
char_PC2board = getchar();
}
else {
/* do nothing */
}
char_PC2board -= 0x30;
if ((char_PC2board >= 0x01) && (char_PC2board <= 0x04)) {
CMD_Buffer.Data[CMD_Buffer.WrIdx++] = char_PC2board;
}
else {
/* do nothing */
}
if (CMD_Buffer.RdIdx >= CMD_BUFFER_SIZE) {
CMD_Buffer.WrIdx = 0;
CMD_Buffer.RdIdx = 0;
}
else {
/* do nothing */
}
CEC_CMD_Task();
CEC_Receive();
/* CEC Received data display on PC */
if (gCEC_RcvEnd_Flag == SET) {
gCEC_RcvEnd_Flag = CLEAR;
printf("CEC_Recv: ");
for (tmp_i=0; tmp_i<=gCEC_RcvCnt; tmp_i++) {
printf(" %02x", gCEC_RcvDataBuf[tmp_i]);
}
printf("\r\n");
gCEC_RcvCnt = 0;
}
else {
/* do nothing */
}
/* CEC Send data display on PC */
if (gCEC_SndEnd_Flag == SET) {
gCEC_SndEnd_Flag = CLEAR;
printf("CEC_Send: ");
for (tmp_i=0; tmp_i<=gCEC_SendCnt; tmp_i++) {
41
TMPM330 アプリケーションノート
138
139
140
141
142
143
144
145
146
147
printf(" %02x", gCEC_SendDataBuf[tmp_i]);
}
printf("\r\n");
gCEC_SendCnt = 0;
}
else {
/* do nothing */
}
}
}
[9 行目: システムクロック、I/O ポートを設定]
[15 行目: TMRB0 初期設定]
[16 行目: TMRB0 タイマレジスタ設定 1ms]
[17 行目: TMRB1 初期設定]
[18 行目: TMRB1 タイマレジスタ設定 1ms]
[20 行目: UART I/O ポート設定]
[21 行目: UART 初期化]
[23 行目: RMC1 I/O ポート設定]
[24 行目: RMC1 channel 設定]
[26 行目: CEC port K コントロールレジスタ設定]
[27 行目: CEC port K ファンクションレジスタ設定]
[28 行目: CEC port K 入力イネーブルレジスタ設定]
[29 行目: CEC 初期化]
[31,32,33,34,35,36,37,38,39行目: 割り込み、スタンバイ解除要求のアクティブ状態設定]
[40,41,42行目: 解除入力設定]
[43,44,45,46,47,48,49行目: 割り込み許可]
[50 行目: TMRB1 動作開始]
[52 行目: Sleep モード解除要因設定]
[56 行目: リモコン受信イネーブルレジスタを受信禁止に設定]
[57 行目: RMC1 受信データ取得]
[87 行目: リモコン受信イネーブルレジスタを受信許可に設定]
[93 行目: Sleep モードへ移行]
[118 行目: CEC コマンド送信タスク]
[119 行目: CEC データ受信]
6-4-2 CEC 制御関数 : [cec.c]
6-4-2-1 CEC 初期化
CEC のレジスタ及び変数を初期化します。
論理アドレスは 14bit 目を指定します。
42
TMPM330 アプリケーションノート
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void CEC_Init( void )
{
API_CEC_IP_Enable(ENABLE);
API_CEC_Idle(ENABLE);
API_CEC_SoftReset();
gCEC_PhyAddr = CECLOGICADR;
API_CEC_LogAdrSet( gCEC_PhyAddr );
API_CEC_RcvRegSet(CECRCR1DATA,CECRCR2DATA,CECRCR3DATA);
gCEC_IO_Cectce.reg = IP_CEC_FREE_05;
API_CEC_SndRegSet(gCEC_IO_Cectce.reg);
API_CEC_RcvEnable(ENABLE);
gCEC_SendStatus = 0;
gCEC_SendMode = 0;
gCEC_RcvMode = 0;
gCEC_RcvCnt = 0;
gCEC_RcvEnd_Flag = 0;
gCEC_Command_Mode = CEC_CMD_MODE_IDLE;
}
[3 行目: CEC 動作許可]
[4 行目: CEC IDLE 時の動作許可]
[5 行目: CEC ソフトウェアリセット許可]
[7 行目: CEC ロジカルアドレスレジスタ設定]
[8 行目: CEC 受信コントロールレジスタ 1,2,3 設定]
[10 行目: CEC 送信コントロールレジスタ設定]
[11 行目: CEC 受信制御許可]
6-4-2-2 待機命令送信
CEC 待機命令を送信します。
システムスタンバイ(36H)を設定します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void CEC_Send_Standby( void )
{
gCEC_SendDataBuf[0] = BROADCAST;
gCEC_SendDataBuf[1] = OPSTANDBY;
gCEC_SendByte = 0x01;
gCEC_SendCnt = 0;
gCEC_SendMode = 1;
gCEC_IO_Cectce.byte[0] = IP_CEC_BRD + IP_CEC_FREE_05;
API_CEC_SndRegSet(gCEC_IO_Cectce.reg);
gCEC_IO_Cectce.byte[0] = IP_CEC_BRD + IP_CEC_FREE_03;
gCEC_SendBuffer.byte[0] = gCEC_SendDataBuf[0];
gCEC_SendBuffer.byte[1] = 0x00;
API_CEC_SndDataSet(gCEC_SendBuffer.reg);
API_CEC_SndStart(ENABLE);
}
[9 行目: CEC 送信コントロールレジスタ設定]
[13 行目: CEC 送信をバッファにセット]
[14 行目: CEC 送信制御許可]
43
TMPM330 アプリケーションノート
6-4-2-3 CEC リモコンパススルー
CEC リモコンパススルーコマンド
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
31
32
33
34
35
36
37
void CEC_RemoConThrough( uint8_t request, uint8_t key_value )
{
switch (request) {
case CMD_CEC_USER_CONTROL_PRESSED:
gCEC_SendDataBuf[0] = RECDEVICE;
gCEC_SendDataBuf[1] = CMD_CEC_USER_CONTROL_PRESSED;
gCEC_SendDataBuf[2] = key_value;
gCEC_SendByte = 0x02;
gCEC_SendCnt = 0;
gCEC_SendMode = 1;
gCEC_IO_Cectce.byte[0] =IP_CEC_FREE_05;
API_CEC_SndRegSet(gCEC_IO_Cectce.reg);
gCEC_IO_Cectce.byte[0] =IP_CEC_FREE_03;
gCEC_SendBuffer.byte[0] = gCEC_SendDataBuf[0];
gCEC_SendBuffer.byte[1] = 0x00;
API_CEC_SndDataSet(gCEC_SendBuffer.reg);
API_CEC_SndStart(ENABLE);
break;
case CMD_CEC_USER_CONTROL_RELEASED:
gCEC_SendDataBuf[0] = RECDEVICE;
gCEC_SendDataBuf[1] = CMD_CEC_USER_CONTROL_RELEASED;
gCEC_SendByte = 0x01;
gCEC_SendCnt = 0;
gCEC_SendMode = 1;
gCEC_IO_Cectce.byte[0] =IP_CEC_FREE_07;
API_CEC_SndRegSet(gCEC_IO_Cectce.reg);
gCEC_IO_Cectce.byte[0] = IP_CEC_FREE_03;
gCEC_SendBuffer.byte[0] = gCEC_SendDataBuf[0];
gCEC_SendBuffer.byte[1] = 0x00;
API_CEC_SndDataSet(gCEC_SendBuffer.reg);
API_CEC_SndStart(ENABLE);
break;
default:
/* do nothing */
break;
}
}
[12,26 行目: CEC 送信コントロールレジスタ設定]
[16,30 行目: CEC 送信バッファレジスタ設定]
[17,31 行目: CEC 送信制御許可]
6-4-2-4 CEC コマンドタスク
CEC コマンドバッファを確認し、バッファが空いてなかったら、次のコマンドを送信します。
コマンドの種類は、パワー, システムスタンバイ, プレイ, ストップの 4種類に対応しています。
44
TMPM330 アプリケーションノート
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
void CEC_CMD_Task( void )
{
switch (gCEC_Command_Mode) {
case CEC_CMD_MODE_IDLE:
if (CMD_Buffer.RdIdx < CMD_Buffer.WrIdx) {
gCEC_Command_Mode = CEC_CMD_MODE_START;
}
else {
/* do nothing */
}
break;
case CEC_CMD_MODE_START:
switch (CMD_Buffer.Data[CMD_Buffer.RdIdx]) {
case KEY_POWER: /* [Power] */
gCEC_Command_Mode = CEC_CMD_MODE_USER_PRESSED;
gCEC_Send_Cmd = CEC_POWER;
break;
case KEY_STANDBY: /* [Standby] */
gCEC_Command_Mode = CEC_CMD_MODE_STANDBY_SEND;
gCEC_Send_Cmd = CEC_STANDBY;
break;
case KEY_PLAY: /* [Play] */
gCEC_Command_Mode = CEC_CMD_MODE_USER_PRESSED;
gCEC_Send_Cmd = CEC_PLAY;
break;
case KEY_STOP: /* [Stop] */
gCEC_Command_Mode = CEC_CMD_MODE_USER_PRESSED;
gCEC_Send_Cmd = CEC_STOP;
break;
default:
CMD_Buffer.RdIdx++;
gCEC_Command_Mode = CEC_CMD_MODE_IDLE;
break;
}
break;
case CEC_CMD_MODE_STANDBY_SEND:
CEC_Send_Standby( );
gCEC_Command_Mode = CEC_CMD_MODE_OK;
break;
case CEC_CMD_MODE_USER_PRESSED:
CEC_RemoConThrough(CMD_CEC_USER_CONTROL_PRESSED,
gCEC_Send_Cmd );
gCEC_Command_Mode = CEC_CMD_MODE_USER_RELEASED;
gCecTime = CECTIMEOUT;
break;
case CEC_CMD_MODE_USER_RELEASED:
if (gCEC_SendMode == CLEAR) {
if (gCecUnP == SET) {
gCecUnP = CLEAR;
CEC_RemoConThrough( CMD_CEC_USER_CONTROL_RELEASED, 0 );
gCEC_Command_Mode = CEC_CMD_MODE_OK;
}
45
TMPM330 アプリケーションノート
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
else {
/* do nothing */
}
}
else {
/* do nothing */
}
break;
case CEC_CMD_MODE_OK:
if (gCEC_SendMode == CLEAR) {
gCEC_Command_Mode = CEC_CMD_MODE_IDLE;
CMD_Buffer.RdIdx++;
}
else {
/* do nothing */
}
break;
default:
break;
}
}
[37 行目: システムスタンバイコマンド送信]
[41,50 行目: CEC コマンド送信]
6-4-2-5 CEC 受信
CEC 受信割り込み処理に受信データがあるかを確認し、データがあれば、
gCEC_RcvDataBuf[ ]に保存します。データが最終フレームの場合は、フラグをセットします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void CEC_Receive(void)
{
if (gCEC_RcvMode == SET) {
gCEC_RcvMode = CLEAR;
gCEC_RcvDataBuf[gCEC_RcvCnt] = gCEC_RcvBuffer.byte[0];
gCEC_RcvCnt++;
if ((gCEC_RcvBuffer.byte[1] & CEOF) == CEOF) {
gCEC_RcvEnd_Flag = SET;
}
else {
/* do nothing */
}
}
else {
/* do nothing */
}
}
46
TMPM330 アプリケーションノート
6-4-3 割り込み関数 : [system_it.c]
6-4-3-1 CEC 受信割り込み処理
CEC 受信データバッファレジスタを読み取り、データ受信フラグを設定します。
[3 行目: INTCECRX 割り込み要求をクリア]
[4 行目: CEC 受信割り込みステータスレジスタ情報取得]
[5 行目: CEC 受信データ取得]
6-4-3-2 CEC 送信割り込み処理
CEC 送信ステータスを確認し、送信中且つエラーでない場合は、次のCECデータを送信します。
送信終了又はエラーの場合は、送信を停止します。
1
2
3
4
5
6
7
void INTCECRX_IRQHandler(void) {
CG->ICRCG= 0x06;
gCEC_RcvStatus = API_CEC_RcvIntStatus();
gCEC_RcvBuffer.reg = API_CEC_RcvDataRead();
gCEC_RcvMode = 1;
}
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
void INTCECTX_IRQHandler(void) {
CG->ICRCG= 0x0c;
gCEC_SendStatus = API_CEC_SndIntStatus();
switch(gCEC_SendStatus){
case 0x01:
if ( gCEC_SendCnt < gCEC_SendByte ) {
++gCEC_SendCnt;
if ( gCEC_SendCnt >= gCEC_SendByte ) {
gCEC_SendBuffer.byte[1] = 0x01;
gCEC_SndEnd_Flag = 1;
}
else {
gCEC_SendBuffer.byte[1] = 0x00;
}
gCEC_SendBuffer.byte[0] = gCEC_SendDataBuf[gCEC_SendCnt];
API_CEC_SndDataSet(gCEC_SendBuffer.reg);
}
else {
/* do nothing */
}
break;
default:
gCEC_SendMode = 0;
break;
}
47
TMPM330 アプリケーションノート
[4 行目: CEC 送信割り込みステータスレジスタ情報取得]
[17 行目: CEC 送信バッファレジスタに送信データを設定]
27 }
48
TMPM330 アプリケーションノート
6-5 リモコン(RMC)
6-5-1 TMPM330 RMC デモ : [main.c]
6-5-1-1 メインプログラム
メイン処理
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
31
32
33
34
35
36
37
38
39
int main(void)
{
SYSSTAT fSysSleep;
Set_System();
NVIC_EnableIRQ(INTRX0_IRQn);
NVIC_EnableIRQ(INTTX0_IRQn);
NVIC_EnableIRQ(INTRMCRX1_IRQn);
UART_Init();
Timer_ChInit(TMRB0, TMRB_MOD, TMRB_CR, TMRB_FFCR);
API_TMRB_RG1_Write(TMRB0, ONEMS);
RMC_IO_Configuration(RMC1);
RMC_ChInit(RMC1);
PowerMode_SetClearFactor(CF_RMCRX1, CF_ENABLE, CF_RISING);
/* Initialize Variables */
gSIORdIndex = 0;
gSIOWrIndex = 0;
fSIO0_INT = 0;
fTMRB0_INT = 0;
fSysSleep = WAKE;
fRMCDone = UNDONE;
fRMCPress = RELEASE;
printf("TMPM330 RMC DEMO\r\n");
for (;;) {
if (fRMCDone == DONE) {
API_RMC_RcvEnable(RMC1, DISABLE);
RMCRcv(RMC1);
switch (gRMC_Command) {
/* special keys: sleep -> normal */
case SEVEN_KEY:
PrintCode(FORMAT, gRMC_Address, gRMC_Command);
if(fSysSleep == SLEEP) {
fSysSleep = WAKE;
printf("Wakeup from Sleep\r\n");
}
else {
/* do nothing */
}
break;
49
TMPM330 アプリケーションノート
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/* special keys: normal -> sleep */
case NINE_KEY:
if (fSysSleep == WAKE) {
fSysSleep = SLEEP;
PrintCode(FORMAT, gRMC_Address, gRMC_Command);
printf("Now, Going to Sleep\r\n"); API_RMC_RcvEnable(RMC1, ENABLE);
Delay_ms(1000);
PowerMode_N2Sleep();
}
else {
API_RMC_RcvEnable(RMC1, ENABLE);
Delay_ms(1000);
PowerMode_N2Sleep();
}
break;
/* other keys */
default:
if (fSysSleep == WAKE) {
PrintCode(FORMAT, gRMC_Address, gRMC_Command);
}
else {
API_RMC_RcvEnable(RMC1, ENABLE);
Delay_ms(1000);
PowerMode_N2Sleep();
}
break;
}
API_RMC_RcvEnable(RMC1, ENABLE);
}
else {
/* do nothing */
}
}
}
[5 行目: システムクロック、I/O ポートを設定]
[6 行目: 割り込み初期化]
[7,8 行目: 割り込み許可]
[9 行目: UART 初期化]
[10 行目: TMRB0 初期設定]
[11 行目: TMRB0 タイマレジスタ設定]
[12 行目: RMC I/O ポート初期化]
[13 行目: RMC channel 設定]
[14 行目: Sleep モード解除要因設定]
[26 行目: RMC 受信禁止]
[27 行目: RMC 受信データ取得]
[31,44,59 行目: RMC 受信データを出力]
[46,51,62,68 行目: RMC受信許可]
[48,53,64 行目: Sleep モードへ移行]
50
TMPM330 アプリケーションノート
6-5-1-2 コード出力
リモコン信号の、カスタマコード(アドレス)、データコード(コマンド)を出力します。
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
void PrintCode(char * ch, uint16_t add, uint32_t com)
{
#ifdef RMC_1
printf("%s: %02x %02x\r\n ", ch, add, com); #endif
#ifdef RMC_2
printf("%s: %02x %02x\r\n ", ch, add, com); #endif
#ifdef RMC_3
printf("%s: %04x %06x\r\n ", ch, add, com); #endif
#ifdef RMC_4
if (gRMC_4Address != 13) {
printf("%s: %02x %02x\r\n ", ch, add, com); }
else {
printf("%s: %04x %02x\r\n ", ch, add, com); }
#endif
#ifdef RMC_5
printf("%s: %02x %02x\r\n ", ch, add, com); #endif
}
6-5-2 RMC 制御関数 : [rmc.c]
6-5-2-1 RMC I/O 設定
RMC の I/O ポートを設定します。
ポート E3 と F3 を RMC0 と RMC1 に設定します。
1
2
3
4
5
6
7
void RMC_IO_Configuration(RMC_TypeDef * RmcChSel)
{
API_RMC_Init(RmcChSel);
if (RmcChSel == RMC0) {
/************* RMC0(PE3) port setting **************/
API_PORT_Fr1RegSet(PORTE, 0x08);
API_PORT_IeRegSet(PORTE, 0x08);
51
TMPM330 アプリケーションノート
8
9
10
11
12
13
14
15
16
17
}
else if(RmcChSel == RMC1) {
/************* RMC1(PF3) port setting **************/
API_PORT_Fr1RegSet(PORTF, 0x08);
API_PORT_IeRegSet(PORTF, 0x08);
}
else {
/* do nothing */
}
}
[3 行目: RMC 初期化]
[6 行目: RMC0 Port E ファンクションレジスタ1設定 ]
[7 行目: RMC0 Port E 入力イネーブル制御レジスタ設定 ]
[11 行目: RMC1 Port F ファンクションレジスタ1設定 ]
[12 行目: RMC1 Port F 入力イネーブル制御レジスタ設定 ]
6-5-2-2 RMC 初期化
RMC チャネルを有効、及び IR フォーマットにより各属性を設定します。
1
2
3
4
5
6
7
void RMC_ChInit(RMC_TypeDef * RmcChSel)
{
API_RMC_IP_Enable(RmcChSel, ENABLE);
API_RMC_Idle(RmcChSel, ENABLE);
API_RMC_RcvRegSet(RmcChSel, RMCRCR1, RMCRCR2, RMCRCR3, RMCRCR4);
API_RMC_RcvEnable(RmcChSel, ENABLE);
}
[3 行目: RMC 動作許可]
[4 行目: RMC IDLE 時の動作許可]
[5 行目: RMC 受信コントロールレジスタ 1,2,3,4,設定 ]
[6 行目: RMC 受信許可 ]
6-5-2-3 RMC 受信処理
RMC受信データからカスタマコード(アドレス) とデータコード (コマンド)を読み取ります。
1
2
3
4
5
6
7
8
9
10
11
12
13
void RMCRcv(RMC_TypeDef * RmcChSel)
{
fRMCDone = UNDONE;
#ifdef RMC_1
gRMC_Address = uRMCBuf.byte[3];
gRMC_Command = uRMCBuf.byte[1];
#endif
#ifdef RMC_2
gRMC_Address = ((uRMCBuf.byte[1] & 0x07) << 2)
+ ((uRMCBuf.byte[0] & 0xC0) >> 6);
gRMC_Command = uRMCBuf.byte[0] & 0x3F;
#endif
52
TMPM330 アプリケーションノート
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#ifdef RMC_3
gRMC_Address = (uint16_t)uRMCBuf_KA.reg;
gRMC_Command = uRMCBuf.reg & 0x00FFFFFF;
#endif
#ifdef RMC_4
switch (gRMC_4Address) {
case 5: /* 5-bit address */
gRMC_Address = uRMCBuf.byte[0] & 0x1F;
gRMC_Command = ((uRMCBuf.byte[1] & 0x0F) << 3)
+ ((uRMCBuf.byte[0] & 0xE0) >> 5);
break;
case 8: /* 8-bit address */
gRMC_Address = uRMCBuf.byte[0];
gRMC_Command = uRMCBuf.byte[1] & 0x7F;
break;
case 13: /* 13-bit address */
gRMC_Address = ((uRMCBuf.byte[1] & 0x1F) << 8)
+ uRMCBuf.byte[0];
gRMC_Command = ((uRMCBuf.byte[2] & 0x0F) << 3)
+ ((uRMCBuf.byte[1] & 0xE0) >> 5);
break;
default:
printf("RMC RECEIVE ERROR in RMC_4 FORMAT\r\n"); break;
}
#endif
#ifdef RMC_5
gRMC_Address = (uRMCBuf.byte[1] & 0x7C) >> 2;
gRMC_Command = ((uRMCBuf.byte[1] & 0x03) << 6)
+ ((uRMCBuf.byte[0] & 0xFC) >> 2);
if ((uRMCBuf.byte[0] & 0x02) == 0x00) {
gRMC_Command ^= 0xff;
}
else {
/* do nothing */
}
#endif
}
53
TMPM330 アプリケーションノート
6-5-3 割り込み処理 : [system_it.c]
6-5-3-1 RMC 受信割り込み処理
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
void INTRMCRX1_IRQHandler(void)
{
uint16_t RcvStatus = 0;
RcvStatus = API_RMC_RcvIntStatus(RMC1);
#ifdef RMC_1
/********************* FOR RMC_1 FORMAT ***********************/
if (RcvStatus == 0x20A0) {
uRMCBuf.reg = RMC1->RBUF1;
gRMCTimeOut = 0;
if(fRMCPress == RELEASE) {
fRMCPress = PRESS;
}
else {
/* do nothing */
}
}
else {
if (RcvStatus == 0x2080 && fRMCPress) {
gRMCTimeOut = 0;
}
else {
/* do nothing */
}
}
#endif
#ifdef RMC_2
/********************* FOR RMC_2 FORMAT ***********************/
if ((RcvStatus&0xF07F) == 0x400E) {
uRMCBuf.reg = RMC1->RBUF1;
gRMCTimeOut = 0;
if(fRMCPress == RELEASE) {
fRMCPress = PRESS;
}
else {
/* do nothing */
}
}
else {
/* do nothing */
}
#endif
#ifdef RMC_3
/********************* FOR RMC_3 FORMAT ***********************/
if (RcvStatus == 0x2030) {
54
TMPM330 アプリケーションノート
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
uRMCBuf.reg = RMC1->RBUF1;
uRMCBuf_KA.reg = RMC1->RBUF2;
gRMCTimeOut = 0;
if(fRMCPress == RELEASE) {
fRMCPress = PRESS;
}
else {
/* do nothing */
}
}
else {
/* do nothing */
}
#endif
#ifdef RMC_4
/********************* FOR RMC_4 FORMAT ***********************/
if (RcvStatus == 0x208C) {
gRMC_4Address = 5;
}
else if(RcvStatus == 0x208F) {
gRMC_4Address = 8;
}
else if(RcvStatus == 0x2094) {
gRMC_4Address = 13;
}
else {
gRMC_4Address = 0;
}
if (gRMC_4Address) {
uRMCBuf.reg = RMC1->RBUF1;
gRMCTimeOut = 0;
if (fRMCPress == RELEASE) {
fRMCPress = PRESS;
}
else {
/* do nothing */
}
}
else {
/* do nothing */
}
#endif
#ifdef RMC_5
/********************* FOR RMC_5 FORMAT ***********************/
if (RcvStatus == 0x200F) {
static IO_SFR32_u RMC_5_data[2];
if(gRMC_5_Cnt < 2) {
RMC_5_data[gRMC_5_Cnt++].reg
= RMC1->RBUF1;
}
else {
55
TMPM330 アプリケーションノート
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
if ((RMC_5_data[0].byte[0] +
RMC_5_data[1].byte[0]) != 0xFF) {
gRMC_5_Cnt = 0;
}
else {
uRMCBuf.reg = RMC_5_data[0].reg;
}
}
gRMCTimeOut = 0;
if (fRMCPress == RELEASE) {
fRMCPress = PRESS;
}
else {
/* do nothing */
}
}
else {
/* do nothing */
}
#endif
/* Detect RMC input TIMEOUT */
if ((fRMCPress) == PRESS && !fTMRB0_INT) {
fTMRB0_INT = 1;
API_TMRB_RunSet(TMRB0, TMRB_STOP, TMRB_STOP);
API_INT_SER_0_31_Set(INT_BIT18);
API_TMRB_RunSet(TMRB0, TMRB_RUN, TMRB_RUN);
}
else {
/* do nothing */
}
CG->ICRCG = 0x0B;
}
[5 行目: RMC 受信ステータスレジスタ情報取得]
[121 行目: TMRB0 動作停止&クリア]
[122 行目: TMRB0 割り込み許可]
[123 行目: TMRB0 動作開始]
6-5-3-2 タイマ割り込み 0
1
2
3
4
5
6
7
8
9
10
11
void INTTB0_IRQHandler (void) {
if (++gRMCTimeOut > 300) {
gRMCTimeOut = 0;
fTMRB0_INT = 0;
#ifdef RMC_5
gRMC_5_Cnt = 0;
#endif
fRMCPress = RELEASE;
fRMCDone = DONE;
NVIC_DisableIRQ(INTTB0_IRQn);
56
TMPM330 アプリケーションノート
12
13
14
15
16
}
else {
/* do nothing */
}
}
[11 行目: TMRB0 割り込み許可]
57
TMPM330 アプリケーションノート
6-6 タイマ(TMRB)
6-6-1 TMPM330 TMRB デモ: [main.c]
6-6-1-1 メインプログラム
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
31
32
33
34
35
36
37
38
39
int main(void)
{
uint8_t Rate = 0;
uint16_t Duty[5]={0x08D0, 0x0758, 0x04E6, 0x0273, 0x00FA}; uint8_t PPGmode = FALSE;
uint8_t key_info;
/* Initialize system */
Set_System();
LCD_Configuration();
LCD_Light(ON);
/* Set PH6 as TB3IN0 */
API_PORT_CrRegSet(PORTH, INITPORTHCR);
API_PORT_Fr1RegSet(PORTH, INITPORTHFR1);
API_PORT_PupRegSet(PORTH, INITPORTHPUP);
API_PORT_IeRegSet(PORTH, INITPORTHIE);
/* Set PI0 as TB0OUT for PPG output */
API_PORT_Init(PORTI);
API_PORT_CrRegSet(PORTI, INITPORTICR);
API_PORT_Fr1RegSet(PORTI, INITPORTIFR1);
API_PORT_PupRegSet(PORTI, INITPORTOPUP);
/* Initialize TMRB0, TMRB5, TMRB3, TMRB8 */
TMRB_ChInit(TB0, TMRB_MOD_PPG, TMRB_CR_PPG, TMRB_FFCR_PPG);
TMRB_ChInit(TB5, TMRB_MOD_1ms, TMRB_CR_1ms, TMRB_FFCR_1ms);
TMRB_ChInit(TB3, TMRB_MOD_FM_EX, TMRB_CR_FM_EX, TMRB_FFCR_FM_EX);
TMRB_ChInit(TB8,TMRB_MOD_FM_FFOUT,TMRB_CR_FM_FFOUT,
TMRB_FFCR_FM_FFOUT);
API_TMRB_RG1_Write(TB8, TMRB8TIME);
NVIC_EnableIRQ(INTTB5_IRQn);
/* 1ms setting */
API_TMRB_RG1_Write(TB5, TMRB5TIME);
API_TMRB_RunSet(TB5, TMRB_RUN, TMRB_RUN);
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text(" General Timer");
58
TMPM330 アプリケーションノート
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text(" ");
do { /* wait for K1 pressed */
key_info = API_PORT_BitIn(KEY_PORT, KEY1);
} while (key_info == TRUE);
do { /* wait for key released */
key_info = API_PORT_Read(KEY_PORT) & KEYRELEASE;
} while (key_info != KEYRELEASE);
PPGmode = TRUE;
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text("K2: Change Duty");
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text("K3: Measure Frq");
/* PPG setting */
API_TMRB_RG1_Write(TB0, TMRB0TIME);
API_TMRB_RG0_Write(TB0, TMRB0DUTY);
API_TMRB_RunSet(TB0, TMRB_RUN, TMRB_RUN);
for (;;) {
key_info = API_PORT_Read(KEY_PORT);
switch(key_info) {
case K2: /* PPG mode */
do {
key_info = API_PORT_Read(KEY_PORT) & KEYRELEASE;
} while (key_info != KEYRELEASE);
PPGmode = TRUE;
API_TMRB_RunSet(TB0, TMRB_STOP, TMRB_STOP);
TMRB_ChInit(TB0, TMRB_MOD_PPG, TMRB_CR_PPG, TMRB_FFCR_PPG);
Rate++;
if(Rate >= DUTYMAX) {
Rate = DUTYINIT;
}
else {
/* do nothing */
}
API_TMRB_RG0_Write(TB0, Duty[Rate]);
API_TMRB_RG1_Write(TB0, TMRB0TIME);
API_TMRB_RunSet(TB0, TMRB_RUN, TMRB_RUN);
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text("PPG OUT");
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text(DutyRateToString(Rate));
break;
case K3: /* Frequency Measurement */
do {
key_info = API_PORT_Read(KEY_PORT) & KEYRELEASE;
} while (key_info != KEYRELEASE);
59
TMPM330 アプリケーションノート
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
PPGmode = FALSE;
NVIC_EnableIRQ(INTTB8_IRQn);
API_TMRB_RunSet(TB3, TMRB_RUN, TMRB_RUN);
API_TMRB_RunSet(TB8, TMRB_RUN, TMRB_RUN);
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text("Freq Measure");
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text("f= 0Hz");
break;
default:
if((PPGmode == FALSE) && (fFreqMOK == TRUE)) {
fFreqMOK = FALSE;
Cal_Freq();
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text("Freq Measure");
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text(FrequencyToString(gFreq[0]));
NVIC_EnableIRQ(INTTB8_IRQn);
}
else {
/* do nothing */
}
break;
}
}
}
[9 行目: CG レジスタ設定、WDT 禁止、ボタン、LCD、A/D I/O 設定]
[10 行目: LCD 初期化]
[11 行目: LCD バックライトオン]
[14,15,16,17 行目: ポート PH6 を TB3IN0 入力に設定]
[20,21,22,23 行目: ポート PI0 を PPG出力に設定]
[26 行目: タイマ 0 を PPG出力モードに設定]
[27 行目: タイマ 5 をインタバルタイマモードに設定 1ms 周期]
[28 行目: タイマ 3 を両エッジキャプチャ取込みに設定]
[29 行目: タイマ 8 をトリガイネーブルに設定]
[31 行目: タイマ 8 のタイマカウント値設定(26ms)]
[32 行目: タイマ 5 割り込み許可]
[35 行目: タイマ 5 のタイマカウント値設定(1ms)]
[36 行目: タイマ 5 カウント開始]
[38,39,40,41 行目: LCD 表示設定]
[43,44,45,46,47,48 行目: KEY1 入力待ち]
[52,53,54,55 行目: LCD 表示設定]
[58,59 行目: タイマ 0の 1ms 周期で Duty10%に設定]
[60 行目: タイマ 0 カウント開始]
[70 行目: タイマ 0 停止]
60
TMPM330 アプリケーションノート
[71 行目: タイマ 0 を PPG出力モードに設定]
[79,80,81 行目: タイマ 0 の Duty 変更]
[83,84,85,86 行目: LCD 表示設定]
[93 行目: タイマ 8 割り込み許可]
[94 行目: タイマ 3 カウント開始]
[95 行目: タイマ 8 カウント開始]
[97,98,99,100 行目: LCD 表示設定]
[105 行目: 平均周波数の計算]
[107,108,109,110 行目: LCD 表示設定]
[112 行目: タイマ 8 割り込み許可]
6-6-1-2 平均周波数の計算
1
2
3
4
5
6
7
8
9
void Cal_Freq(void)
{
uint8_t i;
for(i = 1; i < TIMES; i++) {
gFreq[0] += gFreq[i];
}
gFreq[0] = gFreq[0] / TIMES;
}
6-6-2 タイマ制御関数 : [timer.c]
6-6-2-1 タイマ初期化
1
2
3
4
5
6
7
8
9
void TMRB_ChInit(TB_TypeDef * TmrbChSel, uint8_t MOD, uint8_t CR, uint8_t FFCR)
{
API_TMRB_Init(TmrbChSel);
API_TMRB_IP_Enable(TmrbChSel, ENABLE);
API_TMRB_ModSet(TmrbChSel, MOD);
API_TMRB_CrSet(TmrbChSel, CR);
API_TMRB_FFCrSet(TmrbChSel, FFCR);
API_TMRB_RunSet(TmrbChSel, TMRB_STOP, TMRB_STOP);
}
[3 行目: タイマの初期化]
[4 行目: タイマ割り込み許可]
[5 行目: モードレジスタの設定]
[6 行目: コントロールレジスタを設定する]
[7 行目: フリップフロップコントロールレジスタを設定する]
[8 行目: タイマカウント停止]
61
TMPM330 アプリケーションノート
6-6-3 文字列変換処理: [tmrb_tostring.c]
6-6-3-1 デューティレート文字列変換
LCD 表示用にデューティレートを文字列に変換します。
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
31
32
char * DutyRateToString(uint8_t num)
{
static char duty[9]="Duty: %";
switch(num) {
case 0:
duty[6] = '1';
duty[7] = '0';
break; /* Duty: 10% */
case 1:
duty[6] = '2';
duty[7] = '5';
break; /* Duty: 25% */
case 2:
duty[6] = '5';
duty[7] = '0';
break; /* Duty: 50% */
case 3:
duty[6] = '7';
duty[7] = '5';
break; /* Duty: 75% */
case 4:
duty[6] = '9';
duty[7] = '0';
break; /* Duty: 90% */
default:
/* do nothing */
break; /* no other cases */
}
return duty;
}
6-6-3-2 周波数文字列変換
LCD 表示用に周波数値を文字列に変換します。
1
2
3
4
5
6
char * FrequencyToString(int32_t freq)
{
static char ret[11]= "f= 0Hz";
int32_t oldfreq = 0;
uint8_t i = 0;
62
TMPM330 アプリケーションノート
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
if (freq != 0) {
while (freq && (i < 7)) {
oldfreq = freq;
freq = (freq / 10) * 10;
ret[8-(i++)] = oldfreq - freq + 0x30;
freq = freq/10;
}
}
else {
ret[8] = '0';
i = 1;
}
/* blank left digits */
for(; i < 7; i++) {
ret[8-i] = 0x20;
}
return ret;
}
6-6-4 割り込み処理: [system_it.c]
6-6-4-1 タイマ 5 割り込み (インタバルタイマ)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void INTTB5_IRQHandler(void)
{
static uint16_t tb5count = 0;
static uint8_t ledon = 0x0F;
tb5count++;
if (tb5count >= 500) {
tb5count = 0;
/* reverse LED output */
ledon = ~ledon;
API_PORT_Out(LED_PORT_1, ledon);
API_PORT_Out(LED_PORT_2, ledon);
}
else {
/* do nothing */
}
}
[11,12行目: LED点灯]
6-6-4-2 タイマ 8 割り込み (周波数測定)
1
2
3
4
void INTTB8_IRQHandler(void)
{
static uint8_t tb8count = 0;
uint8_t TMRB_Status = 0;
63
TMPM330 アプリケーションノート
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
31
TMRB_Status = API_TMRB_IntStatusRead(TB3);
if ((TMRB_Status & TMRBINTTBOF) == CLEAR) {
/*
frequency = number of pulses / interval
number of pulses = |CP0_TMRB3 - CP1_TMRB3|
interval = 26ms
*/
gFreq[tb8count] = (API_TMRB_CP0_Read(TB3)
- API_TMRB_CP1_Read(TB3)) * 1000 / 26;
gFreq[tb8count] = abs(gFreq[tb8count]);
tb8count++;
if (tb8count >= TIMES) {
fFreqMOK = TRUE;
tb8count = 0;
NVIC_EnableIRQ(INTTB8_IRQn);
}
else {
/* do nothing */
}
}
else {
/* do nothing */
}
}
[6 行目: タイマステータスレジスタ値の取得]
[14 行目: キャプチャレジスタ値の取得]
[22 行目: タイマ 8 割り込み禁止]
64
TMPM330 アプリケーションノート
6-7 リアルタイマクロック(RTC)
6-7-1 TMPM330 RTC デモ: [main.c]
6-7-1-1 メインプログラム
初期条件及び RTC割り込みの有効設定。
RTC 割り込みフラグをチェックし、フラグが設定されたら、LCD の RTC 値を更新します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void main(void)
{
__disable_irq();
Set_System();
RTC_Init();
CG->IMCGC = IO_CG_IMCGC_RTC_ON;
NVIC_EnableIRQ(INTRTC_IRQn);
__enable_irq();
LCD_Configuration();
LCD_Light(ON);
for (;;) {
if( fIntRTC ){
fIntRTC = 0;
RTC_Display();
}
}
}
[3 行目: 割り込み禁止]
[4 行目: CG レジスタ設定、WDT 禁止、ボタン、LCD、I/O 設定]
[5 行目: RTC 初期化]
[7 行目: RTC 割り込みを有効に設定]
[8 行目: 割り込み許可]
[10 行目: LCD 初期化]
[11 行目: LCD バックライトオン]
[16 行目: RTC 表示]
6-7-1-2 RTC 表示
LCD にて RTC の値を表示します。
RTC レジスタからクロック値を二回読み取り、同じであれば(秒桁だけで比較します。クロックが
同じであれば、秒桁の値が同じ)、データが正確である為、LCD にて表示します。
1 void RTC_Display(void)
65
TMPM330 アプリケーションノート
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
31
32
33
34
35
36
37
38
39
40
41
42
43
{
uint8_t eYear,eMonth,eDate;
uint8_t eHour,eMinute,eSecond;
uint8_t eSecond_2;
API_RTC_Set_PageSel(IP_RTC_PAGE0);
eYear = (uint32_t)(RTC->YEARR);
eMonth = (uint32_t)(RTC->MONTHR);
eDate = (uint32_t)(RTC->DATER);
eHour = (uint32_t)(RTC->HOURR);
eMinute = (uint32_t)(RTC->MINR);
eSecond = (uint32_t)(RTC->SECR);
eSecond_2 = (uint32_t)(RTC->SECR);
if (eSecond == eSecond_2) {
tRTC_Display[0] = 2+0x30;
tRTC_Display[1] = 0+0x30;
tRTC_Display[2] = ((eYear&0xf0)>>4)+0x30;
tRTC_Display[3] = (eYear&0x0f)+0x30;
tRTC_Display[4] = '/';
tRTC_Display[5] = ((eMonth&0xf0)>>4)+0x30;
tRTC_Display[6] = (eMonth&0x0f)+0x30;
tRTC_Display[7] = '/';
tRTC_Display[8] = ((eDate&0xf0)>>4)+0x30;
tRTC_Display[9] = (eDate&0x0f)+0x30;
tRTC_Display[10] = 0;
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text(tRTC_Display);
tRTC_Display[0] = ((eHour&0xf0)>>4)+0x30;
tRTC_Display[1] = (eHour&0x0f)+0x30;
tRTC_Display[2] = ':';
tRTC_Display[3] = ((eMinute&0xf0)>>4)+0x30;
tRTC_Display[4] = (eMinute&0x0f)+0x30;
tRTC_Display[5] = ':';
tRTC_Display[6] = ((eSecond&0xf0)>>4)+0x30;
tRTC_Display[7] = (eSecond&0x0f)+0x30;
tRTC_Display[8] = 0;
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text(tRTC_Display);
}
}
[7 行目: ページ0のクロック選択]
[8 行目: 年桁レジスタ値の取得 ]
[9 行目: 月桁レジスタ値の取得 ]
[10 行目: 日桁レジスタ値の取得 ]
[12 行目: 時間桁レジスタ値の取得 ]
[13 行目: 分桁レジスタ値の取得 ]
[14 行目: 秒桁レジスタ値の取得 ]
[15 行目: 秒桁レジスタ値の取得 ]
66
TMPM330 アプリケーションノート
6-7-2 RTC 制御関数 : [rtc.c]
6-7-2-1 RTC 初期化
RTC 初期化処理。
RTC クロック及び割り込みモードを設定します。
RTC 開始時刻は、2009/07/01 00:00:00 です。
RTC 割り込み周波数は、1Hz です。
1
2
3
4
5
6
7
8
9
10
void RTC_Init(void)
{
API_RTC_Init();
API_RTC_Set_PAGER(IP_RTC_PAGE0);
API_RTC_Set_RESTR(RTCDIS16HZ | RTCRSTTMR);
API_RTC_Set_ClkHMS(_00H,_00M,_00S);
API_RTC_Set_ClkYMDW(_09Y,_07M,_01D,_WED);
API_RTC_Set_PAGER(IP_RTC_CLK_ENABLE);
API_RTC_Set_PAGER(IP_RTC_INT_ENABLE | IP_RTC_CLK_ENABLE);
}
[3 行目: RTC 初期化]
[4 行目: ページレジスタ設定(0 ページ選択)]
[5 行目: リセットレジスタ設定(割り込みソース信号:1Hz、時計リセット)]
[6 行目: 時刻設定(00:00:00)]
[7 行目: 日付設定(09 07 01)]
[8 行目: ページレジスタ設定(時計割り込み許可)]
[9 行目: ページレジスタ設定(INTRTC 割り込み許可、時計割り込み許可)]
6-7-3 割り込み処理 : [system_it.c]
RTC 割り込み処理。
割り込み要求をクリアします。
1
2
3
4
5
void INTRTC_IRQHandler(void)
{
CG->ICRCG = 0x08;
fIntRTC = 1;
}
[3 行目: RTC 割り込み要求のクリア]
(注)
<ENATMR>および<ENAAML>の各々の割り込み許可ビットと、INTENA の割り込み許可ビットは
下記の設定順番を守り、同時に設定しないようにしてください。
(時計/アラーム許可と割り込み許可の設定間に時間差を設ける。)
67
TMPM330 アプリケーションノート
6-8 A/D変換(ADC)
6-8-1 TMPM330 ADC デモ: [main.c]
6-8-1-1 メインプログラム
初期条件及び A/D 変換割り込みを有効に設定します。
A/D 変換割り込みフラグ(fIntADC)を確認し、セットされたら、A/D 変換値を更新して LCD に表
示します。
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
31
32
33
34
35
36
void main(void)
{
uint8_t key_info;
__disable_irq();
Set_System();
NVIC_EnableIRQ(INTAD_IRQn);
__enable_irq();
LCD_Configuration();
LCD_Light(ON);
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text("Press K1 to ADC ");
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text(" then K2 to MIC ");
do {
key_info = API_PORT_BitIn(KEY_PORT, KEY1);
} while (key_info == SET);
/* Display RV1 value */
ADC_Init();
API_ADC_VrefSet(ENABLE);
Delay_ms(1);
API_ADC_Start_Set();
do {
fMIC = CLEAR;
if (fIntADC == SET) {
fIntADC = CLEAR;
ADC_Display();
}
key_info = API_PORT_BitIn(KEY_PORT, KEY2);
} while (key_info == SET);
/* Display MIC value */
MIC_Init();
68
TMPM330 アプリケーションノート
37
38
39
40
41
42
43
44
45
46
47
48
API_ADC_VrefSet(ENABLE);
Delay_ms(1);
API_ADC_Start_Set();
for (;;) {
fMIC = SET;
if (fIntADC == SET) {
fIntADC = CLEAR;
ADC_Display();
}
}
}
[5 行目: 割り込み禁止]
[6 行目: CG レジスタ設定、WDT 禁止、ボタン、LCD、A/D I/O 設定]
[7 行目: A/D 割り込み許可]
[8 行目: 割り込み許可]
[10 行目: LCD 初期化]
[11 行目: LCD バックライトオン]
[13 行目: LCD1 行目のコマンド送信]
[14 行目: LCD に文字列“Press K1 to ADC”を送信]
[15 行目: LCD2 行目のコマンド送信]
[16 行目: LCD に文字列“then K2 to MIC”を送信]
[18 行目: KEY1 入力待ち]
[22 行目: ボリューム用 A/D コンバータの初期化]
[23 行目: VREF を印加]
[25 行目: A/D 変換開始]
[36 行目: MIC 用 A/D コンバータの初期化]
[37 行目: VREF を印加]
[39 行目: A/D 変換開始]
6-8-1-2 A/D 変換表示
LCD に A/D変換値を表示します。
A/D 変換値を読み込み、LCD の第1行目にパーセント表示を、第2行目にバー表示します。
1
2
3
4
5
6
7
8
9
10
11
12
13
void ADC_Display(void)
{
uint16_t adc_value = 0;
uint16_t volumn;
uint8_t adc_i;
adc_value = API_ADC_DataRead(_ADCREG08);
volumn = (adc_value * 100) / 0x03ff;
if (fMIC == SET) {
tADC_Display[0] = 'M';
tADC_Display[1] = 'i';
tADC_Display[2] = 'c';
69
TMPM330 アプリケーションノート
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
}
else {
tADC_Display[0] = 'A';
tADC_Display[1] = 'D';
tADC_Display[2] = 'C';
}
tADC_Display[3] = ' ';
tADC_Display[4] = 'V';
tADC_Display[5] = 'a';
tADC_Display[6] = 'l';
tADC_Display[7] = 'u';
tADC_Display[8] = 'e';
tADC_Display[9] = ':';
/* Display the value */
if (volumn >= 100) {
tADC_Display[10] = (volumn / 100) + 0x30;
tADC_Display[11] = ((volumn / 10) % 10 ) + 0x30;
tADC_Display[12] = (volumn % 10) + 0x30;
}
else {
tADC_Display[10] = ' ';
if(volumn / 10) {
tADC_Display[11] = (volumn / 10) + 0x30;
}
else {
tADC_Display[11] = ' ';
}
tADC_Display[12] = (volumn % 10) + 0x30;
}
tADC_Display[13] = 0;
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text(tADC_Display);
/* Display the value volumn percent, the 100% is 16 x '*' */
volumn = volumn * 16;
volumn = volumn / 100;
for (adc_i = 0; adc_i < 16; adc_i++) {
tADC_Display[adc_i] = 0;
}
for (adc_i = 0; adc_i < volumn; adc_i++) {
tADC_Display[adc_i] = '*';
}
adc_i++;
tADC_Display[adc_i] = 0;
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text(tADC_Display);
}
[7 行目: A/D 変換結果を取得]
70
TMPM330 アプリケーションノート
6-8-2 ADC 制御関数 : [adc.c]
6-8-2-1 ADC 初期化
IAR 社 TMPM330-SK 評価キットに付属のサンプルプログラムを利用します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void ADC_Init(void)
{
// Potentiometer port --- PC, PD
API_ADC_ChSet(ADC_IN);
// set ADC as data polling mode
API_ADC_MOD0_Set(0x04);
}
void MIC_Init(void)
{
// Potentiometer port --- PC, PD
API_ADC_Init();
API_ADC_ChSet(MIC_AIN);
// set ADC as data polling mode
API_ADC_MOD0_Set(0x04);
}
[4,14 行目: A/D チャネルセット]
[7,16 行目: リピートモード設定:リピート変換モード、
チャネル固定リピート変換モード設定:1 回変換するごとに割り込み発生]
6-8-2-2 A/D 変換値読み取り
IAR 社 TMPM330-SK 評価キットに付属のサンプルプログラムを利用します。
1
2
3
4
5
6
7
8
9
10
11
12
uint16_t ADC_Get_Value(void)
{
uint16_t AdcValue = 0;
API_ADC_VrefSet(ENABLE);
Delay_ms(1);
API_ADC_Start_Set();
// wait the conversion complete
while(!(API_ADC_MOD0_Read() & 0x80));
AdcValue = API_ADC_DataRead(_ADCREG08);
return AdcValue;
}
[4 行目: VREF を印加]
[6 行目: A/D 変換開始]
71
TMPM330 アプリケーションノート
[8 行目: A/D 変換終了の確認]
[9 行目: A/D 変換結果の取得]
6-8-3 割り込み処理: [system_it.c]
6-8-3-1 A/D 変換割り込み処理
A/D 変換が終了したことをメイン関数に通知するフラグを設定します。
1
2
3
4
void INTAD_IRQHandler(void)
{
fIntADC = SET;
}
72
TMPM330 アプリケーションノート
6-9 フラッシュ(FLASH)
6-9-1 TMPM330 Flash デモ: [main.c]
6-9-1-1 メインプログラム
TMPM330 は リセットされると、PC は、メイン関数から開始します。
LED 点滅によって、プログラムA及びプログラムBが切り替わったことを判断します。
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
int main(void)
{
for(;;) {
__disable_irq();
API_WDT_Set_WdtEnaDis(DISABLE);
#if defined ( __CC_ARM )
__ResetSP();
#elif defined ( __ICCARM__ )
asm ("MOV R0, #0");
asm ("LDR SP, [r0]");
#endif
CG->PLLSEL = 0;
PG->CR = 0x0f;
PG->DATA = 0x0f;
PJ->CR = 0x0f;
PJ->DATA = 0x0f;
PB->CR = PB->CR & 0x0f;
PB->IE = PORTB->IE | 0xf0;
__enable_irq();
Demo();
Burn_Flash_Entry();
}
}
[6 行目: WDT 禁止]
[8~13 行目: スタックポインタの初期化(初期値はアドレス 00000000H に配置します)]
[27 行目: デモのメイン処理を実行]
[28 行目: プログラムコードを Flash から RAMへコピーし、Flash 書き込みを行います。]
73
TMPM330 アプリケーションノート
6-9-1-2 デモ
LED点滅デモを行います。 KEY1~4の何れかのキーが押されると、LED点滅デモが終了しま
す。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void Demo(void)
{
uint32_t i;
uint8_t key_info;
LED_IO = 0x0f;
do {
LED_IO ^= 0x0f;
for (i=0; i<0x55555;i++) {
/* do nothing */
}
key_info = (PB->DATA & KEYRELEASE) ^ KEYRELEASE;
if (key_info != CLEAR) {
for (i=0; i<0xffff; i++) {
/* do nothing */
}
key_info = (PB->DATA & KEYRELEASE) ^ KEYRELEASE;
}
}while (key_info == CLEAR);
}
6-9-1-3 フラッシュ書き込みエントリ
プログラムコードをFlashからRAMにコピーし、Flash書き込みを行います。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void Burn_Flash_Entry(void)
{
uint32_t size;
uint32_t i;
char tLCDData[17];
size = SIZE_PORT_CODE;
My_Copy_In_Flash(ADDR_PORT_RUN, ADDR_PORT_STORE, size);
size = SIZE_LCD_CODE;
My_Copy_In_Flash(ADDR_LCD_RUN, ADDR_LCD_STORE, size);
LCD_IO_Configuration();
LCD_Configuration();
LCD_Light(ON);
tLCDData[0] = 'R';
74
TMPM330 アプリケーションノート
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
tLCDData[1] = 'A';
tLCDData[2] = 'M';
tLCDData[3] = ' ';
tLCDData[4] = 't';
tLCDData[5] = 'r';
tLCDData[6] = 'a';
tLCDData[7] = 'n';
tLCDData[8] = 's';
tLCDData[9] = 'f';
tLCDData[10] = 'e';
tLCDData[11] = 'r';
tLCDData[12] = 'r';
tLCDData[13] = 'i';
tLCDData[14] = 'n';
tLCDData[15] = 'g';
tLCDData[16] = 0;
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text(tLCDData);
tLCDData[0] = '.';
tLCDData[1] = '.';
tLCDData[2] = '.';
tLCDData[3] = '.';
tLCDData[4] = '.';
tLCDData[5] = '.';
tLCDData[6] = 0;
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text(tLCDData);
size = SIZE_BF_CODE;
My_Copy_In_Flash(ADDR_BF_RUN, ADDR_BF_STORE, size);
size = SIZE_DEMO_BIN;
My_Copy_In_Flash(ADDR_DEMO_STORE_BUF, ADDR_DEMO_RUN, size);
for (i=0; i<0xfffff; i++) {
/* do nothing */
}
Burn_Flash();
}
[48,51行目: フラッシュ実行ルーチンをコピーします]
[56行目: プログラムAとプログラムBを書き換えます]
75
TMPM330 アプリケーションノート
6-9-1-4 フラッシュコピー
フラッシュ実行ルーチンをコピーします。
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
31
32
33
void My_Copy_In_Flash(uint32_t* dest, uint32_t* source, uint32_t size)
{
uint32_t* dest_addr;
uint32_t* source_addr;
uint32_t i;
uint32_t tmps,tmpd;
uint32_t mask;
dest_addr = dest;
source_addr = source;
for (i=0; i<(size>>2) ;i++) {
*dest_addr = *source_addr;
dest_addr++;
source_addr++;
}
if (size & 0x00000003) {
mask = 0xffffff00;
i = size & 0x00000003;
tmps = *source_addr;
tmpd = *dest_addr;
while(i-1) {
mask = mask << 8;
i--;
}
tmps = tmps & (~mask);
tmpd = tmpd & (mask);
*dest_addr = tmps+tmpd;
}
else {
/* do nothing */
}
}
76
TMPM330 アプリケーションノート
6-9-2 Flash 制御関数 : [flash.c]
6-9-2-1 フラッシュ書き込み(切り替え)
プログラムAとプログラムBを書き換えます。
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
31
32
33
34
35
36
37
38
39
40
41
42
void Burn_Flash(void)
{
uint32_t size;
uint32_t i;
uint32_t* addr_source;
uint32_t* addr_dest;
char tLCDData[17];
tLCDData[0] = 'E';
tLCDData[1] = 'r';
tLCDData[2] = 'a';
tLCDData[3] = 's';
tLCDData[4] = 'i';
tLCDData[5] = 'n';
tLCDData[6] = 'g';
tLCDData[7] = '.';
tLCDData[8] = '.';
tLCDData[9] = '.';
tLCDData[10] = '.';
tLCDData[11] = '.';
tLCDData[12] = '.';
tLCDData[13] = 0;
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text(tLCDData);
tLCDData[0] = ' ';
tLCDData[1] = 0;
Send_To_LCD(SECOND_LINE, LCD_COMMAND);
Send_LCD_Text(tLCDData);
FLASH_EraseBlock(ADDR_DEMO_RUN);
for (i=0; i<0xfffff; i++) {
/* do nothing */
}
tLCDData[0] = 'R';
tLCDData[1] = 'e';
tLCDData[2] = 'w';
tLCDData[3] = 'r';
tLCDData[4] = 'i';
tLCDData[5] = 't';
tLCDData[6] = 'i';
tLCDData[7] = 'n';
77
TMPM330 アプリケーションノート
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
tLCDData[8] = 'g';
tLCDData[9] = '.';
tLCDData[10] = '.';
tLCDData[11] = '.';
tLCDData[12] = '.';
tLCDData[13] = '.';
tLCDData[14] = '.';
tLCDData[15] = 0;
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text(tLCDData);
size = SIZE_DEMO_BIN;
addr_source = ADDR_DEMO_STORE;
addr_dest = ADDR_DEMO_RUN;
while (size > 512) {
My_Copy_In_RAM(ADDR_DEMO_RUN_BUF, addr_source, 512);
Write_Flash(addr_dest, ADDR_DEMO_RUN_BUF, 512);
addr_dest = addr_dest + 512/4;
addr_source = addr_source + 512/4;
size = size - 512;
}
My_Copy_In_RAM(ADDR_DEMO_RUN_BUF, addr_source, size);
Write_Flash(addr_dest, ADDR_DEMO_RUN_BUF, size);
FLASH_EraseBlock(ADDR_DEMO_STORE);
size = SIZE_DEMO_BIN;
Write_Flash(ADDR_DEMO_STORE, ADDR_DEMO_STORE_BUF, size);
for (i=0; i<0xfffff; i++) {
/* do nothing */
}
tLCDData[0] = 'F';
tLCDData[1] = 'i';
tLCDData[2] = 'n';
tLCDData[3] = 'i';
tLCDData[4] = 's';
tLCDData[5] = 'h';
tLCDData[6] = 'e';
tLCDData[7] = 'd';
tLCDData[8] = 0;
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text(tLCDData);
for (i=0; i<0xfffff; i++) {
/* do nothing */
}
tLCDData[0] = ' ';
tLCDData[1] = 0;
Send_To_LCD(FIRST_LINE, LCD_COMMAND);
Send_LCD_Text(tLCDData);
78
TMPM330 アプリケーションノート
95
96
97
98
99
100
101
#if defined ( __CC_ARM )
__ResetPC();
#elif defined ( __ICCARM__ )
asm ("MOV R0, #4");
asm ("LDR PC, [r0]");
#endif
}
[31行目: デモを実行したプログラムのFlash領域にブロック消去の実行]
[58行目: デモプログラムを1ページ(512byte)単位でRAMにコピー]
[59行目: 1ページ(512byte)単位でFlashに書き込む]
[64行目: デモプログラムを1ページ(512byte)単位でRAMにコピー]
[65行目: 1ページ(512byte)単位でFlashに書き込む]
[67行目: 書き込まれたプログラムのFlash領域にブロック消去の実行]
[行目: デモを実行したプログラムに書き換える]
[95~100行目: ソフトウェアリセット(リセットベクタはアドレス00000004Hに配置します)]
6-9-2-2 フラッシュ書き込み
フラッシュ書き込み
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void Write_Flash(uint32_t* addr_dest, uint32_t* addr_source, uint32_t len)
{
uint32_t size;
uint32_t* source;
uint32_t* dest;
dest = addr_dest;
source = addr_source;
size = len;
while (size > 512) {
FLASH_WritePage(dest, source, 512);
size = size - 512;
dest = dest + 512/4;
source = source + 512/4;
}
FLASH_WritePage(dest, source, size);
}
[11,16 行目: 1 ページ(512byte)単位の Flash 書き込み]
6-9-2-3 フラッシュブロック消去
フラッシュ1ブロック消去処理
1
2
3
4
uint8_t FLASH_EraseBlock(uint32_t* block_addr)
{
uint32_t* addr1;
uint32_t* addr2;
79
TMPM330 アプリケーションノート
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
uint32_t* blk_adr;
uint32_t counter;
blk_adr = (uint32_t*)((uint32_t)block_addr & 0xffff8000);
if ((uint32_t)blk_adr > (FLASH_END)) {
return ERR_FA;
}
else {
/* do nothing */
}
#ifdef _BOOT_ROM
if ((uint32_t)blk_adr < (FLASH_BEGIN)) {
return ERR_FA;
}
else {
/* do nothing */
}
#endif
if (Check_Protect(blk_adr)) {
return ERR_PRO;
}
else {
/* do nothing */
}
addr1 = (uint32_t*)(FLASH_BEGIN + FLASH_CMD_BC1_ADDR);
addr2 = (uint32_t*)(FLASH_BEGIN + FLASH_CMD_BC2_ADDR);
__disable_irq();
*addr1 = FLASH_CMD_BC1_DATA;
*addr2 = FLASH_CMD_BC2_DATA;
*addr1 = 0x00000080;
*addr1 = FLASH_CMD_BC1_DATA;
*addr2 = FLASH_CMD_BC2_DATA;
*blk_adr = 0x00000030;
counter = OVER_TIME;
while(!FC_FLCS_RDY_BSY) {
if (!(counter--)) {
*addr2 = 0xf0;
__enable_irq();
return ERR_OT;
}
else {
/* do nothing */
}
}
*addr2 = 0xf0;
__enable_irq();
return ERR_NONE;
}
[23行目: 消去ブロックが消去禁止設定(プロテクト状態)か確認します]
80
TMPM330 アプリケーションノート
[40行目: フラッシュコントロールレジスタの0ビットを判定し、自動動作終了を確認します]
6-9-2-4 フラッシュページ書き込み
1ページ単位でフラッシュに書き込みます。
TMPM330FDFGのフラッシュの、1ページは512バイトです。
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
31
32
33
34
35
36
37
38
39
40
41
42
43
uint8_t FLASH_WritePage(uint32_t* page_addr, uint32_t* data, uint16_t size)
{
uint32_t* addr1;
uint32_t* addr2;
uint32_t* page_adr;
uint32_t* source;
uint32_t counter;
uint16_t i;
uint16_t len;
uint32_t mask;
uint32_t buf;
len = size;
if (len > 512) {
return ERR_SIZE;
}
else {
/* do nothing */
}
page_adr = (uint32_t*)((uint32_t)page_addr & 0xfffffe00);
if ((uint32_t)page_adr > (FLASH_END)) {
return ERR_FA;
}
else {
/* do nothing */
}
#ifdef _BOOT_ROM
if ((uint32_t)page_adr < (FLASH_BEGIN)) {
return ERR_FA;
}
else {
/* do nothing */
}
#endif
if (Check_Protect(page_adr)) {
return ERR_PRO;
}
else {
/* do nothing */
}
addr1 = (uint32_t*)(FLASH_BEGIN + FLASH_CMD_BC1_ADDR);
addr2 = (uint32_t*)(FLASH_BEGIN + FLASH_CMD_BC2_ADDR);
81
TMPM330 アプリケーションノート
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
__disable_irq();
*addr1 = FLASH_CMD_BC1_DATA;
*addr2 = FLASH_CMD_BC2_DATA;
*addr1 = 0x000000a0;
source = data;
len = len & 0xfffc;
for(i=0;i<(len/4);i++) {
*page_adr = *source;
source++;
}
mask = 0xff000000;
buf = *source;
for(i=0;i<(4 + len -size);i++) {
buf = buf | mask;
mask = mask >> 8;
}
*page_adr = buf;
for (i=(512-size)>>2;i>0;i--) {
*page_adr = 0xffffffff;
}
counter = OVER_TIME;
while(!FC_FLCS_RDY_BSY) {
if (!(counter--)) {
*addr2 = 0xf0;
__enable_irq();
return ERR_OT;
}
else {
/* do nothing */
}
}
*addr2 = 0xf0;
__enable_irq();
return ERR_NONE;
}
[35行目: 書き込みブロックが書き込み禁止設定(プロテクト状態)か確認します]
[66行目: フラッシュコントロールレジスタの0ビットを判定し、自動動作終了を確認します]
82
TMPM330 アプリケーションノート
6-9-2-5 ページブロックチェック
ページ/ブロックが保護(プロテクト状態)かチェックします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
uint8_t Check_Protect(uint32_t* addr)
{
uint8_t block;
uint32_t block_pro;
block = Addr_To_BN(addr);
block_pro = FC->FLCS;
block_pro = block_pro >> 16;
block_pro = block_pro & 0x3f;
if ((block_pro >> block) & 0x00000001) {
return 1;
}
else {
/* do nothing */
}
return 0;
}
[6 行目: フラッシュアドレスをブロック番号に変換します]
6-9-2-6 アドレスブロック番号変換
フラッシュアドレスをブロック番号に変換します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
uint8_t Addr_To_BN(uint32_t* addr)
{
uint8_t block;
uint32_t f_adr;
f_adr = (uint32_t)addr & (FLASH_END-FLASH_BEGIN);
if (f_adr >= 0x60000) {
block = 0;
}
else {
f_adr = f_adr >> 15;
block = 5;
while(f_adr) {
f_adr = f_adr >> 1;
block--;
}
}
83
TMPM330 アプリケーションノート
20
21
return block;
}
6-9-2-7 RAM コピー
RAM実行ルーチンをコピーします。
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
31
32
33
void My_Copy_In_RAM(uint32_t* dest, uint32_t* source, uint32_t size)
{
uint32_t* dest_addr;
uint32_t* source_addr;
uint32_t i;
uint32_t tmps,tmpd;
uint32_t mask;
dest_addr = dest;
source_addr = source;
for (i=0; i<(size>>2); i++) {
*dest_addr = *source_addr;
dest_addr++;
source_addr++;
}
if (size & 0x00000003) {
mask = 0xffffff00;
i = size & 0x00000003;
tmps = *source_addr;
tmpd = *dest_addr;
while (i-1) {
mask = mask << 8;
i--;
}
tmps = tmps & (~mask);
tmpd = tmpd & (mask);
*dest_addr = tmps+tmpd;
}
else {
/* do nothing */
}
}
84
TMPM330 アプリケーションノート
6-10 低消費電力(Low Power)
低消費電力とは、STOP モードまたは、SLEEP モードに移行することです。
サンプルプログラムは、SLEEP モードに対応しています。
6-10-1 Low Power 制御関数 : [power_mode.c]
この機能は、CEC と RMCのサンプルプログラムで提供しています。
6-10-1-1 パワーモード変更
この関数を呼ぶと、MCUは、SLEEPモードに入ります。
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
uint8_t PowerMode_N2Sleep(void)
{
uint32_t count;
__disable_irq();
API_CG_WupTimeSel(0x10, CG_WUPSel_XT1);
CG_OSCCR_XTEN = 1;
CG_OSCCR_WUEON = 1;
count = 0xffff;
while (CG_OSCCR_WUEF) {
if (count == 0x00) {
__enable_irq();
return ERR_OT;
}
else {
count--;
}
}
API_CG_WupTimeSel(0x60, CG_WUPSel_X1);
API_CG_StbyModeSel(0x02);
NVIC->ICPR[0] = 0xffffffff;
NVIC->ICPR[1] = 0xffffffff;
__DSB();
__WFI();
__enable_irq();
return ERR_NONE;
}
[6行目: ウォームアップカウンタを低速発振器(XT1)に選択します]
[7行目: 低速発振器を発振させます]
[8行目: ウォーミングアップタイマをスタートさせます]
85
TMPM330 アプリケーションノート
[10行目: ウォーミングアップステータスでウォーミングアップの終了を待ちます]
[20行目: ウォームアップカウンタを高速発振器(X1)に選択します]
[21行目: 低消費電力モードの選択(SLEEPモード)]
[22,23行目: 割り込み保留クリアレジスタ セット]
[25行目: WFI命令を実行することで、選択された低消費電力モードに移行します]
6-10-1-2 要因設定クリア
この関数は、低消費電力モードの解除要因を設定することができます。
解除要因は、設定或いはクリアでき、また、トリガ条件を設定できます。
この関数は、他の解除要因にも拡張できます。
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
void PowerMode_SetClearFactor(uint8_t name, uint8_t cmd, uint8_t condition)
{
switch (name) {
case CF_CECRX:
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGB,20))) = 1;
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGB,21))) = 1;
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGB,22))) = 0;
CG_IMCGB_INT6EN = cmd;
break;
case CF_RMCRX0:
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGB,28))) = 1;
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGB,29))) = 1;
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGB,30))) = 0;
CG_IMCGB_INT7EN = cmd;
break;
case CF_RMCRX1:
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGC,28))) = 1;
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGC,29))) = 1;
(*((__IO uint32_t *)BITBAND_PERI(&CG->IMCGC,30))) = 0;
CG_IMCGC_INTBEN = cmd;
break;
default:
/* do nothing */
break;
}
}
[5,6,7,8 行目: CEC 受信割り込み要因での解除設定]
[12,13,14,15 行目: リモコン0割り込み要因での解除設定]
[19,20,21,22 行目: リモコン1割り込み要因での解除設定]
86
TMPM330 アプリケーションノート
変更履歴
Rev 日付 Page 変更項目
1.0 ‘10/2/9 - 初版
2.0 ‘10/5/13 ALL CMSIS Device Peripheral Access Layer for TX03(V2.0.4)
へ対応
本資料に関するお問い合わせは 弊社ウェブサイトにてお受けしております。
http://www.semicon.toshiba.co.jp/
株式会社 東芝 セミコンダクター社 〒105-8001 東京都港区芝浦1-1-1
(HWJ-1122B)
本資料の内容の一部または全部を株式会社東芝に無断で転載、複製することを禁じます。 Copyright © 2010 TOSHIBA CORPORATION All Rights Reserved.