In this article we will learn about CH32V003 GPIO Inputs, their hardware characteristics, how to configure them and use it in the application.

As you might already know by now the in CH32V003 MCU you have up to 18 IOs (20 Pin package) and each could be configured as Input if required.
There are 3 group of ports as discussed already in previous article about GPIO output i.e Port A, C, and D.
CH32V003 MCU Pinout

Read Datasheet
I would strongly recommend you to read the datasheet and go through the electrical characteristics section to know more about capability and limitation of GPIO port/pins.
Not all the pins are 5V volt tolerant(FT is 5V tolerant). See the pinout table in the datasheet as shown in the image below.

Hardware Circuit for Input
Switch can be connected to test GPIO as input both in polling mode and in interrupt mode.

Note about GPIO D7 / NRST
Please note PD7 is by default is configured as MCU reset pin, you need to configure it as GPIO by configuring it with WCH Link Programmer Utility or in the code.

Two options to change
1.
FLASH_Unlock();
FLASH_EraseOptionBytes();
FLASH_UserOptionByteConfig(OB_STOP_NoRST, OB_STDBY_NoRST, OB_RST_NoEN, OB_PowerON_Start_Mode_USER);
FLASH_Unlock();
2.
if your have WCH-Link Utility in your computer. You also can use it to change PD7 mode.

GPIO as Input Example Code for CH32V003
In order to configure any pin as GPIO as input, you need to use the following code, let us call that in a function “GPIOConfig
” as shown below, this will be the initialization code and need to be called before using the GPIO.
For any configuration, clock for that GPIO port needs to be enabled first.
Two parameters are there for any GPIO when configuring as output
- GPIO_Pin: this is to define which Pin, for example for D3 it will be GPIO_Pin_3
GPIO_Mode
: to configure if the Input will be with internal pull-up resistance(GPIO_Mode_IPU) or pull-down resistance(GPIO_Mode_IPU) or input which is floating (GPIO_Mode_IN_FLOATING).
void GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0}; //structure variable used for the GPIO configuration
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); // to Enable the clock for Port D
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // Defines which Pin to configure
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // Defines Output Type
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
In order to read the GPIO input there are two functions
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadInputData(GPIO_TypeDef *GPIOx);
GPIO_ReadInputDataBit
is used to get the status of single bit/pin whether it is high or low.GPIO_ReadInputData
function is used to read the full port, example if D0-7 data port need to be read, this function could be used.
GPIO Input in Polling Mode
Let is now see how we can write the code to check the status GPIO Inpt pin and then glow the LED as per the status. So, we will see if GPIO Input pin is Low we will glow the LED and if it is High LED will be OFF.
D3 is the input and D4 is output for LED.
void GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0}; //structure variable used for the GPIO configuration
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); // to Enable the clock for Port D
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // Defines which Pin to configure
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // Defines Output Type
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // Defines which Pin to configure
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // Defines Output Type
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // Defines speed
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void)
{
uint8_t GPIOInputStatus = 0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SystemCoreClockUpdate();
Delay_Init();
GPIO_Config();
while(1)
{
GPIOInputStatus = GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_3);
if(GPIOInputStatus == 0)
{
GPIO_WriteBit(GPIOD, GPIO_Pin_4, RESET);
}
else
{
GPIO_WriteBit(GPIOD, GPIO_Pin_4, SET);
}
Delay_Ms(100);
}
}
See the result on the actual hardware


GPIO Input in Interrupt Mode
To use GPIO input in the interrupt mode we need to use External Interrupt (EXTI)
let us see how we need to configure it to receive the interrupt.
Code works like GPIO D4 is configured for output, D3 is configured for input with internal pull up. External interrupt line in enabled on D3 using function GPIO_EXTILineConfig
for interrupt on falling edge (EXTI_Trigger_Falling
). Interrupt in enable on EXTI7_0_IRQn
so that when falling edge is detected on D3, Interrupt handler funcion (EXTI7_0_IRQHandler) will be called.
In the code below what we are doing is initally we are making LED OFF and when D3 gets falling edge, interrupt occurs and it rases a Flag(interruptFlag
, declared as global variable).
This flag is then check in While(1), if Flag is high, LED is made ON.
/* Global Variable */
uint8_t interruptFlag = 0;
/*********************************************************************
* @fn EXTI0_INT_INIT
*
* @brief Initializes EXTI0 collection.
*
* @return none
*/
void EXTI0_INT_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
EXTI_InitTypeDef EXTI_InitStructure = {0};
NVIC_InitTypeDef NVIC_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD, ENABLE);
// Configuration for LED on D4
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
//Configuration for GPIO Input on D3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* GPIOD ----> EXTI_Line0 */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource3);
EXTI_InitStructure.EXTI_Line = EXTI_Line3;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI7_0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SystemCoreClockUpdate();
Delay_Init();
EXTI0_INT_INIT();
GPIO_WriteBit(GPIOD, GPIO_Pin_4, SET); // Set LED OFF initially
while(1)
{
Delay_Ms(100);
if(interruptFlag == 1)
{
GPIO_WriteBit(GPIOD, GPIO_Pin_4, RESET);
interruptFlag = 0;
}
}
}
void EXTI7_0_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
/*********************************************************************
* @fn EXTI0_IRQHandler
*
* @brief This function handles EXTI0 Handler.
*
* @return none
*/
void EXTI7_0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line3)!=RESET)
{
interruptFlag = 1;
EXTI_ClearITPendingBit(EXTI_Line3); /* Clear Flag */
}
}
I hope you are able to follow the article easily and now understood how to use GPIO as digital input. For more details I would again encourage you to go through the datasheet and reference manual for deeper understanding.
See also:
- Setting up the Development Environment for CH32V003: Compile and Run first example code
- CH32V003: GPIO as Output
- CH32V003: GPIO as Input (Polling, Interrupt)
- CH32V003: UART Transmit / Receive data
- CH32V003: PWM output with Frequency and Duty Cycle Control
- CH32V003: ADC for analog signal measurement
- CH32V003: I2C Interface
- CH32V003: SPI Interface
- CH32V003: Timer Interrupt
- CH32V003: How to read 64-bit Unique ID
I am currently working as an embedded systems design consultant and helping companies build custom embedded products, develop test automation solution for their PCB.
If you have any feedback about the blog, you can share in the comments below or you can also contact me directly.
Read more interesting articles on Embedded Systems Design.