问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

51单片机入门:流水灯实现方法详解

创作时间:
作者:
@小白创作中心

51单片机入门:流水灯实现方法详解

引用
CSDN
1.
https://blog.csdn.net/Dasis/article/details/145451738

本文将介绍51单片机入门中的流水灯实现方法,内容包括宏定义、函数定义、延时函数、标准库函数中的循环移位函数、循环移位函数与左移和右移运算符的区别、Keil中Debug的用法等知识点,并通过具体代码示例进行说明。

1. 宏定义

define进行宏定义的典型用法:

#define uchar unsigned char

注意宏定义后面不能加分号,它是预处理指令不是语句。其中用“uchar”直接替换了unsigned char。此时我们可以用uchar去定义变量类型如:

uchar i;

等价于:

unsigned char i;

对于上面的宏定义我们是用来给已有数据类型取别名。对已有数据类型取别名一般还有使用关键字typedef,定义方法如下:

typedef 已有数据类型 新的数据类型;(要加分号)

2. 函数的定义

函数就是将多条语句集合在一块,来完成一种特定功能。函数分为标准函数库,和用户自定义函数。

标准函数库:Keil编译器提供的,不需要用户进行定义。

自定义函数:用户根据自己需要编写的函数,它必须在使用前先定义。自定义函数一般格式为:

函数类型 函数名 (形式参数表)
{
    局部变量定义
    函数体语句
}

3. 延时函数

自定义函数:延时函数delay(毫秒级)

void delay(unsigned int z)
{
    unsigned int x, y;
    for(x = z; x > 0; x--) //只控制下面一句,无需花括号
        for(y = 114; y > 0; y--); //嵌套循环
}

给形参z赋值,如延时100毫秒:

delay(100);

(根据上面的循环语句,总共会循环11400次,对应时间为100ms,实现软件延时的功能)

在高级程序中使用delay函数(软件延时)的机会很少,这种方式会耗费CPU时间,我们可以使用定时器或者其他方法来实现延时功能。后期如果需要使用延时,可以直接将这个函数复制过来,在Keil中通过debug查看一次for循环得多长时间,然后加入嵌入的for循环,看嵌入后一次for循环的时间来计算y的值,利用y的值来控制内部for循环一次为1ms。

4. 标准库函数中的循环移位函数

标准库函数:

intrins.h

内部函数

字符型循环左移:_crol_,参与运算的数据是char型的就可以来用执行循环左移,不适用于整型数据,具体使用方法见下面的例子

字符型循环右移:_cror_,参与运算的数据是char型的就可以来用执行循环右移,不适用于整型数据

为什么目前常使用char类型,这是因为51单片机中有4组8位的IO口,8位对应一个字节,也就是一个char类型

#include <intrins.h>
void tets_crol (void)
{
    unsigned char a;
    unsigned char b;
    a = 0xFE; //1111 1110
    b = _crol_(a,1); //b now is 0xFD 二进制为1111 1101,左移一位,最高位移动到最低位
}

5. 循环移位函数与左移和右移运算符的区别

使用字符型循环左移:

#include <intrins.h>
void tets_crol (void)
{
    unsigned char a;
    unsigned char b;
    a = 0xFE; //1111 1110
    b = _crol_(a,1); //b now is 0xFD 二进制为1111 1101
}

使用左移运算符:

a = 0xFE; //1111 1110
b = a<<1; //b now is 0xFC 二进制为1111 1100,左移一位,使用0填充最低位

区别:循环左移是把最高位移到最低位上,左移运算符是把最高位移除最低位补0

6. Keil中Debug的用法

通过以下代码可以实现流水灯的效果,下载到开发板也是可以正常运行的。

#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
uchar temp; //LED灯相关变量
//毫秒级延时函数定义
void delay(uint z)
{
    uint x,y;
    for(x = z; x > 0; x--) //只控制下面一句,无需花括号
        for(y = 114; y > 0; y--);//嵌套循环
}   
void main()
{
    temp = 0xfe; //1111 1110
    P1 = temp;
    delay(100);
    while(1)
    {
        temp = _crol_(temp, 1);
        P1 = temp;
        delay(100);
    }
}

下面将如何使用Keil中的debug,通过debug功能可以看到IO口执行完每条语句之后的变化

  • 开启debug之前需要修改晶振频率为实际使用时间
  • 在debug之前需要先点击“Rebuild”
  • 以下为开启Debug的按钮:
  • 开启之后界面图如下:可以看到汇编语言代码、寄存器及值、运行时间(运行至当前代码所需时间,通过记录求差值可以得到一段代码运行所需时间)
  • 打开需要观察的P1口的值,通过单步可以看到每一行代码执行后IO口值的变化,同时观察时间变化,如果时间和预期不对应的话,需要检查晶振频率设置是否正确
  • P1的0~7都打钩,表示均为1,这也是前面提到的IO口打开后默认均为1,P1的值等价于0xFF,
  • 可以通过右下角“Watch1”位置添加需要监控的变量,通过右键设置显示的进制。
  • 左上角为"重置",点击左上角的“step”后就会回到程序的起始位置
  • 通过左侧双击可以设置断点
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号