PSoC Creator
をテンプレートにして作成
トップ
新規
一覧
単語検索
ヘルプ
開始行:
[[&ref(home.gif);:https://kitagawa.merl.jp/]]
~
Visitor No. &counter(total);
Cypress Semiconductor社PSoC Creator 関連のメモです。ここ...
~
----
*目次 [#k218fc8f]
#contents();
*メモ [#z5b56d96]
***PSoC4ファミリー(ARM Cortex-M0版PSoC)の選択 [#def158c5]
ADCがSAR 1個だけであることを除くと低消費電力で使いやすい...
|CY8C4000系|クロック16MHz, フラッシュ16kB, シリアルポート...
|CY8C4100系|クロック24MHz, フラッシュ32kB, I2C/SPI/UART2...
|CY8C4200系|クロック48MHz, フラッシュ32kB, DMA, I2C/SPI/U...
----
//
// 予備知識----------------------------------------------...
//
***電源構成 [#dcfb22cc]
VDDD, VDDA, VDDR, VCCDなどいろいろあって忘れそうなのでデ...
#ref(power_supply.png)
-電源電圧は、1.8-5.5V
--Bluetoth LE搭載ファミリは、1.9-5.5V(1.9V以下でも動作す...
-内部LDOはデフォルトで有効
--無効にした場合は、VDD1.71-1.89V、VCCDとVDDDをショートする
***低消費電力モード [#had8f8ce]
PSoCでは、チップ全体の電力モードの他に、各回路モジュール...
|モード|消費電力|アクティブへの復帰方法|
|アクティブ|1.3mA - 14mA|-|
|スリープ|1.0mA - 3mA|任意の割り込み|
|ディープスリープ|1.3uA - 15uA|GPIO, WDTタイマー, I2C, コ...
|ハイバネート|150nA - 1uA|GPIO, コンパレータ, 外部リセッ...
|ストップ|20nA - 80nA|Wakeupピン, 外部リセットピン|
***MiniProg3の接続 [#e1433a2c]
純正の書き込み器MiniProg3によるPSoC生チップのプログラムに...
#ref(HSSP.png)
-プログラムとデバッグにSWD(ARM Serial Wire Debug)を利用する
-どのポートがSWDかは、データシートでSWDを検索する
-SWDポートは汎用IOと共有なので、プログラム専用にするとSWD...
----
//
// 基本操作----------------------------------------------...
//
***GPIO(PSoC Creatorの基本操作) [#q60fc28b]
学部生、卒研生向け、プログラムとデバックの手順解説。ここ...
-PSoC外部の回路製作
--下図のようなタクトスイッチを押すとLEDが点灯する回路例を...
#ref(led_sw.png)
-PSoC内部の回路設計
--PSoC Creatorを起動
--File - New - Project...
---Taget device = PSoC4, PSoC4200BLE (使用するデバイスに...
--Empty schematic - Nextボタン
---Workspace name, Location, Peoject nameを適当に設定 - F...
--右欄のComponent Catalog - Cypressタブ - Ports and Pins ...
---Componentを選んでComponent Catalog下のOpen datasheetの...
--ここでは内部回路を作成しないので配線を行う必要はないが...
#ref(pin_01s.png)
--回路図に配置したPinのシンボルをダブルクリックして、下記...
---HW connection: プログラム制御の場合チェック無し、回路...
---Drive mode: 出力回路の設定。スイッチ入力の場合はResist...
---Initial drive state(初期状態のHigh, Lowに合わせる)
---Analog 入力と出力の場合は、原則としてHigh impedance a...
入力ピン
&ref(pin_input.png,,50%);
出力ピン
&ref(pin_output.png,,50%);
--左欄のWorkspace Explorer - Sourceタブ - Design Wide Res...
--右欄のPin_1, Pin_2 をピンアサイン図(Design01.cydwr)のポ...
#ref(pin_02s.png)
-プログラムの作成
--左欄のWorkspace Explorer - Sourceタブ - Source Files - ...
--下図のようにmain.cのプログラムを入力
---通常、無限ループ for(;;) の上には、電源投入時の初期化...
---CyGlobalIntEnable; では、CPUへの割り込みを許可してい...
---Pin_2_Write(!Pin_1_Read()); では、Pin_1の状態(H or L)...
--ツールバーの Build ボタンをクリックして、プログラムをビ...
#ref(pin_03s.png,,60%)
-プログラムの書き込み
--MiniProg3を回路基板のピンヘッダに挿す
--メニューより、Debug - Select target and program...
--MiniProg3を選択
---Port Settingボタンをクリックし下図のように設定して、OK...
--PSoC 4200 BLE CY8C4247LQ*-BL483(ターゲットのデバイス)...
---しばらく待つと書き込みが始まる
#ref(program_port.png,,70%)
--MiniProg3から電源供給されているので、MiniProg3を挿した...
-デバッグ
PSoC Creatorのデバッグ機能は、非常に便利で、回路基板上で...
--ツールバーの Debugボタンをクリックすると、プログラムの...
#ref(debug_01zs.png,,75%)
--プログラムコードが表示されているウインドウ左側のグレー...
---プログラムの行に赤丸が付いて、ブレークポイント(プログ...
--Step Overボタンをクリックして、関数毎にプログラムを実行...
---Step Into で、関数内部に入り、Step Out で関数の実行前...
---タクトスイッチを押しながら Step Overボタンをクリックす...
#ref(debug_03zs.png,,75%)
--Stop Debuggingボタンで、デバッグモードを一旦終了し、上...
--再度、Debugボタンをクリックし、動作を確認する
--下の方の Localsタブをクリックすると、変数 x の値が表示...
---Step Overボタンをクリックすると、xの値がインクリメント...
---Registersタブをクリックすると、各種レジスタの内容が表...
---注意:変数に値を代入しても、値がプログラム中で使用され...
----
//
// LCDと電源制御-----------------------------------------...
//
***I2C LCDと電源制御 [#u9c0fd1b]
小型キャラクタ液晶ディスプレイの使用例。3.3V動作、I2C接続...
#ref(lcd.jpg,,60%)
#ref(lcd_pwr.png)
-I2C (SCB mode), Character LCD with I2C interface, Digita...
#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のピン設定...
#ref(lcd_06.png,,70%)
#ref(lcd_07.png,,70%)
-Digital Output Pin, Digital Input Pinの設定(CGND_1, SW_...
--CGND_1は、Open drain, drives low(出力がLowでない時は、...
--SW-IN_1は、Resistive pull up(スイッチを押さないときはH...
#ref(lcd_08.png,,70%)
#ref(lcd_09.png,,70%)
-main.cの記述
--SW_IN_1_Read()でスイッチを読み取り、LowだったらCGND_1を...
--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 P...
}
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や無線モジュールとの標準的な接続方法の例。TXとRXは互い...
#ref(uart.jpg,,40%)
#ref(uart.png)
-UART(SCB mode)を配置し、rx_inにDigital Input Pin, tx_out...
--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 に設...
#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の記述
--UARTポートから文字列を受信し、Received Data = に続けて...
--ここでは、受信デリミタとして、CR (0x0d)を使用し、送信に...
--UartGetChar()は、バッファにデータが無いときに、NULL (0x...
---ヒント:1回のRXバッファ読み出しまでに、全データを受信...
--FTDT USB-Serial変換器を接続した状態では、PSoCの書き込み...
#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 Uart...
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");
}
}
}
----
//
// ADCとIDAC---------------------------------------------...
//
***ADCとIDAC [#na389981]
IDAC(Current Digital to Analog Converter)から出力した電圧...
- アナログ回路を使用するため、VDDAにアナログ電源(3.3V)を...
- ADCの入力にバッファ(ボルテージフォロワ)を接続した場合...
- IDACの出力電圧の設定とADC結果の読み出しのためにUARTを使...
-- DAC 以外のコマンドを送ると、Unknownと表示され、IDACの...
- IDACは、8bit 電流DACであり、LSB = 1.2mA または 2.4mAか...
-- LSB = 1.2uA とすると、I = 1.2uA * Digital, V = R * I =...
-- R = 10kohm とすると、V = 0.012 * Digital (V), 最大値 =...
#ref(adc.png,,70%)
- Component Catalog から以下の部品を選んで配置する。
-- Analog - ADC - Sequencing SAR ADC 1個
-- Analog - Amplifiers - Opamp 1個
-- Analog - DAC -Current DAC 1個
-- Communications - UART (SCB mode) 1個
-- Ports and Pins - Analog Pin 3個
-- Ports and Pins - Digital Input Pin 1個
-- Ports and Pins - Digital Output Pin 1個
#ref(adc_01.png,,70%)
- 各コンポーネントを下記のように設定。
#ref(adc_02.png,,60%)
-- Sample mode を Hardware trigger に設定
--- 一定周期で連続サンプリングを行う場合は Free running, ...
-- ここでは、Input range = VDDA(3.3Vを想定)、Single end...
--- この設定では、VSS(0V) から VDDA(3.3V)が入力電圧範囲と...
--- Single ended result format = Signed しか選べない (選...
--- 上記の設定では、V = (3.3V/2017) * Digital = 0.0016121...
-- Samples averaged = 8 としたので、8回サンプリングした平...
-- Averaging mode = Fixed Resolution にすると、Samples av...
#ref(adc_03.png,,60%)
-- Sequenced channel でADCの入力ポート数を変更できる。
--- 回路図に示されているようにADCの入力に、アナログマルチ...
-- Mode欄で、入力をシングルまたは差動に設定できる。
-- Acquisition times で、チャネル毎にサンプル&ホールド回...
--- 出力インピーダンス大きい信号源の場合は、S/H回路でサン...
#ref(adc_04.png,,60%)
-- Mode を Follower にすると、オペアンプがボルテージフォ...
#ref(adc_05.png,,60%)
-- 以下の設定は、UARTの項で説明したのと同じ。
#ref(adc_06.png,,60%)
#ref(adc_07.png,,60%)
#ref(adc_08.png,,60%)
- main.c の記述
-- UARTから"DAC 1.0"のような文字列(strData)を受信すると、...
--- 注意:文字列strDataをstrtokで分解すると、strDataのポ...
--- UartGetChar()関数は、文字列をNULL終端しないので、自分...
-- ADCの結果を、そのチャネルの入力設定を用いて電圧値に変...
#include "project.h"
#include "stdlib.h"
#include "stdio.h"
int main(void)
{
CyGlobalIntEnable; /* Enable global interrupts. */
// Initiallization of UART module
UART_1_Start();
UART_1_UartPutString("ADC and DAC example with PSoC\...
uint32 rxData;
int8 ptr;
char strData[] = "\0";
char *cmd = "\0";
char *para = "\0";
// IDAC valiables
uint32 dacData = 0u;
float32 vout = 0.0;
// ADC valiables
int16 adcData[2];
// float32 vin[2];
char adchex_0[6], adchex_1[6]; // 0x + 12bit + ...
// char adcv_0[16], adcv_1[16];
// Initiallization of ADC, OPA, IDAC
ADC_SAR_Seq_1_Start();
Opamp_1_Start();
IDAC_1_Start();
IDAC_1_SetValue(dacData);
for(;;)
{
// Checking command buffer and IDAC output
rxData = UART_1_UartGetChar();
if(rxData) {
memset(strData, '\0', strlen(strData) + strl...
ptr = 0;
// Read until CR delimiter from RX buffer
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();
// Detection of command and parameter token
cmd = strtok(strData, " ");
para = strtok(NULL, " ");
// Decode of command
if(!strcmp(cmd, "DAC") || !strcmp(cmd, "dac"...
// Calculation of digital input of DAC
vout = strtof(para, NULL);
if(vout > 3.06) vout = 3.06; // Over ra...
else if(vout < 0) vout = 0.0; // Under r...
dacData = (uint32)vout/0.012; // LSB = 1...
// Echo to UART
UART_1_UartPutString(" DAC: ");
UART_1_UartPutString(cmd);
UART_1_UartPutString(" ");
UART_1_UartPutString(para);
UART_1_UartPutString(" \r\n");
// Output from IDAC
IDAC_1_SetValue(dacData);
// Software delay (ms) from DAC output t...
CyDelay(1u);
}
// Message for the unknown command
else UART_1_UartPutString("Unknown command\r...
}
// ADC aquisiotion
ADC_SAR_Seq_1_StartConvert(); // Trigger
ADC_SAR_Seq_1_IsEndConversion(ADC_SAR_Seq_1_WAIT...
// Getting the adc results
adcData[0] = ADC_SAR_Seq_1_GetResult16(0);
adcData[1] = ADC_SAR_Seq_1_GetResult16(1);
// Conversion to voltage
// vin[0] = ADC_SAR_Seq_1_CountsTo_Volts(0, ADC_...
// vin[1] = ADC_SAR_Seq_1_CountsTo_Volts(1, ADC_...
// Sending ADC results to UART
snprintf(adchex_0, 6, "%#x", adcData[0]);
snprintf(adchex_1, 6, "%#x", adcData[1]);
// snprintf(adcv_0, 16, "%f", vin[0]);
// snprintf(adcv_1, 16, "%f", vin[1]);
UART_1_UartPutString("ADC1: ");
UART_1_UartPutString(adchex_0);
// UART_1_UartPutString(" ");
// UART_1_UartPutString(adcv_0);
UART_1_UartPutString(" ");
UART_1_UartPutString("ADC2: ");
UART_1_UartPutString(adchex_1);
// UART_1_UartPutString(" ");
// UART_1_UartPutString(adcv_1);
UART_1_UartPutString("\r\n");
// Software delay (ms) until next aquisiotion
CyDelay(1000u);
}
}
----
//
// GPIO割り込みとスリープ--------------------------------...
//
***GPIO割り込みとディープスリープ [#z9447da4]
GPIOピンにつないだスイッチによる、ディープスリープモード...
#ref(int.jpg,,10%)
#ref(int.png,,70%)
- Component Catalogより、Ports and Pins - Digital Input P...
#ref(int_01.png,,60%)
- 各コンポーネントを下記のように設定。
- Digital Input Pin の設定を行うと、irq端子が現れるので...
#ref(int_02.png,,60%)
#ref(int_03.png,,60%)
#ref(int_04.png,,60%)
#ref(int_05.png,,60%)
- Workspace Explorer の Interrupts をダブルクリックし、Pr...
-- これにより、割り込みの優先度が決まる(値が小さい方が優...
#ref(int_06.png,,60%)
- main.c の記述
-- SW_Pinによる割り込み isr_1 とグローバル割り込みを有効...
-- SW_Pinによる割り込みが発生すると、ISR (Interrupt Servi...
#include "project.h"
// GPIO interrupt service routine
CY_ISR(sw_isr_led){
// Clear pin interrupt
SW_Pin_ClearInterrupt();
}
int main(void)
{
// Assign the interrupt ve ctor
isr_1_StartEx(sw_isr_led);
CyGlobalIntEnable; /* Enable global interrupts. */
for(;;)
{
// Transition to deep sleep mode or sleep mode
// CySysPmSleep();
CySysPmDeepSleep();
// 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();
}
}
----
//
// WDT(タイマー)割り込みとディープスリープ-------------...
//
***WDT(タイマー)割り込みとディープスリープ [#c2ba416a]
WDT (Watchdog Timer)によるディープスリープモード(または...
#ref(int.png,,80%)
- Component Catalogより、System - Global Signal Reference...
- LEDの点灯で動作を確認するため、Ports and Pins - Digital...
#ref(wdt_01.png,,60%)
- Global Signal Reference, isr_1, Digital Output Pinを下...
-- Global Signal Reference の Global Signal Name として、...
-- isr_1 の Interrupt Type は、DERIVED を選択。
--- Interrupt Typeでは、割り込みのソースに対して、レベル...
#ref(wdt_02.png,,60%)
#ref(wdt_03.png,,60%)
#ref(wdt_04.png,,60%)
- Workspace Explorer の Interrupts をダブルクリックし、Pr...
-- これにより、割り込みの優先度が決まる(値が小さい方が優...
#ref(wdt_06.png,,60%)
- Workspace Explorer の Clocks をダブルクリックし、クロッ...
- Configure System Clocks ウインドウが開くので、Timer(WDT...
#ref(wdt_07.png,,60%)
#ref(wdt_08.png,,50%)
- main.c の記述
-- WDT_INTERVAL にWDT(Watchdog Timer) に タイマー設定時間...
--- ILOは、ディープスリープモードでも動作し続ける。ILO の...
--- WDTのカウンターは、16bit (65,536カウント) なので、T =...
-- SLEEP_INTERVAL に、ウエークアップする周期(s)を設定する。
--- WDT は、約2秒までしかカウントできないので、SLEEP_INTE...
-- WDTによる割り込み isr_1 、グローバル割り込みを有効にし...
-- WDTによる割り込みが発生すると、ISR (Interrupt Service ...
#include "project.h"
#define WDT_INTERVAL 1000 // (ms)
#define ILO_FREQ 32 // (kHz)
#define SLEEP_INTERVAL 5 // (s) for long interval over ...
// 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 inter...
// Initiallization of WDT
// Counter 0 of Watchdog time generates peridically ...
CySysWdtWriteMode(CY_SYS_WDT_COUNTER0, CY_SYS_WDT_MO...
// Set interval as desired value
CySysWdtWriteMatch(CY_SYS_WDT_COUNTER0, ((uint32)(WDT_I...
// 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 loo...
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...
CyDelayUs(150u);
// Transition to deep sleep mode or sleep mode
CySysPmDeepSleep();
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 ...
// _Stop(); _Sleep();
sleep_time = 0; // Reset counter
}
}
}
----
//
// snprintf によるfloat - ASCII 変換---------------------...
//
***snprintf による float - ASCII 変換 [#tb1d2552]
PSoC Creator の snprintf, sprintf では、%f の処理ができな...
[参考] sprintf では、変換後の最大文字数を指定できないため...
- 下記のディレクティブをmain.cに追加 [UARTデータシートを...
-- floatを扱うライブラリが追加される。
- Workspace Explorer の Systemをダブルクリック。
-- Heep Size を 0xffに変更してビルド。
--- デフォルトのヒープサイズ(0x80)では暴走するようなので...
/* Add an explicit reference to the floating point print...
#if defined (__GNUC__)
asm (".global _printf_float");
#endif
~
#ref(printf.png,,70%)
終了行:
[[&ref(home.gif);:https://kitagawa.merl.jp/]]
~
Visitor No. &counter(total);
Cypress Semiconductor社PSoC Creator 関連のメモです。ここ...
~
----
*目次 [#k218fc8f]
#contents();
*メモ [#z5b56d96]
***PSoC4ファミリー(ARM Cortex-M0版PSoC)の選択 [#def158c5]
ADCがSAR 1個だけであることを除くと低消費電力で使いやすい...
|CY8C4000系|クロック16MHz, フラッシュ16kB, シリアルポート...
|CY8C4100系|クロック24MHz, フラッシュ32kB, I2C/SPI/UART2...
|CY8C4200系|クロック48MHz, フラッシュ32kB, DMA, I2C/SPI/U...
----
//
// 予備知識----------------------------------------------...
//
***電源構成 [#dcfb22cc]
VDDD, VDDA, VDDR, VCCDなどいろいろあって忘れそうなのでデ...
#ref(power_supply.png)
-電源電圧は、1.8-5.5V
--Bluetoth LE搭載ファミリは、1.9-5.5V(1.9V以下でも動作す...
-内部LDOはデフォルトで有効
--無効にした場合は、VDD1.71-1.89V、VCCDとVDDDをショートする
***低消費電力モード [#had8f8ce]
PSoCでは、チップ全体の電力モードの他に、各回路モジュール...
|モード|消費電力|アクティブへの復帰方法|
|アクティブ|1.3mA - 14mA|-|
|スリープ|1.0mA - 3mA|任意の割り込み|
|ディープスリープ|1.3uA - 15uA|GPIO, WDTタイマー, I2C, コ...
|ハイバネート|150nA - 1uA|GPIO, コンパレータ, 外部リセッ...
|ストップ|20nA - 80nA|Wakeupピン, 外部リセットピン|
***MiniProg3の接続 [#e1433a2c]
純正の書き込み器MiniProg3によるPSoC生チップのプログラムに...
#ref(HSSP.png)
-プログラムとデバッグにSWD(ARM Serial Wire Debug)を利用する
-どのポートがSWDかは、データシートでSWDを検索する
-SWDポートは汎用IOと共有なので、プログラム専用にするとSWD...
----
//
// 基本操作----------------------------------------------...
//
***GPIO(PSoC Creatorの基本操作) [#q60fc28b]
学部生、卒研生向け、プログラムとデバックの手順解説。ここ...
-PSoC外部の回路製作
--下図のようなタクトスイッチを押すとLEDが点灯する回路例を...
#ref(led_sw.png)
-PSoC内部の回路設計
--PSoC Creatorを起動
--File - New - Project...
---Taget device = PSoC4, PSoC4200BLE (使用するデバイスに...
--Empty schematic - Nextボタン
---Workspace name, Location, Peoject nameを適当に設定 - F...
--右欄のComponent Catalog - Cypressタブ - Ports and Pins ...
---Componentを選んでComponent Catalog下のOpen datasheetの...
--ここでは内部回路を作成しないので配線を行う必要はないが...
#ref(pin_01s.png)
--回路図に配置したPinのシンボルをダブルクリックして、下記...
---HW connection: プログラム制御の場合チェック無し、回路...
---Drive mode: 出力回路の設定。スイッチ入力の場合はResist...
---Initial drive state(初期状態のHigh, Lowに合わせる)
---Analog 入力と出力の場合は、原則としてHigh impedance a...
入力ピン
&ref(pin_input.png,,50%);
出力ピン
&ref(pin_output.png,,50%);
--左欄のWorkspace Explorer - Sourceタブ - Design Wide Res...
--右欄のPin_1, Pin_2 をピンアサイン図(Design01.cydwr)のポ...
#ref(pin_02s.png)
-プログラムの作成
--左欄のWorkspace Explorer - Sourceタブ - Source Files - ...
--下図のようにmain.cのプログラムを入力
---通常、無限ループ for(;;) の上には、電源投入時の初期化...
---CyGlobalIntEnable; では、CPUへの割り込みを許可してい...
---Pin_2_Write(!Pin_1_Read()); では、Pin_1の状態(H or L)...
--ツールバーの Build ボタンをクリックして、プログラムをビ...
#ref(pin_03s.png,,60%)
-プログラムの書き込み
--MiniProg3を回路基板のピンヘッダに挿す
--メニューより、Debug - Select target and program...
--MiniProg3を選択
---Port Settingボタンをクリックし下図のように設定して、OK...
--PSoC 4200 BLE CY8C4247LQ*-BL483(ターゲットのデバイス)...
---しばらく待つと書き込みが始まる
#ref(program_port.png,,70%)
--MiniProg3から電源供給されているので、MiniProg3を挿した...
-デバッグ
PSoC Creatorのデバッグ機能は、非常に便利で、回路基板上で...
--ツールバーの Debugボタンをクリックすると、プログラムの...
#ref(debug_01zs.png,,75%)
--プログラムコードが表示されているウインドウ左側のグレー...
---プログラムの行に赤丸が付いて、ブレークポイント(プログ...
--Step Overボタンをクリックして、関数毎にプログラムを実行...
---Step Into で、関数内部に入り、Step Out で関数の実行前...
---タクトスイッチを押しながら Step Overボタンをクリックす...
#ref(debug_03zs.png,,75%)
--Stop Debuggingボタンで、デバッグモードを一旦終了し、上...
--再度、Debugボタンをクリックし、動作を確認する
--下の方の Localsタブをクリックすると、変数 x の値が表示...
---Step Overボタンをクリックすると、xの値がインクリメント...
---Registersタブをクリックすると、各種レジスタの内容が表...
---注意:変数に値を代入しても、値がプログラム中で使用され...
----
//
// LCDと電源制御-----------------------------------------...
//
***I2C LCDと電源制御 [#u9c0fd1b]
小型キャラクタ液晶ディスプレイの使用例。3.3V動作、I2C接続...
#ref(lcd.jpg,,60%)
#ref(lcd_pwr.png)
-I2C (SCB mode), Character LCD with I2C interface, Digita...
#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のピン設定...
#ref(lcd_06.png,,70%)
#ref(lcd_07.png,,70%)
-Digital Output Pin, Digital Input Pinの設定(CGND_1, SW_...
--CGND_1は、Open drain, drives low(出力がLowでない時は、...
--SW-IN_1は、Resistive pull up(スイッチを押さないときはH...
#ref(lcd_08.png,,70%)
#ref(lcd_09.png,,70%)
-main.cの記述
--SW_IN_1_Read()でスイッチを読み取り、LowだったらCGND_1を...
--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 P...
}
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や無線モジュールとの標準的な接続方法の例。TXとRXは互い...
#ref(uart.jpg,,40%)
#ref(uart.png)
-UART(SCB mode)を配置し、rx_inにDigital Input Pin, tx_out...
--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 に設...
#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の記述
--UARTポートから文字列を受信し、Received Data = に続けて...
--ここでは、受信デリミタとして、CR (0x0d)を使用し、送信に...
--UartGetChar()は、バッファにデータが無いときに、NULL (0x...
---ヒント:1回のRXバッファ読み出しまでに、全データを受信...
--FTDT USB-Serial変換器を接続した状態では、PSoCの書き込み...
#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 Uart...
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");
}
}
}
----
//
// ADCとIDAC---------------------------------------------...
//
***ADCとIDAC [#na389981]
IDAC(Current Digital to Analog Converter)から出力した電圧...
- アナログ回路を使用するため、VDDAにアナログ電源(3.3V)を...
- ADCの入力にバッファ(ボルテージフォロワ)を接続した場合...
- IDACの出力電圧の設定とADC結果の読み出しのためにUARTを使...
-- DAC 以外のコマンドを送ると、Unknownと表示され、IDACの...
- IDACは、8bit 電流DACであり、LSB = 1.2mA または 2.4mAか...
-- LSB = 1.2uA とすると、I = 1.2uA * Digital, V = R * I =...
-- R = 10kohm とすると、V = 0.012 * Digital (V), 最大値 =...
#ref(adc.png,,70%)
- Component Catalog から以下の部品を選んで配置する。
-- Analog - ADC - Sequencing SAR ADC 1個
-- Analog - Amplifiers - Opamp 1個
-- Analog - DAC -Current DAC 1個
-- Communications - UART (SCB mode) 1個
-- Ports and Pins - Analog Pin 3個
-- Ports and Pins - Digital Input Pin 1個
-- Ports and Pins - Digital Output Pin 1個
#ref(adc_01.png,,70%)
- 各コンポーネントを下記のように設定。
#ref(adc_02.png,,60%)
-- Sample mode を Hardware trigger に設定
--- 一定周期で連続サンプリングを行う場合は Free running, ...
-- ここでは、Input range = VDDA(3.3Vを想定)、Single end...
--- この設定では、VSS(0V) から VDDA(3.3V)が入力電圧範囲と...
--- Single ended result format = Signed しか選べない (選...
--- 上記の設定では、V = (3.3V/2017) * Digital = 0.0016121...
-- Samples averaged = 8 としたので、8回サンプリングした平...
-- Averaging mode = Fixed Resolution にすると、Samples av...
#ref(adc_03.png,,60%)
-- Sequenced channel でADCの入力ポート数を変更できる。
--- 回路図に示されているようにADCの入力に、アナログマルチ...
-- Mode欄で、入力をシングルまたは差動に設定できる。
-- Acquisition times で、チャネル毎にサンプル&ホールド回...
--- 出力インピーダンス大きい信号源の場合は、S/H回路でサン...
#ref(adc_04.png,,60%)
-- Mode を Follower にすると、オペアンプがボルテージフォ...
#ref(adc_05.png,,60%)
-- 以下の設定は、UARTの項で説明したのと同じ。
#ref(adc_06.png,,60%)
#ref(adc_07.png,,60%)
#ref(adc_08.png,,60%)
- main.c の記述
-- UARTから"DAC 1.0"のような文字列(strData)を受信すると、...
--- 注意:文字列strDataをstrtokで分解すると、strDataのポ...
--- UartGetChar()関数は、文字列をNULL終端しないので、自分...
-- ADCの結果を、そのチャネルの入力設定を用いて電圧値に変...
#include "project.h"
#include "stdlib.h"
#include "stdio.h"
int main(void)
{
CyGlobalIntEnable; /* Enable global interrupts. */
// Initiallization of UART module
UART_1_Start();
UART_1_UartPutString("ADC and DAC example with PSoC\...
uint32 rxData;
int8 ptr;
char strData[] = "\0";
char *cmd = "\0";
char *para = "\0";
// IDAC valiables
uint32 dacData = 0u;
float32 vout = 0.0;
// ADC valiables
int16 adcData[2];
// float32 vin[2];
char adchex_0[6], adchex_1[6]; // 0x + 12bit + ...
// char adcv_0[16], adcv_1[16];
// Initiallization of ADC, OPA, IDAC
ADC_SAR_Seq_1_Start();
Opamp_1_Start();
IDAC_1_Start();
IDAC_1_SetValue(dacData);
for(;;)
{
// Checking command buffer and IDAC output
rxData = UART_1_UartGetChar();
if(rxData) {
memset(strData, '\0', strlen(strData) + strl...
ptr = 0;
// Read until CR delimiter from RX buffer
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();
// Detection of command and parameter token
cmd = strtok(strData, " ");
para = strtok(NULL, " ");
// Decode of command
if(!strcmp(cmd, "DAC") || !strcmp(cmd, "dac"...
// Calculation of digital input of DAC
vout = strtof(para, NULL);
if(vout > 3.06) vout = 3.06; // Over ra...
else if(vout < 0) vout = 0.0; // Under r...
dacData = (uint32)vout/0.012; // LSB = 1...
// Echo to UART
UART_1_UartPutString(" DAC: ");
UART_1_UartPutString(cmd);
UART_1_UartPutString(" ");
UART_1_UartPutString(para);
UART_1_UartPutString(" \r\n");
// Output from IDAC
IDAC_1_SetValue(dacData);
// Software delay (ms) from DAC output t...
CyDelay(1u);
}
// Message for the unknown command
else UART_1_UartPutString("Unknown command\r...
}
// ADC aquisiotion
ADC_SAR_Seq_1_StartConvert(); // Trigger
ADC_SAR_Seq_1_IsEndConversion(ADC_SAR_Seq_1_WAIT...
// Getting the adc results
adcData[0] = ADC_SAR_Seq_1_GetResult16(0);
adcData[1] = ADC_SAR_Seq_1_GetResult16(1);
// Conversion to voltage
// vin[0] = ADC_SAR_Seq_1_CountsTo_Volts(0, ADC_...
// vin[1] = ADC_SAR_Seq_1_CountsTo_Volts(1, ADC_...
// Sending ADC results to UART
snprintf(adchex_0, 6, "%#x", adcData[0]);
snprintf(adchex_1, 6, "%#x", adcData[1]);
// snprintf(adcv_0, 16, "%f", vin[0]);
// snprintf(adcv_1, 16, "%f", vin[1]);
UART_1_UartPutString("ADC1: ");
UART_1_UartPutString(adchex_0);
// UART_1_UartPutString(" ");
// UART_1_UartPutString(adcv_0);
UART_1_UartPutString(" ");
UART_1_UartPutString("ADC2: ");
UART_1_UartPutString(adchex_1);
// UART_1_UartPutString(" ");
// UART_1_UartPutString(adcv_1);
UART_1_UartPutString("\r\n");
// Software delay (ms) until next aquisiotion
CyDelay(1000u);
}
}
----
//
// GPIO割り込みとスリープ--------------------------------...
//
***GPIO割り込みとディープスリープ [#z9447da4]
GPIOピンにつないだスイッチによる、ディープスリープモード...
#ref(int.jpg,,10%)
#ref(int.png,,70%)
- Component Catalogより、Ports and Pins - Digital Input P...
#ref(int_01.png,,60%)
- 各コンポーネントを下記のように設定。
- Digital Input Pin の設定を行うと、irq端子が現れるので...
#ref(int_02.png,,60%)
#ref(int_03.png,,60%)
#ref(int_04.png,,60%)
#ref(int_05.png,,60%)
- Workspace Explorer の Interrupts をダブルクリックし、Pr...
-- これにより、割り込みの優先度が決まる(値が小さい方が優...
#ref(int_06.png,,60%)
- main.c の記述
-- SW_Pinによる割り込み isr_1 とグローバル割り込みを有効...
-- SW_Pinによる割り込みが発生すると、ISR (Interrupt Servi...
#include "project.h"
// GPIO interrupt service routine
CY_ISR(sw_isr_led){
// Clear pin interrupt
SW_Pin_ClearInterrupt();
}
int main(void)
{
// Assign the interrupt ve ctor
isr_1_StartEx(sw_isr_led);
CyGlobalIntEnable; /* Enable global interrupts. */
for(;;)
{
// Transition to deep sleep mode or sleep mode
// CySysPmSleep();
CySysPmDeepSleep();
// 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();
}
}
----
//
// WDT(タイマー)割り込みとディープスリープ-------------...
//
***WDT(タイマー)割り込みとディープスリープ [#c2ba416a]
WDT (Watchdog Timer)によるディープスリープモード(または...
#ref(int.png,,80%)
- Component Catalogより、System - Global Signal Reference...
- LEDの点灯で動作を確認するため、Ports and Pins - Digital...
#ref(wdt_01.png,,60%)
- Global Signal Reference, isr_1, Digital Output Pinを下...
-- Global Signal Reference の Global Signal Name として、...
-- isr_1 の Interrupt Type は、DERIVED を選択。
--- Interrupt Typeでは、割り込みのソースに対して、レベル...
#ref(wdt_02.png,,60%)
#ref(wdt_03.png,,60%)
#ref(wdt_04.png,,60%)
- Workspace Explorer の Interrupts をダブルクリックし、Pr...
-- これにより、割り込みの優先度が決まる(値が小さい方が優...
#ref(wdt_06.png,,60%)
- Workspace Explorer の Clocks をダブルクリックし、クロッ...
- Configure System Clocks ウインドウが開くので、Timer(WDT...
#ref(wdt_07.png,,60%)
#ref(wdt_08.png,,50%)
- main.c の記述
-- WDT_INTERVAL にWDT(Watchdog Timer) に タイマー設定時間...
--- ILOは、ディープスリープモードでも動作し続ける。ILO の...
--- WDTのカウンターは、16bit (65,536カウント) なので、T =...
-- SLEEP_INTERVAL に、ウエークアップする周期(s)を設定する。
--- WDT は、約2秒までしかカウントできないので、SLEEP_INTE...
-- WDTによる割り込み isr_1 、グローバル割り込みを有効にし...
-- WDTによる割り込みが発生すると、ISR (Interrupt Service ...
#include "project.h"
#define WDT_INTERVAL 1000 // (ms)
#define ILO_FREQ 32 // (kHz)
#define SLEEP_INTERVAL 5 // (s) for long interval over ...
// 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 inter...
// Initiallization of WDT
// Counter 0 of Watchdog time generates peridically ...
CySysWdtWriteMode(CY_SYS_WDT_COUNTER0, CY_SYS_WDT_MO...
// Set interval as desired value
CySysWdtWriteMatch(CY_SYS_WDT_COUNTER0, ((uint32)(WDT_I...
// 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 loo...
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...
CyDelayUs(150u);
// Transition to deep sleep mode or sleep mode
CySysPmDeepSleep();
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 ...
// _Stop(); _Sleep();
sleep_time = 0; // Reset counter
}
}
}
----
//
// snprintf によるfloat - ASCII 変換---------------------...
//
***snprintf による float - ASCII 変換 [#tb1d2552]
PSoC Creator の snprintf, sprintf では、%f の処理ができな...
[参考] sprintf では、変換後の最大文字数を指定できないため...
- 下記のディレクティブをmain.cに追加 [UARTデータシートを...
-- floatを扱うライブラリが追加される。
- Workspace Explorer の Systemをダブルクリック。
-- Heep Size を 0xffに変更してビルド。
--- デフォルトのヒープサイズ(0x80)では暴走するようなので...
/* Add an explicit reference to the floating point print...
#if defined (__GNUC__)
asm (".global _printf_float");
#endif
~
#ref(printf.png,,70%)
ページ名: