STC8G1K08Aでprintf(SDCC)を実行することができましたのでメモします。

printfとなっていますが、今回は、メモリを節約するうえで、printf_tinyとなっています。"...”文での表示や、int定数のHEX、DEC表示が行えます。

シリアル通信を行う上で、 通信方法を確認しておきます。
通信速度は38400bps、8ビット、1ストップビット、ノンパリティーとします。

原発振は、書き込みの際にstcgalで指定している -t 22118.4(22.1184MHz)です。
これをCLKDIVレジスタで1/2に設定することにより、SYSCLKは 11.059200MHzになります。

シリアルクロックの設定は、タイマー1を使用し、8ビット自動リロードモードに設定します。
タイマーのカウント値は T1=256-(SYSclk/(32*bandrate))=256-11059200/(32*38400)=256-9=247
HEX表示にしてT1=247=0xf7となります。

また、xdata領域の書き換えは、P_SW2に0x80を設定する必要があります

これらの情報によりuartのイニシャライズルーチンは下記のようになります。

// uart 初期化
void uart_init(void) {
	
  P_SW2 = 0x80;
  CLKDIV = 0x02;	//システムクロック分周値を 1/2にセット
  P_SW2 = 0x00;
	
  AUXR = 0xc0;	//SYSCLK/1 timer0 or timer1 clock souce 
    SCON  = 0x50;   //UARTはモード1に設定、受信イネーブル
					//SCON=01010000B
    TMOD |= 0x20;   //タイマー1を8ビット自動リロードモードに設定
					//TMOD=00100000B
    TH1   = 0xf7;   //タイマーカウンターセット
  TL1	  = 0xf7;
    TR1   = 1;      // タイマー1スタート

}

1文字シリアル出力は、SBUFに出力する文字を設定し、SCONのTIビットが1になるまでループする。

// 1文字シリアル出力
int putchar(int data) {
	TI = 0;			//SCONのTI(1bit目)をケリア
	SBUF = data;	//dataからSBUFバッファーに格納
	while (!TI);	//SCONのTI(1bit目)が"1"なるまでループ
	return data;
}

同様に1文字入力は、SCONのRIが1になったら、SBUFからデータを読み込む。

// 1文字シリアル入力
int getchar(void) {
    while (!RI);     //SCONのRI(0bit目)が"1"なるまでループ
    RI = 0;          //SCONのRI(0bit目)をクリア
    return SBUF;     // 受信データ返却
}

putchar関数ができたら、printf関数が使用できます。今回はprintf_tiny関数を使用します。

void main(void)		//main関数
{
	P3M0 = 0x00;	//P3ポートを準双方向モードに
	P3M1 = 0x00;
	P5M0 = 0x00;	//P5ポートを準双方向モードに
	P5M1 = 0x00;	
	
	int	i;
	uart_init();
	printf_tiny("STC8G1K08A Uart communication Test !\r\n");
	i = 1000;
	printf_tiny("i(DEC)=%d i(HEX)=%x 1000+i= %d \r\n",i,i,1000+i);
	putchar('>');
	while(1)
		putchar(getchar());
}

全体のプログラムは下記のとおりです。

// STC8G1K08A printf SDCC
//
// STC8G1K08A   MPU
// Flash ROM 8Kbyte
// RAM       1Kbyte
// 
// SDCC 4.0.0
//
// file name STC8G1K08A_printf.c
// $ sdcc -mmcs51 --model-small --xram-size 0x400 --xram-loc 0x0000 --code-size 0x2000 STC8G1K08A_printf.c
// $ packihx STC8G1K08A_printf.ihx > STC8G1K08A_printf.hex
// $ stcgal -P stc8g -t 22118.4 -p /dev/ttyUSB0 STC8G1K08A_printf.hex
//

#include <8052.h>
#include <stdio.h>

//xdata アドレスセット
#define CLKDIV (*(unsigned char volatile __xdata *)0xfe01)

//BYTE 指定可能なレジスター
__sfr __at  0x8e AUXR  ;
__sfr __at  0xba P_SW2  ;

__sfr __at  0xb2 P3M0  ;    
__sfr __at  0xb1 P3M1  ;    
__sfr __at  0xca P5M0  ;    
__sfr __at  0xc9 P5M1  ;


// uart 初期化
void uart_init(void) {
    
    P_SW2 = 0x80;
    CLKDIV = 0x02;  //システムクロック分周値を 1/2にセット
    P_SW2 = 0x00;
    
    AUXR = 0xc0;    //SYSCLK/1 timer0 or timer1 clock souce 
    SCON  = 0x50;   //UARTはモード1に設定、受信イネーブル
                    //SCON=01010000B
    TMOD |= 0x20;   //タイマー1を8ビット自動リロードモードに設定
                    //TMOD=00100000B
    TH1   = 0xf7;   //タイマーカウンターセット
    TL1   = 0xf7;
    TR1   = 1;      // タイマー1スタート

}

// 1文字シリアル出力
int putchar(int data) {
    TI = 0;         //SCONのTI(1bit目)をケリア
    SBUF = data;    //dataからSBUFバッファーに格納
    while (!TI);    //SCONのTI(1bit目)が"1"なるまでループ
    return data;
}

// 1文字シリアル入力
int getchar(void) {
    while (!RI);     //SCONのRI(0bit目)が"1"なるまでループ
    RI = 0;          //SCONのRI(0bit目)をクリア
    return SBUF;     // 受信データ返却
}
void main(void)     //main関数
{
    P3M0 = 0x00;    //P3ポートを準双方向モードに
    P3M1 = 0x00;
    P5M0 = 0x00;    //P5ポートを準双方向モードに
    P5M1 = 0x00;    
    
    int i;
    uart_init();
    printf_tiny("STC8G1K08A Uart communication Test !\r\n");
    i = 1000;
    printf_tiny("i(DEC)=%d i(HEX)=%x 1000+i= %d \r\n",i,i,1000+i);
    putchar('>');
    while(1)
        putchar(getchar());
}

コンパイルします。

$ sdcc -mmcs51 --model-small --xram-size 0x400 --xram-loc 0x0000 --code-size 0x2000 STC8G1K08A_printf.c

SDCCが吐き出すヘキサコード(ihx)をインテルヘキサコード(hex)に変換します。

$ packihx STC8G1K08A_printf.ihx > STC8G1K08A_printf.hex
packihx: read 29 lines, wrote 46: OK.

STC8G1K08Aへ書き込みします。
STC8G1K08Aの電源をOFFにしてから、stcgalを起動し、電源をONしたほうが、書き込みが確実でした。

$ stcgal -P stc8g -t 22118 -p /dev/ttyUSB0 STC8G1K08A_printf.hex
Waiting for MCU, please cycle power: done
Target model:
  Name: STC8G1K08A-8PIN
  Magic: F794
  Code flash: 8.0 KB
  EEPROM flash: 4.0 KB
Target frequency: 22.123 MHz
Target BSL version: 7.3.13U
Target wakeup frequency: 36.800 KHz
Target ref. voltage: 1185 mV
Target mfg. date: 2024-07-01
Target options:
  reset_pin_enabled=False
  clock_gain=high
  watchdog_por_enabled=False
  watchdog_stop_idle=True
  watchdog_prescale=64
  low_voltage_reset=False
  low_voltage_threshold=2
  eeprom_erase_enabled=True
  bsl_pindetect_enabled=False
  por_reset_delay=long
  rstout_por_state=high
  uart1_remap=False
  uart2_passthrough=True
  uart2_pin_mode=push-pull
  epwm_open_drain=True
  program_eeprom_split=8192
Loading flash: 613 bytes (Intel HEX)
Target frequency: Target 22.118 MHz
Adjusted frequency: 22.130 MHz(0.056%)
Switching to 115200 baud: done
Erasing flash: done
Writing flash: 1088 Bytes [00:00, 6844.23 Bytes/s]
Finishing write: done
Setting options: done
Target UID: F794C4161F25D0
Disconnected!

GUI(グラフィカルユーザーインターフェース)ベースのgtktermを起動します。
($ sudo apt-get install gtkterm でインストールします)
ラズベリーのマークから、アクセサリー → Serial port terminal
configuration → port
port: /dev/ttyUSB0
Band Rate: 38400
でOKキー

STC8G1K08Aの電源をOFFにしてから、再度ONすれば
下記のメーセージが出力され、任意のキーがエコーバックされたらOKです。

STC8G1K08A Uart communication Test !
i(DEC)=1000 i(HEX)=3E8 1000+i= 2000 
>asdfg
おすすめの記事