シリアル通信

パソコン等と通信を行うためには、マイコンとは別にRS-232ドライバ/レシーバと呼ばれるICが必要です。
これは、マイコン内部の電圧(3V~5V)と、RS-232通信規格で決まっている電圧(±9V)が異なるので、
電圧変換(レベル変換と言う)を行うためです。

RS-232ドライバ/レシーバ

ここで記述するシリアル通信プログラムは、UART割り込みを使用します。
SH2マイコン等では、SCI(シリアルコミュニケーションインタフェース)と呼んでいましたが、
R8C/15では、UARTと呼んでいます。

HEWの場合、ベクタアドレス関係は、「sect30.inc」ファイルに記述します。
(割り込み番号は、ハードウェアマニュアルp73参照)
「sect30.inc」ファイルの「variable vector section」の記述を下記の通り変更します。



.lword dummy_int ; vector 16
.glb _uart0_t
.lword _uart0_t ; vector 17 UART0 transmit
.glb _uart0_r
.lword _uart0_r ; vector 18 UART0 receive
.lword dummy_int ; vector 19



では、実際のプログラムを記述します。
通信速度は、マイコンのクロックに影響されますが、ここでは先に示した内臓高速オンチップオシレータにより
8MHzで駆動していることを前提とします。

ポイントは、連続的にバッファ空割り込みを使ってデータを転送するときの2個目のデータをセットするタイミングです。
バッファ空割り込みは、バッファに書き込んだデータが、実際に転送するレジスタに読み込まれたときに発生するもので、
転送中のデータを送り終わる前にバッファにデータをセットすることで次々に絶えずデータを送ることができる便利な機能です。
しかし、まず最初のデータをバッファに書き込まないと、割り込み自体が発生しないなんて不便な部分もあります。
連続転送の手順は以下の通りです。

1つ目のデータを直接バッファに書き込む。
と、ここで、1つ目のデータがバッファから転送用レジスタに送られるのを待つ。
2つ目のデータも直接バッファに書き込む。
3つ目のデータからは、FIFO配列に保存する。
1つ目のデータが転送終了、バッファにある2つ目のデータが転送用レジスタに格納、割り込み発生。
割り込み処理で、3つ目以降のデータを順次バッファに書き込めはOK。



/* UART0初期化 */
uart_init(38400, 8, 0, 1); // bps,bit,parity,stopBit
asm("FSET I"); // 全体の割り込み許可

/* キャラクタコードでのエコーバック */
while(1){
data = uart_getc(); /* 1文字受信 */
if ( 0 <= data ) {
uart_put_char_hex((unsigned char)data); /* 数値送信 */
uart_putc((unsigned char)0x0d); /* CR */
uart_putc((unsigned char)0x0a); /* LF */
}
}



/************************************************************************/
/* */
/* 通信処理プログラム */
/* */
/* CPU TYPE :R8C/Tiny 15Group (8MHz) */
/* Copyright :西 憲一郎 */
/* */
/************************************************************************/
// 注)9ビット転送には対応していません

#define BUFF_SIZE 256
typedef struct {
unsigned short len;
unsigned short read;
unsigned short write;
unsigned char *buff;
} FIFO;
static unsigned char rxbuff[BUFF_SIZE];
static unsigned char txbuff[BUFF_SIZE];
static FIFO rxfifo;
static FIFO txfifo;

/****************************************/
/* UART0 初期化 */
/****************************************/

#define PCLOCK (8000000)
uart_init(
unsigned short bps, /* 1200~51200 */
unsigned char bit, /* 7 or 8 */
unsigned char parity, /* 0:なし 1:奇数 2:偶数 */
unsigned char stopBit ) /* 1 or 2 */
{
/* RX FIFO */
rxfifo.len = 0;
rxfifo.read = 0;
rxfifo.write = 0;
rxfifo.buff = rxbuff;

/* TX FIFO */
txfifo.len = 0;
txfifo.read = 0;
txfifo.write = 0;
txfifo.buff = txbuff;

if(bit == 7) {
smd2_u0mr = 1; // 調歩7bit(p140)
smd1_u0mr = 0;
smd0_u0mr = 0;
} else {
smd2_u0mr = 1; // 調歩8bit
smd1_u0mr = 0;
smd0_u0mr = 1;
}

if(stopBit == 2) {
stps_u0mr = 1; // 2ストップビット
} else {
stps_u0mr = 0; // 1ストップビット
}

if(parity == 0) {
prye_u0mr = 0; // パリティ禁止
} else {
prye_u0mr = 1; // パリティ許可
if(parity == 1) {
pry_u0mr = 0; // 奇数パリティ
} else {
pry_u0mr = 1; // 偶数パリティ
}
}

ckdir_u0mr = 0; // 内部クロック

u0c0 = 0x00; // f1で8MHz、CMOS出力、LSBファースト
u0c1 = 0x07; // 受信許可、送信許可
ucon = 0x00; // 送信バッファ空で割り込み、連続受信禁止

u0brg = ((PCLOCK / 16) / bps) - 1; // bps設定

/* 割り込み開始 */
s0ric = 0x04; // 受信割り込み(レベル4)(p74)
s0tic = 0x04; // 送信割り込み(レベル4)
}

/****************************************/
/* 数値出力 */
/****************************************/

short uart_put_char_hex(
unsigned char data )
{
char hex;

hex = data>>4;
hex &= 0x0F;
if ( hex<10 ) {
hex += 0x30;
} else {
hex += 55;
}
uart_putc(hex);

hex = data;
hex &= 0x0F;
if ( hex<10 ) {
hex += 0x30;
} else {
hex += 55;
}
uart_putc(hex);

}

short uart_put_short_dec(
unsigned short data )
{
char dec;

dec = data/10000;
data = data%10000;
dec += 0x30;
uart_putc(dec);

dec = data/1000;
data = data%1000;
dec += 0x30;
uart_putc(dec);

dec = data/100;
data = data%100;
dec += 0x30;
uart_putc(dec);

dec = data/10;
data = data%10;
dec += 0x30;
uart_putc(dec);

dec = data;
dec += 0x30;
uart_putc(dec);
}

/****************************************/
/* 1文字格納 */
/****************************************/

short uart_putc(
unsigned char data )
{
short ret;
short i;

ret = -1;

s0tic = 0x00; // 送信割り込み禁止

if(ti_u0c1 == 1) { // 送信バッファレジスタが空なら直接書き込む
ret = data;
u0tb = ret; // データ送信
for( i=0; i<10; i++){} // タイミング調整
} else {
if ( BUFF_SIZE > txfifo.len ) {
txfifo.buff[txfifo.write] = data; // バッファへ書き込み

txfifo.len++;
txfifo.write++;
if ( BUFF_SIZE <= txfifo.write ) {
txfifo.write = 0;
}
ret = data;
}
else {
}
}

s0tic = 0x04; // 送信割り込み許可

return (ret);
}

/****************************************/
/* 1文字取得 */
/****************************************/

short uart_getc()
{
short data;

data = -1;

s0ric = 0x00; // 受信割り込み禁止

if ( 0 != rxfifo.len ) {
data = rxfifo.buff[rxfifo.read]; // バッファから読み出し

rxfifo.len--;
rxfifo.read++;
if ( BUFF_SIZE <= rxfifo.read ) {
rxfifo.read = 0;
}
}

s0ric = 0x04; // 受信割り込み許可

return (data);
}

/****************************************/
/* 受信割り込み */
/****************************************/

#pragma interrupt uart0_r // 受信割り込み処理関数指定
void uart0_r(void)
{
unsigned short data; // u0rbレジスタは必ず16ビット単位で読み出す

data = u0rb; // データ取得
data &= 0x00ff;

if ( BUFF_SIZE > rxfifo.len ) {
rxfifo.buff[rxfifo.write] = data; // バッファへ書き込み

rxfifo.len++;
rxfifo.write++;
if ( BUFF_SIZE <= rxfifo.write ) {
rxfifo.write = 0;
}
}
}

/****************************************/
/* 送信割り込み */
/****************************************/

#pragma interrupt uart0_t // 割り込み処理関数指定
void uart0_t(void)
{
unsigned short data;

if ( 0 < txfifo.len ) {
data = txfifo.buff[txfifo.read]; // バッファから読み出し

txfifo.len--;
txfifo.read++;
if ( BUFF_SIZE <= txfifo.read ) {
txfifo.read = 0;
}
u0tb = data; // データ送信
}
else {
}
}



(○ルファプ○ジェクト社の7046用サンプルプログラムを参考にさせて頂きました)


© Rakuten Group, Inc.