• 51单片机学习笔记_2 LED 模块


    程序编写前言

    新建项目 new μversion project

    选择 CPU 型号:Keil 中没有完全对应的 STC89C52 版本,用Atmel 中的 AT89C52 即可,不用把8051启动文件添加到工程中。

    AT 和 STC 是两种型号的单片机。有的 STC 单片机上面还有 AT 接口,AT 使用那个接口烧录程序。STC 就用 USB 下载。

    新建好后有一个文件夹:source group,代码文件都在其中。

    选中该文件夹,右键新建new item,新建c语言文件。可以选c/cpp/asm

    在魔术棒 Output 选项中添加 “ create HEX file".

    程序框架

    #include "reg52.h"
    void main()
    {
        while(1)
        {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    编译:translate按钮

    建立:build按钮,也有编译的作用,只编译发生变动的文件。

    重新建立:rebuild,编译所有文件(速度慢不建议)。

    报错如果显示:缺少root segment根段,即没有找到主函数。

    头文件作用

    #include和`#include “reg52.h"都可以。区别在于<>直接去软件安装处搜索头文件,而”"先在该项目下查找头文件,找不到再去软件安装处,再找不到就报错。

    查看头文件可以在左侧的结构树对应的c文件目录下打开,或者右键“reg52.h" open 打开。

    该头文件中定义了52单片机内部所有功能寄存器,把地址值如0x80赋值给P0等端口。

    程序烧录

    程序编译建立没有错误,也开启了魔术棒创建 HEX 文件选项,那么 build 后就会在对应路径中找到生成的 HEX 文件。

    在 STC-ISP 中选定单片机型号、串口、晶振频率(可以直接看开发板上的晶振上面有写),选择对应的 HEX 文件,先断电开发板,再点击下载,再开机,就可以查看呈现在开发板上的效果。

    HELLO WORLD——LED部分

    LED 发光二极管。

    image-20230125222255962

    image-20230125222332854

    下面两个黑色的方块就是8个电阻。电阻是限流作用,防止电流过大烧毁 LED。

    电阻上面写着小小的“102”,代表10*10^2,即1kΩ。

    每个 LED 正极是一定通电流的,如果负极接地,那么这个 LED 被点亮。否则两头都是高电平点不亮(这里的电平是 TTL 电平,高5低0)。

    单片机如何驱动高低电平?在 MCU 内,CPU 接到指令(如P2^0口赋1,即高电平)CPU 把数据写入寄存器,寄存器数据通过驱动器放大后变为5V/0V 电平输出。

    点亮 LED

    GPIO(general purpose input output) 即通用输入输出端口,可以通过软件控制其输入和输出.

    image-20220905111036720

    • 电源引脚: Vcc, GND
    • 晶振引脚:XTAL1 2
    • 复位引脚:RST VPD,不做其他功能。
    • 下载引脚:TXD RXD
    • GPIO引脚:Px.x的都是 GPIO 引脚,大致分为P0 P1 P2 P3,每组8个IO,P3还有附加功能,比如串口、外部中 断、计数器等。每个引脚每次只能使用一个功能。
    #include "reg52.h"
    sbit LED1=P2^0; //将 P2.0 管脚定义为 LED1
    //我们也可以直接给P2整个赋值。比如P2=0xFE,即1111 1110,就只会点亮最后一个 LED 灯,和 P2^0=0 效果是一样的。
    void main()
    {
        LED1=0; //LED1 端口设置为低电平,就会被点亮
        while(1)//单片机默认不断执行主程序。如果没有这个死循环,单片机就会不断点亮点亮点亮点亮……不如点亮一次之后无限延时。
        {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    编译结果里面的几个数据的意义:

    code:表示程序所占用 FLASH 的大小。

    data:数据储存器内部 RAM 占用大小。

    xdata:数据储存器外部 RAM 占用大小。

    LED 闪烁

    只需要点亮——延时——熄灭——延时循环即可。

    单片机频率单位是 MHz 兆赫兹,所以只是单纯的亮灭亮灭肉眼看不出亮灭的效果。所以需要延时。

    延时可以写一个这样的函数:

    typedef unsigned int u16
    void delay(u16 ten_us){
        while(ten_us--);
    }
    
    • 1
    • 2
    • 3
    • 4

    u16 代表16位的无符号整型数据。这是一个比较常用的定义,unsigned char 定义为 u8, unsigned int 定义为 u16。当 ten_us 超出 u16 的范围后,跳出 while 循环。

    然后就LED1=0;delay(50000);LED1=1;delay(50000);循环即可.

    但是,STC-ISP 可以根据晶振频率和要延时的时间生成延时函数,真的牛!不过注意软件上标明的适用系列版本。

    image-20230125224132185

    其中 _nop_() 函数包括在 INTRINS.H 头文件中,是一个空语句,就只会产生延时的效果。

    不过 STC-ISP 只能生成固定时长的延时函数。如果想要像自己写的那个 delay() 函数一样传入参数,延时对应长度的毫秒/微秒呢?

    很简单,我们先生成延时1毫秒/微秒的函数,然后把函数中的内容重复执行传入参数遍。

    void Delay1ms(unsigned int xms)		//@11.0592MHz
    {
    	unsigned char i, j;
     	while(xms--){//这里是修改过的
            _nop_();
            _nop_();
            _nop_();
            i = 11;
            j = 190;
            do
            {
                while (--j);
            } while (--i);
         }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Keil 软件仿真

    使用仿真功能查看 LED 闪烁案例中的实际延时时间。

    1. 点击魔术棒,选择 Target 选项卡,设置 Xtal 为12M或11.0592M,根据开发板晶振修改对应值。
    2. 点击黑色放大镜中有红色d的仿真按钮,进入仿真页面

    image-20220905153847511

    我们要关注的参数是sec。

    1. 点击RST按钮重新复位系统参数,sec 变为0。然后在要调试的行前双击,就会出现红色块的断点,点击8运行时就会直接运行到断点处。再次点击就会运行到下一处断点处。
    2. 点击红色标记8运行,运行到36行时显示用时:0.00039s,再次点击运行到37行,用时:0.45s
    3. 可见delay花费时间约为0.45s

    LED 流水灯

    学会了点亮和延时,流水灯的原理就很好懂了。就是给P2的所有端口赋值为:1111 1110,每次只有一个为0即点亮,这个点亮的0从最高位逐渐降到最低位。

    取反后即为:

    1000 0000

    0100 0000

    0010 0000

    0001 0000

    0000 1000

    0000 0100

    0000 0010

    0000 0001

    也就是一个移位运算,0x01<

    #include "reg52.h"
    # define LED P2
    void delay(unsigned int i){
    	while(i--){}
    }
    void main()
    {
        while(1)
        {
    			int i=0;
    			for(i;i<8;i++){
    				LED=~(0x01<<i);
    				delay(50000);
    			}
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    移位函数

    位运算的移位操作只能补0,但是 Keil C51 软件内有对应的移位库函数,左移_crol_(),右移_cror_(),包含在 intrins.h 库中

    移位函数会把移出去的位补到空位,一个循环。

    #include "reg52.h"
    #include "intrins.h"
    # define LED P2
    void delay(unsigned int i){
    	while(i--){}
    }
    void main()
    {
        LED=~(0x01);
    	delay(50000);
        while(1)
        {
    			LED=_crol_(LED,1);
    			delay(50000);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    适配器模式
    C/S架构学习之使用poll实现TCP中型并发服务器
    小程序的使用
    Java底层自学大纲_分布式篇
    深入流行推荐引擎3:Spotify音乐推荐系统
    如何实现redis的高可用?
    JavaScript - async 和 await 修饰符的基本使用方法
    企业知识库有什么价值?
    python字符串格式化函数 - format
    “我们为什么要做 iVX ? ” ——访 iVX CEO 孟智平 了解 iVX 企业文化
  • 原文地址:https://blog.csdn.net/jtwqwq/article/details/126747684