Playing with the stm32f4 Discovery Board

Many moons ago, on the recommendation of a few of the firmware wizards at work I got myself an stm32f4 discovery board to play with (this was pre-Raspberry Pi!) and set myself up a development environment on my Mac to have a play.

The toolchain runs out of Eclipse and I can’t remember exactly how I set it up (sorry!) but I know I referenced posts from the two blogs below:

  1. cu.rious.org (http://cu.rious.org/make/stm32-toolchain-on-mac-os-x/)
  2. http://www.alexwhittemore.com (http://www.alexwhittemore.com/open-source-ide-and-toolchain-for-the-stm32f4-discovery-on-mac-osx-lion/)

After a quick tester to make sure I could actually get code to run on the board using the onboard LEDs to display random numbers as binary, I decided to create a simple “dice” project by interfacing the board to a 7-segment display via a latch / decoder / driver. The code running on the board would then generate a random number between 1 and 6 and display it on the LED display. Initially I was just going to use a button to generate the number but it occurred to me that a much more interesting user experience would be to actually ‘shake the dice’ and as the board has accelerometers on it, I figured that was the way to go.

Now if it’s a tutorial you’re after, this probably ain’t going to help you much, it’s more of a description of how I approached the project so apologies in advance if that’s what you’re after. Similarly, it’s pretty basic and there may well be much better circuits and code that would do the job. This is more of a description of how I picked my way through the thing to get it working.

The 7-segment display circuit

The 7-segment display circuit

I built the circuit on breadboard and used an old cable from a PIC programmer to connect it to the stm32 board. The circuit is powered from the board itself after I tested it and found it just about fitted inside the limit for current. Now I’m a software guy and I know pretty much sod all about electronics so no laughing all you hardware ninjas!

  • The BLANK pin on the board was connected to pin 13 on GPIOC
  • D1 was connected to GPIOE pin 4
  • D2 was connected to GPIOE pin 5
  • D3 was connected to GPIOE pin 6
  • D4 can be connected to any of the other GPIOE pins as it’ll always be low (in fact I could have just tied it to GND but hey ho!).

The code runs as a very simple state machine. I used 4 different states:

  1. STARTING – this is when all the initialisation happens;
  2. WAITING – everything is initialised and we’re waiting for the first shake;
  3. SHAKING – the player is shaking the board;
  4. DISPLAYING – the result is being displayed.
/**
* @brief  This function handles SysTick Handler.
* @param  None
* @retval None
*/
void SysTick_Handler(void) {

    /* Sort out any pending timers */
    TimingDelay_Decrement();

    /*
     * We can enter the shaking state if the dice is waiting
     * or displaying
     * the previous result
    */
    switch(state) {
    case STARTING:
        /* do nothing we're waiting for the initialisation */
        break;

    case WAITING: /* fall through */
    case DISPLAYING:
        /* is there movement? */
        if (IsShaking()) {

            /*yes, blank the 7-seg and move state */
            blankNumber();
            state = SHAKING;

            bounceDelayCounter = BOUNCE_DELAY;

        }
        break;

    case SHAKING:
        /* have we stopped shaking? */
        if (!IsShaking()) {
            bounceDelayCounter--;

            if (bounceDelayCounter <= 0) {

                /* Yes, show a random number and move state */
                showRandomNumber();
                state = DISPLAYING;
            }
        }
        break;
    }
}

The code above shows the implementation of the interrupt handler for the system timer which is initialised in the main() function along with the IO ports, random number generator and accelerometer. Once the board is in the WAITING state, it’ll detect shaking and enter the SHAKING state. The de-bouncing stuff adds a short delay after the player has stopped shaking to make sure they’re done before displaying the number. I ripped it out of some switch debouncing code I already had from a previous experiment, hence the name.


/* Returns true if the board is moving */
int8_t IsShaking() {

    /* read the accel to see if anything is happening */
    Buffer[0] = 0;
    Buffer[2] = 0;
    Buffer[4] = 0;

    LIS302DL_Read(Buffer, LIS302DL_OUT_X_ADDR, 6);

    /* Remove the offsets values from data */
    Buffer[0] -= X_Offset;
    Buffer[2] -= Y_Offset;
    Buffer[4] -= Z_Offset;

    uint8_t temp1 = ABS((int8_t)(Buffer[0]));
    uint8_t temp2 = ABS((int8_t)(Buffer[2]));
    uint8_t temp3 = ABS((int8_t)(Buffer[4]));

    tempAcceleration = MAX(MAX(temp1, temp2), temp3);

    return tempAcceleration > SENSITIVITY && tempAcceleration < (256 - SENSITIVITY);
}

The IsShaking function is pretty simple too. All it does is read the accelerometer values into a global buffer, removes the offsets that it read during the initialisation phase, makes all the values (X, Y and Z axis) positive numbers and finds the biggest one. If that is in a range that takes into account a constant sensitivity value (set by experiment) then it returns true. Otherwise it returns false.

/*
 * Returns a 32 bit random number.
 */
int32_t getRandomNumber() {

    /* Wait for the data to appear.*/

    while(RESET == RNG_GetFlagStatus(RNG_FLAG_DRDY)){}

    return RNG_GetRandomNumber();
}

/*
* Shows a random number on the 7 seg display.
*/
id showRandomNumber() {

    uint32_t rnd= 0;
    /* Get a random number between 1 and 6 */
    do {
        rnd = getRandomNumber();

        /* mask off the bottom 3 bits */
        rnd = rnd & 0x00000007;

    } while (rnd == 0 || rnd == 7);

    /*
     * Create a bit mask of the pins to set
     */
    uint16_t displayPinsToSet = 0;

    /* Mask out bits 1-3 so we can set up the pins to show the output */
    if (rnd & 1) {
        displayPinsToSet |= GPIO_Pin_4;
    }
    if (rnd & 2) {
        displayPinsToSet |= GPIO_Pin_5;
    }
    if (rnd & 4) {
        displayPinsToSet |= GPIO_Pin_6;
    }

    /*
    * Clear out whatever state is on the 7-seg then update with
    * the new value
    */
    GPIO_ResetBits(GPIOE, GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6);
    GPIO_SetBits(GPIOE, displayPinsToSet);

    /*
    * This pin connects to the ripple blanking pin on the 4511. When it
    * goes high the seven segment driver displays a number.
    */
    GPIO_SetBits(GPIOC, GPIO_Pin_13);
}

The code above shows how the random number is retrieved from the random number generator and then the relevant pins set. Once that has happened the blank pin is set so that the number is displayed. That’s all the interesting code, the rest of it is just initialisation stuff which happens in main(). That’s just about creating and filling in the right data structures and putting the program into the WAITING state.

I realise this isn’t exactly a complete listing, this has been more of a description of my meanderings through the project and if you’re looking for a tutorial this won’t help a great deal but if for some reason you’d like to get hold of the source code let me know and I’ll zip it up and put it somewhere for you to download.

So this project was my first play with embedded programming on the STM32 board and it was pretty good fun. It was also my first foray into digital electronics so I was pretty chuffed to get the whole thing working! I’ve since got a Raspberry Pi to play with so I suspect my next project will have that in it somewhere.

Advertisements
3 comments
  1. Tony said:

    I am very interested in trying this out on my board. I have been tinkering with the accelerometer, but I never thought to incorporate the random number generator to emulate a dice throw. It is a really neat idea. Can you post the source like you mentioned?

    • Hi Tony, thanks for dropping by it’s much appreciated. Unfortunately I wrote that code a while back and it was on a laptop that has since died so I’m not able to post the whole thing. Sorry about that!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: