← Back to Studying Paths

Peripheral Interfacing

Peripherals are the bridge between your microcontroller and the physical world. Understanding how to configure and control GPIOs, timers, interrupts, and external sensors is fundamental to embedded systems development.

[Diagram: MCU connected to LEDs, buttons, sensors, and displays]

General Purpose I/O (GPIO)

GPIOs are the most basic form of peripheral—digital pins that can be configured as inputs or outputs to interact with external components.

GPIO Configuration

// Configure GPIO pin as output (pseudo-code) GPIO_SetMode(GPIOA, PIN_5, GPIO_MODE_OUTPUT); GPIO_SetOutputType(GPIOA, PIN_5, GPIO_PUSH_PULL); GPIO_SetSpeed(GPIOA, PIN_5, GPIO_SPEED_HIGH); // Toggle LED GPIO_Toggle(GPIOA, PIN_5);

Reading Digital Inputs

// Configure as input with pull-up resistor GPIO_SetMode(GPIOB, PIN_0, GPIO_MODE_INPUT); GPIO_SetPull(GPIOB, PIN_0, GPIO_PULL_UP); // Read button state (active low) if (GPIO_Read(GPIOB, PIN_0) == 0) { // Button is pressed handle_button_press(); }

⚠️ Debouncing: Mechanical switches bounce when pressed, causing multiple false triggers. Always implement software or hardware debouncing!

Timers and Counters

Timers are essential for creating precise delays, generating PWM signals, measuring pulse widths, and scheduling periodic tasks.

Timer Modes

// Configure timer for 1ms interrupt void Timer_Init(void) { // Prescaler: divide clock to get 1MHz (1µs ticks) TIM2->PSC = (SystemCoreClock / 1000000) - 1; // Auto-reload: count to 1000 for 1ms period TIM2->ARR = 1000 - 1; // Enable update interrupt TIM2->DIER |= TIM_DIER_UIE; // Start timer TIM2->CR1 |= TIM_CR1_CEN; }

Interrupts

Interrupts allow the MCU to respond immediately to events without constantly polling, making your code more efficient and responsive.

[Diagram: Interrupt flow - Event → ISR → Resume main code]

Interrupt Types

Writing an ISR (Interrupt Service Routine)

// External interrupt handler for button press void EXTI0_IRQHandler(void) { if (EXTI->PR & EXTI_PR_PR0) { // Check pending flag EXTI->PR = EXTI_PR_PR0; // Clear flag (write 1 to clear) // Handle the interrupt - keep it SHORT! button_pressed_flag = 1; } } // In main loop, process the flag while (1) { if (button_pressed_flag) { button_pressed_flag = 0; process_button_action(); // Heavy processing here } }

💡 Best Practice: Keep ISRs short! Set a flag and do the heavy work in the main loop or a task. Avoid blocking calls and printf in ISRs.

Sensor Integration

Sensors convert physical quantities into electrical signals. Common interfaces include analog (ADC), digital (GPIO), and protocol-based (I2C, SPI).

Common Sensor Types

Example: Reading I2C Temperature Sensor

// Read temperature from BMP280 (simplified) float read_temperature(void) { uint8_t data[3]; // Read raw temperature registers I2C_ReadRegisters(BMP280_ADDR, 0xFA, data, 3); // Combine bytes into 20-bit raw value int32_t raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4); // Apply compensation formula (from datasheet) float temp = compensate_temperature(raw); return temp; }

Display Interfacing

Displays provide visual feedback. Common types include character LCDs, graphic LCDs, OLEDs, and seven-segment displays.

Popular Display Interfaces

// Initialize SSD1306 OLED via I2C void OLED_Init(void) { OLED_Command(0xAE); // Display OFF OLED_Command(0xD5); // Set clock divide OLED_Command(0x80); OLED_Command(0xA8); // Set multiplex ratio OLED_Command(0x3F); // 64 rows OLED_Command(0xAF); // Display ON } void OLED_Print(const char* str) { while (*str) { OLED_WriteChar(*str++); } }

🎯 Key Takeaway: Mastering peripheral interfacing unlocks the ability to connect your embedded system to virtually any sensor, actuator, or display—bringing your projects to life!