How To Program A Really Cheap Microcontroller

There are rumors of a cheap chip that does USB natively, has an Open Source toolchain, and costs a quarter. These aren’t rumors: you can buy the CH552 microcontroller right now. Surprisingly, there aren’t many people picking up this cheap chip for their next project. If there’s no original projects using this chip, no one is going to use this chip. Catch 22, and all that.

Like a generous god, [Aaron Christophel] has got your back with a working example of programming this cheap chip, and doing something useful with it. It blinks LEDs, it writes to an I2C display, and it does everything you would want from a microcontroller that costs a few dimes.

The CH552, and its friends the small CH551 all the way up to the CH559, contain an 8051 core, somewhere around 16 kB of flash, the high-end chips have a USB controller, there’s SPI, PWM, I2C, and it costs pennies. Unlike so many other chips out there, you can find SDKs and toolchains. You can program the chip over USB. Clearly, we’re looking at something really cool if someone writes an Arduino wrapper for it. We’re not there yet, but we’re close.

To program these chips, [Aaron] first had to wire up the microcontroller into a circuit. This was just a bit of perf board, a resistor, a few caps, and a USB A plug. That’s it, that’s all that’s needed. This is a fairly standard 8051 core, so writing the code is relatively easy. Uploading is done with the WCHISPTool software, with options available for your favorite flavor of *nix.

But it gets better. One of the big features of the CH552 is USB. That means no expensive or weird programmers, yes, but it also means the CH552 can emulate a USB HID device. The CH552 can become a USB keyboard. To demo this, [Aaron] programmed a CH552 board (DE, here’s the Google translatrix) loaded up with touch pads and LEDs to become a USB keyboard.

If you don’t feel like soldering up one of these yourself, there are some suppliers of CH554 dev boards, and the files for [Aaron]’s projects are available here. Check out the videos below, because this is the best tutorial yet on programming and using some very interesting chips that just appeared on the market.

60 thoughts on “How To Program A Really Cheap Microcontroller

    1. Aliexpress doesn’t stock anything. Some primary suppliers list directly on it, but often they only list on Taobao, and secondary resellers decide which products to try and make a profit on by relisting on Aliexpress. Unusual microcontrollers for super-cheap chinese devices don’t usually fall in that category, as the western market is very strongly PIC/AVR/ARM dominated.

  1. Looks like a winner except for the 8051 architecture. I haven’t coded for it since about 1988 for a reason. I know that I am older than it is, but there really are better options today, and for the last n decades, where n>3.

    1. True if you’re writing in assembly language.

      In C, there’s some foolery with memory types — 8051 limited to 256 bytes or something silly onboard — but that’s about the only thing you’d notice, right? (Not an 8051 expert.)

      If there’s enough code between me and the metal, it might as well be a Turing Machine. :)

      1. The 8051 is a pain dealing with memory. You have to deal with near (8-bit pointer) and far (16-bit). This affects unction calls as you might need same function for mixed types. SDCC offers a generic pointers, but with great overhead.
        Copying far to far memory on the base 8051 is a pain as it has only one 16 bit pointer that can be used as index. So each byte copied take a lot of cycles as it involves swapping the index register as well. Most (but not all implementations) added extra register(s) but that requires the compiler’s awareness.

    1. With an 8051 core, an Arduino wrapper is fairly unlikely. Arduino’s libraries are all C++ based and I’ve never seen any open source C++ compiler for that core. SDCC is C-only.

    1. The specification is for 200 flash cycles, but we’ve programmed them way more times than that and haven’t run into any issues. Seems fine for hacking, and for production they probably would only be written a few times.

  2. Neat! LCSC.com seems to stock quite a few variants. Please don’t go and clear the shelves, I want to pick up a few myself but will probably do a breakout or some mini dev-board first. So hope there will be some left in a week or two.
    https://lcsc.com/search?q=ch55

    Anyway, other alternative 8051s – with native USB, in the ½-buck range are the SiLabs EFM8 stuff, e.g. “universal bee” (big points deduction for the stupid “bee” naming scheme thing, WTH is the deal guys..?) EFMs were really nice and all; but at 0.60$ (1k), what really tickles the trigger finger is the chinese pricing, where we reach 0.25$ already at a bag of 500.

    If these works out the way they look, we’ll probably have a new favorite go-to guy when it comes to cheap-ass programmable native USB stuff. Cheers!

    Agree with Sprite_tm though, 8051 is not exactly fresh. A 25c basic low-end RiscV with native USB would be nice. Please make it so.

    1. I think the 8051 isnt well suited for highlevel languages. This will make it a bit inefficient. My guess the resulting code will do as programmed, but not efficient (slow and bulky).

      Arm instruction set for example is developed with c in mind.

      Whether you care is what the purpose of your application is.

    2. Also no if forced to use SDCC (open source compiler). Used it many times years ago, but the compiler doesn’t generate efficient code. Depending on your 8051 core (how much extra speed up by vendor) this can be very slow. Chinese vendors might use crappy cores.

      SilLabs licensed Keil (with badly implemented Eclipse IDE) and have improved quite a bit on their 8051.

      1. The core used in these take 1 cycle per instruction byte, except for DIV and any instructions that modify the instruction pointer (which take an extra 2/3 cycles). The USB peripheral has DMA access to XDATA, and the other peripherals are mostly vanilla 8051. The USB also works without an external crystal, and the built in USB bootloader means it doesn’t even need a programming header, so it’s basically a single part solution for simple bit wiggling and protocol implementations over USB, for less than the price of a cheap USB cable. Of course if there was a part with a more modern architecture that fit this niche and price point, it would be grand.

        1. Even then, there are a lot of packet segmentation and reassembly going on in a typical USB driver. These operations do a lot of short blocks of memory copying between hardware queues and buffers and in some cases memory fills for padding.
          Depending on how flexible the DMA is and if there are additional channels available, it might help. Sometimes the copy could be in tiny 8 bytes blocks which adds overheads. e.g. control queue
          (been there done that and hate 8051)

    3. there is no gcc for 8051, all good compilers are paid, sdcc may work but when I tried it and looked at the result it was not nice. DPTR reloading same value again and again.
      Look what gets generated for single “OPAMPMC|=0x80” line:
      mov dptr,#_OPAMPMC
      movx a,@dptr
      mov r7,a
      orl ar7,#0x80
      mov dptr,#_OPAMPMC
      mov a,r7
      movx @dptr,a

        1. Prob best to put “bitwise or” in brackets. In whatever default font I’m using, I can tell the difference, it’s even thinner. But why leave room for ambiguity? The brackets would be the English type, not logical.

      1. Thats because the variable is classed “memory bound” probably for reliability, hence the value of writing up a matrix of variable attributes when writing in assembler to maintain highest efficiency (which I do as a matter of course and dead easy too for limitations of 8051 architecture) to get the most out of it. Isn’t there a switch/attribute or some such identifier to assign priority to variable usage/efficiency Or its a facile implementation of a compiler built down to a price :/

        1. Are you real person or is this some sort of AI text generator? I understand every word, the grammar looks fine too but still I don’t get the meaning of any part of any sentence at all :-(

          1. Hrrm, here we go.
            1. That variable is bound to (main) memory (ie not the internal register set or efficiently accessed 128 bytes) eg 64k space so the compiler defaults to treating it and all like it with full 16 bit addressing.
            2. When writing assembler cognisant of these issues one can improve efficiency and reduce risk/debug issues too by drawing up a matrix of variables such as to ensure variable types and their locations treated most optimally.
            3. I do this as a well tested habit even with far more complex processors as well as other attribute matrices outside software such as linguistic sets.
            4. It is of course very easy for the base 8051 memory architecture even the few enhancements with multiple pages and can be done by hand all to easily faster than excel unless you’ve set up a VB script to pull them out…
            5. For the compiler mentioned which I have no experience with, I ask is there some compiler variable attribute or overall switch modifier eg first 128 bytes that can be set when defining selected variables so as to force the compiler to use more compact and more efficient addressing ie first 128 bytes only Or some other if paging available ?
            6. Or is that compiler limited in such options as in it was written down to a price without any upgrade option or first craft beta for distribution eg simplest for the $ or time to create it.

            And yes I have studied some linguistics and a few languages informally and when sporadically writing posts on several forums occassionally select wording according to disparate audiences influenced by the thread context (usually) to see who’s awake or has the mindset to question or let it wash over them like water off a duck’s back or a couple of other variants as a selection criteria if worth indulging them. This is not to imply I don’t have code or fiddle with code to experiment with as to me so much of human vocabulary regardless of language has simple mechanical like patterns I find boring now and then and logical therefore I consider it and this is one way I liven things up a bit. I can’t confirm or deny I did that on this occasion especially if the script wrote this – with a switch modifier of course so it’s a tad more explanatory not assuming defaults ;-)
            Cheers

          2. Thank you Mike for your answer. I will answer just to point 1. Yes the address is in external memory so using DPTR is of course fine. However initialising it twice with same value and also using extra r7 register should not be needed and good compiler should optimise it to something like:
            mov dptr,#_OPAMPMC
            movx a,@dptr
            orl a,#0x80
            movx @dptr,a
            as there are no branches in the code so the flow and register values are pretty easy to determine.

            As for the rest, if you are AI then a pretty good one :-)

      2. Adding an user pee hole optimizer rule might fix this but at the same time introduces possible bugs. SDCC doesn’t really look at the bigger picture to try to optimize things unlike the rest of the paid compilers. Sadly this architecture does require a lot of optimizing – very low code density, lack of registers generic pointers/accumulators.

        For speeding up I/O like this, better off writting that part in assembly because the SDCC compiler gets in the way. Given the microcontroller choices available these days, I would/could avoid one that forces me using SDCC.

    4. If there were a GCC port it would not matter, I guess. SDCC is a sometimes PITA to use. It crashes on some code. It generates incorrect assembly on some code. But hey, at least it’s free, so probably developing for 8051 is still better than develoling for PIC.

      Also if you limit yourself to devices with 256 bytes of internal RAM the memory model doesn’t give much headache, but as far as I can see this is not the case with WCH chips.

      1. Who ever used Pascal to program an 8051? Who is it who programs microcontrollers at all and can even remember Pascal, if they actually took it? The only people who ever learned Pascal were at college before they realised they may as well go the 15% further and just teach C. I can only imagine this compiler is the result of some made Pascal-fan.

        Fortunately Pascal resembles C enough it might not be hard to knock up a C -> Pascal convertor. Only a shame it’s not the other direction, since theres -to-C convertors for any language you can think of, some languages don’t even have compilers available, just a to-C convertor is all you need.

        1. “The only people who ever learned Pascal were at college before they realised they may as well go the 15% further and just teach C”

          I resemble that remark…. Of course, I worked in fortran, PL/I, IBM 360/370 assembler (asmh, with macros, was such an improvement I almost thought there was no need for higher level languages anymore…), PDP10 asm, and a bunch of others first. As well as 8080 (8085, Z80, as well), 8051, 6502 (et cetera), and a pile of others I don’t recall. I do miss PL/M, a little…

          Interesting point of trivia: one of the earlier C compilers for system/370 (early 1980’s… it WAS IBM iron, after all) compiled to Pascal. Debugging sucked, as many compiled structures were truly bizarre. Ya. Had to change a lot of habits fast with that one. I was glad when that was replaced with a native compiler, despite the need to rework a lot of code base, that built structs compatible with the MVS system structure macro’s, rather than the Pascal “we put it wherever we want just to piss you off, screw with your boolean expressions, and use nonstandard character sizes to boot” record model.

        2. I used Pascal to program a DS5000 based instrumention system, Pascal isn’t the limitation, the programmer is. Yes, we had a Pascal to C translator, it was mostly changing one Pascal word for a C word.

          When the language becomes a problem, get a new programmer and the problem strangely disappears.

  3. I do not understand why a price difference of any uC board under EUR 5 would be significant for hobbyists.
    It’s silly to pay EUR 45 for an “arduino” board but wen boards are < EUR 5 then price becomes irrelevant and other factors should dominate your choice.

    USB can be mandatory for projects, but lot's of uC's have USB nowadays.
    I think the "Blue Pill" boards are among the top of the sub EUR 5 boards. Plenty of raw speed (32-bit / 72MHz) and peripherals (DMA, multi -level interrupt controller and much, much more) Good tools: ST-Link V2, Black magic Probe, GCC(+GDB).
    STM32F103C8T6 still hase some dark sides though. The extra complexity (Few thousand pages of documentation) that comes inherently with all these peripherals is complete overkill in a lot of projects and because this processor is one of the oldest in the STM32 range it has a bunch of quirks that have been ironed out in later generations.

    If you know of a more powefull sub EUR 5 board or with better tools / less quircks then I'd like to see a Hackaday article about that. I'm curious what RISC-V is going to do. Is it going to scale down into these cheap small uC families, or will it stay bigger? Any comments about better sub EUR 5 boards with better tools than the "Blue Pill" are welcome :)

    1. I’d recommend looking beyond just the cost of the dev board and at the cost & availability (including minimum ancillary parts) of the micro itself when incorporated into final projects.
      For example, while the “blue pill” dev boards are cheap, trying to find similarly cheap STM32F103 chips on their own makes using that platform less clear-cut as, unless you have space for the entire dev board, it becomes a bit of a dead-end for traditional development purposes.

      1. Get the STM32F103s from the same place as the blue pills, and they’re around a buck each, and there are firms that’ll sell you lots of 100 each.

        But once you start up on big multiples, getting the chip with exactly the features you need starts to pay off. So maybe in those quantities the STMF103 doesn’t fit — there are a ton of other microcontrollers with a variety of interesting features in the one-buck range.

        I’m totally convinced that, for $2, the blue pill boards are at a hobbyist-level sweet spot right now, though. I’ve burned through 50+ over the last three years, and I buy them by the ten-pack.

    1. 8051 is not a general purpose microprocessor like the Motorola 68000, but rather it is an early form of embedded microcontroller. There is no MMU inside, since it is not designed to run end user apps in the desktop computer sense of the word. Only way you could get CH552 to present as equivalent to an early desktop-class system is via custom virtual-machine firmware shoehorned into it’s program ROM (might also need some external RAM in the form of an SPI peripheral.. :-). Cheers.

  4. There’s an Arduino port now, idk when it came out. Basically a c++ to c conversion behind the scenes, and have to exchange . for _ generally. It’s all well documented and on GitHub with examples etc (ch55xduino)

Leave a Reply to Valentin AngelovskiCancel reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.