GPIO Principles

GPIOs are the interface between the PSoC™️ and the outside world. They allow you to connect the PSoC™️ to just about any type of external component, be it analog or digital. To enable this functionality, PSoC™️ GPIOs can take on any one of 14 different drive modes. Each drive mode is a combination of of 7 output configurations along with the selection to enable or disable the input buffer. When enabled, the input buffer allows the CPU to directly read a digital value from the pin. The output configurations that PSoC™️ GPIOs can take on are the following below.

Drive Mode

A drive mode is essentially a specific electrical configuration that a GPIO can take on. The PSoC™️ GPIOs support seven primary drive modes:

Strong

Used for digital outputs, able to pull the pin high or low. These are often used for LEDs.

High Impedance

(High-Z) – Used for digital input pins and analog pins.

Resistive Pull Up

Able to drive the pin low, but only pulls the pin high through a resistor so that an external source can force the pin low. These are often used for active low buttons.

Resistive Pull Down

Able to drive the high, but only pulls the pin low through a resistor so that an external source can force the pin high.

Open Drain Drives Low

Able to drive the pin low, can be pulled high externally. These are often used for wired-or communication standards such as I2C.

Open Drain Drives High

Able to drive the pin high, can be pulled low externally.

Resistive Pull Up and Down

DC biases the pin, useful for some analog pins. Also allows external sources to force the pin to the opposite state.

External Components

LED (Light Emitting Diode)

An LED is a device that glows when you pass electrical current through it. The brightness of the LED depends on the amount of current that passes through it. If you pass too much current through the LED it will blow up (think fire and smoke). In general, LEDs are connected in series with a resistor that limits the amount of current (remember Ohms law? V=IR... look at the schematics below). You can vary the brightness of an LED by either controlling the input voltage (which limits the current) or by "blinking" the LED faster than the human eye can see and varying the duty-cycle (see PWM). An LED is connected to a PSoCTM in one of two ways:

  • Active High (driving the LED with a "1" lights it up)

  • Active Low (driving the LED with a "0" lights it up)

Mechanical switch (push-button)

A mechanical switch is an electromechanical device that electrically connects two terminals when it is in the closed position. A very common type of switch is a push-button. In this case, the terminals are connected when the button is pressed. When connecting a button to a PSoCTM, the pin is typically configured using a resistor that pulls the PSoCTM input to either Vdd or Vss. This is done so a separate resistor is not required on the board.

On Infineon development kits, buttons are typically active low and do not have a separate resistor so the pin should be configured as an input with resistive pullup and the pin's initial state should be set to a 1 so that the pin will be pulled high when the button is not being pressed.

The circuit can be configured as:

  • Active High (when the button is pressed the PSoCTM reads "1")

  • Active Low (when the button is pressed the PSoCTM reads "0") The active low case is much more common.

The active low case is much more common.

Potentiometer (a.k.a. pot)

A pot is a 3-terminal electromechanical (meaning that mechanical movements cause electrical actions) analog device. Two of its terminals normally connect to power and ground while the third terminal is used for output. The output terminal produces a voltage that varies between power and ground based on the position of the dial. Mechanically, a pot uses a sliding contact along a resistor to form an adjustable resistor voltage divider. A pot may be thought of as simply an analog voltage reference source.

The arrow in the pot schematic symbol represents the variable contact, controlled by turning the dial. As the contact slides toward the power rail (Vdd), the output voltage (Vout) rises higher. As the contact slides toward ground (Vss), Vout drops.

สำหรับการเขียนโปรแกรมติดต่อกับ GPIO บน PSoC™️ ไม่ว่าจะเป็นการตั้งค่าเริ่มต้นให้กับแต่ละ pin (Pin Configuration and initialization) การอ่าน/เขียนข้อมูล (Read and Write Data) รวมถึงการทำให้ pin สามารถสร้างสัญญาณอินเทอร์รัพท์ (Interrupt Generation) ตามการเปลี่ยนของสัญญาณ (rising, falling หรือ ทั้งสองกรณี)

ในกรณีที่ GPIO pin นั้นๆถูกใช้ในการสื่อสารหรือหน้าที่อื่นๆเช่น การสื่อสารผ่าน I²C หรือ PWM เป็นต้น ก็ไม่จำเป็นที่จะต้องกำหนดตามเงื่อนไขข้างต้น

ตัวแปรชนิด enum หลักๆที่จะถูกเรียกใช้ในการตั้งค่าเริ่มต้นให้กับ pin ได้แก่ cyhal_gpio_direction_t จะใช้ในการกำหนดทิศทางข้อมูล (จะให้เป็น Input หรือ Output), cyhal_gpio_drive_mode_t จะใช้ในการกำหนดโหมดการขับ (drive mode) และ cyhal_gpio_event_t สำหรับการกำหนดการสร้างสัญญาณอินเทอร์รัพท์เมื่อเกิดเหตุการณ์ใดๆ กับ pin นั้นๆ (GPIO events) เพื่อไปเรียกฟังก์ชันเป้าหมายที่กำหนดไว้ (callback)

โดยฟังก์ชันที่จะกำหนดลักษณะของการทำงานเริ่มต้นให้แต่ละ pin จะได้แก่ฟังก์ชัน cyhal_gpio_init โดยจะมีการระบุหมายเลข pin, pin direction, pin drive mode และค่าสถานะของ pin เริ่มต้น (initial value) ดังตัวอย่างข้างล่าง

cy_rslt_t rslt;
bool read_val;
bool write_val = true;
 
// Initialize pin P0_0 as an input
rslt = cyhal_gpio_init(P0_0, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_NONE, false);

// Initialize pin P0_1 GPIO as an output with strong drive mode and initial value = false (low)
rslt = cyhal_gpio_init(P0_1, CYHAL_GPIO_DIR_OUTPUT, CYHAL_GPIO_DRIVE_STRONG, false);
 
// Read the logic level on the input pin
read_val = cyhal_gpio_read(P0_0);

// Write the value to the output pin
cyhal_gpio_write(P0_1, write_val);

ตัวอย่างการกำหนดการสร้างสัญญาณ interrupt

uint32_t global_count = 0;
cyhal_gpio_callback_data_t cb_data =
{
    .callback     = gpio_interrupt_handler,
    .callback_arg = (void*)&global_count
};
 
// Interrupt handler callback function
void gpio_interrupt_handler(void* handler_arg, cyhal_gpio_event_t event)
{
    CY_UNUSED_PARAMETER(event);
    // Increment global_count (passed as handler_arg) using a pointer
    uint32_t* count = (uint32_t*)handler_arg;
    *count = *count + 1;
 
    // Toggle pin P0_1 on every interrupt
    cyhal_gpio_toggle(P0_1);
}
 
cy_rslt_t snippet_cyhal_gpio_interrupt()
{
    cy_rslt_t rslt;
 
    // Initialize pin P0_0 GPIO as an input pin
    rslt = cyhal_gpio_init(P0_0, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_NONE, false);
 
    // Initialize pin P0_1 GPIO as an output with strong drive mode and initial value = true (high)
    if (CY_RSLT_SUCCESS == rslt)
    {
        rslt = cyhal_gpio_init(P0_1, CYHAL_GPIO_DIR_OUTPUT, CYHAL_GPIO_DRIVE_STRONG, true);
    }
 
 
    if (CY_RSLT_SUCCESS == rslt)
    {
        // Register callback function - gpio_interrupt_handler and pass the value global_count
        cyhal_gpio_register_callback(P0_0, &cb_data);
 
        // Enable falling edge interrupt event with interrupt priority set to 3
        cyhal_gpio_enable_event(P0_0, CYHAL_GPIO_IRQ_FALL, 3, true);
    }
 
    return rslt;
}

Ref: ModusToolboxTM Software Training - Level 2 – PSoCTM MCUs

Last updated

Assoc. Prof. Wiroon Sriborrirux, Founder of Advance Innovation Center (AIC) and Bangsaen Design House (BDH), Electrical Engineering Department, Faculty of Engineering, Burapha University