RSS

Archive for February, 2014

Clocks, Reset Signals and Switch Debouncing

Sunday, February 16th, 2014

Every computer needs a clock circuit to synchronise the operation of the various components. A CPU is no exception. In this post we will create a clock for the CPU. We will also add reset and single step circuits.

The brief for this post is as follows:

  • The reset circuit must be capable of generating both high and low reset signals.
  • A stop/run circuit should allow the CPU to be stopped by the user and the clock single stepped.
  • Internal clock source with a master clock of 4 MHz.
  • Selectable clock frequency which is a fraction (half, quarter etc.) of the master clock source.

Reset Signals

The requirement to have both high and low reset signals is not really too complex as a single inverter can provide this capability. The most complex part of this requirement is to remove the switch bounce from the signal.

Switch De-bouncing

For new readers, switch bounce occurs due to the imperfect nature of mechanical switch. For a brief period of time when a switch is depressed or released there will be a period where the electrical signal is not stable. If you connect an oscilloscope to a switch in an electrical circuit and press the switch you are likely to see traces such as the following:

Switch Bounce

Switch Bounce

The obvious outcome of this is that the circuit can act as though the switch has been pressed multiple times in a short period of time. The answer to the problem is to de-bounce the switch. This removes the additional signals which can be generated. For microcontroller developers there are two possible solutions to this problem, software or hardware de-bouncing. As we have no conventional software environment available to us we must achieve this by hardware de-bouncing.

There are many possible solutions to this problem and you can find some discussions in the following links:

In this circuit there are two switches to debounce, the reset switch and the clock selection switch. The reset switch is a momentary switch and the clock selection switch is a rotary switch. The rotary switch should be viewed as a momentary switch for the purposes of this exercise.

The problem of debouncing the switch can be broken down into two distinct components, namely removing the jitter by rounding off the signal and the squaring off the rounded signal. The jitter can be rounded off by the use of a RC circuit. The above articles suggest that the rounded signal can be squared using an inverter with a Schmitt trigger.

Time to break out the breadboard, oscilloscope and the calculator.

The first thing to examine is the amount of bounce for the switches being used. Hooking up the momentary switch and a resistor resulted in the following traces for the depression of the switch:

Switch Bounce Depression

Switch Bounce Depression

And for the release of the switch:

Switch Bounce Release

Switch Bounce Release

Taking some measurements we see that the maximum bounce appears to be about 5ms for the momentary switch.

Repeating the exercise for the rotary switch reveals that this switch was a lot dirtier. The bouncing continued for about 10ms in the worst case.

Taking the worst case scenario we should assume that the switch is unstable for 10ms and 20ms would allow for an extreme case.

There are two possibilities for debouncing, hardware and software. For a large commercial run where a microcontroller is in use then software debouncing would be used as it requires no additional components. As this is a small run, hardware debouncing is a possibility.

Hardware Debouncing (Circuit 1)

This first hardware debouncer will use an RC network connected to a Schmitt triggered inverter. The basic circuit is:

2RC Debounce

2RC Debounce

The capacitor C4 charges through R4 and R5. When the capacitor is charged the input to the inverter is high and the output will be low.

Depressing the switch starts the discharge cycle for the capacitor. The capacitor slowly discharges through R4 until it is below the level associated with logic 0 on the inverter. The output of the inverter then goes to logic level 1. The hysteresis of the inverter makes the gate resistant to the time the voltage applied to the input of the inverter is between logic 1 and logic 0. So pressing the switch takes the output high and releasing the switch takes the output from the circuit low.

The trick with the circuit above is to select values for R4, R5 and C which eliminate the bounce at both the charge and discharge points in the circuits operation. This circuit gives an output something similar to the following:

RC Added to Switch

RC Added to Switch

The yellow trace shows the output of the circuit when the oscilloscope probe is connected to the input of the inverter. As you can see, the noisy signal has been replaced by a rapid decay at the start (when the switch is depressed) and a longer rise at the end when the switch is released.

Hardware Debouncing (Circuit 2)

In the last post I was looking at the MSP430. The intention is to look at how it can be used for software debouncing (we’ll come on to that later). The MSP430 Launchpad has a reset button connected to Port 1, pin 3 (P1.3) and this switch is also debounced (the schematics are freely available from TI’s web site). The debounce circuit on the MSP430 looks something like this:

MSP430 Launchpad Debounce Circuit

MSP430 Launchpad Debounce Circuit

Modifying this to add an inverter we get the following:

Modified MSP430 Debounce Circuit

Modified MSP430 Debounce Circuit

The discharge when the button is pressed is a lot quicker but the charging when the button is released show the same characteristics as Hardware Debouncing (Circuit 1). Examining the trace we see that the output from the inverter is good enough for the job at hand.

Software Debouncing

The algorithm for software debouncing is relatively trivial. The microcontroller waits and detects the changing input on of the the pins (say going low to high). Once detected, start a timer and wait for the worst case scenario (we set this to 20ms for the switches being used in this circuit). If at the end of the time period the signal is still high then set the output high, otherwise start the whole process again.

Now this algorithm works well for a single input to a microcontroller but what if you have multiple inputs and outputs all of which need debouncing. This is the scenario with this circuit as the rotary switch allows one selection to be made from a multiple of inputs. In this case the rotary switch acts like multiple switches. Following the above algorithm would require multiple interrupts and timers, many more than found on low end microcontrollers.

Modifying the algorithm to use timers and counters can solve this problem.

  1. Initialise an array of counters (one for each input) to 0
  2. Set the outputs to the same level as the inputs
  3. Setup a timer to trigger on a regular period (say 8ms)
  4. For each input, if the input is different to the output increment the counter for that input, otherwise set the counter to 0
  5. For each counter, if the value has exceeded the threshold count then set the output to the same level as the input

Although this is a little more convoluted it does allow switch debouncing for multiple switches with a simple and cheap microcontroller.

Software Debouncing on the MSP430

The software debouncer will be implemented in MSP430 assembler code developed using IAR Embedded Workbench.

The first thing we need is somewhere to store the counters and some workspace for the application. This application is small and so the registers on the chip should suffice.

;--------------------------------------------------------------------------------------------------
;
;   Switch debouncer for the home made CPU.  This will debounce five switches
;   four through Port 1 and 1 through port 2.
;
;   Copyright (c) Mark Stevens 2014
;
;--------------------------------------------------------------------------------------------------
#include <msp430.h>

;--------------------------------------------------------------------------------------------------
;
;   Global definitions
;
;--------------------------------------------------------------------------------------------------
;
;   Define some symbolic names for the registers holding the counts of the number of interrupts
;   for which the value on the input differs from the output.
;
#define  port0Count r4
#define  port1Count r5
#define  port2Count r6
#define  port3Count r7
;
;   Now some temporary workspace for the Watchdog ISR.
;
#define inputRegister r9
#define temporaryRegister r10
;
INTERRUPT_BASE      equ     0xffe0                  ; Base address of the interrupt vector table.
MAX_COUNTS          equ     4                       ; 4 counts equates to 24ms.

The above defines some symbolic names for the counters and maps these names onto four registers. These are also two registers reserved for workspace for the application.

;--------------------------------------------------------------------------------------------------
;
;   Main program
;
;--------------------------------------------------------------------------------------------------
                    org     0xf800                          ; Program Reset
main                mov     #0x280, SP                      ; Initialize stackpointer
StopWDT             mov.w   #WDT_MDLY_8, &WDTCTL            ; WDT ~8ms interval timer
                    bis.b   #WDTIE, &IE1                    ; Enable WDT interrupt
                    ;
                    ;   Setup the counters.
                    ;
                    mov.w   #0, port0Count
                    mov.w   #0, port1Count
                    mov.w   #0, port2Count
                    mov.w   #0, port3Count
                    ;
                    ;   P1.0, 2, 4, 6 are inputs, P1.1, 3, 5, 7 are outputs.
                    ;
                    bis.b   #0xaa, &P1DIR
                    mov.b   &P1IN, &P1OUT                   ; Start with the outputs equal to the inputs.
                    ;
                    ;   Put the chip to sleep waiting for interupts.  Put it back to sleep
                    ;   if it ever wakes up.
                    ;
Mainloop            bis.w   #CPUOFF + GIE, SR               ; CPU off, enable interrupts
                    jmp     Mainloop

The main program initialises the counters and the ports and turns on the watchdog interrupt (triggered every 8ms – approx). The main program then puts the chip to sleep until the Watchdog interrupt fires.

;--------------------------------------------------------------------------------------------------
;
;   Watchdog interrupt
;
;   Check the input pins (0, 2, 4, 6) and if they are different to the output pins then increment
;   the counter for that pin.
;
;   If the counter reaches MAX_COUNT then transfer the input to the output.
;
;   If the input equals the output then set the counter to 0.
;
;--------------------------------------------------------------------------------------------------
WatchdogISR         mov.b   &P1IN, inputRegister
                    mov.b   &P1OUT, temporaryRegister
                    clrc
                    rrc     temporaryRegister
                    xor.b   temporaryRegister, inputRegister
                    and     #BIT0, inputRegister
                    jz      resetPort0Counter               ; Input bit and output bit are the same.
                    ;
                    ;   Now check the port counters
                    ;
                    inc     port0Count
                    cmp     #MAX_COUNTS, port0Count
                    jne     checkPort2                      ; Not enough differences.
                    ;
                    ;   Transfer the input to the output and reset the counter.
                    ;
                    bit.b   #BIT0, &P1IN
                    jz      resetPort0
                    bis.b   #BIT1, &P1OUT
                    jmp     resetPort0Counter
resetPort0          bic.b   #BIT1, &P1OUT
resetPort0Counter   mov.w   #0, port0Count
checkPort2          ;
                    ;   Checking the remaining ports is left as an exercise for later.
                    ;
                    reti

This is where calculations are performed. Note that the above code only works for one input pin but it can easily be extended to work with four pins. The first thing this routine does is to extract the input and output states of the port. It then works out if there is a difference between the input on P1.0 and the output on P1.1.

The middle block of code increments the counter and checks to see if the counter has reached the threshold. If it hasn’t then we move on to the next port.

The final block of code is executed if the port input/output are different. It transfers the input to the output and then resets the counter.

Deploying this code to the MSP430 and connecting a switch gave the following trace on the oscilloscope:

Switch With Delay

Switch With Delay

As you can see, there is a delay between the switch being depressed and the output being set. The blue trace is wired to the microcontroller input and the yellow trace is the output.

Selecting a debouncer

After many hours working on this circuit I have elected to go with Hardware Debouncing (Circuit 2) with the addition of the Schmitt inverter. This circuit is relatively simple and also meets my long term design goals for this project, namely to use only 1970/80’s technology and using logic gates where possible. It also removes the issue that the MSP430 has a maximum supply voltage of 3.6V and the remainder of this project will be working at 5V.

Selecting the Inverter

Throughout this design process I hit an issue with the inverters I have. I was trying to use the 74LS14 hex Schmitt inverter. For some reason this chip was outputting 1V on the input pin of the logic gate. I could not get the circuits above to work and in the end I ordered some 74HCT14 Schmitt Inverters. Voila, I now have a working debounce circuit.

Something to investigate later…

Reset Circuit

One possibility would be to use the output from the debounced reset switch as a reset signal. This would lead to a variable length reset pulse. Whilst an overly long reset pulse would not be an issue there may be problems if the pulse is too small. This can be solved by using an NE555 timer in monostable mode. The reset signal will still be variable but it will never be shorter than the defined by the components used to control the NE555.

The schematic for the basic monostable NE555 circuit looks as follows:

NE555 Reset Circuit

NE555 Reset Circuit

The length of the pulse is determined by the following formula:

t ~= 1.1RC

In our case R = R3 and C = C2. So this gives:

t ~= 1.1 * R3 * C2>
=> t ~= 1.1 * 45,000 * 100 * 10-9
=> t ~= 4.95ms

At 4.95ms this might be a little close to the 5ms bounce seen by some of the switches in use. Increasing the values of R3 and C = C2 will increase the duration of the reset pulse. Making R3 = 180K we see the following at the end of the signal:

NE555 End of  Reset Signal

NE555 End of Reset Signal

The full reset pulse looks like this:

NE555 Full Reset Pulse

NE555 Full Reset Pulse

Clock Circuit

The clock for the project can be broken down into two parts:

  • Oscillator
  • Clock Divider
  • Oscillator Circuit

    The oscillator circuit will provide the circuit with the “master clock”. These have been used previously on this blog in the TLC5940 circuit developed a few years ago. In the spirit of reusing old work where possible we will use the basic oscillator circuit from that post here. By changing the 8 MHz resonator for a 4 MHz part we should be able to achieve a 4 MHz master clock signal.

    The schematic for the oscillator can be found below.

    Dividing the Clock

    Dividing the clock circuit by two is easy enough to achieve using a flip-flop. The basic logic diagram is as follows:

    Flip-Flop Divider

    Flip-Flop Divider

    Circuit courtesy of Electronics Tutorials.

    This is easily implemented using the 7474 Dual D-Type Flip-Flops with Preset and Clear.

    The selection of the clock should also be easy if we make the decision that it is invalid to change the clock frequency whilst the system is running. We will rely upon the user to have the discipline not to change the clock in run mode. Since this is an initial design we can look at changing it later.

    This decision means that initially we do not have to worry about glitches due to the clock frequency being changed.

    The selection of the clock frequency can be achieved by feeding all of the clocks into one input of a dual input AND gate. The second input to the gate can then be connected to a rotary switch. The switch will connect the second input to high for the selected frequency. All of the inputs to the other gates will then be grounded. This means that only one gate allows a clock signal through to the system clock signal output.

    We can also use the debounce circuit described above to ensure a smooth transition from one clock to another.

    The schematic for this looks like this:

    Oscillator and Clock Dividers

    Oscillator and Clock Dividers

    By hooking up the logic analyser to the system clock output and the various outputs from the clock divider circuit we see the following:

    Clock and Flip Flop Output

    Clock and Flip Flop Output

    Hooking up the rotary switch to the debounce circuit and the AND gates will allow the selection of the master clock output.

    Conclusion

    The home built CPU is on it’s way. We now have a heart beat (clock) for the circuit and a method for issuing a reset request to the circuit.

    One final refinement would be the addition of a buffer driver chip to the circuit to allow for the fact that the clock and reset signals will be being fed into a larger circuit.

    MSP430 Launchpad

    Sunday, February 9th, 2014

    Shortly after it’s launch, I purchased a Texas Instruments MSP430 Launchpad board. It was about the time I had started to move away from the Netduino family of microcontrollers and started to look at alternatives to stretch myself a little more. I never managed to get the board talking to my laptop at the time and eventually gave up in frustration.

    The last week I found the board and in possession of a new laptop and new OS I decided to give it one final go. A few downloads later (about 500MB to be precise) and I have it working!

    MSP540 Launchpad

    The MSP430 Launchpad (MSP430-EXP430G2) is a small development board for the MSP430 value line microcontrollers. The board is supplied with two variants of the MSP43 microcontroller, namely the MSP430G2231 and MSP430G2211 (both in DIP form).

    I was attracted to this board for a few reasons:

    • DIP packaging means that they can be used on breadboard (also available as SMD components)
    • Cost. The microcontrollers themselves are available for as little as 50p in the UK
    • Available in a wide variety of options (memory etc.)
    • Free development tools

    The board is not a large board and it contains very little circuitry apart from the integrated debugger.

    MSP430 Launchpad

    MSP430 Launchpad

    Only thing which remained was to see if I could get it working on my PC.

    Development Tools

    When it comes to developing for the MSP430 there are two options which I considered, the Texas Instruments Code Composer Studio and IAR systems Embedded Workbench.

    Code Composer Studio is based on the popular Eclipse platform. The installation was quick and simple. The installer even asked if the add-ons for the MSP430 should be added into an existing Eclipse installation. This software does not appear to have any code restrictions.

    The IAR installation is the same IAR Embedded Workbench which I have used in the past with the STM8S. The only difference is the addition of MSP430 support. The free Kickstarter edition of this software is limited to 4Kbytes of code for traditional MSP430 devices (8KBytes for MSP430X) and you are not allowed to use the system to develop commercial applications.

    I have installed both of these tools as they both have their merits. I like the IAR compiler suite as I have one tool which I can use for the development of both MSP430 and STM8S applications. The code size limitation is unlikely to be an issue at the moment and as a hobbyist I am not intending to use the tool commercially.

    Code Composer has the advantage that it has a little integration with Texas instruments web site and examples. For instance, the Resource explorer will allow you to easily access the MSP430 Wiki pages. These are really minor advantages as the examples are freely available and the Wiki web site is easily found. The main advantage with Code Composer is that there does not appear to be any restriction on use.

    Other tools are also available and more information can be found on the Texas Instruments web site.

    Hardware

    The MSP430 Launchpad board is split into two areas. The upper quarter of the board contains the circuitry necessary to support programming chip and debugging the application deployed to the chip. The lower three quarters of the board are home to the 20 pin DIP socket for the MSP430, some headers, switches and LEDs. The headers will need to be added when you receive the board.

    The switches and two LEDs are connected to the MSP430 by default and are great for the beginner as you can start to interact with the microcontroller immediately.

    There is also space for an external oscillator should one be required.

    Connecting the Board

    This is where I ran into problems last time and sure enough it is where I ran into problems this time.

    Having installed Code Composer I expected to have everything installed which was required to start using the MSP430 Launchpad board. So I fired up Code Composer, set up a new project using one of the Blinky LED examples, plugged in the board and prepared to hit the Debug button.

    Plugging in the board gave me the usual message from Windows about a new USB device and the system set off looking for drivers. A minute or so later and I received the wonderful news that the driver could not be found.

    Great! Say hello to Mr Google.

    After a little searching I found some articles which indicated that the drivers needed updating (I’d already guessed that but always good to have it confirmed). A little more searching led me to the driver download page.

    A quick installation later and the board was still not recognised. Try another USB port (getting desperate now). Driver installation window pops up and this time no error. Hitting the debug button in Code Composer deployed my Blinky sample application.

    Interestingly, when I plugged the board into the original USB port it was recognised this time and I could deploy and debug from that port as well.

    Generating a Pulse

    Now I have a working environment it is time to write my own application. The first application I am going to attempt will generate a pulse using the internal watchdog. This is not a million miles away from the Blinky application in the samples. The main difference is that rather than use a loop to determine when the pulses are generated we will be using the in built watchdog.

    I have chose to use IAR for this project as I am already familiar with the tool. Setting up a new project works the same way as using this platform for the STM8S. The only real difference is the need to change the device and debugger types.

    First Step is to create and empty project:

    • Create a new workspace (File->New Workspace)
    • Create a new project (Project-%gt;Create New Project)
    • Select the MSP430 tool chain and a C project with a main application
    • Decide where you are going to put the application and give the project a name

    You should now have a project with one file (main.c) with the following code:

    #include "io430.h"
    
    int main( void )
    {
      // Stop watchdog timer to prevent time out reset
      WDTCTL = WDTPW + WDTHOLD;
    
      return 0;
    }
    

    Next step is to compile the code. This will force the environment to save the project workspace (only the project was saved in the above steps). So press F7 to make the project and enter a name for the workspace in the dialog which is presented. I used the same name for the workspace as I did for the project.

    Next we need to set up the device and debugger types. The device I am using is the MSP430G2231. This is the default chip installed on the board when I purchased the Launchpad. Right click on the project name in the Workspace section of the Embedded Workbench IDE and select Options…

    MSP430 Project Options

    MSP430 Project Options

    In the General Options of the dialog select the device type from the list:

    Set Device Type

    Set Device Type

    Now change the debugger type (driver) from Simulator to FET Debugger:

    Set Debugger Type

    Set Debugger Type

    Next, ensure that the connection is set to Texas Instruments USB-IF:

    Set Debugger Connection Type

    Set Debugger Connection Type

    We are now ready to type in some code and test the connection. Press Ctrl-D in the IDE and the system should connect to the launchpad and deploy the application to the chip. The IDE will highlight the first line of code to be executed:

    MSP430 Application Deployment Successful

    MSP430 Application Deployment Successful

    We are now ready to write our first application.

    #include "io430.h"
    
    //
    //  Watchdog timer ISR.
    //
    #pragma vector = WDT_VECTOR
    __interrupt void WDT_ISR(void)
    {
        //
        //  Clear the interrupt flag for watchdog timer.
        //
        IFG1 &= ~WDTIFG;
        //
        //  Toggle the output pin.
        //
        P1OUT = P1OUT ^ BIT7;
        //
        //  Go back to sleep.
        //
        __bis_SR_register_on_exit(LPM0_bits);
    }
    
    //
    //  Main program loop.
    //
    int main( void )
    {
        //
        //  Set the watchdog to 0.5ms trigger and enable the interrupt.
        //
        WDTCTL = WDT_MDLY_0_5;
        IE1 |= WDTIE;
        //
        //  Configure pin 7 on port 1 as an output pin.
        //
        P1DIR = BIT7;
        //
        //  Set pin 7 high.
        //
        P1OUT = BIT7;
        while   (1)
        {
            __bis_SR_register(LPM0_bits + GIE);
        }
    }
    

    Deploying this application to the chip and connecting up an oscilloscope to Port 1, Pin 7 gives the following trace:

    1.14KHz Pulse From MSP430

    1.14KHz Pulse From MSP430

    Success !

    Conclusion

    The availability of the MSP430 in DIP format makes it an interesting option for prototyping as you can easily breadboard your circuit. The STM8S which I have been using for a couple of years now can be breadboarded but only with the use of additional components.

    The example above should have generated a 1KHz signal as the watchdog was configured to generate an interrupt every 0.5ms. In fact the frequency was a little higher as the interrupt was being generated every 440uS instead. This is not uncommon when using the internal oscillator in a microcontroller. The frequency could be made more accurate by using an external crystal but this would complicate the circuit. For most hobbyist purposes this is accurate enough.