Button, Button, Who Needs a Button?
Touch Sensitive Pins on a TI Microcontroller
Button, Button, Who Needs a Button?
Touch Sensitive Pins on a TI Microcontroller
Sometimes it is desirable for a microcontroller circuit to support human interaction. Some examples are game controllers or remote controls. Many electronics kits come with a type of "momentary switch" which is active only as it is being pressed. Those require something like a pullup resistor, a wire to the pin, and a wire to ground. That's pretty simple. But it is possible to build a human-input circuit that is simpler still. As you will see below, we can do this with a TI microcontroller.
About TI
Texas Instruments is an almost legendary corporation. Mostly when people think Texas, they think big. And TI does not let that image down. It is a giant in its industry. The company was the birthplace of both the first single-chip microcontroller and the electronic calculator. TI is also famous for its 74xx line of small scale integrated circuit chips with gates, shift registers, and the like.
TI's largest business nowadays is analog related chips, but their microcontrollers are still a major part of their business. Anyone can order them through suppliers like Mouser, Digikey or even on Amazon. Like the PIC, STM or Atmel offerings, if you want to work with them, you need more than just the chip itself.
This article will explain how to get started with a somewhat mature line of TI chips called the MSP430s. They are 16-bit, have a range of memory sizes, and come with ‘peripherals’ such as Analog-Digital converters. You can purchase devices to program them for under $20 USD.
Although it might be tempting to just blink an LED on and off to sort of "count coup" on programming it, we will take things a step further and see how to interact with the chip merely by touching its pins. That's right. Those little metal things sticking out of the plastic package can act as an input interface without even hooking up a button. Although TI are far from the only manufacturers to include such technology, it does make for a nice introduction to their chips. As an aside, TI is also one of the licensees of the 8051 architecture, although 8051 is not the subject of this article.
About Microcontrollers
Generally, a microcontroller (from this point, "MCU") is a less powerful processor than you might find in your laptop or smartphone. It has on-chip memory, but far less, and you do not usually hook up disk drives and keyboards to it. Unlike a general purpose computer, the code must be "flashed" onto the chip using only its often small number of pins. Microcontrollers do everything through those pins, whose number can range from as few as eight, to upwards of 128. They run at lower clock speeds and hence also do not require as much cooling as a classic CPU. Once their code (or firmware) has been flashed onto them, they can often just be left alone to fulfill their task, using very little power to do so.
The member of the MSP430 line we will discuss is the MSP430G2553. Along with its programmer (MSP-EXP430G2ET), it can be purchased directly from TI or through one of the major distributors.
Getting in Touch with your MCU
A concept in modern microcontrollers is "Capacitive Touch", which allows inputs to be carried out using no moving parts. Just the capacitor-like behavior of a human finger is enough to interact with such controls. This pin capability is not inherent in every MCU pin from every manufacturer, but rather a feature of some MCUs. In the case of our subject, it includes port 2 pins 0 through 5, and possibly all of its other pins. See the schematics beginning on page 40 of the data sheet referring to "Pin Osc" or "Capacitive Sensing", which are characteristic of capacitive-touch enabled pins. The example code which is followed closely here, broke down the pins into different gesture functions such as volume and diagonal. Since this demo does not have an elaborate layout, all of the pins will be treated the same.
There are some extensive pages out there on how this technology works. For example, TI has a nice explanation at this link https://software-dl.ti.com/trainingTTO/trainingTTO_public_sw/MSP430_LaunchPad_Workshop/v2.20/MSP430_10_Capacitive_Touch.pdf . However, be warned that this document is rather out of date, and some links and information may be hard to locate. A quick summary of the relevant points is:
- Capacitance is a characteristic of electronic devices in that a pair of plate-like conductors can lie parallel to each other with a "dielectric" (or non-conductor) between them, allowing this 'capacitor' to build up a static charge that crests when the voltage drop between the plates reaches the voltage source level.
- Human fingers (or elbows or whatever) also have a capacitance.
- Combining the external human capacitance and the capacitance in your sensor changes the system overall capacitance
- A wave form can be setup on the sensor side whose frequency is dependent on the overall capacitance of the system
- The intrusion of one's finger can change that capacitance and affect the wave form's frequency.
- The MCU can then take measurements of the frequency change to detect the touch or even proximity
- Either a "Relaxation Oscillator", in which the count of wave forms during a fixed period can be leveraged to detect the change, or a "Fast Relaxation Oscillator" can be used, in which an expected number of waves is counted off, and the elapsed time for their passage is used for detection.
As with so many modern technological wonders, the physical world we see and hear every day may not give much of a clue how this works. Articles like the one above can help, and there is much more to study on this topic, if you are interested.
What other devices can do this?
As mentioned above, Capacitive Touch enabled pins are not uncommon on microcontrollers. Of the other MCUs covered in this series, the ones that can also be programmed for this are:
- CH552 - the 8051 Xiao mini board seen in The (Now) Elusive 8051. How to get started with your very own… | by Leslie Foster | Jul, 2025 | Medium
- The PIC24FJ256GA702 used in Talk Like a 70s Sci Fi Monster. An Entertaining Application of Advanced… | by Leslie Foster | Engineering IoT | Medium, and its dsPIC33 counterparts
- One article Microcontroller Secret Signal. PIC16LF18324 LED Trick | by Leslie Foster | Engineering IoT | Medium briefly mentions the STM32. It also can be used for Capacitive Touch sensing.
Those models can directly do Capacitive Touch using just their pins. However, it is also possible to purchase a very inexpensive touch device, and connect it much as you would any other sensor. If you go that route, it could be much simpler to deal with. The very hobbyist-friendly vendor "HiLetgo" offers these boards at about 85 cents US, apiece. They can work with many varieties of microcontrollers and boards, including Arduino, Pico, and any of the MCUs listed above. Both the PIC16LF18324 and the PIC16F630 could work with those.

Typical Touch Sensor: one output signal. Must be powered
The Circuit
This bare-bones wiring is really all it takes to establish the pin-as-sensor, with an LED to use as an indicator: a lit-up "don't touch me" warning.

Just the LED, the power, and a pulled-up reset pin
Our 20 DIP packaged MSP430G2553 has the pinout shown below. You can see it has 20 pins, of which the general purpose IO pins are marked as Pn.m. The 'n' is for the port number and the 'm' is for the bit within the port. If you order any of these and want to use them in breadboards as we do here, you will need "through hole" friendly packages like DIP (dual in-line package). In this one's arrangement, the power and ground pins are directly opposite each other. Also note the reset pin at 16. That must be pulled high with a fairly high valued resistor to avoid constant, flaky reset behavior.

The MSP430G2553’s pinout diagram: courtesy the data sheet
As shown in the image above, the reset pin must be “pulled up” by connecting it to power through a resistor. 10k Ω should work fine. Port 1, pin 0 (P1.0) is connected to the LED through a 100 to 330 Ω resistor, and the LED's other lead is connected to ground. Aside from that, simply connecting the power and the ground pins at the "top" of the chip should be enough for this demonstration. To identify DVCC and DVSS, refer to a slight indentation on that end of the chip, in the middle.

Note the indentation at the very top. The DVCC (power) pin is on its left, while the DVSS (ground) pin is on its right
Of course, in order to make sensing and lighting LEDs happen, you will need to get some power to the breadboard. A breadboard power supply like those usually found in electronics kids, or a pair of 1.5 V batteries should be fine for the required 3 volts. When setting up power, try to stick to a rule of "power to red/ground to black" to avoid confusion. Below is a video clip to see it in action. Of course you must program the chip as described below. It will not do anything out of the box.
https://youtube.com/shorts/aQDLyL9QQzQ?feature=share
This is probably the simplest circuit that can do anything of any interest. But we can do more.
Capacitive touch circuits like this are typically wired to surfaces that can be used to capture gestures like sliding or pressing. Rather than just approaching that small pin with a finger, let us instead connect something. Please power down the circuit before making changes. This is doubly advisable here, because the software takes baseline pin settings on startup. If the circuit conditions change after those settings are taken, the sensor may not work.

Cat’s Whiskers extension of pins
https://www.youtube.com/watch?v=WTXXOEJr4NI Whiskers in action
Programming the MCU

MSP-EXP403G2ET Development Kit. This also serves as a nice pinout diagram
The MSP-EXP430G2ET development kit above (aka “Launchpad) can be bought with an MSP430G2553 microcontroller included. As the DIP socket label shows, other MSP430G2xxx MCUs can be programmed with this board as well. At the top of the image, you can see a USB socket. When that is connected to a laptop or desktop, it not only can flash the chip, but also power it. This setup is conceptually very similar to an Arduino board, but more flexible in some ways. You could try out many variants using all those jumpers, as you evaluate chips for inclusion in PCB projects, or you could simply build something for personal use.
A word to the wise about the MCU socket: it may take some finesse to get chips into and out of it. The action of connecting is to just push the pins into the holes (keeping the power-end-marked notch lined up with the similar notch in the socket). However, this can be easier said than done. TI has packed a lot of great stuff onto this little board, and you have to work around that. There is a technique that seems to work pretty consistently, as shown here.

Pinch the chip between both forefingers/thumb combinations, drop it delicately so its pins align with the socket holes. When you can feel that it is right and taking force equally, push down

Fully seated, with no bent pins
You have to exercise caution not only to avoid bending these sharp pins, but also to avoid getting cut by them. Do not worry about pushing the chip as far as it will go unless you want to leave it in the board permanently. Just making good contact is sufficient to program the MCU.
Extracting the chip is also delicate, if not more so. A small flat-tip screwdriver is good, unless you have an actual socket puller. Trying to do this with just your fingers often results in a "chip flip", after which you may wind up pin-pricking your fingers. Please do not assume that other through-hole sockets are any different. Some may have more "play" on entry, but this socket obviously makes very good contact. Also, when your MSP-EXP430G2ET arrives, if you got the chip, it should already be in. You can run this project right in that board, if you connect an external LED and resistor to pin P1.0.
Once the chip is inserted, the next step is to flash the code. The code we will use is a modified version of some older TI example code which can most easily be found here: https://github.com/ngarg87/RO_PINOSC_TA0_WDTp_One_Button_Compact, which was graciously setup by user ngarg87. Use this command to download it.
git clone https://github.com/ngarg87/RO_PINOSC_TA0_WDTp_One_Button_Compact
For working with these MCUs, a good choice is an IDE (Integrated Development Environment) provided by TI called Code Composer Studio (CCS). It is based on VS Code, so if you are familiar with that, there will be few surprises. See CCSTUDIO IDE, configuration, compiler or debugger | TI.com for downloading. Said to work with Windows, Linux and MacOS, it has a workspace approach. Once the IDE has been installed, create a new project (see below) and copy all the github files into its folder under the directory called "workspace_ccstheia", to establish the code as a CCS project. It should look like this in a directory listing:
C:\>dir ..\workspace_ccstheia\RO_PINOSC_TA0_WDTp_1BC
...
Directory of C:\Users\yourname\workspace_ccstheia\RO_PINOSC_TA0_WDTp_1BC
09/07/2025 08:36 PM <DIR> .
09/08/2025 10:40 PM <DIR> ..
09/07/2025 08:13 PM 721 .ccsproject
09/07/2025 08:13 PM 152 .clangd
09/07/2025 08:13 PM 23,748 .cproject
09/07/2025 08:13 PM 589 .project
09/07/2025 08:15 PM <DIR> .settings
09/07/2025 08:36 PM 119,419 CTS_HAL.c
09/07/2025 08:36 PM 5,364 CTS_HAL.h
09/07/2025 08:36 PM 33,894 CTS_Layer.c
09/07/2025 08:36 PM 4,846 CTS_Layer.h
09/08/2025 10:31 PM <DIR> Debug
09/07/2025 08:36 PM <DIR> Library
09/07/2025 08:13 PM 8,984 lnk_msp430g2553.cmd
09/08/2025 10:30 PM 9,358 main.c
09/07/2025 08:15 PM 10,090 structure.c
09/07/2025 08:15 PM 18,810 structure.h
09/07/2025 08:15 PM <DIR> targetConfigs
12 File(s) 235,975 bytes
The original example code is setup to take several different input pins as mentioned above. But we will treat them all as a single input for simplicity. Next, replace the “main.c” file contents with this.
/* --COPYRIGHT--,BSD
* Copyright (c) 2012, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --/COPYRIGHT--*/
//******************************************************************************
// RO_PINOSC_TA0_One_Button_Compact example
// Touch the middle element to turn on/off the center button LED
// Uses the low-level API function calls for reduced memory footprint.
// Note: Baseline tracking is implemented in the Application Layer
// RO method capactiance measurement using PinOsc IO, TimerA0, and WDT+
//
// Schematic Description:
//
// MSP430G2452
// +---------------+
// |
// C--------|P2.4
// C----------|P2.1
// C------|P2.3
// C--------|P2.2
// |
// C----------|P2.5
// |
// C----------|P2.0
//
// The WDT+ interval represents the measurement window. The number of
// counts within the TA0R that have accumulated during the measurement
// window represents the capacitance of the element. This is lowest
// power option with either LPM3 (ACLK WDTp source) or LPM0 (SMCLK WDTp
// source).
//
//******************************************************************************
#include "CTS_Layer.h"
typedef enum
{
INIT_PRESS,
// TYPE_PRESS,
CHECK_PRESS,
ACTION_PRESS
} Press_state;
// Define User Configuration values //
//----------------------------------//
#define DELAY 5000 // Timer delay timeout count - 5000*0.1msec = 500 msec
// Sensor settings
#define KEY_middle 0x1B0 // Defines the min count for a "key press"
// Set to ~ half the max delta expected
#define KEY_up 0x180
#define KEY_down1 0x180
#define KEY_down2 0x230
#define KEY_left 0x590
#define KEY_right 0x590
#define KEY_diag_left 0x300
#define KEY_diag_right 0xA0
#define num_keys 7
#define delta 50
// Global variables for sensing
unsigned int base_cnt[7];
unsigned int meas_cnt[7];
unsigned int delta_cnt[7];
unsigned int touch_lvl[7] = {KEY_middle, KEY_down1, KEY_up, KEY_left, KEY_right, KEY_diag_left, KEY_diag_right};
unsigned int touch[7];
unsigned int touch_occurred;
unsigned int delta_array[50];
unsigned int delta_array2[50];
unsigned int j=0;
unsigned int any_press=0;
unsigned int press=0;
unsigned int press2 = 0;
unsigned int counter=0;
Press_state Press_machine=INIT_PRESS;
char key_pressed, key_loc;
int cycles;
// Sleep Function
// Configures Timer A to run off ACLK, count in UP mode, places the CPU in LPM3
// and enables the interrupt vector to jump to ISR upon timeout
void sleep(unsigned int time)
{
TA0CCR0 = time;
TA0CTL = TASSEL_1+MC_1+TACLR;
TA0CCTL0 &= ~CCIFG;
TA0CCTL0 |= CCIE;
__bis_SR_register(LPM3_bits+GIE);
__no_operation();
}
// Main Function
void main(void)
{
unsigned int test_down=0;
unsigned int enter = 0;
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1, 8, 12 or 16MHz
DCOCTL = CALDCO_1MHZ;
BCSCTL1 |= DIVA_0; // ACLK/(0:1,1:2,2:4,3:8)
BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO
P1OUT = 0x00; // Clear Port 1 bits
P1DIR |= BIT0; // Set P1.0 as output pin
P2SEL &= ~(BIT6 + BIT7); // Configure XIN (P2.6) and XOUT (P2.7) to GPIO
P2OUT = 0x00; // Drive all Port 2 pins low
P2DIR = 0xFF; // Configure all Port 2 pins outputs
// Initialize Baseline measurement
TI_CAPT_Raw(&middle_button,&base_cnt[0]);
TI_CAPT_Raw(&volume_down1,&base_cnt[1]);
TI_CAPT_Raw(&volume_up1,&base_cnt[2]);
TI_CAPT_Raw(&left1,&base_cnt[3]);
TI_CAPT_Raw(&right1,&base_cnt[4]);
TI_CAPT_Raw(&diag_left1,&base_cnt[5]);
TI_CAPT_Raw(&diag_right1,&base_cnt[6]);
// Main loop starts here
while (1)
{
int i;
// Take raw delta measurement
TI_CAPT_Raw(&middle_button,&meas_cnt[0]);
TI_CAPT_Raw(&volume_down1,&meas_cnt[1]);
TI_CAPT_Raw(&volume_up1,&meas_cnt[2]);
TI_CAPT_Raw(&left1,&meas_cnt[3]);
TI_CAPT_Raw(&right1,&meas_cnt[4]);
TI_CAPT_Raw(&diag_left1,&meas_cnt[5]);
TI_CAPT_Raw(&diag_right1,&meas_cnt[6]);
touch_occurred = 0;
for (i =0; i<num_keys; i++) {
if(base_cnt[i] < meas_cnt[i])
// Handle baseline measurment for a base C decrease
{ // beyond baseline, i.e. cap decreased
base_cnt[i] = (base_cnt[i]+meas_cnt[i]) >> 1; // Re-average baseline up quickly
delta_cnt[i] = 0; // Zero out delta for position determination
touch[i]=0;
}
else
{
delta_cnt[i] = base_cnt[i] - meas_cnt[i]; // Calculate delta: c_change
if (delta_cnt[i] > touch_lvl[i]) {
touch[i] = 1;
touch_occurred = 1;
}
}
}
delta_array[j] = delta_cnt[0]; //test logging code
delta_array2[j++] = delta_cnt[1]; //test logging code
if (j==50) j=0;
enter = 1;
counter++;
switch(Press_machine)
{
case INIT_PRESS:
if (touch_occurred) {
counter = 0;
if (touch[0] || touch[1] || touch[2] || touch[3] || touch[4] || touch[5] || touch[6]) {
any_press = 1;
Press_machine = CHECK_PRESS;
}
}
case CHECK_PRESS:
if (any_press) { // press flag has been set so it's all invalid until release
if ((delta_cnt[0] > 100) || (delta_cnt[1] > 100) || (delta_cnt[2] > 100) || (delta_cnt[3] > 100) || (delta_cnt[4] > 100) || (delta_cnt[5] > 100) || (delta_cnt[6] > 100)) {
__no_operation(); //something still being touched, do nothing else
}
else Press_machine = ACTION_PRESS;
}
break;
case ACTION_PRESS:
if (any_press && (counter < 20))
{
// turn on LED
P1OUT |= BIT0;
delta_array[j-1]=696;
sleep(3000);
}
any_press = 0;
Press_machine=INIT_PRESS;
break;
}
// turn off LED
base_cnt[0] = base_cnt[0] - 1; // Adjust baseline down, should be slow to
base_cnt[1] = base_cnt[1] - 1; // Adjust baseline down, should be slow to
base_cnt[2] = base_cnt[2] - 1; // Adjust baseline down, should be slow to
base_cnt[3] = base_cnt[3] - 1; // Adjust baseline down, should be slow to
base_cnt[4] = base_cnt[4] - 1; // Adjust baseline down, should be slow to
base_cnt[5] = base_cnt[5] - 1; // Adjust baseline down, should be slow to
base_cnt[6] = base_cnt[6] - 1; // Adjust baseline down, should be slow to
P1OUT &= ~BIT0;
}
} // End Main
/******************************************************************************/
// Timer0_A0 Interrupt Service Routine: Disables the timer and exists LPM3
/******************************************************************************/
#pragma vector=TIMER0_A0_VECTOR
__interrupt void ISR_Timer0_A0(void)
{
TA0CTL &= ~(MC_1);
TA0CCTL0 &= ~(CCIE);
__bic_SR_register_on_exit(LPM3_bits+GIE);
}
#pragma vector=PORT2_VECTOR, \
PORT1_VECTOR, \
TIMER0_A1_VECTOR, \
NMI_VECTOR,COMPARATORA_VECTOR, \
ADC10_VECTOR
__interrupt void ISR_trap(void)
{
// the following will cause an access violation which results in a PUC reset
WDTCTL = 0;
}
The code above is modified from the original to treat all pin inputs the same.
Below is a high-level set of screen shots showing how to setup the project in the IDE. The first step is to create the project.

Create a new project
Once it has been created, copy the folder from the github repository into the folder that is created. The name shown is "RO_PINOSC_TA0_WDTp_1BC", but you can choose a different name.

This is how the project looks in CCS

The menu popup off of the program’s folder

Using “Flash Project” to get the code where we need it
The last step is where the code finally gets to the chip.
Once flashed, the chip may be left in the Launchpad (assuming you get the LED and resistor connected), or the chip may be pulled out of the programmer and plugged into a breadboard as shown in the earlier image.
The code above uses a 1MHz wave form, captures the initial input counts over a time window, and then goes into a loop of captures which it compares to the baseline. As it samples, it maintains baseline settings.
Conclusions
We saw that we can detect a touch with an MCU. There a number of practical applications. For instance, gesture controls can be used without a heavy infrastructure. If you get to know your way around PCBs, you could have touchable surfaces printed right onto a board. During its heyday, Palm corp had devices that could record notes using a gesture alphabet. The Palm used a stylus, but that could be accomplished with a a more elaborate touch sensor. As a possibly opposite example of a practical application, if you did not want something to be touched at all, you could build a touch-alarm and notify of the infraction with a loud buzzer. Enjoy your newfound knowledge!
Acknowledgements
Many thanks to Drew Foster for editorial input, and a shout out to GitHub user “ngarg87” for preserving the code from TI and making it available.
References
MSP430G2x53, MSP430G2x13 Mixed Signal Microcontroller datasheet (Rev. J) Data Sheet
https://www.ti.com/design-development/embedded-development/msp430-mcus.html#hardware Launchpad Development Board
https://github.com/ngarg87/RO_PINOSC_TA0_WDTp_One_Button_Compact Software
https://software-dl.ti.com/trainingTTO/trainingTTO_public_sw/MSP430_LaunchPad_Workshop/v2.20/MSP430_10_Capacitive_Touch.pdf Concept Overview
메타데이터
- post_id
- 620e69cd1ad1
- slug
- button-button-who-needs-a-button-620e69cd1ad1
- url
- https://medium.com/@lfoster.se.be/button-button-who-needs-a-button-620e69cd1ad1
- canonical_url
- https://medium.com/@lfoster.se.be/button-button-who-needs-a-button-620e69cd1ad1
- author_url
- https://medium.com/@lfoster.se.be
- status
- ok
- fetched_at
- 2026-07-17 11:44:46