#author("2018-12-05T15:06:21+00:00","","") [[&ref(home.gif);:http://jaco.ec.t.kanazawa-u.ac.jp/kitagawa/]] ~ Visitor No. &counter(total); Cypress Semiconductor社PSoC Creator (PSoC3以上) 関連のメモです。 ~ ---- *目次 [#k218fc8f] #contents(); *コメント欄 [#d1b3049c] #pcomment(reply); *メモ [#z5b56d96] ***PSoC4ファミリー(ARM Cortex-M0版PSoC)の選択 [#def158c5] ADC/DACが弱いことを除くと低消費電力で使いやすい。4200にはBluetoothLE版もある。 -CY8C4000ファミリ:クロック16MHz, フラッシュ16kB, シリアルポートはI2Cのみ(送信用ソフトウエアUARTはあり) -CY8C4100ファミリ:クロック24MHz, フラッシュ32kB, I2C/SPI/UART2個, LCD, 12bit-ADC -CY8C4200ファミリ:クロック48MHz, フラッシュ32kB, DMA, I2C/SPI/UART4個, CAN2個, LCD, 12bit-ADC, プログラマブルロジック // // 予備知識------------------------------------------------------------------------------------------------ // ***電源構成 [#dcfb22cc] VDDD, VDDA, VDDR, VCCDなどいろいろあって忘れそうなのでデータシートを要約。 #ref(power_supply.png) -電源電圧は、1.8-5.5V --Bluetoth LE搭載ファミリは、1.9-5.5V(1.9V以下でも動作するが、BLEは停止) -内部LDOはデフォルトで有効 --無効にした場合は、VDD1.71-1.89V、VCCDとVDDDをショートする ***MiniProg3の接続 [#e1433a2c] 純正の書き込み器MiniProg3によるPSoC生チップのプログラムに関する覚え書き。もっとも、MiniProg3は値段が高いので、マニアには敬遠されているらしい。PSoC Programmerを起動して、Utilitiesタブからファームウエアをアップデートしておく(古いファームウエアだと、Power Cycleモードが使用できないと聞いている)。 #ref(HSSP.png) -プログラムとデバッグにSWD(ARM Serial Wire Debug)を利用する -どのポートがSWDかは、データシートでSWDを検索する -SWDポートは汎用IOと共有なので、プログラム専用にするとSWD_IO, SWD_CLKを割り当てた2ポート分の汎用IOが使えなくなることに注意 // // 基本操作------------------------------------------------------------------------------------------------ // ***スイッチとLED(開発の流れ) [#ic8f5d07] 学部生、卒研生向け、プログラムとデバックの手順解説。ここでは、CY8CKIT-142 PSoC4 BLEモジュール(CY8C4247LQI-BL483搭載、技適認証済み)を使用しましたが、BLEを使わないなら PSoC4 CY8C4245あたりでも。 -PSoC外部の回路製作 --下図のようなタクトスイッチを押すとLEDが点灯する回路例を考える。電源VDDDは、MiniProg3から供給(VTARG)する。 #ref(led_sw.png) -PSoC内部の回路設計 --PSoC Creatorを起動 --File - New - Project... ---Taget device = PSoC4, PSoC4200BLE (使用するデバイスに合わせて) - Nextボタン --Empty schematic - Nextボタン ---Workspace name, Location, Peoject nameを適当に設定 - Finishボタン --右欄のComponent Catalog - Cypressタブ - Ports and Pins - Digital Input Pin と Digital Output Pin をドラッグして各1個づつ回路図シート(TopDesign.cysch)に配置 ---Componentを選んでComponent Catalog下のOpen datasheetの文字をクリックまたは配置した部品を右クリックして、ポップアップメニューから Open Datasheet... を選ぶと、選んだComponentのデータシートが表示され、Find Code Example...を選ぶとプログラム例のリストが表示される --ここでは内部回路を作成しないので配線を行う必要はないが、回路の配線が必要な場合は、回路図欄左端のツールボックスで #ref(pin_01s.png) --回路図に配置したPinのシンボルをダブルクリックして、下記のように設定 - OKボタン ---HW connection: プログラム制御の場合チェック無し、回路制御の場合☑有り ---Drive mode: 出力回路の設定。スイッチ入力の場合はResistive pull up (押さないときHighとする)、LED点灯の場合はStrong ---Initial drive state(初期状態のHigh, Lowに合わせる) 入力ピン &ref(pin_input.png,,50%); 出力ピン &ref(pin_output.png,,50%); --左欄のWorkspace Explorer - Sourceタブ - Design Wide Resource - Pins をダブルクリック --右欄のPin_1, Pin_2 をピンアサイン図(Design01.cydwr)のポートP2[2], P2[3]にそれぞれドラッグするか、右欄のPort列のドロップダウンリストから、割り当て先のポートP2[2], P2[3]を選択する #ref(pin_02s.png) -プログラムの作成 --左欄のWorkspace Explorer - Sourceタブ - Source Files - main.c をダブルクリック --下図のようにmain.cのプログラムを入力 ---通常、無限ループ for(;;) の上には、電源投入時の初期化処理のコードを入力し、for(;;)ループの中に通常のプログラムを入力する ---CyGlobalIntEnable; では、CPUへの割り込みを許可している(このプログラムでは割り込みを使用しないので、無くてもよい) ---Pin_2_Write(!Pin_1_Read()); では、Pin_1の状態(H or L)を読み取り、Pin_1の否定をPin_2に出力している --ツールバーの Build ボタンをクリックして、プログラムをビルドする #ref(pin_03s.png,,60%) -プログラムの書き込み --MiniProg3を回路基板のピンヘッダに挿す --メニューより、Debug - Select target and program... --MiniProg3を選択 ---Port Settingボタンをクリックし下図のように設定して、OKボタンをクリック --PSoC 4200 BLE CY8C4247LQ*-BL483(ターゲットのデバイス)を選択して、OK/Connectボタンをクリック ---しばらく待つと書き込みが始まる #ref(program_port.png,,70%) --MiniProg3から電源供給されているので、MiniProg3を挿したままで動作確認を行う -デバッグ PSoC Creatorのデバッグ機能は、非常に便利で、プログラム、動作確認、 --ツールバーの Debugボタンをクリックすると、プログラムの書き込みが行われ、続いてデバッグモードになる #ref(debug_01zs.png,,75%) --プログラムコードが表示されているウインドウ左側のグレーの列をクリック ---プログラムの行に赤丸が付いて、ブレークポイント(プログラムを一旦停止させる場所)が設定される --Step Overボタンをクリックして、関数毎にプログラムを実行して動作を確認する ---Step Into で、関数内部に入り、Step Out で関数の実行前に戻る ---タクトスイッチを押しながら Step OverボタンをクリックするとLEDが点灯する #ref(debug_03zs.png,,75%) --Stop Debuggingボタンで、デバッグモードを一旦終了し、上図のようにプログラムを追加(例として変数の内容を確認してみる) --再度、Debugボタンをクリックし、動作を確認する --下の方の Localsタブをクリックすると、変数 x の値が表示される ---Step Overボタンをクリックすると、xの値がインクリメントされることが確認できる ---Registersタブをクリックすると、各種レジスタの内容が表示される ---注意:変数に値を代入しても、値がプログラム中で使用されない場合は、Localsに変数が表示されない // // LCDと電源制御------------------------------------------------------------------------------------------------ // ***I2C LCDと電源制御 [#u9c0fd1b] 小型キャラクタ液晶ディスプレイの使用例。3.3V動作、I2C接続の Xiamen Zettler Electronics社 AQM0802A-RN-GBW を使用。秋月でピッチ変換キット(AE-AQM0802)が販売されている。また、電源制御例を示す。LCDは低消費電力だが、1mA程度消費するので、小容量バッテリーや環境エネルギー駆動の場合、スイッチを押したときだけ表示し、しばらく表示したら電源を切る。電源は、PSoCのGNDとは分離されたCGNDラインに接続し、CGNDをPSoCのIO(オープンドレイン)でON/OFFする。VDDはON/OFFせず、パスコンに充電した状態を保つ。 #ref(lcd.jpg,,60%) #ref(lcd_pwr.png) -I2C (SCB mode), Character LCD with I2C interface, Digital Bidirectional Pin 2個, Digital Input Pin, Digital Output Pin を配置する。I2Cの設定を Show I2C terminals に設定してからI2CモジュールとDigital Bidirectional Pin の配線を行う。 #ref(lcd_01.png,,70%) -I2Cの設定 --PSoCをマスター、LCDをスレーブとする。 #ref(lcd_02.png,,70%) #ref(lcd_03.png,,70%) -I2C_LCDの設定 --LCDのスレーブアドレスは、0x7C(データシートで要確認) --基本コマンドはデフォルトで設定されているので、カスタムコマンドを追加する。 ---ContrastSetのCMD byte 2 = 0x70 の1桁目(0)を変更すると、コントラストが変えられる。 #ref(lcd_04.png,,70%) #ref(lcd_05.png,,70%) -Digital Bidirectional Pinの設定(I2C_SCL, I2C_SDA) --外付けプルアップ抵抗を使用しない場合は、PSoCのピン設定を Resistive pull up にする。外付けプルアップ抵抗(LCDモジュール変換基板に搭載)を使用する場合は、Open drain, drives low にする。 #ref(lcd_06.png,,70%) #ref(lcd_07.png,,70%) -Digital Output Pin, Digital Input Pinの設定(CGND_1, SW_IN_1) --CGND_1は、Open drain, drives low(出力がLowでない時は、オープンとなり電流が流れない)。 --SW-IN_1は、Resistive pull up(スイッチを押さないときはHigh、スイッチを押すとLow)。 #ref(lcd_08.png,,70%) #ref(lcd_09.png,,70%) -main.cの記述 --SW_IN_1_Read()でスイッチを読み取り、LowだったらCGND_1をLowにしてLCDの電源を入れる。 --LCDの初期化、カーソル位置設定、文字の出力を行い、一定時間待ってから、CGND_1をHighにしてLCDの電源を切る。 #include "project.h" void I2C_LCD_Init(void) { CyDelay(40u); //40ms waiting I2C_LCD_1_FunctionSet_Nor(); I2C_LCD_1_ReturnHome(); I2C_LCD_1_FunctionSet_Ext(); I2C_LCD_1_InternalOscFrq(); I2C_LCD_1_ContrastSet(); I2C_LCD_1_PwrIconContrast(); I2C_LCD_1_FollowerCtrl(); CyDelay(200u); //200ms waiting I2C_LCD_1_FunctionSet_Nor(); I2C_LCD_1_DisplayOn(); I2C_LCD_1_Clear(); I2C_LCD_1_EntryModeSet(); //I2C_LCD_1_WriteControl(0x0fu); //Disp:On Cursor:On Position:On } void I2C_LCD_Location(uint8 row, uint8 column) { if(row == 0){ I2C_LCD_1_SetDDRAM(0x80u + column); }else{ I2C_LCD_1_SetDDRAM(0xC0u + column); } } int main(void) { CyGlobalIntEnable; /* Enable global interrupts. */ // LCD CGND = Low CGND_1_Write(0); // Initiallization of I2C and LCD I2C_1_Start(); I2C_LCD_1_Start(); for(;;) { // LCD CGND = Low if(!SW_IN_1_Read()) { CGND_1_Write(0); I2C_LCD_Init(); CyDelay(100u); // LCD output I2C_LCD_Location(0u,0u); I2C_LCD_1_PrintString("Enjoy,"); CyDelay(1000u); I2C_LCD_Location(1u,0u); I2C_LCD_1_PrintString("PSoC4!"); CyDelay(1000u); I2C_LCD_1_Clear(); // Software delay loop (ms) CyDelay(1000u); // LCD CGND = High CGND_1_Write(1); } } } // // UART------------------------------------------------------------------------------------------------ // ***UART [#wd72373a] PCや無線モジュールとの標準的な接続方法の例。写真は、PCとの接続に使用したUSB-Serial変換モジュール。TXとRXは互いにクロスさせることに注意。プルアップ抵抗は、PSoCの入出力ピンで設定することもできるが、外部抵抗の使用が推奨されている。 #ref(uart.jpg,,40%) #ref(uart.png) -UART(SCB mode)を配置し、rx_inにDigital Input Pin, tx_outにDigital Output Pin を配線接続する --UARTには下記の3種類がある。UART (SCB mode)は、ハードウエアリソースを消費しないが、ピン配置に制約がある。 ---Software Transmit UART: CPUを使って実行する。送信専用。 ---UART (SCB mode): SCB(シリアル通信用ハードウエア)で実装する。 ---UART:UDB(汎用ディジタルブロック)を使って実装する。 #ref(uart_01.png,,70%) -UART(SCB mode)の設定 --ここでは、Baud rate = 115200bps, Oversampling = 8 に設定。クロック周波数との関係により、実際の通信速度には、誤差が発生するので、誤差が 2.5% より小さくなるように、適当なOversamplingを設定する。実際の通信速度は、Applyボタンをクリックすると、Baud rateの右側に表示される。 #ref(uart_02.png,,70%) #ref(uart_03.png,,70%) #ref(uart_04.png,,70%) -入出力ピンの設定 --外付けのプルアップ抵抗を想定し、ここではプルアップしない。 #ref(uart_05.png,,70%) #ref(uart_06.png,,70%) -main.cの記述 --受信した文字列を、Received Data = に続けてエコーさせる例。受信した文字列(strData)をスペース等に分割して、コマンドとパラメータを受け取る場合に使用できる。 --ここでは、受信デリミタとして、CR (0x0d)を使用し、送信には、CR+LF (0x0d, 0x0a)を使用している。 --UartGetChar()は、エラーまたはバッファにデータが無いときに、NULL (0x00)を返すので、NULLは読み飛ばしている。 #include "project.h" int main(void) { CyGlobalIntEnable; /* Enable global interrupts. */ // Initiallization of UART module UART_1_Start(); UART_1_UartPutString("UART with PSoC \r\n"); uint32 rxData; uint8 ptr; char strData[] = ""; for(;;) { // Checking ASCII char in RX buffer // If you need to check non-ASCII code, use UartGetByte() rxData = UART_1_UartGetChar(); if(rxData) { memset(strData, '\0', strlen(strData)); ptr = 0; // Read until CR delimiter while(rxData != 0x0d) { if(rxData != 0x00) { strData[ptr] = rxData; ptr++; } rxData = UART_1_UartGetChar(); } // Echo of RX data UART_1_UartPutString("Received Data = "); UART_1_UartPutString(strData); UART_1_UartPutString("\r\n"); // Clear RX buffer and RX FIFO UART_1_SpiUartClearRxBuffer(); } } } // // ADCとIDAC------------------------------------------------------------------------------------------------ // ***ADCとIDAC [#na389981] // // 割り込みとスリープ------------------------------------------------------------------------------------------------ // ***割り込みとスリープ [#je66ab26]