As mentioned in the first section, the LPC1114 processor is a 32-bit processor, but its GPIO port does not connect all 32 pins, but only connects 12 pins per group (note that the fourth group only connects 6 pins), with a total of 4 groups and 42 pins. They all have the following characteristics:
1. GPIO pins can be configured as input or output by software
2. Each independent port pin can be used as an input pin for external interrupt (edge or level triggered)
3. Edge-triggered interrupts can be configured as rising edge triggered, falling edge triggered, and dual edge triggered
4. Level-triggered interrupt pins can be configured as high level or low level triggered
5. All GPIO pins are input by default
6. Reading and writing data from the port can be masked by address bits 13:2
The specific usage and configuration of the port will be discussed later. Here we first look at how the structure of the "general purpose input/output port GPIO" is defined. The code is as follows.
typedef struct
{
union {
__IO uint32_t MASKED_ACCESS[4096]; /*!< Offset: 0x0000 to 0x3FFC Port data Register for pins PIOn_0 to PIOn_11 (R/W) */
struct {
uint32_t RESERVED0[4095];
__IO uint32_t DATA; /*!< Offset: 0x3FFC Port data Register (R/W) */
};
};
uint32_t RESERVED1[4096];
__IO uint32_t DIR; /*!< Offset: 0x8000 Data direction Register (R/W) */
__IO uint32_t IS; /*!< Offset: 0x8004 Interrupt sense Register (R/W) */
__IO uint32_t IBE; /*!< Offset: 0x8008 Interrupt both edges Register (R/W) */
__IO uint32_t IEV; /*!< Offset: 0x800C Interrupt event Register (R/W) */
__IO uint32_t IE; /*!< Offset: 0x8010 Interrupt mask Register (R/W) */
__I uint32_t RIS; /*!< Offset: 0x8014 Raw interrupt status Register (R/ ) */
__I uint32_t MIS; /*!< Offset: 0x8018 Masked interrupt status Register (R/ ) */
__O uint32_t IC; /*!< Offset: 0x801C Interrupt clear Register (R/W) */
} LPC_GPIO_TypeDef;
The above code defines the structure of the GPIO port of LPC1114. Since GPIO is located in the AHB part of the memory map, it can be seen from the code that, like the structure discussed above, the member variables it defines are mapped to the GPIO registers in the AHB using offset addresses. The special part is that there is an additional definition of union. To understand this definition, we must go back to the register description of the AHB module. The following figure shows the register distribution of the GPIO part in the AHB module.
The GPIODATA register is the data register of the GPIO. The data stored in it is directly output to the GPIO pins, and the data input by the pins will also be placed in this register. Therefore, to control the level of the port (whether input or output), the GPIODATA register must be operated. Similarly, the GPIODATA register is also a 32-bit structure, and its address occupies 4 bytes. However, the GPIO port has only 12 pins, so the GPIODATA register only uses the lower 12 bits to map the GPIO port pins.
It can also be seen from the above figure that the offset address of the GPIODATA register is from 0x0000 to 0x3FFC. The highest address is 0x3FFC because each GPIODATA register unit occupies 4 bytes, so there are 0x3FFC/4=0xFFF (i.e. 4095) GPIODATA register units in total. Since the address is counted from the 0th unit, there are a total of 4096 units. And 2 to the 12th power is exactly equal to 4096, so it can just represent the capacity of 12 pins. From this, it can be seen that the value of each pin level (whether input or output) can find a corresponding unit in the GPIODATA register (because there are 4096 pin states and there are 4096 GPIODATA address units). Why is this done? Why not use a port register to describe the port pins (let's call it "method one"), and write (or read) this port register? In fact, most other microcontrollers do this. Here, LPC1114 has to spend 4096 address units to describe all the pin states (let's call it "method 2"), and there must be a reason for it. In fact, it should be said that LPC1114 includes both methods (because strictly speaking, "method 1" is included in "method 2"). As for the advantage of "method 2", it is actually that the level on a certain pin can be changed without changing the state of other pins. In theory, "method 1" can also achieve this function through the logical operation of "and or" (other microcontrollers do the same), but it must be achieved through the steps of "read-modify-write". For example, to achieve the output of a high level only for the 7th pin of the P0 port, the program can be written as "P0 |= 1<<7", which is actually "P0 =P0| 0b10000000", which shows that it first reads the value of P0, then modifies it (and 0b10000000), and finally writes the result back to P0. Method 2 is much simpler, and it is enough to directly access the unit with address 0b10000000. The following is a detailed discussion of how method 2 implements bit operations.
In order to implement the bit operation of "Method 2", a new concept - mask (MASK) is introduced in LPC1114. It uses a 14-bit structure to describe the mask operation. Only the port pin value corresponding to the bit with a value of 1 in the mask structure will take effect. For example, if you want to change the level of the 7th pin of the port, then in the mask structure corresponding to this port, the value of the mask bit corresponding to the 7th pin must be 1. At the same time, it should be noted that the mask bit does not correspond to the port position one by one, but the mask structure as a whole is "shifted left" by two bits to correspond! Since the number of port pins is 12, and the mask structure is "shifted left" by two bits as a whole, it needs to be described by a 14-bit structure. Based on this, the mask bit corresponding to the 7th pin just now should be the 9th bit. To change the level of the 7th pin, the value of the 9th bit in the mask structure must be 1. This process can be described by the following figure. As for why the mask structure needs to be "shifted left" by two bits, it will be discussed in detail later.
It can also be seen from the above figure that the address of GPIODATA is GPIO base address + shield address (offset address). There are 4 groups of GPIO ports in LPC1114, and their base addresses are: port0 is 0x50000000; port1 is 0x50010000; port2 is 0x50020000; port3 is 0x50030000. Each group of ports has its own shield address. The 4 groups of GPIO base addresses plus their respective shield addresses are: port0 is 0x50000000~0x50003FFC; port1 is 0x50010000~0x50013FFC; port2 is 0x50020000~0x50023FFC; port3 is 0x50030000~0x50033FFC. Each group has 4096 32-bit units.
Next, let's discuss why the shield structure needs to be "left-shifted" two bits before it can be matched. There is no explanation for this even in the management documents. But through observation, it can be seen that although the shield structure is described by only 14 bits, since the processor itself is a 32-bit structure, the length of each shield structure itself is still 32 bits, but it only uses the lower 14 bits. In other words, a shield structure takes up 4 bytes of address. And all (4096) shield structures will occupy 4×4096 addresses. Because the address is counted from 0, the address occupied by the entire shield structure is 4×4096-1=16383, which is 0x3FFC in hexadecimal. Corresponding to the "GPIO Register Distribution Table" above, it will be found that this value is exactly the maximum value of the GPIODATA register address offset. What is the relationship between the two? In fact, it can only prove one point, that after the concept of shield structure is introduced, the shield structure is the GPIODATA register! More precisely, it is the GPIODATA register with address 0x000~0x3FF8 (because the last shielding structure with address 0x3FFC is not shielded at all (all values are 1), it can be considered that it has no shielding effect, so it is generally used as a port register (ie "method one")).
Now let's go back to the "GPIO register distribution table" and see that the address of GPIODATA in the first row is 0x000~0x3FF8, which is actually 4095 shield structures, each occupying 4 bytes of address, corresponding to "method 2" when used; the address of GPIODATA in the second row is 0x3FFC, which is equivalent to the port register, occupying a total of 4 bytes of address, corresponding to "method 1" when used. But you can only choose one of the two methods, you can't use both methods at the same time!
Since the union (or union) in C language has the feature of address space reuse, it is most appropriate to use the union to define GPIODATA. The following is a separate discussion of this part of the definition, the code is as follows.
union {
__IO uint32_t MASKED_ACCESS[4096]; /*!< Offset: 0x0000 to 0x3FFC Port data Register for pins PIOn_0 to PIOn_11 (R/W) */
struct {
uint32_t RESERVED0[4095];
__IO uint32_t DATA; /*!< Offset: 0x3FFC Port data Register (R/W) */
};
};
It can be seen that two parts of reused content are defined in the union. The first part is a "uint32_t" type MASKED_ACCESS (masked) array, which defines a total of 4096 element spaces. Each array element occupies a 4-byte address, and the 4096 MASKED_ACCESS arrays occupy a total address space of 0x3FFC. Each unit has a readable and writable attribute (__IO). From the address allocation, it can be seen that this array includes all masked structure parts from masking all bits (address 0x0000) to not masking any bits (address 0x3FFC). MASKED_ACCESS[0] corresponds to address 0x0000, masking all bits; MASKED_ACCESS[1] corresponds to address 0x0004 (each occupies 4 bytes), the binary number is 0b00000000000100 (14 bits, shifted left by two bits to correspond), that is, the port's 0th pin is not masked; MASKED_ACCESS[2] corresponds to address 0x0008, the binary number is 0b00000000001000 (14 bits, shifted left by two bits to correspond), that is, the port's 1st pin is not masked; MASKED_ACCESS[3] corresponds to address 0x000C , the binary number is 0b00000000001100 (14 bits, shifted left two bits to correspond), that is, the 0th and 1st pins of the port are not masked; MASKED_ACCESS[4] corresponds to the address 0x0010, and the binary number is 0b00000000010000 (14 bits, shifted left two bits to correspond), that is, the 2nd pin of the port is not masked; and so on; the last array element is MASKED_ACCESS[4095], the corresponding address is 0x3FFC, and the binary number is 0b11111111111100 (14 bits, shifted left two bits to correspond), that is, no port pins are masked.
At this point, we should be able to answer the previous question "Why is the mask structure represented by 12 bits shifted left by 2 bits?" This is because there is a 4-byte difference between each MASKED_ACCESS array element. In order for each mask structure to correspond to its corresponding array element, each mask structure must be multiplied by 4. However, in bit operations, shifting left by 2 bits is equivalent to multiplying by 4, so using a 14-bit mask structure shifted left by 2 bits is equivalent to multiplying each mask structure by 4, which eliminates the need to multiply 4 by 4 for all 4096 mask structures! This is the real reason why the mask structure needs to be shifted left by two bits!
The second part of the union is a variable DATA of type "uint32_t". Because 4095 empty arrays of type "uint32_t" are defined before it, the first 4095 units in the shield structure are avoided. Therefore, the starting address of the final variable DATA is 0x3FFC, which is the address of the last shield structure. As mentioned earlier, the value of the last shield structure is all 1, that is, no shielding. The variable DATA is used here to replace the last shield structure, which is very clever. It is equivalent to writing a value to DATA, and the corresponding level can be obtained on the pin of the port. At this time, it can be considered as a port register, not a shield structure. DATA must also have readable and writable attributes (__IO).
Let's use an example to illustrate the whole process. For example, how do you make bits 0, 3, and 10 of group 0 GPIO output 1, while keeping the other bits unchanged?
First of all, if we want these three bits to output 1, we need to write 1 to the mask bits corresponding to these three bits. Then the corresponding 14-bit mask structure should be "0b01000000100100", which is "0x1024" in hexadecimal. This "0x1024" is a unit between the addresses 0x0000~0x3FFC, which is mapped to one of the 4096 MASKED_ACCESS array elements through the union. But which MASKED_ACCESS array element is it? Since there is a 4-fold relationship between them, 0x1024/4=0x409, which is 1033 in decimal, that is, MASKED_ACCESS[1033] unit. The data written to the port is 12 bits without left shift, that is, "0b010000001001", which is exactly "0x409" in hexadecimal, and 1033 in decimal, which is the number of the array element. Therefore, by executing MASKED_ACCESS[1033]=0x409, it is possible to output 1 for bits 0, 3, and 10. In fact, executing MASKED_ACCESS[1033]=0xFFF has the same effect, because except for bits 0, 3, and 10, which are 1, the other bits can be any value. Similarly, to output 0 for bits 0, 3, and 10, executing MASKED_ACCESS[1033]=0x000 and executing MASKED_ACCESS[1033]=0xBF6 have the same effect.
So in summary, the array unit that MASKED_ACCESS wants to reference is the decimal number of the 12-bit value to be output to the pin. Of course, to actually reference it, you also need to perform address mapping in the predefined part of the program, as shown below.
#define LPC_AHB_BASE (0x50000000UL)
#define LPC_GPIO0_BASE (LPC_AHB_BASE + 0x00000)
#define LPC_GPIO1_BASE (LPC_AHB_BASE + 0x10000)
#define LPC_GPIO2_BASE (LPC_AHB_BASE + 0x20000)
#define LPC_GPIO3_BASE (LPC_AHB_BASE + 0x30000)
#define LPC_GPIO0 ((LPC_GPIO_TypeDef *) LPC_GPIO0_BASE )
#define LPC_GPIO1 ((LPC_GPIO_TypeDef *) LPC_GPIO1_BASE )
#define LPC_GPIO2 ((LPC_GPIO_TypeDef *) LPC_GPIO2_BASE )
#define LPC_GPIO3 ((LPC_GPIO_TypeDef *) LPC_GPIO3_BASE )
With the above pre-definition, the previous example can be implemented by executing LPC_GPIO0->MASKED_ACCESS[1033]=0x409.
Let's review the operation on port 2 in the first demonstration example. The main code is as follows.
while(1)
{
LPC_GPIO2->DATA = 0xAAA;
delay_ms(500);
LPC_GPIO2->DATA = 0x555;
delay_ms(500);
}
From this, we can see that it is implemented by "method 1", that is, directly writing to the DATA variable. Because all 12 bits are changing, this method is used.
As for the rest of the union definition, since it is the same as the SYSCON analysis, you can refer to the previous content for analysis, so I will not repeat it here. Finally, don't forget that since the union is introduced in the program, you need to add the sentence "#pragma anon_unions" in the predefined part, which has been explained in the previous chapter. If you use the header file inclusion method, the definition exists in the header file LPC11xx.h.
Previous article:LPC1114 General Purpose Input/Output Ports (GPIO) Continued
Next article:Simulation of clock configuration
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- Sn-doped CuO nanostructure-based ethanol gas sensor for real-time drunk driving detection in vehicles
- Design considerations for automotive battery wiring harness
- Do you know all the various motors commonly used in automotive electronics?
- What are the functions of the Internet of Vehicles? What are the uses and benefits of the Internet of Vehicles?
- Power Inverter - A critical safety system for electric vehicles
- Analysis of the information security mechanism of AUTOSAR, the automotive embedded software framework
- [ESP32-Korvo Review] 07 Compile the first project hello world
- 【Project source code】Design of XPT2046 touch controller based on FPGA
- MCU restart freeze problem help
- How to use an op amp to control the FB feedback pin of an adjustable power supply?
- TTGO-LCD development board example
- National Technology N32G032 Motor Control Board Hardware Usage Guide
- What is a Class D power amplifier?
- CBB capacitors and monolithic capacitors have better frequency characteristics, small dielectric loss, wide response range, high insulation impedance, and no polarity.
- Recommend a mall for purchasing electronic components: free shipping for new customers’ first order, and also provide services such as sample application and technical support!
- Membrane switch components