Using the Capacitive Touch Sensor on the FRDM-KL46Z

Created by Ben Roloff, last modified on Jan 22, 2019


The FRDM-KL46Z from Freescale comes with various features on it. One of the features is a capacitive touch sensing input module. NXP-Freescale provides a software library to run the touch sensor, but this tutorial will go over how to use it without the libraries. The touch sensing software can be found here. For this tutorial we will be using Keil 5.18a.

Helpful Links

KL46P121M48SF4RM.pdf (5.2 MB) - Reference Manual for Chip

FRDM-KL46Z_UM.pdf (1.8 MB) - User Manual for Board


Touch_Sen.c (2.5 KB)

Touch_Sen.h (646 Bytes)



// TSI initialization function
void Touch_Init()
    // Enable clock for TSI PortB 16 and 17
    TSI0->GENCS = TSI_GENCS_OUTRGF_MASK |  // Out of range flag, set to 1 to clear
                                //TSI_GENCS_ESOR_MASK |  // This is disabled to give an interrupt when out of range.  Enable to give an interrupt when end of scan
                                TSI_GENCS_MODE(0u) |  // Set at 0 for capacitive sensing.  Other settings are 4 and 8 for threshold detection, and 12 for noise detection
                                TSI_GENCS_REFCHRG(0u) | // 0-7 for Reference charge
                                TSI_GENCS_DVOLT(0u) | // 0-3 sets the Voltage range
                                TSI_GENCS_EXTCHRG(0u) | //0-7 for External charge
                                TSI_GENCS_PS(0u) | // 0-7 for electrode prescaler
                                TSI_GENCS_NSCN(31u) | // 0-31 + 1 for number of scans per electrode
                                TSI_GENCS_TSIEN_MASK | // TSI enable bit
                                //TSI_GENCS_TSIIEN_MASK | //TSI interrupt is disables
                                TSI_GENCS_STPE_MASK | // Enables TSI in low power mode
                                //TSI_GENCS_STM_MASK | // 0 for software trigger, 1 for hardware trigger
                                //TSI_GENCS_SCNIP_MASK | // scan in progress flag
                                TSI_GENCS_EOSF_MASK ; // End of scan flag, set to 1 to clear
                                //TSI_GENCS_CURSW_MASK; // Do not swap current sources
    // The TSI threshold isn't used is in this application
//    TSI0->TSHD =     TSI_TSHD_THRESH(0x0000) |
//                                TSI_TSHD_THRESL(0x0000);

The initialization sets the necessary registers TSI module to run the touch sensor. The TSI module has three registers the General Control and Status Register (GENCS), the DATA register, and the threshold register (TSHD). The DATA register isn’t used in the initialization; it is only needed to access the data and needs nothing to be initialized. In the GENCS register controls the TSI and how it operates. The user can decide to operate in one of four modes, the first just reads capacitance, the next two work on reading a certain threshold, and the last is for noise detection. The range and overall configuration is controlled by the REFCHRG, DVOLT, EXTCHRG, PS, and NSCN. Changes these values will change the range that the touch sensor reads and outputs. The enable bit is set with TSIEN_MASK. STM_MASK is necessary to be set to 1 if a hardware trigger is desired, since we are using a software trigger, we will not set it. The ESOR_MASK is not set, so that we use an out of range interrupt. If it is set, an interrupt will be sent at the end of a scan. The SCNIP flag is not set because it is read only. It signals when a scan is in progress.

The Threshold register is not used in this application, because we are operating in the first mode. If we would use mode 2, 0100, or mode 3, 1000, we would need to set the register. TSHD is split into two half words. The upper threshold and lower threshold.



// Function to read touch sensor from low to high capacitance for left to right
int Touch_Scan_LH(void)
    int scan;
    TSI0->DATA =     TSI_DATA_TSICH(10u); // Using channel 10 of The TSI
    TSI0->DATA |= TSI_DATA_SWTS_MASK; // Software trigger for scan
    scan = SCAN_DATA;
    TSI0->GENCS |= TSI_GENCS_EOSF_MASK ; // Reset end of scan flag
    return scan - SCAN_OFFSET;

This function works by select one of the two channels on the board. This one is channel 10. Channel 10 reads the capacitance from low to high. The first thing needed after that is to set the software trigger to start a scan. After the scan is complete we then read the data. After getting the data we reset the end of scan flag, so that we may run another scan later. We return our scan data minus a desired offset.


// Function to read touch sensor from high to low capacitance for left to right
int Touch_Scan_HL(void)
    int scan;
    TSI0->DATA =     TSI_DATA_TSICH(9u); // Using channel 9 of the TSI
    TSI0->DATA |= TSI_DATA_SWTS_MASK; // Software trigger for scan
    scan = SCAN_DATA;
    TSI0->GENCS |= TSI_GENCS_EOSF_MASK ; // Reset end of scan flag
    return scan - SCAN_OFFSET;

This function works the same way as Touch_Scan_LH, but instead of using channel 10 it uses channel 9. Channel 9 reads the capacitance as high to low from left to right.


SCAN_OFFSET - This is an offset for for the scan result. This allows a larger range, but keeps the start at 0.

SCAN_DATA - This is a quick way of getting the data that is stored in TSI0_DATA_TSICNT.


This can be used for many different applications, but a helpful one for seeing what values you are getting is one displaying the value on the LCD screen. The main code shown below uses the LCD code given here.


int main()
    uint16_t x;
    uint32_t i;
    // initialize the LCD and TSI
        x = Touch_Scan_LH();    // Get the touch sensor input
        SegLCD_DisplayDecimal(x); // Display the value
        for ( i = 0; i < 2900000; i++); // Delay


Any questions or comments please go to our TechForum