Exploring STC MCU Part 3 – Samples, bugs, and the first lines of code

I am digging deeper into the STC 8051 ecosystem by attempting to write my first bits of actual code on this platform. This experiment took me a few days to execute as I need to wrestle a few bugs along the way, and ended up getting me ordering a few samples from STC directly.

Wrestling the bootloader bug

By the end of the last part, I discovered a bug with IAP15W4K61S4: it won’t start running my own code and stuck in the bootloader no matter what I try. Running the code through the debugger works though.

It will take me a few more days before I can figure out the reason behind the bug. Meanwhile I will keep in contact with STC and update them with the status of the bug.

Close-up shot of IAP15F2K61S2.
Close-up shot of IAP15F2K61S2.

This bug also forced me to make a change in this experiment: I will use the older but better proved chip IAP15F2K61S2 as the experiment chip instead. IAP15F2K61S2 comes with the following features:

  • The same 1-clock 8051 core as IAP15W4K61S4, 28MHz maximum clock speed
  • 2kB onboard RAM (256B IRAM, 1792B XRAM), 61kB onboard unified Flash ROM
  • 3 timers
  • 2 UARTs
  • SPI Master
  • 3 Capture/Compare/PWM controllers independent of 8051 timers
  • 10-bit 8-channel ADC
  • Built-in RC oscillator, power-on reset and watchdog timer

 Samples from STC

When I called up STC to ask them about the bug, they suggested that my chips may be defective and they can give me a few samples to try with. I filled out the sample request form immediately and sent it back to them. You will probably need a corporate identity to do this, and I borrowed the name of the company my mom worked for.

Chips in boxes like above. And for your first sample, you get a free U8W-Mini.
Chips in boxes like above. And for your first sample, you get a free U8W-Mini.

Today the samples arrived in nice little boxes, along with their U8W-Mini offline programmer/ICD unit. The unit is based on one of their dual-serial MCU with a USB to UART chipset (CH340G) built in.

This unit saves me a few components when breadboarding the experiments, otherwise it functions next to identical when I was using a FTDI breakout or my M180v4 USB to UART adapter module. Sadly it cannot debug parts that is not on their ICD part support list.

Blinking the LED

LED-blinking code is fairly similar to the Arduino sketch, but since this is a new platform I have to implement delay() myself.

The hardware is straightforward with the MCU, clock oscillator and the LED. I have ignored the bypass caps as the power supply module on my breadboard have already included those, and since it is not biting me yet for experiments I got lazy.

Diagram of the STC51 Blink circuit.
Diagram of the STC51 Blink circuit.
This is the debug setup used for the blinking LED experiment.
This is the debug setup used for the blinking LED experiment.

I had a bit of problem implementing the timing functions, as when running at 30MHz I cannot get a nice integral microsecond for each timer interrupt, no matter which mode I set it in. Since the IAP15F2K61S2 microcontroller maxes out at 28MHz anyway I decided to operate the experiment at 24MHz instead, giving me a nice 128µs per interrupt when running the clock with a 1/12 prescaler.

// systick.c

#include "systick.h"

void systick_init(void)
{
 TMOD = TMOD & 0xf0 | 0x02; // Timer 0 in 8-bit counter mode.
 TL0 = 0; // Reset counter
 TH0 = 0; // Autoreload 0
 ET0 = 1; // Enable interrupt on timer 0;
 EA = 1; // Enable global interrupt;
 TR0 = 1; // Start timer 0
}

volatile unsigned long millis_counter = 0;
volatile unsigned int micros_counter = 0;

void systick(void) interrupt 1
{
 micros_counter += 128;
 if (micros_counter >= 1000)
 {
 millis_counter++;
 micros_counter -= 1000;
 }
}

void yield(void)
{
 ; // TODO: Kick the dog here.
}

unsigned long millis(void)
{
 unsigned long ms;
 
 EA = 0; // Enter critical section
 ms = millis_counter;
 EA = 1; // Exit critical section
 
 return ms;
}

unsigned long micros(void)
{
 unsigned long ms;
 unsigned int us;
 unsigned short count;
 
 EA = 0; // Enter critical section
 ms = millis_counter;
 us = micros_counter;
 count = TL0;
 EA = 1; // Exit critical section
 
 return ms * 1000 + us + count / 128;
}

void delay(unsigned long time)
{
 long end;

 end = millis() + time;
 wait(end - (long)millis() > 0);
}

void delayMicrosecond(unsigned long time)
{
 long end;
 
 end = micros() + time;
 wait(end - (long)micros() > 0);
}

The main loop looks similar to the infamous Arduino “hello world” sketch. This shows the work have to be done behind the scenes to get an environment not too dissimilar to Arduino up and working. (and I was even thinking of creating an Arduino-compatible board, along with the appropriate cores, for STM32.)

// main.c

#include "system.h"

int main(void)
{
 systick_init();
 
 for (;;)
 {
 P27 = !P27;
 delay(500);
 }
}

Next time we will let it speak up over serial.

Leave a Reply