PIC18F14K50のEUSARTで自動baudレート検出を行ってみます。

 

使用するのは、秋月通商のPIC18F14K50使用USB対応超小型マイコンボードです。

 

上記のボードに「PIC16F1827とPIC18F14K50のUSART接続」のところで紹介しました「Device-CDC-SerialEmulator」のソフトが入っています。

 

試験では、上記のボードのTXとRXを直接接続して(実機にはレベル変換のトランジスタが入っていますが5Vで動作させるのでトランジスタは無くても大丈夫です)TeraTermで接続し、キーボードから入力した文字がそのまま表示されることを確認します。

 

現在の設定

 

EUSART関連の設定をメモしておきます。(関係無いところもあるかも)

CONFIGURATION

  CPUDIV = NOCLKDIV システムクロックを分周しない

  USBDIV = OFF プライマリオシレータから直接USBクロックを受け取る

  FOSC = IRC 内部RCオシレータ

  PLLEN = ON 4xPLLオン

InitializeSystem

  ADCON1 |= 0x0F;

InitializeUSART

  unsigned char c;

  ANSELH = 0;

  OSCCON = 0b01110000; //内部クロック16MHz

  UART_TRISRx = 1;

  UART_TRISTx = 0;

  RCSTA = 0b10010000; //Single Character RX

    SPEN=1,RX9=0,SREN=0,CREN=1,ADDEN=0,FERR=0,OERR=0,RX9D=0

  TXSTA = 0b00100100; //TX enable BRGH = 1

    CSRC=0,TX9=0,TXEN=1,SYNC=0,SENDB=0,BRGH=1,TRMT=0,TX9D=0

  BAUDCON = 0x08; //BRG16 = 1

    ABDOVF=0,RCIDL=0,DTRXP=0,CKTXP=0,BRG16=1,-,WUE=0,ABDEN=0

  SPBRGH = 1; //64MHz 57600baud H8-3069に合わせて57600baudに変更しています。

  SPBRG = 21;

  c = RCREG; //読み込み

 

オシレータモジュールのデータシートを見ていると64MHzと考えられるようになってきました。

上の計算で57600baudでTeraTermの読み書きが出来たのが不思議ですが…

 

で、PIC18F14K50では、USBをフルスピード48MHzで動作させるための内部オシレータがない!

しかも、内部オシレータの最高周波数は32MHzまで。

ん?でも、私の手元にあるのはPIC18F14K50単品ではなく、PIC18F14K50使用USBマイコンボード。

 

ここでボードの説明書を見て納得

秋月のPIC18F14K50使用USB対応超小型マイコンボードにはOSC1に12MHzのクリスタルが接続されていました。

(気付くのが遅い 前、回路を組んだ時に気付けよ 私)

 

ということで、システムクロックを

 FOSC=HS

 4xPLLオン

 CPUDIV<1:0>=00

で48MHzにします。

 

EUSART非同期モードのbaudレート表を見てみると

 SYNC=0 TXSTAのbit4

 BRGH=0 TXSTAのbit2

 BRG16=1 BAUDCONのbit3

で300baud~115.2kbaudまで対応出来そうです。(この考え方間違ってないかな?)

取り敢えず、57.6kbaudで試してみます。

 SPBRGH:SPBRG=51(10進)

 

MPLAB X IDEで「Clean and Build Main Project」実行

ボードを書き込みモードにして「USB Bootloader」を起動

上で作成したhexファイルを流し込みます。

 

ボードを実行モードに戻してUSBを接続

TeraTermを起動してボーレートを57600に設定

何かキーボード入力してみる。

 

次に、TeraTermのボーレートを115200に変更

何か入力してみる。

 

あら不思議。どちらもきちんと表示されました。

結局、110~921600まで全てきちんと表示されました。

 

ということで、main.cのプログラムを確認

「Device-CDC-SerialEmulator」には自動baudレート検出プログラムが入っていました。

 

/******************************************************************************
 * Function:        void mySetLineCodingHandler(void)
 *
 * PreCondition:    USB_CDC_SET_LINE_CODING_HANDLER is defined
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This function gets called when a SetLineCoding command
 *                  is sent on the bus.  This function will evaluate the request
 *                  and determine if the application should update the baudrate
 *                  or not.
 *
 * Note:           
 *
 *****************************************************************************/
#if defined(USB_CDC_SET_LINE_CODING_HANDLER)
void mySetLineCodingHandler(void)
{
    //If the request is not in a valid range
    if(cdc_notice.GetLineCoding.dwDTERate.Val > 115200)
    {
        //NOTE: There are two ways that an unsupported baud rate could be
        //handled.  The first is just to ignore the request and don't change
        //the values.  That is what is currently implemented in this function.
        //The second possible method is to stall the STATUS stage of the request.
        //STALLing the STATUS stage will cause an exception to be thrown in the
        //requesting application.  Some programs, like HyperTerminal, handle the
        //exception properly and give a pop-up box indicating that the request
        //settings are not valid.  Any application that does not handle the
        //exception correctly will likely crash when this requiest fails.  For
        //the sake of example the code required to STALL the status stage of the
        //request is provided below.  It has been left out so that this demo
        //does not cause applications without the required exception handling
        //to crash.
        //---------------------------------------
        //USBStallEndpoint(0,1);
    }
    else
    {
        //Update the baudrate info in the CDC driver
        CDCSetBaudRate(cdc_notice.GetLineCoding.dwDTERate.Val);
       
        //Update the baudrate of the UART
        #if defined(__18CXX) || defined(__XC8)
        {
            DWORD_VAL dwBaud;
            dwBaud.Val = (DWORD)(GetSystemClock()/4)/line_coding.dwDTERate.Val-1;
            SPBRG = dwBaud.v[0];
            SPBRGH = dwBaud.v[1];
        }
    }
}
#endif

 

mySetLineCodingHandler(void)という関数でSPBRGとSPBRGHの値を書き換えているようです。

mySetLineCodingHandlerという関数はUSB_CDC_SET_LINE_CODING_HANDLERが有効なときに実行可能になるようです。

そして、USB_CDC_SET_LINE_CODING_HANDLERはusb_config.hにありました!

では、mySetLineCodingHandlerの呼び出し元はどこか。main.cにはありませんでした。あせる

Overviewによると、バスにSetLineCodingコマンドが送られたら実行されるとか。

usb_config.hがインクルードされると自動ボーレート変換が標準で付いてくるという認識で良いのかな?

115200baudより高い周波数には対応してないのかな?

必要に迫られたらもっと深く掘り下げます。 汗

 

MENUに戻る