Cypress Semiconductor社PSoC Creator 関連のメモです。ここでは、PSoC4を使用しますが、PSoC3, PSoC5でも同じです。
コメントはありません。 Comments/PSoC Creator?
ADCがSAR 1個だけであることを除くと低消費電力で使いやすい。BluetoothLE搭載版もある。
VDDD, VDDA, VDDR, VCCDなどいろいろあって忘れそうなのでデータシートを要約。
近年のMCUには、電力モードを切り替えるコマンドが用意されている。PSoCでは、チップ全体の電力モードの他に、各回路モジュール毎の電源ON/OFFをプログラムで個別に切り替えることができる。全体の電源モードは、5段階用意されているが、定期的に動作させてデータを取得する場合は、スリープまたはディープスリープが使用できる。外部からの何らかのイベントで動作させる場合には、ハイバネートかストップが有用。ここでは、PSoC 4 の電力モードについて、データシートをまとめておく。
| モード | 消費電力 | アクティブへの復帰方法 |
| アクティブ | 1.3mA - 14mA | - |
| スリープ | 1.0mA - 3mA | 任意の割り込み |
| ディープスリープ | 1.3uA - 15uA | GPIO, WDTタイマー, I2C, コンパレータ, 外部リセットピン |
| ハイバネート | 150nA - 1uA | GPIO, コンパレータ, 外部リセットピン |
| ストップ | 20nA - 80nA | Wakeupピン, 外部リセットピン |
純正の書き込み器MiniProg3によるPSoC生チップのプログラムに関する覚え書き。もっとも、MiniProg3は値段が高いので、マニアには敬遠されているらしい。PSoC Programmerを起動して、Utilitiesタブからファームウエアをアップデートしておく(古いファームウエアだと、Power Cycleモードが使用できないと聞いている)。
学部生、卒研生向け、プログラムとデバックの手順解説。ここでは、CY8CKIT-142 PSoC4 BLEモジュール(CY8C4247LQI-BL483搭載、技適認証済み)を使用しましたが、BLEを使わないなら PSoC4 CY8C4245あたりでも。
PSoC Creatorのデバッグ機能は、非常に便利で、プログラム、動作確認、
小型キャラクタ液晶ディスプレイの使用例。3.3V動作、I2C接続の Xiamen Zettler Electronics社 AQM0802A-RN-GBW を使用。秋月でピッチ変換キット(AE-AQM0802)が販売されている。また、電源制御例を示す。LCDは低消費電力だが、1mA程度消費するので、小容量バッテリーや環境エネルギー駆動の場合、スイッチを押したときだけ表示し、しばらく表示したら電源を切る。電源は、PSoCのGNDとは分離されたCGNDラインに接続し、CGNDをPSoCのIO(オープンドレイン)でON/OFFする。VDDはON/OFFせず、パスコンに充電した状態を保つ。
#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);
}
}
}
PCや無線モジュールとの標準的な接続方法の例。TXとRXは互いにクロスさせることに注意。プルアップ抵抗は、PSoCの入出力ピンで設定することもできるが、外部抵抗の使用が推奨されている。複数トークンを含む場合の受信処理は、ADCとIDACの項を参照。写真は、PCとの接続テストに使用した USB-Serial変換モジュール(スイッチサイエンス FTDI USBシリアル変換アダプター Rev.2)。
#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();
}
// NULL termination
strData[strlen(strData)] = '\0';
// Clear RX buffer and RX FIFO
UART_1_SpiUartClearRxBuffer();
// Echo of RX data
UART_1_UartPutString("Received Data = ");
UART_1_UartPutString(strData);
UART_1_UartPutString("\r\n");
}
}
}
GPIOピンにつないだスイッチによる、ディープスリープモード(または他の低消費電力モード)からの復帰の例。
WDT (Watchdog Timer)による、ディープスリープモード(またはスリープモード)からの復帰の例。回路は、GPIO割り込みの例と同じ。
#ref(): File not found: "wdt_05.png" at page "PSoC Creator"
#include "project.h"
#define WDT_INTERVAL 1000 // (ms)
#define ILO_FREQ 32 // (kHz)
#define SLEEP_INTERVAL 5 // (s) for long interval over 2000ms
// WDT interrupt service routine
CY_ISR(wdt_isr_led){
// Clear interrupt flag to enable next interrupt
CySysWdtClearInterrupt(CY_SYS_WDT_COUNTER0_INT);
}
int main(void)
{
int16 sleep_time = 0; // Counter for the sleep interval
// Initiallization of WDT
// Counter 0 of Watchdog time generates peridically interrupt to wakeup system
CySysWdtWriteMode(CY_SYS_WDT_COUNTER0, CY_SYS_WDT_MODE_INT);
// Set interval as desired value
CySysWdtWriteMatch(CY_SYS_WDT_COUNTER0, ((uint32)(WDT_INTERVAL * ILO_FREQ)));
// clear counter on match event
CySysWdtWriteClearOnMatch(CY_SYS_WDT_COUNTER0, 1u);
// Enable watchdog
// enable the counter 0
CySysWdtEnable(CY_SYS_WDT_COUNTER0_MASK);
// check if counter 0 is enabled, otherwise keep looping here
while(!CySysWdtReadEnabledStatus(CY_SYS_WDT_COUNTER0));
// Assign the interrupt vector
isr_1_StartEx(wdt_isr_led);
CyGlobalIntEnable; /* Enable global interrupts. */
for(;;)
{
// Clear watchdog counter before deep sleep
CySysWdtResetCounters(CY_SYS_WDT_COUNTER0_RESET);
// reset watchdog counter requires several LFCLK cycles to take effect
CyDelayUs(150u);
// Transition to deep sleep mode or sleep mode
CySysPmSleep();
if (sleep_time < SLEEP_INTERVAL) sleep_time++;
else {
// Wakeup components
// _Start(); _Wakeup();
// Main process
LED_Pin_Write(1);
CyDelay(100u);
LED_Pin_Write(0);
// Sleep components (store the state before sleep)
// _Stop(); _Sleep();
sleep_time = 0; // Reset counter
}
}
}