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