N76E003 C-Kurs
In letzter Zeit habe ich sehr viel Zeit verschwendet, weil ich nie
richtig C gelernt habe. Jetzt habe ich angefangen, ein Buch zur
Einführung zu lesen: C programmieren von Anfang an, von Helmut
Erlenkötter, rororo, 25. Auflage Juli 2019. Das Buch gibt es schon seit
20 Jahren, und es ist immer weiter gepflegt worden. Das Lesen hat mir
so viel Freude gemacht, dass ich unbedingt etwas testen wollte. Aber
darf es auch mit dem N76E003 sein? Dann hätte die Sache einen doppelten
Nutzen. Ich würde nicht nur C lernen, sondern gleich auch testen, wie
kompatibel SDCC mit dem Standard-C ist.
Der erste Test war erfolgreich! Das Startbeispiel habe ich in JFE
eingegeben. Das erste Beispiel aus dem Buch sieht so aus:
#include <stdio.h>
/* bsp10001.c /02.c */
main()
{
printf ("\nDies ist ein erstes C-Programm.\n");
printf ("\nWie Sie sehen, kann 'printf' ");
printf ("nicht nur Text drucken,\n");
printf ("\sondern auch rechnen.\n\n");
printf ("13 * 7 = %i \n", 13 * 7);
}
Zusätzlich muss natürlich noch das hardwarenahe Zeug wie getchar und
purchar dabei sein. Und ich muss die Ports einrichten und am Ende noch
while(1); einfügen, weil der Controller sonst kein Ende findet.
#include <N76E003.h>
#include <stdio.h>
void InitUART0_Timer1(long Baudrate);
char getchar(void);
void putchar(char);
void delay(void);
void main(void)
{
P0M1=0;P0M2=0;P1M1=0;P1M1=0;
InitUART0_Timer1(9600);
/* bsp10001.c /02.c */
printf ("\nDies ist ein erstes C-Programm.\n");
printf ("\nWie Sie sehen, kann 'printf' ");
printf ("nicht nur Text drucken,??/n");
printf ("\sondern auch rechnen.??/n??/n");
printf ("13 * 7 = %i \n", 13 * 7);
while (1);
}
void InitUART0_Timer1(long Baudrate) //T1M = 1, SMOD
= 1
{
SCON =
0x50; //UART0 Mode1,REN=1,TI=1
TMOD |= 0x20;
//Timer1 Mode1
PCON |=
128; //SMOD = 1 UART0 Double
Rate Enable
CKCON
|=16; //set_T1M
T3CON &=
~64; //BRCK = 0 Serial port 0
baud rate clock source = Timer1
TH1 = 256 -
(1000000/Baudrate+1);
/*16 MHz */
TR1 = 1;
TI =
1;
//For printf
}
char getchar(void)
{
char c;
while (!RI);
c = SBUF;
RI = 0;
return (c);
}
void putchar(char c)
{
while (!TI);
TI = 0;
SBUF = c;
}
void delay(void)
{
int i,j;
for(i=0;i<0xff;i++)
for(j=0;j<0xff;j++);
}
Das zweite Beispiel behandelt die sogenannten Trigraphs: Statt \n kann
man auch schreiben: ??/n. Sowas habe ich noch nie gesehen. Es wurde
wohl auch nur verwendet, wenn irgendwelche alten Rechner den Backslash
nicht auf der Tatstatur hatten. Aber es wird hier immer noch
unterstützt wie das Beispiel zeigt. SDCC kennt die Schreibweise und behandelt sie korrekt.
Bei diesen Escapesequenzen geht es um
den Zeilenumbruch. Dazu wird ein Byte 10 gesendet. Andere meinen, es
sollte eine 13 sein, wieder andere wollen beides. Bei verschiedenen
Tests mit unterschiedlichen Terminalprogrammen schnitt der Serielle
Monitor in der Arduino-IDE am besten ab. Das soll also jetzt immer mein
Monitor sein.
Beim dritten Beispiel im Buch geht es darum, dass man mit nur einem
printf gleich zwei ganze Zeilen mit Platzhaltern und Rechnungen
ausgeben kann. Ich mache das jetzt immer so, dass ich das alte main
stehenlasse und leicht umbenenne. Davor kommt dann die neue main. Damit
spare ich Arbeit, weil der Dateiname gleich bleibt, keine neue Datei
erzeugt werden muss und ich kein neues ihx in den Brenner eingeben
muss. Die Faulheit siegt ....
void main(void)
{
P0M1=0;P0M2=0;P1M1=0;P1M1=0;
InitUART0_Timer1(9600);
/* bsp10003.c */
printf ("\nJetzt rechne ich: \n");
printf ("3 + 2 = %i\n3 - 2 = %i\n", 3 + 2, 3 - 2);
printf ("12 * 3 = %i\n", 12 * 3);
printf ("12 / 3 = %i\n", 12 / 3);
while (1);
}