ロボット工作研究室Wiki - SH-Tiny テクニック/シリアル通信と分割コンパイル
SH-Tiny テクニック


 シリアル通信によってPCとマイコンの間で情報をやりとりできるようになると、PCをマイコンのユーザーインターフェースとして使えるためたいへん便利です。
 また、それとあわせて、プログラムの一部を別のファイルに移動して、読みやすいプログラムを作成する方法も紹介してみます。


※更新が滞っているため、先にサンプルだけ置いておきます。動作未検証。
※スタンバイ解除を忘れていたので修正

シリアル通信

マイコンからの送信

#include "iodefine.h"

void main(void){
    int i;
    
    CPG.FRQCR.WORD = 0x16db;   // Iφ=48MHz
    
    STB.CR3.BIT._SCI1 = 0; //SCI1 モジュールスタンバイ解除
    
    PFC.PACRL3.BIT.PA11MD=0x06;  //TXD0端子に設定
    PFC.PACRL3.BIT.PA10MD=0x06;  //RXD0端子に設定
    
    SCI1.SCSMR.BIT.CA = 0;   //調歩同期式
    SCI1.SCSMR.BIT.CHR = 0;  //データ長8bit
    SCI1.SCSMR.BIT._PE = 0;  //パリティビットなし
    SCI1.SCSMR.BIT.STOP = 0; //ストップビット長1bit
    SCI1.SCSMR.BIT.CKS = 0;  //クロックセレクト Pφ
    
    SCI1.SCBRR = 19;         // 分周比 24MHz -> 38400bps
    
    SCI1.SCSCR.BIT.TE = 1;   //送信許可
    SCI1.SCSCR.BIT.RE = 1;   //受信許可
    
    
    while(!SCI1.SCSSR.BIT.TDRE); //送信バッファが空くまで待つ
    SCI1.SCTDR = 'A';            //'A'(0x41)をセット
    SCI1.SCSSR.BIT.TDRE = 0;     //送信を通知
    
    
    while(1); //無限ループ
}

 以下作成中...
マイコンでの受信

#include "iodefine.h"

//1バイト送信する関数
void putc(const char c) {
    while(!SCI1.SCSSR.BIT.TDRE); //送信バッファが空くまで待つ
    SCI1.SCTDR = c;              //キャラクタをセット
    SCI1.SCSSR.BIT.TDRE = 0;     //送信を通知
}

//1バイト受信する関数
int getc(void) {
    int x;
    while (!(SCI1.SCSSR.BYTE & 0x78)); //受信バッファが埋まるのを待つ
    x = SCI1.SCRDR & 0xff;             ////キャラクタを取得
    SCI1.SCSSR.BYTE &= ~0x78;          // RDRF、エラーフラグも一応0に
    return x;
}

void main(void){
    int i;
    
    CPG.FRQCR.WORD = 0x16db;   // Iφ=48MHz
    
    STB.CR3.BIT._SCI1 = 0; //SCI1 モジュールスタンバイ解除
    
    PFC.PACRL3.BIT.PA11MD=0x06;  //TXD0端子に設定
    PFC.PACRL3.BIT.PA10MD=0x06;  //RXD0端子に設定
    
    SCI1.SCSMR.BIT.CA = 0;   //調歩同期式
    SCI1.SCSMR.BIT.CHR = 0;  //データ長8bit
    SCI1.SCSMR.BIT._PE = 0;  //パリティビットなし
    SCI1.SCSMR.BIT.STOP = 0; //ストップビット長1bit
    SCI1.SCSMR.BIT.CKS = 0;  //クロックセレクト Pφ
    
    SCI1.SCBRR = 19;         // 分周比 24MHz -> 38400bps
    
    SCI1.SCSCR.BIT.TE = 1;   //送信許可
    SCI1.SCSCR.BIT.RE = 1;   //受信許可
    
    
    while(1){
        //送られてきた文字をそのまま送り返す
        putc(getc());
    }
}

 以下作成中...

分割コンパイル

分割コンパイルの基礎
シリアル通信プログラムのモジュール化

 とりあえず送信のみ。
 "sci.c"というファイルと"sci.h"というファイルを作り、プロジェクトフォルダに放り込む。
 [プロジェクト]>[ファイルの追加]メニューから"sci.c"を選択。

"sci.h"の内容

extern void sci_init();
extern void sci_printstr(const char *str);

"sci.c"の内容

#include "iodefine.h"
#include "sci.h"

#define CHAR_NULL 0x00
#define CHAR_CR   0x0d
#define CHAR_LF   0x0a

void sci_init(){
    
    PFC.PACRL3.BIT.PA11MD=0x06;  //TXD0端子に設定
    PFC.PACRL3.BIT.PA10MD=0x06;  //RXD0端子に設定
    
    STB.CR3.BIT._SCI1 = 0; //SCI1 モジュールスタンバイ解除
    
    SCI1.SCSMR.BIT.CA = 0;   //調歩同期式
    SCI1.SCSMR.BIT.CHR = 0;  //データ長8bit
    SCI1.SCSMR.BIT._PE = 0;  //パリティビットなし
    SCI1.SCSMR.BIT.STOP = 0; //ストップビット長1bit
    SCI1.SCSMR.BIT.CKS = 0;  //クロックセレクト Pφ
    
    SCI1.SCBRR = 19;         // 分周比 24MHz -> 38400bps
    
    SCI1.SCSCR.BIT.TE = 1;   //送信許可
    SCI1.SCSCR.BIT.RE = 1;   //受信許可
    
}

void putc(const char c) {
    while(!SCI1.SCSSR.BIT.TDRE); //送信バッファが空くまで待つ
    SCI1.SCTDR = c;              //キャラクタをセット
    SCI1.SCSSR.BIT.TDRE = 0;     //送信を通知
}

//文字列の送信
void sci_printstr(const char *str){
    char d;
    while(*str != CHAR_NULL) {
        d = *str++;
        if(d == '\n'){
            putc(CHAR_CR);
            putc(CHAR_LF);
        }else{
            putc(d);
        }
    }
}

メインソースの内容

#include "iodefine.h"
#include "sci.h"

void main(void){
    int i;
    
    CPG.FRQCR.WORD = 0x16db;   // Iφ=48MHz
    
    sci_init();
    
    sci_printstr("Hello World!\n");
    
    while(1);
}

ビルドが成功すると自動的にヘッダファイルの一覧に"sci.h"が追加される。
メイン文がとてもすっきりしているのがわかる。