STC8G1K08A winziges 349-Byte-UART-Hello-World-Demo
Siehe auch:
- Möchten Sie nur ein einfaches Demo ohne die Größenoptimierung? Siehe STC8G1K08A minimales UART-Hello-World-Demo
In unserem vorherigen Beitrag STC8G1K08A minimales UART-Hello-World-Demo haben wir gezeigt, wie man FwLib_STC8 verwendet, um eine einfache UART-Hello-World-Anwendung für den STC8G1K08A zu schreiben, die nur etwas über 2,2 KB groß ist.
Während dieses Beispiel sehr einfach ist, leidet es unter einem großen Problem im Zusammenhang mit dem SDCC-Funktionsumfang: Zum jetzigen Zeitpunkt unterstützt SDCC nicht das Entfernen ungenutzter Funktionen aus der gelinkten Ausgabe. Das bedeutet, dass wenn Sie irgendeine Funktion aus der UART-Bibliothek verwenden, Sie die gesamte Bibliothek linken, was viel Code-Größen-Overhead hinzufügt.
Um dies zu beheben, können wir den Code inlinen und etwas optimieren.
#include "fw_uart.h"
/* Keep the baud rate in one place so the Timer1 reload formula stays obvious. */
#define UART1_BAUD_RATE 115200UL
/* Reproduce the library's SYSCLK calculation without calling any runtime code. */
#define UART1_SYSCLK_HZ (__CONF_FOSC / ((__CONF_CLKDIV == 0) ? 1UL : (unsigned long)__CONF_CLKDIV))
/* UART1 mode 1 uses Timer1 overflow divided by four as its baud-rate clock. */
#define UART1_TIMER1_RELOAD (65536UL - (UART1_SYSCLK_HZ / (4UL * UART1_BAUD_RATE)))
/* Keep the entire message in one memory area so the library can stream it out. */
static unsigned char uart_message[] = "Hello, world from UART1!\r\n";
static void UART1_SendString(unsigned char *str)
{
while (*str)
{
SBUF = *str++;
TI = 0;
while (!TI)
{
}
}
}
#define TICKS_MS (__CONF_FOSC / ((__CONF_CLKDIV == 0) ? 1UL : (unsigned long)__CONF_CLKDIV) / 9000UL)
static void delay_ms(unsigned int ms)
{
unsigned int i;
do
{
i = TICKS_MS;
while (--i)
{
}
} while (--ms);
}
static void UART1_Init(void)
{
/*
* Open the extended SFR bank so we can write CLKDIV before bringing UART1 up.
* B7 = 1: enable access to the extended SFR region.
* B6..B0 = 0: leave the other bank-switching and peripheral-routing controls unchanged.
*/
P_SW2 = 0x80;
/* Apply the configured clock divider with a direct whole-register write. */
CLKDIV = __CONF_CLKDIV;
/*
* Return to the normal SFR bank now that the clock divider is programmed.
* B7 = 0: disable extended SFR access again.
* B6..B0 = 0: keep the remaining P_SW2 controls inactive in this minimal demo.
*/
P_SW2 = 0x00;
/*
* Select the high-speed internal RC oscillator band that the trim values were tuned for.
* 0x03 keeps only IRCBAND[1:0], which are the band-select bits.
* Any upper bits in the configuration value are discarded so we only touch the documented band field.
*/
IRCBAND = (__CONF_IRCBAND & 0x03);
/* Load the matching voltage trim byte for that RC band. */
VRTRIM = __CONF_VRTRIM;
/* Load the high-speed RC fine-trim byte. */
IRTRIM = __CONF_IRTRIM;
/*
* Load the low-speed RC trim field even though this demo runs from the fast internal clock.
* 0x03 keeps only LIRTRIM[1:0], which are the valid low-speed trim bits.
* Any upper bits are forced low so we do not write undefined values into that register.
*/
LIRTRIM = (__CONF_LIRTRIM & 0x03);
/*
* Put UART1 into the standard 8-bit asynchronous mode and allow the receiver to run.
* 0x50 = 0101 0000b.
* SM0 = 0, SM1 = 1: select UART mode 1, the usual 8-bit UART with variable baud rate.
* SM2 = 0: disable multiprocessor address filtering, so every received byte is accepted.
* REN = 1: enable the UART receiver.
* TB8 = 0, RB8 = 0: ninth-bit transmit/receive state starts cleared because mode 1 does not use it.
* TI = 0, RI = 0: clear both transmit and receive status flags before the first character.
*/
SCON = 0x50;
/*
* Configure Timer1 as the baud-rate generator that UART1 will count from.
* 0x40 = 0100 0000b.
* B6 = 1: run Timer1 in 1T mode so it increments every system clock instead of every 12 clocks.
* B0 = 0: keep UART1's baud source on Timer1 rather than switching it to Timer2.
* B5..B1 = 0: leave the unrelated AUXR features disabled in this demo.
*/
AUXR = 0x40;
/*
* Put Timer1 into the reload mode expected by the FwLib UART code path.
* 0x00 = 0000 0000b.
* GATE1 = 0: Timer1 starts and stops only from TR1, not from the external INT1 pin.
* C/T1 = 0: Timer1 counts clock ticks, not external events.
* M1_1 = 0, M0_1 = 0: select the Timer1 mode that this STC8 library uses for UART baud generation.
* The Timer0 half of TMOD is also cleared because this demo does not use Timer0.
*/
TMOD = 0x00;
/* Load the high byte of the compile-time Timer1 reload value. */
TH1 = (unsigned char)(UART1_TIMER1_RELOAD >> 8);
/* Load the low byte so the very first overflow already uses the right baud rate. */
TL1 = (unsigned char)(UART1_TIMER1_RELOAD & 0xFF);
/* Start Timer1 so UART1 can derive its bit timing. */
TR1 = 1;
}
void main(void)
{
/* A zero-initialized unsigned loop variable gives a compact full-range delay. */
unsigned int settle = 0;
UART1_Init();
/* Hand the whole NUL-terminated message buffer to the local string transmit helper. */
while (1)
{
UART1_SendString(uart_message);
delay_ms(1000);
}
}Wie man flasht
Siehe unseren Beitrag Wie man STC8G1K08A mit stcgal flasht
Wie man die serielle Ausgabe überprüft
Überprüfen Sie die Ausgabe mit
picocom -b 115200 /dev/ttyUSB0Speichernutzung
===== Memory usage summary for uart_minimal_size_demo =====
Internal RAM layout:
0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00:|0|0|0|0|0|0|0|0|S|S|S|S|S|S|S|S|
0x10:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x20:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x30:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x40:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x50:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x60:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x70:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x80:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x90:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xa0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xb0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xc0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xd0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xe0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xf0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0-3:Reg Banks, T:Bit regs, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack, A:Absolute
Stack starts at: 0x08 (sp set to 0x07) with 248 bytes available.
No spare internal RAM space left.
Other memory:
Name Start End Size Max
---------------- -------- -------- -------- --------
PAGED EXT. RAM 0 256
EXTERNAL RAM 0x0001 0x0020 32 1024
ROM/EPROM/FLASH 0x0000 0x015c 349 8192
==========================================================mit SDCC 4.2.0 #13081 - 349 Bytes Flash sind eine enorme Verbesserung gegenüber den 2,2 KB des vorherigen Beispiels.
Beachten Sie, dass Sie individuell wählen können, ob Sie nur FwLib-Funktionen in Ihr Projekt kopieren (die liberalen Apache-Lizenzbedingungen von FwLib_STC8 erlauben dies, aber Sie müssen möglicherweise die Urheberrechtserklärung beibehalten), oder sie insgesamt “inlinen”, um den Code noch mehr zu komprimieren. In unserem obigen Code haben wir uns für eine Mischung aus beidem entschieden.