Mbed BK Ed2 CH 14
Mbed BK Ed2 CH 14
If you use or reference these slides or the associated textbook, please cite the original authors’ work as follows:
Toulson, R. & Wilmshurst, T. (2016). Fast and Effective Embedded Systems Design - Applying the ARM mbed
(2nd edition), Newnes, Oxford, ISBN: 978-0-08-100880-5.
www.embedded-knowhow.co.uk
Letting Go of the mbed Libraries
The mbed library contains many useful functions, which allow us to write simple
and effective code. This seems a good thing, but it is also sometimes limiting.
What if we want to use a peripheral in a way not allowed by any of the
functions? Therefore it is useful to understand how peripherals can be
configured by direct access to the microcontroller’s registers. In turn, this leads
to a deeper insight into some aspects of how a microcontroller works. As a by-
product, and because we will be working at the bit and byte level, this study
develops further skills in C programming.
Control Register Concepts
How does the CPU, running its program, communicate with all the peripherals
on the microcontroller?
Control Register Concepts
Each microcontroller peripheral has one or more system control registers which
act as the doorway between the peripheral and the CPU.
To the CPU, these
registers look just like
memory locations, and
each has its own address
in the memory map.
The microcontroller
peripherals also usually
generate interrupts, for
example to flag when an
ADC conversion is
complete.
mbed Digital I/O Control Registers
Using the control registers, it is possible to set each port pin as an input or as an
output. Each port has a 32-bit register whose bits control the direction of each of
its pins, called the FIODIR registers. There are also single-byte versions.
A second set of registers, called FIOPIN, hold the data value of the
microcontroller’s pins, whether they have been set as input or output.
76(P0.9/MOSI1)
77(P0.8/MISO1)
78(P0.7/SCK1)
79(P0.6)
46(P0.0/TXD3/SDA1)
47(P0.1/RXD3/SCL1)
60(P0.18/MOSI) 81(P0.4/CAN_RX2)
61(P0.17/MISO) 80(P0.5/CAN_TX2)
62(P0.15/TXD1/SCK) 48(P0.10/TXD2/SDA2)
63(P0.16/RXD1) 49(P0.11/RXD2/SCL2)
9(P0.23/AD0.0) 75(P2.0/PWM1.1)
8(P0.24/AD0.1) 74(P2.1/PWM1.2)
7(P0.25/AD0.2) 73(P2.2/PWM1.3)
6(P0.26/AD0.3/AOUT) 70(P2.3/PWM1.4)
21(P1.30/AD0.4) 69(P2.4/PWM1.5)
20(P1.31/AD0.5) 68(P2.5/PWM1.6)
/*Program Example 14.1: Sets up a digital output pin using control registers, and
flashes an led.
*/
// function prototypes
void delay(void);
int main() {
FIO2DIR0=0xFF; // set port 2, lowest byte to output
while(1) {
FIO2PIN0 |= 0x01; // OR bit 0 with 1 to set pin high
delay();
FIO2PIN0 &= ~0x01; // AND bit 0 with 0 to set pin low
delay();
}
}
//delay function
void delay(void){
int j; //loop variable j
for (j=0;j<1000000;j++) {
j++;
j--; //waste time
}
}
Digital Inputs
We can create digital inputs simply by setting a port bit to input, using the
correct bit in an FIODIR register. Program Example 14.3 develops the previous
example, by including a digital input from a switch.
/* Program Example 14.3: Uses digital input and output using control registers, and
flashes an LED. LEDS connect to mbed pins 25 and 26. Switch input to pin 9.
*/
// function prototypes
void delay(void);
//Define Digital I/O registers
#define FIO0DIR0 (*( volatile unsigned char *)(0x2009C000))
#define FIO0PIN0 (*( volatile unsigned char *)(0x2009C014))
#define FIO2DIR0 (*(volatile unsigned char *)(0x2009C040))
#define FIO2PIN0 (*(volatile unsigned char *)(0x2009C054))
//some variables
char a;
char b;
char i;
int main() {
FIO0DIR0=0x00; // set all bits of port 0 byte 0 to input
FIO2DIR0=0xFF; // set port 2 byte 0 to output
while(1) {
if ((FIO0PIN0&0x01)==1){ // bit test port 0 pin 0 (mbed pin 9)
a=0x01; // this reverses the order of LED flashing
b=0x02; // based on the switch position
}
else {
...
...
The Pin Select Register
The PINSEL register can allocate each pin to one of four possibilities. An
example of part of one register, PINSEL1, is shown. This controls the upper half
of Port 0.
(From LPC17xxx
User Manual Rev.
3.1, UM10360)
The Pin Mode Register
As an example, PINMODE0 is shown. This controls the input characteristics of the
lower half of Port 0. The pattern is the same for every pin, so there’s no need for
repetition. Pull-up and pull-down resistors can be enabled. The repeater mode is a
facility which enables pull-up resistor when the input is a Logic 1, and pull-down if
it’s low. If the external circuit changes so that the input is no longer driven, then the
input will hold its most recent value.
Power Control Registers
To conserve power, it is possible to turn off power and clock to many of the
LPC1768 peripherals. This power management is controlled by the PCONP
register, seen in part here. Where a bit is set to 1, the peripheral is enabled.
Clock Select Registers
Some control is possible over the peripheral’s clock frequency, using the
PCLKSEL registers. This will control the peripheral’s speed of operation and
hence its power consumption. Peripheral clocks are taken from the clock which
drives the CPU, called CCLK. For the mbed, CCLK runs at 96 MHz. Partial
details of PCLKSEL0 are shown. Two bits are used per peripheral to control the
clock frequency to each. The four possible combinations are also shown.
Using the DAC
The LPC1768 DAC has a set of control registers.
DAC power is always enabled, so there is no
need to consider the PCONP register.
The only pin that the DAC output is available on is
Port 0 pin 26, so this must be allocated through
PINSEL1 (where DAC output is labelled AOUT).
This pin is connected to mbed pin 18.
The only register specific to the DAC that we use is the DACR register, shown
here. On the LPC1768 the reference voltage is applied between terminals
labelled VREFP and VREFN; these are connected to 3.3 V and 0 V respectively.
A DAC Application
Program Example 14.4 replicates the simple sawtooth waveform, as first
achieved in Chapter 4. An integer variable, dac_value, is repeatedly
incremented and transferred to the DAC input, in register DACR. It has to be
shifted left 6 times, to place it in the correct bits of the DACR register.
/* Program Example 14.4: Sawtooth waveform on DAC output. View on oscilloscope. Port
0.26 is used for DAC output, i.e. mbed Pin 18
*/
// function prototype
void delay(void);
// variable declarations
int dac_value; //the value to be output
int main(){
PINSEL1=0x00200000; //set bits 21-20 to 10 to enable analog out on P0.26
while(1){
for (dac_value=0;dac_value<1023;dac_value=dac_value+1){
DACR=(dac_value<<6);
delay();
}
}
}
// function prototype
void delay(void);
int main() {
FIO2DIR0=0xFF;// set lower byte of Port 2 to output, this drives bar graph
// shift data 4 bits to right justify, and 2 more to give 10-bit ADC value
ADCdata=(ADCdata>>6)&0x03FF; //and mask
DACR=(ADCdata<<6); //could be merged with previous line,
// but separated for clarity
//delay(); //insert delay if wished
}
}
…
A Conclusion on Using the Control Registers