零基础也能轻松掌握 51 单片机入门到应用指南

这篇教程专为单片机小白打造,从 51 单片机基础讲起,带你搭建开发环境,学习汇编与 C 语言编程。通过 LED 灯闪烁、按键控制、数码管显示等基础实验,以及简易电子钟、温度检测系统等应用案例,结合代码实操,助你快速掌握 51 单片机开发。

目录

一、本篇背景

二、51 单片机基础知识

2.1 什么是 51 单片机

2.2 51 单片机的硬件结构

2.3 51 单片机的引脚功能

三、开发环境搭建

3.1 硬件准备

3.2 软件准备

3.3 开发环境搭建步骤

四、编程语言

4.1 汇编语言

4.2 C 语言

五、基本实验

5.1 LED 灯闪烁实验

5.2 按键控制 LED 灯实验

5.3 数码管显示实验

六、常见应用案例

6.1 简易电子钟

6.2 温度检测系统

七、小结下:


一、本篇背景

在电子技术的广阔领域中,单片机作为一种高度集成化的计算机芯片,以其体积小、成本低、功能强等特点,在工业控制、智能家居、汽车电子等众多领域得到了广泛的应用。51 单片机作为单片机家族中的经典代表,具有结构简单、易于学习等优点,成为了众多电子爱好者和初学者入门单片机编程的首选。本文将以小白的视角,详细介绍 51 单片机的基础知识、开发环境搭建、编程语言、基本实验以及一些常见的应用案例,帮助初学者逐步掌握 51 单片机的开发技术。

二、51 单片机基础知识

2.1 什么是 51 单片机

51 单片机是指以 Intel 8051 内核为基础发展起来的一系列单片机的统称。它最早由 Intel 公司在 1980 年推出,具有 8 位 CPU、4KB 程序存储器(ROM)、128B 数据存储器(RAM)、两个 16 位定时 / 计数器、64KB 外部数据存储器和程序存储器寻址空间等基本资源。后来,许多半导体公司如 Atmel、STC 等在 8051 内核的基础上进行了改进和扩展,推出了各具特色的 51 单片机产品,这些产品在功能和性能上有所提升,但基本的指令系统和架构仍然与 8051 兼容。

2.2 51 单片机的硬件结构

51 单片机的硬件结构主要由 CPU、存储器、I/O 接口、定时 / 计数器、中断系统等部分组成。

  • CPU(中央处理器):是单片机的核心,负责执行程序指令,完成数据的运算和处理。
  • 存储器:包括程序存储器(ROM)和数据存储器(RAM)。程序存储器用于存储用户编写的程序代码,数据存储器用于存储程序运行过程中的临时数据。
  • I/O 接口:是单片机与外部设备进行数据交换的通道,51 单片机通常有 4 个 8 位的并行 I/O 口(P0、P1、P2、P3),可以实现数据的输入和输出。
  • 定时 / 计数器:用于实现定时和计数功能,可用于产生精确的定时信号、测量脉冲信号的频率等。
  • 中断系统:允许单片机在执行主程序的过程中,响应外部或内部的中断请求,暂停主程序的执行,转去执行相应的中断服务程序,处理完中断后再返回主程序继续执行。
  • 2.3 51 单片机的引脚功能

    51 单片机通常采用双列直插式(DIP)封装,具有 40 个引脚。不同的引脚具有不同的功能,下面简要介绍一些主要引脚的功能:

  • 电源引脚:VCC(+5V)和 GND(地),为单片机提供电源。
  • 时钟引脚:XTAL1 和 XTAL2,用于连接外部晶体振荡器,为单片机提供时钟信号。
  • 复位引脚:RST,当该引脚出现高电平并保持一定时间时,单片机将进行复位操作,恢复到初始状态。
  • 并行 I/O 口引脚:P0、P1、P2、P3 口的引脚,用于实现数据的输入和输出。
  • 控制引脚:如 ALE/PROG、PSEN、EA/VPP 等,用于控制单片机的工作模式和数据传输。
  • 三、开发环境搭建

    3.1 硬件准备

  • 51 单片机开发板:市面上有多种类型的 51 单片机开发板可供选择,初学者可以选择一款功能较为齐全、价格适中的开发板,如普中科技的 51 单片机开发板。
  • USB 转串口线:用于将开发板与计算机连接,实现程序的下载和调试。
  • 电源适配器:为开发板提供电源。
  • 3.2 软件准备

  • Keil C51:是一款专门用于 51 单片机编程的集成开发环境(IDE),支持 C 语言和汇编语言编程,具有代码编辑、编译、调试等功能。
  • STC-ISP 下载软件:用于将 Keil C51 编译生成的程序代码下载到 STC 系列 51 单片机中。
  • 3.3 开发环境搭建步骤

    1. 安装 Keil C51:下载 Keil C51 安装程序,按照安装向导的提示进行安装。安装完成后,打开 Keil C51,创建一个新的工程,选择合适的单片机型号。
    2. 安装 STC-ISP 下载软件:下载 STC-ISP 下载软件,解压后运行安装程序。安装完成后,打开 STC-ISP 下载软件,设置好单片机型号、串口波特率等参数。
    3. 连接开发板:使用 USB 转串口线将开发板与计算机连接,确保开发板的电源开关处于打开状态。
    4. 编写并编译程序:在 Keil C51 中编写 51 单片机程序代码,点击编译按钮进行编译。如果代码没有错误,编译器将生成一个十六进制(.hex)文件。
    5. 下载程序:打开 STC-ISP 下载软件,选择刚才生成的.hex 文件,点击下载按钮,将程序下载到单片机中。

    四、编程语言

    4.1 汇编语言

    汇编语言是一种面向机器的低级语言,它使用助记符来表示机器指令,与单片机的硬件结构密切相关。汇编语言的优点是执行效率高、代码简洁,适合对程序执行时间和内存空间要求较高的场合。下面是一个简单的 51 单片机汇编语言程序示例,实现 LED 灯的闪烁:

    ORG 0000H ; 程序起始地址
    LJMP MAIN ; 跳转到主程序
    ORG 0030H ; 主程序起始地址
    MAIN:
        SETB P1.0 ; 将 P1.0 引脚置高电平,点亮 LED 灯
        LCALL DELAY ; 调用延时子程序
        CLR P1.0 ; 将 P1.0 引脚置低电平,熄灭 LED 灯
        LCALL DELAY ; 调用延时子程序
        SJMP MAIN ; 跳转到主程序开头,循环执行
    DELAY: ; 延时子程序
        MOV R7, #200 ; 设置外层循环次数
    D1: MOV R6, #250 ; 设置内层循环次数
    D2: DJNZ R6, D2 ; 内层循环,R6 减 1,不为 0 则继续循环
        DJNZ R7, D1 ; 外层循环,R7 减 1,不为 0 则继续循环
        RET ; 子程序返回
    END ; 程序结束
    

    4.2 C 语言

    C 语言是一种高级编程语言,具有结构化、模块化、可读性强等优点,易于学习和掌握。在 51 单片机开发中,使用 C 语言可以大大提高开发效率,减少开发周期。下面是一个使用 C 语言实现 LED 灯闪烁的程序示例:

    #include <reg51.h> // 包含 51 单片机的头文件
    #define uchar unsigned char // 定义无符号字符型变量
    #define uint unsigned int // 定义无符号整型变量
    sbit LED = P1^0; // 定义 P1.0 引脚为 LED 控制引脚
    // 延时函数
    void delay(uint time) {
        uint i, j;
        for(i = 0; i < time; i++)
            for(j = 0; j < 123; j++);
    }
    void main() {
        while(1) {
            LED = 1; // 点亮 LED 灯
            delay(500); // 延时 500ms
            LED = 0; // 熄灭 LED 灯
            delay(500); // 延时 500ms
        }
    }
    

    五、基本实验

    5.1 LED 灯闪烁实验

    LED 灯闪烁实验是 51 单片机开发中最基础的实验之一,通过该实验可以熟悉 51 单片机的 I/O 口操作和延时函数的使用。实验步骤如下:

    1. 硬件连接:将开发板上的 LED 灯连接到 P1.0 引脚。
    2. 编写程序:使用 C 语言编写 LED 灯闪烁的程序代码,如上述示例所示。
    3. 编译并下载程序:在 Keil C51 中编译程序,生成.hex 文件,然后使用 STC-ISP 下载软件将程序下载到单片机中。
    4. 观察实验现象:下载完成后,开发板上的 LED 灯将开始闪烁。

    5.2 按键控制 LED 灯实验

    按键控制 LED 灯实验可以让我们了解 51 单片机的输入输出控制原理。实验步骤如下:

    1. 硬件连接:将开发板上的按键连接到 P3.2 引脚,LED 灯连接到 P1.0 引脚。
    2. 编写程序:使用 C 语言编写按键控制 LED 灯的程序代码,示例代码如下:
    #include <reg51.h>
    #define uchar unsigned char
    #define uint unsigned int
    sbit KEY = P3^2; // 定义按键连接的引脚
    sbit LED = P1^0; // 定义 LED 连接的引脚
    void main() {
        while(1) {
            if(KEY == 0) { // 检测按键是否按下
                while(KEY == 0); // 等待按键释放
                LED = ~LED; // 取反 LED 灯的状态
            }
        }
    }
    
    1. 编译并下载程序:同 LED 灯闪烁实验。
    2. 观察实验现象:按下按键,LED 灯的状态将发生改变。

    5.3 数码管显示实验

    数码管显示实验可以让我们学习 51 单片机的数码管驱动原理和段码编码方法。实验步骤如下:

    1. 硬件连接:将开发板上的数码管连接到相应的 I/O 口。
    2. 编写程序:使用 C 语言编写数码管显示的程序代码,示例代码如下:
    #include <reg51.h>
    #define uchar unsigned char
    #define uint unsigned int
    uchar code SEG_CODE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; // 数码管段码表
    sbit LSA = P2^2;
    sbit LSB = P2^3;
    sbit LSC = P2^4;
    void main() {
        uchar i;
        while(1) {
            for(i = 0; i < 10; i++) {
                LSA = 0; LSB = 0; LSC = 0; // 选择第一个数码管
                P0 = SEG_CODE[i]; // 显示数字 i
                for(uint j = 0; j < 50000; j++); // 延时
            }
        }
    }
    
    1. 编译并下载程序:同前两个实验。
    2. 观察实验现象:数码管将依次显示 0 – 9 的数字。

    六、常见应用案例

    6.1 简易电子钟

    简易电子钟可以实现时间的显示和调整功能,是一个比较综合的 51 单片机应用案例。实现步骤如下:

    1. 硬件连接:使用数码管显示时间,按键用于时间调整,同时可以使用定时器来实现精确的计时。
    2. 编写程序:使用 C 语言编写电子钟的程序代码,包括时间计时、数码管显示、按键扫描等功能。示例代码如下:
    #include <reg51.h>
    #define uchar unsigned char
    #define uint unsigned int
    uchar code SEG_CODE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; // 数码管段码表
    sbit LSA = P2^2;
    sbit LSB = P2^3;
    sbit LSC = P2^4;
    sbit KEY1 = P3^2; // 调整小时按键
    sbit KEY2 = P3^3; // 调整分钟按键
    uchar hour = 0, minute = 0, second = 0; // 初始化时间
    // 延时函数
    void delay(uint time) {
        uint i, j;
        for(i = 0; i < time; i++)
            for(j = 0; j < 123; j++);
    }
    // 数码管显示函数
    void display_time() {
        uchar h1, h2, m1, m2;
        h1 = hour / 10;
        h2 = hour % 10;
        m1 = minute / 10;
        m2 = minute % 10;
        LSA = 0; LSB = 0; LSC = 0; P0 = SEG_CODE[h1]; delay(5); // 显示小时十位
        LSA = 1; LSB = 0; LSC = 0; P0 = SEG_CODE[h2]; delay(5); // 显示小时个位
        LSA = 0; LSB = 1; LSC = 0; P0 = 0x40; delay(5); // 显示冒号
        LSA = 1; LSB = 1; LSC = 0; P0 = SEG_CODE[m1]; delay(5); // 显示分钟十位
        LSA = 0; LSB = 0; LSC = 1; P0 = SEG_CODE[m2]; delay(5); // 显示分钟个位
    }
    // 定时器初始化函数
    void timer_init() {
        TMOD = 0x01; // 设置定时器 0 为模式 1
        TH0 = (65536 - 50000) / 256; // 定时器初值
        TL0 = (65536 - 50000) % 256;
        ET0 = 1; // 使能定时器 0 中断
        EA = 1; // 全局中断使能
        TR0 = 1; // 启动定时器 0
    }
    // 定时器中断服务函数
    void timer0_isr() interrupt 1 {
        TH0 = (65536 - 50000) / 256; // 重新加载初值
        TL0 = (65536 - 50000) % 256;
        static uint count = 0;
        count++;
        if(count >= 20) { // 每 1 秒
            count = 0;
            second++;
            if(second >= 60) {
                second = 0;
                minute++;
                if(minute >= 60) {
                    minute = 0;
                    hour++;
                    if(hour >= 24) {
                        hour = 0;
                    }
                }
            }
        }
    }
    // 按键扫描函数
    void key_scan() {
        if(KEY1 == 0) {
            delay(20); // 消抖
            if(KEY1 == 0) {
                while(KEY1 == 0);
                hour = (hour + 1) % 24;
            }
        }
        if(KEY2 == 0) {
            delay(20); // 消抖
            if(KEY2 == 0) {
                while(KEY2 == 0);
                minute = (minute + 1) % 60;
            }
        }
    }
    void main() {
        timer_init();
        while(1) {
            display_time();
            key_scan();
        }
    }
    
    1. 编译并下载程序:同前面的实验。
    2. 观察实验现象:数码管将显示当前的时间,按下按键可以调整时间。

    6.2 温度检测系统

    温度检测系统可以实时检测环境温度,并将温度值显示在数码管上。实现步骤如下:

    1. 硬件连接:使用温度传感器(如 DS18B20)采集温度数据,数码管显示温度值。
    2. 编写程序:使用 C 语言编写温度检测系统的程序代码,包括温度传感器驱动、数码管显示等功能。示例代码如下:
    #include <reg51.h>
    #include <intrins.h>
    #define uchar unsigned char
    #define uint unsigned int
    sbit DQ = P3^7; // DS18B20 数据引脚
    uchar code SEG_CODE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; // 数码管段码表
    sbit LSA = P2^2;
    sbit LSB = P2^3;
    sbit LSC = P2^4;
    // 延时函数
    void delay(uint time) {
        uint i, j;
        for(i = 0; i < time; i++)
            for(j = 0; j < 123; j++);
    }
    // DS18B20 初始化函数
    bit ds18b20_init() {
        bit presence;
        DQ = 1;
        _nop_();
        DQ = 0;
        delay(500); // 延时 480 - 960us
        DQ = 1;
        delay(60); // 延时 60 - 240us
        presence = DQ;
        delay(440); // 延时 480 - 960us
        return presence;
    }
    // DS18B20 写一个字节函数
    void ds18b20_write_byte(uchar dat) {
        uchar i;
        for(i = 0; i < 8; i++) {
            DQ = 0;
            _nop_();
            DQ = dat & 0x01;
            delay(60); // 延时 60 - 120us
            DQ = 1;
            dat >>= 1;
        }
    }
    // DS18B20 读一个字节函数
    uchar ds18b20_read_byte() {
        uchar i, dat = 0;
        for(i = 0; i < 8; i++) {
            DQ = 0;
            _nop_();
            dat >>= 1;
            DQ = 1;
            if(DQ)
                dat |= 0x80;
            delay(60); // 延时 60 - 120us
        }
        return dat;
    }
    // 读取 DS18B20 温度函数
    int ds18b20_read_temp() {
        uchar LSB, MSB;
        int temp;
        ds18b20_init();
        ds18b20_write_byte(0xCC); // 跳过 ROM 操作
        ds18b20_write_byte(0x44); // 启动温度转换
        delay(750); // 等待转换完成
        ds18b20_init();
        ds18b20_write_byte(0xCC); // 跳过 ROM 操作
        ds18b20_write_byte(0xBE); // 读取温度寄存器
        LSB = ds18b20_read_byte();
        MSB = ds18b20_read_byte();
        temp = (MSB << 8) | LSB;
        temp = temp * 0.0625 * 10 + 0.5; // 转换为实际温度值
        return temp;
    }
    // 数码管显示函数
    void display_temp(int temp) {
        uchar t1, t2, t3;
        t1 = temp / 100;
        t2 = (temp % 100) / 10;
        t3 = temp % 10;
        LSA = 0; LSB = 0; LSC = 0; P0 = SEG_CODE[t1]; delay(5); // 显示百位
        LSA = 1; LSB = 0; LSC = 0; P0 = SEG_CODE[t2] | 0x80; delay(5); // 显示十位,带小数点
        LSA = 0; LSB = 1; LSC = 0; P0 = SEG_CODE[t3]; delay(5); // 显示个位
    }
    void main() {
        int temp;
        while(1) {
            temp = ds18b20_read_temp();
            display_temp(temp);
        }
    }
    
    1. 编译并下载程序:同前面的实验。
    2. 观察实验现象:数码管将显示当前的环境温度值。

    七、小结下:

    通过本文的学习,我们从 51 单片机的基础知识入手,逐步了解了开发环境的搭建、编程语言的使用、基本实验的实现以及常见应用案例的开发。对于初学者来说,掌握 51 单片机的开发技术需要不断地实践和积累,通过完成更多的实验和项目,加深对单片机原理和编程方法的理解。希望本文能够帮助广大电子爱好者和初学者快速入门 51 单片机开发,开启电子技术的探索之旅。

    作者:羑悻的小杀马特.

    物联沃分享整理
    物联沃-IOTWORD物联网 » 零基础也能轻松掌握 51 单片机入门到应用指南

    发表回复