ソーマ&るいのマイコン備忘録

マイコン関連の備忘録的なこと

新日本無線(NJR)の神対応

最近では三端子レギュレーターといえばLDOぐらいに普及していますが、低ドロップという特性ゆえのクセのある製品も多いようです。

私自身使用するPICも8ビットから32ビットがメインになり、よって必要な電圧は3.3V、PIC単独の実験であれば4.5V(乾電池×3)からTO-92パッケージで出力電流は100mA程度の簡易なものが使えますが、やれ液晶表示だの音声出力のヘッドホンアンプだのを付けると放熱の余裕を考えて500mA程度の出力が必要になってきます。

ある製作物にNJU7223F33というLDOの採用を検討(秋月電子で一個50円と同クラス最安だったので)したところ、このLDOにはパスコンにセラミックが使えないという情報を発見しました、どういうことなんだろう?とその記事を(URLとか忘れました)見るとデータシートの測定回路には極性のあるコンデンサが使われていて、これはセラミックコンデンサが使用できないことを意味しているという事でした。

今時0.1μの電解コンデンサの入手は難しく(コスト的に)それでは安価なLDOを採用した意味がありません、一個ダメにするつもりで入手容易な積層セラミックと大容量の電解コンデンサで(要するに普通のレギュレーター回路)テストしたところ異常な発振などはありませんでした・・・が、いちおう遊びとはいえ友達に依頼された製作物なので安全性を考慮し、ダメモトでNJRさんにセラコンが使えない理由を問い合わせたところ、なんとデータつきで回答をいただきました。

 

f:id:TDX676BCYA:20191006115944p:plain

NJU7223DL1-33

要するに積層セラミックのような低ESRのコンデンサを使用すると動作が不安定になるので使用不可であるということがわかりました。

メーカーさんによりますと。

「この製品は一世代前の製品であります。

従いまして、セラコン対応等が出来てない製品です。

より使い勝手のよいセラコン対応製品(セラコン対応のNJM2835、NJU7790等)をご使用になることをお勧めします」

ということでした、なるほどです。

単なる一ユーザーに対してこのような親切な対応をしていただきありがとうございました。

 

 

32MM PORTBがMCCP1と競合?

32MM(0064GPL28)で音遊びをしているのですが、PORTBはしっかり0~15まで出ており、その気になればR2RラダーDACなどで16BITPCMサウンドを奏でることも出来ます。

まぁそこまで使わなくてもシンセのOSCなら8Bitでも十分と思い、オシレータの出力にポートBの0~7までリニアに使用。

あと通信用SPIに二本、VCAのEG、VCFのカットオフとレゾナンス にCCP(PWM)をフル活用でマルチ音源化も可能だなぁと夢を膨らませ、オシレーターの音を聞いたらなんかおかしい、歪んでる・・・オシロで波形を確認したらやっぱりヘン、どっかのBITが抜けた状態でした。

もう一度半田付けをチェックしたところちゃんとつながっている、一時的にCVコントロールのデータをDACに流し込んで調べたら、どうやら16の桁(RB4)で0になっている模様、一時的にPORTB4を強制的にON・・・のはずが出力されない・・・。

いろいろ試して半日つぶして原因わからず、なので頭を冷やして翌日ダミーのプロジェクトをMCCで作成していたら気になるところがありました。

MCCP1を使おうとするとRB4がSOSCOとかでロックされてしまいます、DAC以外の入出力はB8以降に並べたかったのでSCCP1の出力をSCCP1のB(RB9)に割り当てたのが間違いだったようです。

とりあえずMCCP1の出力をF(RA1)に割り当てたらRB4が正常に機能しました。

 

プロの技術屋さんに「エラッタシート見れば書いてあるだろwww」と怒られそうな話ではありますが・・・。

 

 

 

TLP2630のバイパスコンデンサ

楽器用インターフェイスMIDIは、グランドループによるノイズ防止のために入出力にフォトカプラ用いて互いを絶縁しています。MIDI信号自体は31250Bpsの非同期という単純なものですが、中途半端な速度のわりに要求するフォトカプラは高速タイプである必要があります。

秋月電子で入手可能な型番で必要な性能を持つTLP2630というデュアルタイプのものを購入したときの事です。

データシートにはしっかり「0.1μのバイパスコンデンサが必要です」と明記されているにもかかわらず、ブレッドボード上で手動でON/OFFする程度の速度なら不要かな?と、取り付けずにチェックしたところまったく動きませんでした。

動作速度にかかわらず、この手の高速タイプには必ず指定されたパスコンをつける必要があるようです。

 

PIC32MM/MXで原因不明の大電力が流れる件

PIC32MM で外部からSPIで周波数を設定できるDDSを作成中に100mA近くの異常な電流が流れていることに気づきました、最高速のクロック(24Mhz)にしてもこれは異常です。出力はPB0~PB9のリニアDACだけですし、不要なピンは全て入力に設定してあります、「ラッチアップでも起こしたのか?」と思って新しいPICに交換したのですが症状は変わりません、取り外してブレッドボードに刺し、電源とコンデンサの最低限の接続をしてみたら正常な電流(約25mA)を示しました、その状態でDACをつないでみても電流はほとんど変わりません、「まさかの入力ピン?」ということでSPIを含め全ての入力においてH(3.3v)をつなぐと大電流が流れることがわかりました、実は基盤を起こしたので、パターンの関係上入力にVDDがつながる箇所があったのです、しかし入力ピンHで大電流が流れるのでは使い物になりません、MCCで何もしない雛形だけ作り直し、入力にVDDをつないでみたら異常な電流は流れませんでした、何が悪いのかサッパリです・・・、でソースをよく見るとMCCで不可解なANSELlの設定があります ANSELA = 0x0002;
ANSELB = 0x400F;

ADCを使うオーダーは一切出していないのになぜかANSELが設定されているのです、自分はこれが気に入らなくて(というかPICで不用意にANSELを設定すると入力ピンが正常に機能しないと記憶していましたが・・・)どちらも0に書き直したんですよね。

結局MCCの作成したとおりに戻したら電流は正常になりました、2週間ほど前にメーカーさんに問い合わせたのですがいまだ回答がありません、(まぁただの一ユーザーですしね)32MXも同じ現象がでます、でもこれは正式なものではありませんのでご参考までに。

 

 

 

ルネサスHpeでリンクエラーが出るときの対処。

ルネサスのHpe(統合環境)でリンクエラー(メモリー割付関連)が出たときの対処です、けっこうわかりづらいのでメモしておきます。

ちなみにこの画像は秋月電子のRX621ボードのものです。

ビルドからRXStandardToolchain...を選びます。

f:id:TDX676BCYA:20180719112449p:plain

 

最適化リンカのセクションから以下の設定画面でそれぞれのアドレスを変更します。

このケースはプログラムではなくてデータ領域が不足してリンク時に'L'(リテラル領域の不足)が起きた場合の例です。

下から二番目に表示されているアドレスがリテラル、その上がプログラムなので、この二箇所のアドレスFFFF5100/FFFF5000 を必要なだけ下げてやります(FFFF4100/FFFF4000)等。

 

f:id:TDX676BCYA:20180719113232p:plain

32MMのADCを使ってみる

MCCで自動生成されたソースをそのまま使ってみたのですが、うまく動かなかったので単純に任意のADCユニットを選択して変換するだけのプログラムを作ってみました。

コンフィグビットやクロックの設定、ポートの設定が完了しているものとして、以下の簡単なプログラムでAD変換することができます。

ADCTrig(delay) のdelayは適当です、24Mhz動作 で20に設定したら動きました。

単純変換の場合、どのADCチャンネルでも変換後の値が入るのはADCxBUF0になります。

 

あと単発メモにもありますが、SCCP1の出力をPORTBに割り当てるとRB4が制御不能になるので特に不自由が無いのであればRAに割り当てたほうが吉です。

 

//ADCユニットの初期化

void ADCInit( void ) {

AD1CON1 = 0x0000;
AD1CON1bits.MODE12 = 1; // 0=10bit 1=12bit
AD1CON2 = 0x0000;
AD1CON3 = 0x000F; // Sample Clock 1:16
AD1CON1bits.ON = 1; // モジュールスタート
}

 

// 変換が終了したか?
int ADCIsDone( void ) {
return AD1CON1bits.DONE; //Wait for conversion to complete
}
// 変換チャンネルを指定
void ADCSetCh( int ch ) {
AD1CHSbits.CH0SA = ch;
}
// 手動トリガ
void ADCTrig( int delay ) {
AD1CON1bits.SAMP = 1;
while( delay --) {
__asm__ volatile ("nop");
}
AD1CON1bits.SAMP = 0;
}

 

 

void RunAdc( void ) {
unsigned short ad0,ad1;

ADCInit();
for ( ;; ) {

ADCSetCh( 0 ); // チャンネル0選択
ADCTrig( 20 ); // アクイジション
while ( !ADCIsDone() ); // 変換終了を待つ
ad0 = ADC1BUF0;

ADCSetCh( 1 ); // チャンネル1選択
ADCTrig( 20 ); // アクイジション
while ( !ADCIsDone() ); // 変換終了を待つ
ad1 = ADC1BUF0;
}
}

PIC32MMのCCP(PWM)を使う

32bitPICの32MM0064GPL28の単純PWM設定です。

コンフィグビットやPLLの設定などはMPLABのMCCで自動的に作成されますのでそちらを利用してください。

8BITマイコンでは単純にPWMと呼んでいたユニットですが32BITマイコンではMCCPとかOCMなどと呼ばれるのでPWM出力が無い?と勘違いしていましたが、32MMにはMCCP1~MCCP3の三つのユニットがあり、そのうち2と3はピン割付可能なピンに出力することが出来ます。

 

具体的にはMCCP1の出力をRA0(ピン2)に(データシートではOCM1Eになっている)。

MCCP2をRP13(ピン24)、MCCP3をRP12(ピン23)に割り付けて見ます。

 

この例では分解能9ビットのPWMをクロック1/4周波数で回していますので、最高動作周波数の24Mhzでは11718Hzになります。

 

ピン割付ですが、不用意な変更を防ぐためにシステムキーの解除が必要になるようです、この処理に関してはMCCが自動作成したソースを流用します。

内容はMPLABのバージョンによって変わる可能性があるので、上記に関しては必ず自動生成されたソースを流用してください。

 

自分でもよくわかっていない部分がありますがCCPXRPとCCPXRBに全体周期-1を設定し(9bit分解能なら 512-1=511)、CCPXRAに0~全体周期の間の値を入れるとDUTYが設定されます、実際には0でdutyが100%になります。

CCPユニット一つに付き、出力端子はA~FまであってCCP1に関しては

CCP1CON2bits.OCEN = 1 として出力端子Eを指定するとRA0に出力されるようなりますが(データシートのピンダイアグラム参照)

CCP2とCCP3の出力はピン割付による指定しか出来なくて、

RPOR3bits.RP13R = 0x0006; // RB13->SCCP2:OCM2 CCP(PWM2)出力

のようにコードで指定するのですが、A~Fのどの端子を指定するとか言うコードは無くて、0x0006がCCP2 0x0007がCCP3という指定になっています、とりあえずは端子Aを許可すると出力されるようです。

 

//
// CCP(PWM)設定
//
void SetCCP( void ) {

 

//
// CCP1の設定
//
CCP1CON1 = 0;
CCP1CON1bits.CLKSEL = 0; // CLK = SYSTEM CLK
CCP1CON1bits.CCSEL = 0; // PWM mode
CCP1CON1bits.T32 = 0; // 16bitTimer
CCP1CON1bits.TMRPS = 1; // Clock/4
CCP1CON1bits.MOD = 5;

CCP1CON2 = 0;
CCP1CON2bits.OCEEN = 1; // PWMパルス出力許可ビット
CCP1CON3 = 0;
CCP1STAT = 0;
//TMRL 0; TMRH 0;
CCP1TMR = 0x0;
// (全体周期/分解能)
CCP1PR = 511;//0x200;
//CMPA 32;
CCP1RA = 256; // Duty
//CMPB 128;
CCP1RB = 511;
//BUFL 0; BUFH 0;
CCP1BUF = 0x0;

CCP1CON1bits.ON = 1; // CCP1 ON

//
// CCP2の設定
//
CCP2CON1 = 0;
CCP2CON1bits.CLKSEL = 0; // CLK = SYSTEM CLK
CCP2CON1bits.CCSEL = 0; // PWM mode
CCP2CON1bits.T32 = 0; // 16bitTimer
CCP2CON1bits.TMRPS = 1; // Clock/4
CCP2CON1bits.MOD = 5;

CCP2CON2 = 0;
CCP2CON2bits.OCAEN = 1; // PWMパルス出力許可ビット
CCP2CON3 = 0;
CCP2STAT = 0;
//TMRL 0; TMRH 0;
CCP2TMR = 0x0;
// (全体周期/分解能)
CCP2PR = 511;//0x200;
//CMPA 32;
CCP2RA = 256; // Duty
//CMPB 128;
CCP2RB = 511;
//BUFL 0; BUFH 0;
CCP2BUF = 0x0;

CCP2CON1bits.ON = 1; // CCP2 ON

//
// CCP3の設定
//
CCP3CON1 = 0;
CCP3CON1bits.CLKSEL = 0; // CLK = SYSTEM CLK
CCP3CON1bits.CCSEL = 0; // PWM mode
CCP3CON1bits.T32 = 0; // 16bitTimer
CCP3CON1bits.TMRPS = 1; // Clock/4
CCP3CON1bits.MOD = 5;

CCP3CON2 = 0;
CCP3CON2bits.OCAEN = 1; // PWMパルス出力許可ビット
CCP3CON3 = 0;
CCP3STAT = 0;
//TMRL 0; TMRH 0;
CCP3TMR = 0x0;
// (全体周期/分解能)
CCP3PR = 511;//0x200;
//CMPA 32;
CCP3RA = 256; // Duty
//CMPB 128;
CCP3RB = 511;
//BUFL 0; BUFH 0;
CCP3BUF = 0x0;

CCP3CON1bits.ON = 1;


}

 

MCCが作成したピン割付やPLL設定時のおまじないルーチン

unlockを呼んだ後必要な設定をして再度lockを掛けます。

 

inline static void SYSTEM_RegUnlock(void) {
SYSKEY = 0x0; //write invalid key to force lock
SYSKEY = 0xAA996655; //write Key1 to SYSKEY
SYSKEY = 0x556699AA; //write Key2 to SYSKEY
}

inline static void SYSTEM_RegLock(void) {
SYSKEY = 0x00000000;
}

 

ピン割付

void SetPinConnect( void ) {

//    ロック解除

SYSTEM_RegUnlock(); // unlock PPS
RPCONbits.IOLOCK = 0;

// ピン割付を行う
RPOR3bits.RP13R = 0x0006; // RB13->SCCP2:OCM2 CCP(PWM2)出力
RPOR2bits.RP12R = 0x0007; // RB12->SCCP3:OCM3 CCP(PWM3)出力

 //    ロック

RPCONbits.IOLOCK = 1; // lock PPS
SYSTEM_RegLock();

}