Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Driving 120 LEDs with 16 I/O Pins and 256-Level Individual Dimming

Tech 2

LED Matrix Diagram

Overview

This implementation utilizes the LED driver RAM table within the microcontroller to achieve two distinct driving modes.

LED Driver Modes

For breathing light effects, only Mode 1 is applicable: Single Scan using RAM2 table.

Mode 1 Operation

  1. Softawre Selection: The current COM line (single COM) is selected via software to initiate scanning.
  2. Scan Completion: When the COM line scanning finishes, the scan cycle ends.
  3. SEG Control: During COM scanning, each bit in SEG01/SEG02 controls one SEG line:
    • Bit = 0: SEG line state controlled by I/O
    • Bit = 1: SEG line outputs constant current
  4. Interrupt Flag: After scanning completes, the COMIF interrupt flag is set and LED scanning stops.

SEG Output Width Control

Two methods control SEG output width:

  • Method 1: SEG output period equals COM width (when COM_CON BIT5 = 0)
  • Method 2: SEG output period controlled by RAM2 (when COM_CON BIT5 = 1)

Interrupt Handler Implementation

In the COM output completion interrupt handler:

// Refresh current COM's 16 SEG data to RAM2 table
for (segment_index = 0; segment_index < 16; segment_index++) {
    *ram2_pointer = com_duty_buffer[segment_index]; // seg1~seg16
    ram2_pointer++; // Populates RAM2 sequentially to refresh SEG brightness duty
}

COM_CON |= 0x88; // Start next scan (GO bit)

// Prepare next COM's 16 SEG data
for (segment_index = 0; segment_index < 16; segment_index++) {
    com_duty_buffer[segment_index] = display_buffer[current_com][segment_index];
}

This refreshes the current COM's 16 SEG data to the RAM2 table for hardware LED refresh and prepares the next COM's data.


Main Loop Control

Simply modify the 8×16 display_buffer array in the main loop to control LED states.

Ghosting Issue and Solutino

Problem: Ghosting artifacts appeared, likely caused by duty cycle assignment to 0 during push-pull operations.

Solution: Adjusted the refresh program structure to eliminate ghosting.

Revised Interrupt Handler

void led_driver_isr(void) interrupt 8 {
    unsigned char units_digit = 0;
    unsigned char tens_digit = 0;
    unsigned char hundreds_digit = 0;
    
    _push_(INSCON);
    INSCON &= 0xBF; // Select special function register page 0
    
    seg_duty_pointer = RAM2_ADDRESS; // Assign RAM2 address to pointer
    COM_CON &= 0x38; // Clear COM output completion interrupt flag
    
    current_com++;
    
    // Battery level processing
    if (battery_percentage != 100) {
        units_digit = battery_percentage % 10;
        tens_digit = battery_percentage / 10;
        hundreds_digit = 0;
    } else {
        units_digit = 0;
        tens_digit = 0;
        hundreds_digit = 1;
    }
    
    // COM line selection and SEG configuration
    switch (current_com) {
        case 1: // COM1
#if (LED_COM_ENABLE & 0x01)
            COM_CON |= 0x00;
            SEG01 = 0xFF; // Select SEG1-8
            SEG02 = 0xFF; // Select SEG9-16
            set_segment(0, tens_digit, 250); // COM1 displays tens digit
            break;
#else
            current_com++;
#endif
        
        case 2: // COM2
#if (LED_COM_ENABLE & 0x02)
            COM_CON |= 0x01;
            SEG01 = 0xFF;
            SEG02 = 0xFF;
            set_segment(1, units_digit, 250); // COM2 displays units digit
            break;
#else
            current_com++;
#endif
        
        // Additional COM cases 3-8 follow similar pattern
        // ...
        
        case 8: // COM8
#if (LED_COM_ENABLE & 0x80)
            COM_CON |= 0x07;
            SEG01 = 0xFF;
            SEG02 = 0xFF;
#endif
            current_com = 0;
            break;
    }
    
    // Refresh current COM's SEG data to RAM2
    for (segment_index = 0; segment_index < 16; segment_index++) {
        *seg_duty_pointer = seg_duty_array[segment_index];
        seg_duty_pointer++;
    }
    
    COM_CON |= 0x88; // Start next scan
    
    // Load next frame data
    for (segment_index = 0; segment_index < 16; segment_index++) {
        seg_duty_array[segment_index] = display_buffer[current_com][segment_index];
    }
    
    _pop_(INSCON);
}

Final Result

After eliminating ghosting, the final program achieves clean LED control.

Note: This implementation demonstrates driving LED panels for floor cleaning devices using Sino Wealth microcontrollers.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.