10150 - Only 1 LED

2011.06.30


Only 1 LED

If you have only 1 LED attached (connected) to your microcontroller, it may appear that the only thing you can do is to switch the LED on, or off. For a beginner, this is not an easy task. Even for an experienced user, reaching this stage of ‘switching one particular LED on or off’ with a new microcontroller is also significant. But of course you can do more with just one LED.


Starting with 1 LED

The LED on the kit is connected with its cathode to GPIOD bit 0. We shall refer to this pin as PD0. So, if we output a logic state of ‘0’ at PD0, the LED will be turned ‘ON’, else it will be turned ‘Off’. No, not that simple.

PD0 is the pin for bit 0 of GPIOD (General Purpose Input Output port D), which has 8 bits. But this pin is also shared with Timer 3 etc. In fact, almost every pin on the microcontroller is usually shared among a GPIO port bit and alternative functions. In using a particular GPIO port pin, it may be necessary to ensure that the alternative functions are not using the same pin, and that the pin, by default, functions as a GPIO pin. In one particular microcontroller, some pins are by default used as inputs for analogue signals. The sharing GPIO pins will not function properly unless the analogue functions are disabled.

PD0, by default, functions as a GPIO pin, and we are not activating Timer 3 yet.

Nowadays, the GPIO ports are usually bidirectional, and are in the input mode on reset.
PD0 has to be configured as an output pin, since it is connected to an LED. To configure the directions of the pins of port D, it is necessary to write an 8-bit value into the Port D Data Direction Register PD_DDR, ‘1’ for output and ‘0’ for input. Since only D0 is to be an output, the rest should be left as inputs. Thus the hexadecimal value 0x01 (=00000001 binary) has to be written to PD_DDR.

A logic gate output may have push-pull(‘1’) or open-drain(‘0’) mode, as configured by the function register PD_CR1. We will select the push-pull mode, while you read up on open-drain mode, if you are confused. You may find that open-drain mode works in the case for the LED because its cathode is connected to the pin.

In addition, to avoid electromagnetic interference, the microcontroller allows you to choose slower switching for the output pins, using PD_CR2. Again, for the time being, you would not notice any difference for this choice. Still it is a good practice to define the speed for completeness.

If you find such configurations tedious, and hard to remember “1 for output” etc, you are not alone. This is the classic approach. There is a better way, but that has to wait. Meanwhile, you still have to know the characteristics of a port pin briefly described above. In fact, you are expected to read the RM0016 Reference Manual, thoroughly. So that we only have to say, “Configure PD0 as a slow push-pull output and output a ‘0’ to turn on the LED.” And here is the program:

//  main12  On-board LED  ON

#include <iostm8s105c6.h>

int main( void ){

  PD_ODR = 0x00 ;   // PD0  On-board LED  (0)ON
  PD_DDR = 0x01 ;   // Output
  PD_CR1 = 0x01 ;   // Push Pull
  PD_CR2 = 0x00 ;   // Slow

  return 0;
}

Changing  PD_ODR = 0x00 ;  to  PD_ODR = 0x01 ;  will turn off the LED.


Still with 1 LED

It may appear silly just to write a program to turn on one LED. And then write another program to turn it off. But this is necessary to verify that the programs do work, in addition to getting familiar with the IDE.

By the way, did you verify that “The LED can be turned ON only if PD0 had been configured as an output pin” ?

Let us move on.

If you can turn on and off an LED, you can then blink the LED by turning it on and off repeatedly. All that is required is to add some time delay after each change. This is necessary because the microcontroller is a high-speed device. For the present moment, the easiest method to add time delay is to do some counting. In the long run, this is not a practical method. So, for example, after turning the LED on (or off), we let the microcontroller count for about 50000 times, which it does quite rapidly. In fact, if it counts much less, say 500 times, your eyes would not be able to see the blinking. Try 5000. But if you want to try 100000, you may have to revise your C language.

Here is the blinking program:

//  main23  On-board LED  Blink

#include <iostm8s105c6.h>

int main( void ){
 
  unsigned int i ;
 
  PD_ODR = 0x00 ;   // PD0  On-board LED  (0)ON
  PD_DDR = 0x01 ;   // Output
  PD_CR1 = 0x01 ;   // Push Pull
  PD_CR2 = 0x00 ;   // Slow
 
  while(1){
    PD_ODR = 0x00 ;       // PD0  On-board LED  '0'=ON
    for(i=0;i<65500;i++); // Software delay
    PD_ODR = 0x01 ;       // PD0  On-board LED  '1'=Off
    for(i=0;i<65500;i++); // Software delay
  }
  
  return 0;
}

The blinking speed can be adjusted by changing the value 65500. Again, there is a high limit on this number, if you remember your C language.

From here, it should be quite obvious that just 1 LED can give different signals. For example, it can blink once, turn off for a while, then blink twice, turn off for a while, …


It can do more

Let us try another program.

//  main33  On-board LED  Brightness Control

#include <iostm8s105c6.h>

int main( void ){
 
  unsigned int i,k ;
 
  PD_ODR = 0x00 ;   // PD0  On-board LED  (0)ON
  PD_DDR = 0x01 ;   // Output
  PD_CR1 = 0x01 ;   // Push Pull
  PD_CR2 = 0x00 ;   // Slow
 
  while(1){
    for(k=5;k<995;k++){
    PD_ODR = 0x00 ;           // PD0  On-board LED  '0'=ON
    for(i=0;i<k;i++);         // ON delay
    PD_ODR = 0x01 ;           // PD0  On-board LED  '1'=Off
    for(i=0;i<(1000-k);i++);  // Off delay
    }
  }
  
  return 0;
}

I leave it to you to understand the program. To see clearly, you may want to cover the red debugging light on the other half of the board.


Bit Operations

A port pin is usually used to turn on (and off) a light or a motor. Although we can connect LED’s to a port of 8 bits, we do not usually turn on 8 lights or motors at the same time. At any one time, only one bit of a port is turned on or off. C language does not include binary numbers. Most operations involving bits are expressed in character variables, using logic operations ‘AND’, ‘OR’ etc. Some C compilers do allow bit operation statements. But different compilers handle such bit operations differently. It is best to write in portable C statements.

Thus to set bit 0 or port B, an ‘OR’ operation is used, writing in hexadecimal notation as PB_ODR = PB_ODR | 0x01. And to clear bit 0, an ‘AND’ operation is used as PB_ODR = PB_ODR & 0xFE. A few bits may be set or clear with one statement. And then there is the ‘exclusive OR’ operation.