A comprehensive embedded systems project for the Nuvoton M261 ARM Cortex-M23 microcontroller, featuring GPIO interrupt handling, UART communication, and various IoT control applications.
- Features
- Hardware Requirements
- Project Structure
- Getting Started
- Main Application
- Example Applications
- Library Documentation
- Building the Project
- Debugging
- Contributing
- GPIO Interrupt Handling - Rising-edge interrupt detection with debouncing
- UART Communication - Serial communication for debugging and data transmission
- System Clock Management - PLL and clock source configuration
- I/O Redirection - Printf support via UART for easy debugging
- PWM Control - DC motor speed and direction control using PWM
- Timer Interrupts - Dual timer implementation for GPIO toggling
- Ultrasonic Sensor Support - HC-SR04 distance measurement
- Debouncing - Hardware debouncing using LIRC clock for reliable input handling
- Microcontroller: Nuvoton M261 (ARM Cortex-M23, 64 MHz)
- Development Tools:
- ARM MDK (Keil µVision) or ARM gcc-none-eabi toolchain
- Serial USB adapter for UART communication
- ST-Link or appropriate debugger for in-circuit debugging
- Optional Components:
- DC motor + L298N motor driver
- HC-SR04 ultrasonic sensor
- Buttons/switches for GPIO input testing
microprocessor-IoT/
├── user/
│ └── main.c # Main application (GPIO interrupt demo)
├── Library/
│ ├── gpio.c # GPIO driver
│ ├── uart.c # UART driver
│ ├── clk.c # Clock management driver
│ └── retarget.c # I/O redirection (printf over UART)
├── CMSIS/
│ ├── system_M261.c # System initialization
│ └── startup_M261.s # Startup assembly code
├── DifferentWorks/
│ ├── pwm_motor_demo.c # DC motor PWM control example
│ ├── ultrasonic_hcsr04.c # Ultrasonic sensor example
│ ├── dual_timer_toggle.c # Dual timer interrupt example
│ └── timer_step_control.c # Timer-based sequence control
├── Include/
│ ├── lcd1602.h # Driver header for 16x2 character LCD
│ ├── ssd1306.h # Main interface for the SSD1306 OLED display
│ ├── ssd1306_conf.h # Configuration file (I2C, MCU family, fonts)
│ ├── ssd1306_fonts.h # Font definitions and bitmap data for OLED
│ └── th06_th08.h # Header for TH06 / TH08 temperature & humid_
│
└── README.md # This file
-
ARM Toolchain Installation
- Install ARM gcc-none-eabi or ARM MDK (Keil µVision)
- Ensure compiler is in your system PATH
-
Nuvoton Support
- Download Nuvoton M261 BSP (Board Support Package)
- Ensure
NuMicro.hand related headers are accessible
-
Serial Terminal
- Install a serial terminal application (PuTTY, TeraTerm, or Arduino IDE Serial Monitor)
- Configure for 115200 baud (default for this project)
-
Clone the Repository
git clone <repository-url> cd microprocessor-IoT
-
Compile the Project
# Using ARM gcc (example) arm-none-eabi-gcc -mcpu=cortex-m23 -c user/main.c -o build/main.o # Link and flash...
-
Flash to Device
- Use your debugger's flashing tool (ST-Link, J-Link, etc.)
- Or use Nuvoton's NuLink debugger
-
Open Serial Terminal
- Connect to the device's UART port
- Set baud rate to 115200
- Watch debug output and interact with the device
File: user/main.c
The main application demonstrates GPIO interrupt handling with debouncing:
- PC0 and PC1 configured as inputs with rising-edge interrupt detection
- PA0 and PA1 configured as outputs
- When PC0 is triggered, PA0 toggles
- When PC1 is triggered, PA1 toggles
- 64-cycle LIRC debounce prevents false triggers
Initializes system resources:
- Enables HIRC, LIRC, and HIRC48 clock sources
- Sets HCLK to HIRC with 1:1 divider
- Configures GPIO pin multiplexing for PA and PC ports
- Enables necessary module clocks
Handles PC port interrupts:
- Checks PC0 interrupt flag and toggles PA0
- Checks PC1 interrupt flag and toggles PA1
- Clears interrupt flags to prevent overflow
Application entry point:
- Calls SYS_Init() for initialization
- Sets GPIO modes (input for PC0/PC1, output for PA0/PA1)
- Enables GPC interrupt in NVIC
- Configures rising-edge detection
- Applies debounce timing (64 LIRC cycles)
- Enters infinite loop
DC motor speed and direction control using PWM:
- Forward: PH6=1, PH7=0 with variable PWM duty cycle
- Reverse: PH6=0, PH7=1 with variable PWM duty cycle
- Demonstrates BPWM (Basic PWM) module configuration
- Includes SysTick delays for smooth acceleration/deceleration
HC-SR04 distance measurement implementation:
- Pulse generation on trigger pin
- Echo pulse width measurement via timer
- Distance calculation from propagation delay
Timer-based GPIO toggling:
- Two independent timers interrupt at different frequencies
- Each timer IRQ toggles corresponding GPIO pins
- Demonstrates NVIC interrupt prioritization
Sequential stepping sequence using timer interrupts:
- Implements state machine using timer interrupts
- Useful for stepper motor or sequential LED control
GPIO_SetMode(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode)
- Sets GPIO operation mode (input, output, open-drain, quasi)
- Example:
GPIO_SetMode(PA, BIT0, GPIO_MODE_OUTPUT);
GPIO_EnableInt(GPIO_T *port, uint32_t u32Pin, uint32_t u32IntAttribs)
- Enables GPIO interrupt with specified edge/level trigger
- Attributes: GPIO_INT_RISING, GPIO_INT_FALLING, GPIO_INT_BOTH_EDGE, GPIO_INT_HIGH, GPIO_INT_LOW
- Example:
GPIO_EnableInt(PC, 0, GPIO_INT_RISING);
GPIO_DisableInt(GPIO_T *port, uint32_t u32Pin)
- Disables interrupt on specified pin
GPIO_SetSlewCtl(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode)
- Controls slew rate (normal, high, fast)
GPIO_SetPullCtl(GPIO_T *port, uint32_t u32PinMask, uint32_t u32Mode)
- Configures pull-up/pull-down resistors
Serial communication interface with configurable baud rate, data bits, stop bits, and parity. Used by retarget.c for printf redirection.
Manages system clocks:
- Clock source selection (HIRC, LIRC, HXT, LXT)
- PLL configuration and control
- Module clock enabling and divider setup
- SysTick configuration
Enables printf/putc/getc functions to use UART:
- Redirects stdout/stdin to UART0
- Supports semihosting fallback
- Includes HardFault handler for debugging
- Create a new project for M261
- Add source files from
user/,Library/,CMSIS/ - Configure compiler settings (optimization, include paths)
- Build and flash using ST-Link or Nuvoton NuLink
# Compile
arm-none-eabi-gcc -mcpu=cortex-m23 -mthumb -c user/main.c -o main.o
arm-none-eabi-gcc -mcpu=cortex-m23 -mthumb -c Library/gpio.c -o gpio.o
# ... compile other files ...
# Link
arm-none-eabi-gcc -mcpu=cortex-m23 -mthumb main.o gpio.o ... -o firmware.elf
# Generate binary
arm-none-eabi-objcopy -O binary firmware.elf firmware.binmake clean
make build
make flashAfter building and flashing:
- Connect USB-to-Serial adapter to UART pins (PB12/PB13)
- Open serial terminal at 115200 baud
- Use
printf()in code for debug messages:printf("GPIO interrupt detected on PC0\r\n");
- Connect ST-Link/Nuvoton NuLink to debug pins (SWD)
- Set breakpoints in IDE
- Step through code execution
- Inspect registers and memory
Use GPIO outputs to indicate program state:
PA0 = 1; // LED on
PA0 = 0; // LED offContributions are welcome! Please:
- Create a feature branch
- Make your changes with clear commit messages
- Test on actual hardware
- Submit a pull request
This project uses Nuvoton M261 Standard Library (Apache-2.0 License). Custom code in this repository is available for educational and commercial use. 02
Created: December 2025 by codedbyelif https://github.com/codedbyelif Target Platform: Nuvoton M261 (ARM Cortex-M23) Language: C (C99 standard)