Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Introduction to 8051 Microcontroller Programming

Tech 2

Overview

The 8051 microcontroller series represents a foundational architecture in embedded systems, featuring an 8-bit CPU, 128 bytes of internal RAM, and up to 64KB of program memory. It operates using a Harvard architecture that separates instruction and data buses.

Core Components

  • CPU: Central processing unit capable of executing 8-bit operations
  • Memory: Internal ROM/Flash for code storage and RAM for data handling
  • Timers/Counters: Two 16-bit timers/counters for time measurement
  • Serial Communication: UART interface for serial data transfer
  • Interrupt System: Support for hardware and software interrupts
  • I/O Ports: Multiple ports configurable for input/output operations

Development Environment Setup

Tools Required

  1. Keil uVision5: Integrated development environment for C programming
  2. STC_ISP: Programming software for flashing code into microcontrollers
  3. USB-to-Serial Converter: For communication between computer and microcontroller

Hardware Configuration

Ensure proper driver installation for USB-to-Serial converters. Create project directories within Keil and configure target settings for specific chip models.

Peripheral Module Implementation

LED Control

Basic Lighting

#include <reg52.h>

void main() {
    P2 = 0xFE; // Turn on first LED
    while(1);  // Infinite loop
}

Blinking Effect

#include <reg52.h>

void delay_ms(unsigned int ms) {
    unsigned char i, j;
    while(ms--) {
        for(i=2; i>0; i--)
            for(j=239; j>0; j--);
    }
}

void main() {
    while(1) {
        P2 = 0xFE; 
        delay_ms(1000);
        P2 = 0xFF;
        delay_ms(1000);
    }
}

Sequential Lighting

#include <reg52.h>

void delay_ms(unsigned int ms) {
    unsigned char i, j;
    while(ms--) {
        for(i=2; i>0; i--)
            for(j=239; j>0; j--);
    }
}

void main() {
    unsigned char shift_reg = 0xFE;
    P2 = shift_reg;
    
    while(1) {
        shift_reg = (shift_reg << 1) | (shift_reg >> 7);
        P2 = shift_reg;
        delay_ms(1000);
    }
}

Button Interface

Basic Button Detection

#include <reg52.h>

void main() {
    while(1) {
        if(P3_5 == 0) {
            P2_0 = 0;
        } else {
            P2_0 = 1;
        }
    }
}

Debounced Button Handling

#include <reg52.h>

void delay_ms(unsigned int ms) {
    unsigned char i, j;
    while(ms--) {
        for(i=2; i>0; i--)
            for(j=239; j>0; j--);
    }
}

void main() {
    while(1) {
        if(P3_5 == 0) {
            delay_ms(20);
            while(P3_5 == 0);
            delay_ms(20);
            P2_0 = ~P2_0;
        }
    }
}

Digital Display

Single Digit Display

#include <reg52.h>
#include "delay.h"

unsigned char digit_codes[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};

void display_digit(unsigned char position, unsigned char digit) {
    if(digit > 9) return;
    
    // Configure control signals
    P2_2 = 0; P2_3 = 0; P2_4 = 0;
    
    switch(position) {
        case 0: P2_2 = 1; break;
        case 1: P2_3 = 1; break;
        case 2: P2_4 = 1; break;
        default: return;
    }
    
    P0 = digit_codes[digit];
    delay_ms(1);
}

void main() {
    display_digit(0, 5);
    while(1);
}

LCD1602 Interface

Basic Functionality

#include <reg52.h>

sbit RS = P2^6;
sbit RW = P2^5;
sbit EN = P2^7;

void lcd_delay() {
    unsigned char i, j;
    for(i=2; i>0; i--)
        for(j=239; j>0; j--);
}

void write_command(unsigned char cmd) {
    RS = 0; RW = 0;
    P0 = cmd;
    EN = 1; lcd_delay(); EN = 0; lcd_delay();
}\n
void write_data(unsigned char dat) {
    RS = 1; RW = 0;
    P0 = dat;
    EN = 1; lcd_delay(); EN = 0; lcd_delay();
}

void lcd_init() {
    write_command(0x38); // 8-bit, 2-line, 5x7
    write_command(0x0c); // Display on, cursor off
    write_command(0x06); // Increment cursor
    write_command(0x01); // Clear screen
}

void main() {
    lcd_init();
    write_data('H');
    write_data('e');
    write_data('l');
    write_data('l');
    write_data('o');
    while(1);
}

Matrix Keypad Input

Key Detection

#include <reg52.h>
#include "delay.h"

unsigned char scan_matrix() {
    // Row scanning
    P1 = 0xF0; 
    if(P1_4 == 0) {
        delay_ms(20); 
        return 1;
    }
    if(P1_5 == 0) {
        delay_ms(20); 
        return 2;
    }
    if(P1_6 == 0) {
        delay_ms(20); 
        return 3;
    }
    if(P1_7 == 0) {
        delay_ms(20); 
        return 4;
    }
    return 0;
}

void main() {
    while(1) {
        unsigned char key = scan_matrix();
        if(key) {
            // Process key press
        }
    }
}

Timer Applications

Time-based LED Blinking

#include <reg52.h>

void timer0_init() {
    TMOD |= 0x01; // Timer0 mode 1
    TH0 = 0x3C;   // Load high byte
    TL0 = 0xB0;   // Load low byte
    ET0 = 1;      // Enable timer0 interrupt
    EA = 1;       // Enable global interrupt
    TR0 = 1;      // Start timer
}

unsigned int count = 0;

void timer0_isr() interrupt 1 {
    TH0 = 0x3C;
    TL0 = 0xB0;
    count++;
    if(count >= 1000) {
        count = 0;
        P2_0 = ~P2_0;
    }
}

void main() {
    timer0_init();
    while(1);
}

Serial Communication

UART Transmission

#include <reg52.h>

void uart_init() {
    PCON |= 0x80; // Baud rate doubler
    SCON = 0x50;  // Mode 1, 8-bit
    TMOD |= 0x20; // Timer1 mode 2
    TH1 = 0xF3;   // Baud rate setting
    TL1 = 0xF3;
    TR1 = 1;      // Start timer
    ES = 1;       // Enable UART interrupt
    EA = 1;       // Enable global interrupt
}

void uart_send_byte(unsigned char byte) {
    SBUF = byte;
    while(!TI);
    TI = 0;
}

void main() {
    uart_init();
    uart_send_byte(0x55);
    while(1);
}

Real-Time Clock DS1302

Time Reading

#include <reg52.h>

sbit SCLK = P3^6;
sbit IO = P3^4;
sbit CE = P3^5;

void ds1302_write(unsigned char addr, unsigned char dat) {
    CE = 1;
    for(unsigned char i=0; i<8; i++) {
        IO = addr & (1<<i);
        SCLK = 1; SCLK = 0;
    }
    for(unsigned char i=0; i<8; i++) {
        IO = dat & (1<<i);
        SCLK = 1; SCLK = 0;
    }
    CE = 0;
}

unsigned char ds1302_read(unsigned char addr) {
    CE = 1;
    for(unsigned char i=0; i<8; i++) {
        IO = addr & (1<<i);
        SCLK = 0; SCLK = 1;
    }
    IO = 1;
    unsigned char dat = 0;
    for(unsigned char i=0; i<8; i++) {
        SCLK = 1; SCLK = 0;
        if(IO) dat |= (1<<i);
    }
    CE = 0;
    return dat;
}

void main() {
    ds1302_write(0x8E, 0x00); // Disable write protection
    // Read time values
    while(1);
}

Temperature Sensor DS18B20

Temperature Measurement

#include <reg52.h>

sbit DQ = P3^7;

unsigned char ds18b20_init() {
    DQ = 1; 
    DQ = 0; 
    for(unsigned char i=0; i<247; i++);
    DQ = 1; 
    for(unsigned char i=0; i<32; i++);
    unsigned char ack = DQ;
    for(unsigned char i=0; i<247; i++);
    return ack;
}

void ds18b20_start() {
    ds18b20_init();
    // Skip ROM command
    // Convert T command
}

float read_temperature() {
    // Read temperature from scratchpad
    return 0.0f;
}

void main() {
    float temp = read_temperature();
    while(1);
}

Motor Control with PWM

Speed Regulation

#include <reg52.h>

sbit motor = P1^0;

void timer0_init() {
    TMOD |= 0x01;
    TH0 = 0xFB;
    TL0 = 0xAE;
    ET0 = 1;
    EA = 1;
    TR0 = 1;
}

unsigned int counter = 0;
unsigned int duty_cycle = 0;

void timer0_isr() interrupt 1 {
    TH0 = 0xFB;
    TL0 = 0xAE;
    counter++;
    if(counter < duty_cycle) {
        motor = 1;
    } else {
        motor = 0;
    }
    if(counter >= 100) counter = 0;
}

void main() {
    timer0_init();
    while(1) {
        if(P3_1 == 0) {
            while(P3_1 == 0);
            duty_cycle += 25;
            if(duty_cycle > 75) duty_cycle = 0;
        }
    }
}

ADC and DAC Conversion

Analog-to-Digital Conversion

#include <reg52.h>

sbit CS = P3^5;
sbit CLK = P3^6;
sbit DIN = P3^4;
sbit DOUT = P3^7;

unsigned int read_adc(unsigned char command) {
    CLK = 0;
    CS = 0;
    
    for(unsigned char i=0; i<8; i++) {
        DIN = command & (0x80>>i);
        CLK = 1; CLK = 0;
    }
    
    unsigned int result = 0;
    for(unsigned char i=0; i<16; i++) {
        CLK = 1; CLK = 0;
        if(DOUT) result |= (0x8000>>i);
    }
    
    CS = 1;
    return result;
}

void main() {
    while(1) {
        unsigned int adc_value = read_adc(0x94); // Read XP channel
        // Process ADC value
    }
}

Infrared Remote Control

Signal Reception

#include <reg52.h>

sbit INT0_PIN = P3^2;

void init_interrupt() {
    IT0 = 1;    // Falling edge trigger
    EX0 = 1;    // Enable external interrupt 0
    EA = 1;     // Enable global interrupts
}

void int0_isr() interrupt 0 {
    static unsigned int pulse_width = 0;
    static unsigned char state = 0;
    
    if(state == 0) {
        // Start pulse detection
        pulse_width = 0;
        state = 1;
    } else {
        // Process received data
        state = 0;
    }
}

void main() {
    init_interrupt();
    while(1);
}

Additional Concepts

Memory Management

  • Code Space: Program instructions stored in Flash
  • Data Space: RAM for variables and stack
  • Special Function Registers: Control peripherals through dedicated addresses

I/O Port Configuration

  • P0: Open-drain output
  • P1/P2/P3: Quasi-bidirectional with pull-up resistors

Timing Considerations

  • Clock Frequency: Typically 11.0592 MHz for standard applications
  • Timer Prescaler: Used to adjust timing precision
  • Interrupt Priorities: Configurable for critical tasks

Common Protocols

  • I2C: Two-wire serial communication
  • SPI: Four-wire synchronous protocol
  • UART: Asynchronous serial communication

Programming Best Practices

  • Use appropriate delay functions for timing
  • Implement debouncing for mechanical switches
  • Handle peripheral initialization properly
  • Manage interrupt service routines efficiently
  • Utilize memory qualifiers like code for constant data

These implementations demonstrate fundamental concepts in 8051 microcontroller programming, covering essential peripherals and communication protocols.

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.