2021年05月29日

PIC32MX2XX RB5ポート注意点

先日、PIC32MX2XXシリーズを使用していて、RB5ポートの出力が意図通りに動かない問題に遭遇しました。今回はその原因と解決方法を紹介したいと思います。PIC32MX250F128BをターゲットにMPLAB X v5.45+Harmony3+XC32 v2.50を使用しています。


RB5ポートをHarmony3のPin SettingsでFunctionをGPIO、DirectionをOutに設定し、コード上でONにしましたが、RB5のみ2.2V付近の中途半端な電圧が出力されるのみで意図したIO変化をさせることができませんでした。

PinSetting.jpg


一般的なPICのGPIOポート設定でよくあるミスとして
・アナログ入力がONになっている(ANSELXが0でない)
・JTAGポートがONになっている(JTAGEN=ON)
・入力専用のポートだった
・OpenDrain設定だった(ODCXが0でない) or OpenDrain専用ポートだった
ということが多々あります。

今回は上記でもなく、MPUのエラッタと思い調べてみましたが、「I2C2モジュールが有効の場合にRB5、RB6がうまく動かない」というエラー以外はなく、I2C2を使用していないため、エラッタでもなさそうです。


データシートのピンアサインを調べてみるとRB5はUSBID用のポートとなっており、USBID関連の設定を見るとHarmony3のデフォルト設定が
USB USBID Selection bitがONとなっており、USBを使用していないにも関わらずデフォルト設定がONになっていることが分かりました。USB USBID Selection bit(FUSBIDIO) をOFFに設定すると意図通りにRB5のON、OFFができるようになりました。


USB_ID_DISABLE.jpg

USB機能があるPIC32MX2XXシリーズ固有の問題ですが、初期設定でUSB USBID Selection bitがUSB側になっているのは不親切だと思いました。ポートが意図した動作をしない場合はポートに割り当て可能な機能について設定状況を一折調べることが大切です。特にUSBやJTAG系の設定はGPIO設定とは設定項目が異なるため、見落としがちなので注意が必要です。
posted by Crescent at 00:00| Comment(0) | 電子工作 | このブログの読者になる | 更新情報をチェックする

2021年05月22日

PIC32MX+Harmony3+ビルド設定

今回はPIC32MX250F128BをターゲットにMPLAB X v5.45+Harmony3+XC32 v2.50を使用する際のビルド設定について紹介します。Harmony3で生成したプロジェクトをXC32でビルドするとデフォルトはワーニングもエラーとして処理する設定となっています。そのため、例えば下記のように未使用の変数があった場合にエラーとなってビルドに失敗します。

../src/app.c:420:10: error: unused variable 'XXXX' [-Werror=unused-variable]

File→Project Propertiesをクリックし、左のXC32(Global Options)のxc32-gccをクリックします。「Option categories」の「Preprocessing and messages」の項目を選択し、「Make warnings into errors」のチェックを外します。OKをクリックして設定を反映させます。OKが押せない場合は左のConf項目でCompiler ToolchainからXC32の対象コンパイラを選択するとOKボタンが有効になります。


XC32_1.jpg


XC32_2.jpg

最終的には未使用変数を削除しますが、試行錯誤している場合は多々未使用変数が残ってしまうものです。デフォルト設定が少し不親切だと感じました。今後のバージョンアップで修正されることに期待です。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2021年05月15日

PIC32MX+Harmony3+ I2C通信

今回はPIC32MX250F128BをターゲットにMPLAB X v5.45+Harmony3を使用してI2C通信を行いました。その際にポイントとなる設定について紹介します。I2C接続の温湿度センサHS3001の読み込みを行いました。なお、ターゲットへの書き込みはPickit3を使用しまし、MPLAB Xには予め、MPLAB Harmony 3 Launcher(旧名称 MPLAB Harmony Configurator 3)をインストールしています。


@プロジェクトファイル作成
MPLAB XのFile→New ProjectからMPLAB Harmony 3のプロジェクトを作成します。

hi2c1.jpg

AHarmony 3設定
Tools→Embedded→Harmony Configurator 3を選択します。左下のAvailable ComponentsからI2C2をクリックし、I2C2を追加します。SPI1が追加されると左上(Active Components)及び中央(Project Graph)にI2C2が表示されます。
中央(Project Graph)のI2C2をクリックし、右のConfiguration Optionsの設定項目を必要に応じて変更します。通常はデフォルトで問題ありません。

また、今回はデバッグ用途にprintfを使用してuartからデバッグ情報を出力するため、UART2とSTDIOを追加しています。必要に応じてUART2のボーレートを右のConfiguration Optionsから変更してください。

hi2c2.jpg

hi2c3.jpg

Bピンアサイン設定
MHC→Tools→Pin Configurationを選択します。Pin DiagramからI2CのSDA2、SCL2を割り付けします。Pin SettingsからI2Cの外付けプルアップ抵抗を省略するためにRB2、RB3のプルアップを有効にしました。

hi2c4.jpg

Cコード生成
設定完了後にGenerate Codeでコードを生成します。

hi2c5.jpg

DI2C通信関数
I2C通信をするためのコードを追加します。I2C通信関数はSource Files/config/default/peripheral/i2c/master内のplib_i2c2_master.cで定義されています。I2C初期化関数は既にinitialization.cに追加されているため、接続するデバイスに応じてI2C読み書き関数を追加します。I2C読み書きを同時にする場合はI2C2_WriteRead関数、読み込みのみの場合はI2C2_Read、書き込みのみの場合はI2C2_Writeの関数を使用します。なお、STM32のHALライブラリでは8bitアドレス(R/Wのbitを含める)で定義しますが、Harmony3のI2Cアドレスは7bitアドレスを定義します。


#define HS300X_ADDR (0x88>>1)

void Get_HS300X_Data(volatile int16_t *tmp, volatile int16_t *hmd)
{
 uint8_t dat[4];
 int16_t tmp_dat,hmd_dat;
 float tempf;
 float humdf;
 I2C2_Read(HS300X_ADDR,dat,4);
 while(I2C2_IsBusy()==true);
 I2C2_Write(HS300X_ADDR,NULL,0);
 while(I2C2_IsBusy()==true);
 tmp_dat = (dat[2]<<8)+dat[3];
 tmp_dat = tmp_dat>>2;
 hmd_dat = ((dat[0]&0x3F)<<8)+dat[1];
 humdf=(float)hmd_dat/(16383.0f)*100.0f;
 tempf=((float)tmp_dat)/(16383.0f)*165.0f-40.0f;
 *hmd = (int16_t)(humdf*100.0f);
 *tmp = (int16_t)(tempf*100.0f);
 return;
}

温湿度センサHS3001は温湿度を読み出しする際、アドレスのみ書き込みすると測定開始される少し特殊な仕様です。そのため、 I2C2_Write ( HS300X_ADDR, NULL, 0)という空データを書き込む処理が入っています。



posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2021年05月08日

PIC32MX+Harmony3+ SPI通信

今回はPIC32MX250F128BをターゲットにMPLAB X v5.45+Harmony3を使用してSPI通信を行いました。その際にポイントとなる設定について紹介します。SPI接続のSRAM(IS62WVS5128FB)の書き込み、読み込みを行いました。なお、ターゲットへの書き込みはPickit3を使用しまし、MPLAB Xには予め、MPLAB Harmony 3 Launcher(旧名称 MPLAB Harmony Configurator 3)をインストールしています。

@プロジェクトファイル作成
MPLAB XのFile→New ProjectからMPLAB Harmony 3のプロジェクトを作成します。

hspi1.jpg

AHarmony 3設定
Tools→Embedded→Harmony Configurator 3を選択します。左下のAvailable ComponentsからSPI1をクリックし、SPI1を追加します。SPI1が追加されると左上(Active Components)及び中央(Project Graph)にSPI1が表示されます。

中央(Project Graph)のSPI1をクリックし、右のConfiguration Optionsの設定項目を必要に応じて変更します。通常はデフォルトで問題ありません。SPIのデフォルトクロック周波数が低いため、1MHz程度に変更します。

また、今回はデバッグ用途にprintfを使用してuartからデバッグ情報を出力するため、UART2とSTDIOを追加しています。必要に応じてUART2のボーレートを右のConfiguration Optionsから変更してください。

hspi2.jpg

hspi3.jpg

Bピンアサイン設定
MHC→Tools→Pin Configurationを選択します。Pin DiagramからSPI1のSDO1、SDI1、SCK1を割り付けします。また、Pin SettingsからCSとしてRA0をGPIO設定しました。Pin TableからRA0を出力に設定し、通信を安定させるためにプルアップを有効にしました。

hspi4.jpg

hspi5-1.jpg



hspi5.jpg

Cコード生成
設定完了後にGenerate Codeでコードを生成します。

hspi6.jpg

DSPI通信関数
SPI通信をするためのコードを追加します。

hspi7.jpg



SPI通信関数はSource Files/config/default/peripheral/spi/spi_master内のplib_spi1_master.cで定義されています。SPI初期化関数は既にinitialization.cに追加されているため、接続するデバイスに応じてSPI読み書き関数を追加します。SPI読み書きを同時にする場合はSPI1_WriteRead関数、読み込みのみの場合はSPI1_Read、書き込みのみの場合はSPI1_Writeの関数を使用します。なお、SPI1のConfiguration Options、Enable Interrupts設定はデフォルトで有効となっています。そのため、書き込み、読み込みした後はSPI1_IsBusy関数でSPI処理の完了を確認するか、SPI処理後に呼び出す関数をSPI1_CallbackRegisterで事前に登録する必要があります。SPI1_CallbackRegisterのサンプルはこちらに上がっているため、詳細の説明は省略します。今回はSPI1_IsBusy関数でSPI処理の完了を確認しました。

また、SPI通信で必要なCSは自動に設定(通信するときのみCSが自動でLOWになる)できますが、今回は手動でIO操作にしました。ピンアサイン設定でRA0を出力に設定したため、自動でHeader Files/config/default/peripheral/gpio内のplib_gpio.hにGPIO_RA0_Set関数やGPIO_RA0_Clear関数が追加されます。追加されたGPIO関数でCSを操作します。SRAMと通信するための全体のコードは下記です。main.cに下記のコードを追加しました。

#define SRAM_WRITE_CMD 2
#define SRAM_READ_CMD 3


void SramWrite(unsigned char *data, unsigned short length)
{
 unsigned char wcmd[4];
 wcmd[0]=SRAM_WRITE_CMD;
 wcmd[1]=0;//High Addr
 wcmd[2]=0;//Mid Addr
 wcmd[3]=0;//Low Addr

 GPIO_RA0_Clear();
 SPI1_Write(wcmd,4);
 while(SPI1_IsBusy()==true);
 SPI1_Write(data,length);
 while(SPI1_IsBusy()==true);
 GPIO_RA0_Set();
}

void SramRead(unsigned char *data, unsigned short length)
{
 unsigned char wcmd[4];
 wcmd[0]=SRAM_READ_CMD;
 wcmd[1]=0;//High Addr
 wcmd[2]=0;//Mid Addr
 wcmd[3]=0;//Low Addr
 
 GPIO_RA0_Clear();
 SPI1_Write(wcmd,4);
 while(SPI1_IsBusy()==true);
 SPI1_Read(data,length);
 while(SPI1_IsBusy()==true);
 GPIO_RA0_Set();
}


SPI1CONCLRやSPI1CONSET、LATACLR等のレジスタを操作してSPI通信やIO操作を行っていましたが、Harmony3でハードレイヤーが抽象化され、コード自動生成時点で最低限の関数が既に実装されています。設定によってはコード自動生成直後にも関わらず、ビルドエラーが発生してコードの修正が必要な場合がありますが、以前に比べると大分、改善しているように感じました。なお、SDカードといったHarmony3の機能や設定によってはSPI1_ReadやSPI1_Writeといった関数名が変わるため、注意が必要です。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2021年05月01日

STM32マイコンUART拡張機能

STM32F7、L4、H7シリーズではUART通信をする際に非常に便利な拡張機能があります。今回はUART拡張機能について紹介します。例えばUARTを利用する際に基板のTXとRXを間違えて逆転させてしまったり(回路上でTXとRXをクロスさせることを忘れていた)、フォトカプラを接続するので論理を逆転させたい(通常は論理反転のバッファICやトランジスタ等で追加ハードウェアで論理反転させる)、DMA受信時のエラー処理を無効にしたい(デフォルトではSTM32のUART受信でフレームエラー等が発生するとクリアするまで受信できない)といったことが多々あると思います。そのような場合にUART拡張機能を利用することでハードウェア追加や修正なしにソフトウェア側の設定変更のみで切り替えることが可能です。

UART拡張機能は下記の通りです。

名称機能
UART_ADVFEATURE_TXINVERTTX論理反転
UART_ADVFEATURE_RXINVERTRX論理反転
UART_ADVFEATURE_DATAINVERTデータビット論理反転
UART_ADVFEATURE_SWAPTX、RX入れ替え
UART_ADVFEATURE_RXOVERRUNDISABLE受信エラー無効
UART_ADVFEATURE_DMADISABLEONERRORDMA受信エラー無効
UART_ADVFEATURE_AUTOBAUDRATEオートボーレート有効
UART_ADVFEATURE_MSBFIRSTMSB有効


UART拡張機能の定義はstm32XX_hal_uart.hで下記のように定義されています。

/*!< No advanced feature initialization */
#define UART_ADVFEATURE_NO_INIT 0x00000000U

/*!< TX pin active level inversion */
#define UART_ADVFEATURE_TXINVERT_INIT 0x00000001U

/*!< RX pin active level inversion */
#define UART_ADVFEATURE_RXINVERT_INIT 0x00000002U

/*!< Binary data inversion */
#define UART_ADVFEATURE_DATAINVERT_INIT 0x00000004U

/*!< TX/RX pins swap */
#define UART_ADVFEATURE_SWAP_INIT 0x00000008U

/*!< RX overrun disable */
#define UART_ADVFEATURE_RXOVERRUNDISABLE_INIT 0x00000010U

/*!< DMA disable on Reception Error */
#define UART_ADVFEATURE_DMADISABLEONERROR_INIT 0x00000020U

/*!< Auto Baud rate detection initialization */
#define UART_ADVFEATURE_AUTOBAUDRATE_INIT 0x00000040U

/*!< Most significant bit sent/received first */
#define UART_ADVFEATURE_MSBFIRST_INIT 0x00000080U


実際に使用する場合はCubeMXで設定するか、下記のコードをUART初期化関数MX_USARTX_UART_Initに追記して使用します。CubeMXで設定する場合は下記のようにUARTの設定項目のAdvanced Featuresから有効/無効を設定します。

uart.jpg

コード上から修正する場合はデフォルトでUART_ADVFEATURE_NO_INITとなっているため、必要な項目を追加して各項目を有効化して使用します。

デフォルト
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;

追加例
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_TXINVERT_INIT | UART_ADVFEATURE_SWAP_INIT;
huart1.AdvancedInit.TxPinLevelInvert = UART_ADVFEATURE_TXINV_ENABLE;
huart1.AdvancedInit.Swap = UART_ADVFEATURE_SWAP_ENABLE;

STM32F7、L4、H7シリーズのみ対応しているのが残念ですが、UART拡張機能の中でもTXとRXの入れ替え機能は非常に便利だと思いました。TXとRXをクロスさせて回路設計することを忘れていたり、クロスさせたはずが回路上で間違えていたり、クロスケーブルがなく、ストレートケーブルしか準備できていなかったり、UARTのTX、RX絡みでよくあるトラブルがソフトウェア上で解決できるのは非常に便利です。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする