Page 1 of 1
reading status inport
Posted: Mon Feb 21, 2011 3:01 pm
by Oberoid
Hi,
does anyone can explain me how can i read the status of an input port.
I have several micro switches attached to my LPC2138 AE edu board and I would like to use them.
Is there a status register wich can be read?
Greets,
F.P.
Re: reading status inport
Posted: Tue Feb 22, 2011 12:23 am
by cfbsoftware
The five pushbuttons on the EA LPC2138 board are connected to pins P0.14 and P1.16-19.
You can access these via the GPIO registers which are defined as IOPIN0 (for pins P0.*) and IOPIN1 (for pins P1.*) in the Astrobe LPC2138 module.
The status of each bit in the register corresponds to the status of one of 32 pins. e.g. the code to check if P1.17 is pressed would look something like this:
Code: Select all
IMPORT LPC := LPC2138, SYSTEM, Main;
...
IF SYSTEM.BIT(LPC.IOPIN1, 17) THEN ...
Refer to Chapter 8 GPIO in the NXP LPC2138 User Manual (UM10120) for more details. If you haven't already got a copy download it from the NXP support site:
http://ics.nxp.com/support/documents/?search=UM10120
Re: reading status inport
Posted: Tue Feb 22, 2011 9:24 am
by Oberoid
Now I now where I can use the SYSTEM.BIT procedure for.
I was trying out SET operations on the status register but maybe this is easier and clearer.
The tutorial of Embedded artists is using a shift register and I would like to explore its functionality by manipulating its control lines myself.
Polling vs interrupt driven programming is another topic that i would like to investigated with buttons.
Thanks for the answer.. I will try it out.
Greets,
F.P.
Re: reading status inport
Posted: Sat Feb 26, 2011 11:03 pm
by Oberoid
I am intrigued by the article "SET: A neglected data type, and its compilation for the ARM" (Wirth 2008)
https://www.astrobe.com/wirth/SETs.pdf and try to apply set types to io registers.
I found this example code in the specification of the SYSTEM.mod of the Oberon System.
http://www-old.oberon.ethz.ch/SYSTEM.html
Code: Select all
PROCEDURE Testbit*; (* Test the presence of a specific bit in scr *)
BEGIN
IF SYSTEM.BIT(SYSTEM.ADR(scr), 6) THEN END; (* first approach *)
IF 6 IN SYSTEM.VAL(SET, scr) THEN END; (* better approach *)
(* or even better, declare scr2 as a SET to starts with *)
SYSTEM.GET(SYSTEM.ADR(value), SYSTEM.VAL(SET, scr2)); (* from memory *)
IF 6 IN scr2 THEN END;
END Testbit;
However, I'm wondering if a procedure, something like Ports.In(port: PORT, VAR status: Status), could be useful.
As a beginner I want to check or set the status of an Port by using the Ports name, eg P101,as a value parameter.
Also the precondition that the port to be read is set as an In port should be met. Maybe with an global variable: Ports.Done a successful read action can be verified.
What would you think is the wisest approach to reading ports: the SYSTEM.BIT, the SYSTEM.GET(SYSTEM.ADR(value), SYSTEM.VAL(SET, scr2)) or the Ports.In(p101, status) way?
Re: reading status inport
Posted: Sun Feb 27, 2011 4:30 am
by cfbsoftware
Some points to be considered before implementing such a module:
- The number of ports that are available depends on the LPC2xxx device being targeted. A general solution would need to support from 1 to 4 ports.
- 4 ports with 32 pins each gives 128 possible values. A system of names P000 to P331 would be unwieldy. I would suggest two parameters: port number and pin number. Port number could be named constants if preferred e.g.
Code: Select all
CONST
Port0* = 0;
Port1* = 1;
Port2* = 2;
Port3* = 3;
However, I see little value in identifying a pin by anything else but its number 0..31.
- User-defined types in Oberon-07 are restricted to pointers, arrays and records. Type aliases (e.g. the proposed types Port and Status) are not supported.
- Some MCUs have fast IO port access (FIO) as well as the legacy (GPIO) system.
Possible precondition checks are:
- Are the Port number and pin number in range?
- Does the port exist on the current target?
- Is the pin available for use as a GPIO pin on the current target? Too complex a check to be worth doing?
Note that IOPIN always returns the status of a pin whether it is defined as an input or output pin so it might only be necessary to check its direction when writing to it.
Given all of the above one possible approach is:
Code: Select all
GPIO.In(CONST portNo, pinNo: INTEGER; VAR value: BOOLEAN);
GPIO.Out(CONST portNo, pinNo: INTEGER; CONST value: BOOLEAN);
If you had a board with pushbuttons connected to pins 0.15 to 0.18 and you wanted them to control leds on pins 1.17 to 1.20 respectively you could write something like:
Code: Select all
(* Untested! *)
FOR pin := 15 TO 18 DO
led := pin + 2;
GPIO.In(port0, pin, state);
GPIO.Out(port1, led, state)
END;
Without a GPIO module I would write it like this:
Code: Select all
(* Untested! *)
SYSTEM.GET(LPC.IOPIN0, port0);
FOR pin := 15 TO 18 DO
led := pin + 2;
IF pin IN port0 THEN
SYSTEM.PUT(LPC.IOCLR1, {led})
ELSE
SYSTEM.PUT(LPC.IOSET1, {led})
END
END
If realtime performance was a critical issue the latter solution would be preferable. Otherwise the choice would depend on the preferences of the individual programmer.
Re: reading status inport
Posted: Sun Feb 27, 2011 11:53 pm
by cfbsoftware
Oberoid wrote:I found this example code in the specification of the SYSTEM.mod of the Oberon System.
Code: Select all
(* or even better, declare scr2 as a SET to starts with *)
SYSTEM.GET(SYSTEM.ADR(value), SYSTEM.VAL(SET, scr2)); (* from memory *)
By definition
SYSTEM features are highly platform/implementation-dependent. To avoid confusion you should always refer to the implementation-specific documentation of the Oberon system that you are curently targeting for information on how to use the SYSTEM features. In Astrobe v3.2 refer to Section
7.23 SYSTEM of the document "Oberon for LPC2000 Microcontrollers".
There you will see that the second parameter of SYSTEM.GET is of type <any basic type>. Hence the SYSTEM.VAL typecast is unnecessary. Typically in Astrobe, the first parameter to SYSTEM.GET is already an address e.g. one of the register address constants defined in the module LPC.mod. Hence the SYSTEM.ADR is not required either. Consequently in Astrobe code, typical examples of the use of SYSTEM.GET are:
Using INTEGER variables:
Code: Select all
(* Real Time Clock *)
VAR
hours, minutes, seconds: INTEGER;
...
...
SYSTEM.GET(LPC.HOUR, hours);
SYSTEM.GET(LPC.MIN, minutes);
SYSTEM.GET(LPC.SEC, seconds);
Using SET variables:
Code: Select all
(* GPIO pin configuration *)
VAR
selection, direction: SET;
...
...
(* Pins P0.16..P0.18, P0.26..P0.29 are configured for GPIO usage by clearing the relevant bits *)
SYSTEM.GET(LPC.PINSEL1, selection);
SYSTEM.PUT(LPC.PINSEL1, selection - {0..5, 20..27});
(* Pins P0.16..P0.18, P0.26..P0.29 are configured as outputs by setting the relevant bits*)
SYSTEM.GET(LPC.IODIR, direction);
SYSTEM.PUT(LPC.IODIR, direction + {16..18, 26..29});