I intend to use an STM32F401RE (on a nucleo board) to capture some time based data.

I am new to ARM and have an 8bit uC (AVR) background. I have a toolchain set up (using gcc as part of AC6 SW4STM32) and have used the HAL Library provided by ST to do simple binking LEDs etc.

I have been importing CubeMX projects into SW4STM32.

I am looking at measuring voltage at 10kS/s for a period if 3 seconds. I want to use the full 12bit ADC.

I would be great full if anyone could help me with the high level code structure before I invest the time learning the functions etc and get bogged down in the coding...

I have something like the below in my head, the interupt being triggered every time a sample is required...

ISR every 1/10000s
    if measure > 0
        read ADC and ouptut to UART        
        if measure == 30000
            measure = 0

    loop forever
        if measure==0
            if start_button == 1
                measure = 1

How does this look as a starting point? Also, what is the general opinion on the use of libraries? In 8bit a 'library' is little more than some labels for registers, they seem much more commonly used in ARM... Should I just accept using the HAL from ST, try and restrict to the CMSIS or really try and continue to poke memory as in 8bit?

Any guidance is greatly received...


2 Answers 2


the simplest would be to set up a timer and in the timer start the adc.

you can set the timer interrupt to the highest / higher priority.

In 8bit a 'library' is little more than some labels for registers,

plenty of libraries are used in the 8-bit world as well. you may be thinking about macros vs. libraries.

they seem much more commonly used in ARM...

due to their complexity and much steeper learning curve.

Should I just accept using the HAL from ST, try and restrict to the CMSIS or really try and continue to poke memory as in 8bit?

it is very difficult to NOT use cmsis to start up the device.

as to library, give it a shot and it may help you get started sooner / quicker.

I typically start with oem libraries but box them in a way that in the future I can replace them with my own code if I so desire.

with an oem library, you typically get quality code + working examples. they do come with a little bit overhead (1-2KB typical) but that's nothing for a typical ARM chip.

edit: here is what I typically do for all of my timer related routines -> they are identically structured but differently implemented on 8/16/32 chips:

  clear the flag;
  _isrptr(); //execute the user handler

timer initialization (prescaler, period)
  stop the timer
  initialize the timer for user-specified prescaler and period
  start the timer - interrupt still disabled

timer activation (isrptr)
  _isrptr = isrptr; //install user handler
  clear the flag
  enable the interrupt

it allow the installation of a user-specified routine in the timer isr. in your case, that user installed routine could be turning on / off the adc, saving / processing the data, setting up a flag ...

this set of routines will be generic and can be ported from chip to chip. it can be implemented via libraries or you can roll your own - completely transparent to the user space code, meaning that you can switch between implementations freely without the need to change user code.

edit 2: here is an example. the following code,

tim1_init(1000, 1000);                  //run tim1 at 1000 prescaler + 1000 period = 1M
tim1_act(led_flp);                      //install user handler

runs on STM8S -> it sets up timer1 to overflow every 1M cycles and then on timer1 overflow it executes led_flp(), installed by tim1_act().

Substantially the same code runs on PIC, AVR, MSP430, PIC24, and various ARM chips. Some versions of it runs of ST's SPL (for STM8 and STM32), others run off Luminary's driverlib, and others run off hard coded code -> in the case of STM8, some off IAR's header files and others off the stm8s.h from the SPL, without actually using the SPL.

This is to show that the question of whether a vendor library should be used is quite moot, if you structure your code appropriately. To the user code, it doesn't make one bit of a difference whether those routines were implemented off a vendor library or rolled by modifying the registers. End of the day, it gets the job done, hopefully done right.

So instead of wasting time on if you should take a particular approach, just take one approach and make sure you do it right.

  • \$\begingroup\$ I guess I am referring to macros really... While I have used a number of libraries, generally these have not been provided by the oem rather a third party (or myself)... \$\endgroup\$
    – OGMGIC
    Feb 18, 2017 at 17:38
  • \$\begingroup\$ macros are far more frequently utilized than libraries. for every library you use, you have likely used several hundreds of macros -> the header files are full of macros for example. \$\endgroup\$
    – dannyf
    Feb 18, 2017 at 17:47
  • \$\begingroup\$ libraries are fairly common in the 8-bit world as well. most compilers now come with all sorts of libraries. then you have vendor provided libraries, like ASF, plib, harmoney, SPL (for STM8 chips for example), ... not to mention your own libraries. it makes no sense to avoid the use of libraries. \$\endgroup\$
    – dannyf
    Feb 18, 2017 at 17:49
  • \$\begingroup\$ I guess I didn't word my meaning very well, I wasn't really suggesting not using libraries, rather avoiding the ST HAL, and coding the functions I required in my own library such that I gain a better understanding and make leaner code by only compiling what I needed... \$\endgroup\$
    – OGMGIC
    Feb 18, 2017 at 18:42
  • \$\begingroup\$ > I gain a better understanding and make leaner code by only compiling what I needed... by writing your own code, you certainly will gain a better understanding of the hardware -> whether that's useful or worthy of the time investment is entirely up to you. whether you can write leaner or better code than the oem library is dependent on your skills. \$\endgroup\$
    – dannyf
    Feb 18, 2017 at 19:30

CMSIS is mostly a framework to make 'just poking memory' simpler to read (using structs and macros). I think it's fair to say you gain nothing by ditching CMSIS and trying to use bare metal.

When it comes to a HAL, things get a little more complicated. Frequently the pin muxing and clock control initialisation required for peripherals is non-trivial. Maybe not too many writes, but working out what is required can take some time - saving this time is where a good HAL can help. The quality might vary but it probably is worth finding a suitable framework which is likely to scale to your future projects and becoming familiar with it. At the point that you need threading and networking, you probably don't want to be doing your own thing for the 'generic' stuff.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.