51单片机开发——day01

news2024/12/23 23:05:30

1、软件安装:

2、单片机(Micro Controller Unit)MCU:

        内部集成了cpu,RAM,ROM,定时器,中断系统,通讯接口,

        用于信息采集处理硬件设备控制;

8051内核所以带了这个内核的单片机都叫51单片机(是所有兼容8031指令系统的单片机统称);

本次学习使用的单片机信息:

3、单片机命名规则:

4、单片机89c52结构

5、LED

TTL电平:高电平5V,低电平0V

寄存器(p2)以8个为单位分组,对应八个IO口,cpu通过配置寄存器的01来控制IO口的高低电平;

编程中用16进制表示,

点亮LED:单片机的晶振不会停,P2会一直工作;

增加循环,让程序停止在循环里,P2不会重复工作;

LED闪烁:

LED流水灯:

        

独立按键控制LED:

按键开关的抖动:

        

按键消抖:可以用触发器过滤,也可以延迟消抖;

独立按键控制LED表示二进制:

独立按键控制LED移位

数码管:

共阴极和共阳极数码管原理图,本次学习使用共阴极数码管;

        

双向缓冲器(把单片机的驱动信号改成控制型号,利用缓冲器去放大高电平达到更好的驱动效果):

LE是跳线帽:把LE接到高电平VCC,LE接到高电平,就保证P00(A0)输入什么B0就接收什么;

(在单片机中高电平的驱动能力有限,其输出的最大电流不能太大,低电平驱动能力强一些,所以采用低电平点亮LED。)

电容正常为皮法拉(pf):

采用电容来保证电路的稳定(电源滤波);

一般情况下数码管由于IO输入端的接口为相同值,所以一般显示相同的值,要实现动态数码管显示可以采用快速切换数字的方法,由于晶振频率的原因,程序执行一遍人眼看不出来,所以可以通过不断执行程序语句来实现动态数码管显示;

74LS138译码器:输入为CBA,输出为Y0-Y7;

静态数码管代码实现:

数码管消影(在段选后把段选清零):

        位选,段选,...()

清零方法在段选后延迟1ms,然后把P0清零;

数码管的驱动方式:

代码实现:

#include <REGX52.H>
#include <../headFile/at89c52.h>
unsigned char NixieTable[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7c,0x39,0x5E,0x79,0x71,0x00};
void Nixie(unsigned char Location,Number){
    switch(Location)
    {
        case 1: //
            P2_4 = 1;
            P2_3 = 1;
            P2_2 = 1;
            break;
        case 2: //LED7
            P2_4 = 1;
            P2_3 = 1;
            P2_2 = 0;
            break;
        case 3: //LED6
            P2_4 = 1;
            P2_3 = 0;
            P2_2 = 1;
            break;
        case 4:  //LED5
            P2_4 = 1;
            P2_3 = 0;
            P2_2 = 0;
            break;
        case 5:  //LED4
            P2_4 = 0;
            P2_3 = 1;
            P2_2 = 1;
            break;
        case 6:  //LED3
            P2_4 = 0;
            P2_3 = 1;
            P2_2 = 0;
            break;
        case 7:  //LED2
            P2_4 = 0;
            P2_3 = 0;
            P2_2 = 1;
            break;
        case 8:  //LED1
            P2_4 = 0;
            P2_3 = 0;
            P2_2 = 0;
            break;
        }
        P0 = NixieTable[Number];
        Delay(1);
        P0 = 0x00;
}
void main()
{
    while(1){
        Nixie(1,0);
        Nixie(2,1);
        Nixie(3,2);
        Nixie(4,3);
        Nixie(5,4);
        Nixie(6,5);
        Nixie(7,6);
        Nixie(8,7);
        }
    }

模块化编程(提高代码可阅读性,可维护性,可移植性):

 LCD1602调试工具:

使用LCD后会和数码管和LED引脚冲突:

#include <REGX52.H>
#include "LCD1602.h"
//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0

//函数定义:
/**
  * @brief  LCD1602延时函数,12MHz调用可延时1ms
  * @param  无
  * @retval 无
  */
void LCD_Delay()
{
    unsigned char i, j;

    i = 2;
    j = 239;
    do
    {
        while (--j);
    } while (--i);
}

/**
  * @brief  LCD1602写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void LCD_WriteCommand(unsigned char Command)
{
    LCD_RS=0;
    LCD_RW=0;
    LCD_DataPort=Command;
    LCD_EN=1;
    LCD_Delay();
    LCD_EN=0;
    LCD_Delay();
}

/**
  * @brief  LCD1602写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void LCD_WriteData(unsigned char Data)
{
    LCD_RS=1;
    LCD_RW=0;
    LCD_DataPort=Data;
    LCD_EN=1;
    LCD_Delay();
    LCD_EN=0;
    LCD_Delay();
}

/**
  * @brief  LCD1602设置光标位置
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @retval 无
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
    if(Line==1)
    {
        LCD_WriteCommand(0x80|(Column-1));
    }
    else if(Line==2)
    {
        LCD_WriteCommand(0x80|(Column-1+0x40));
    }
}

/**
  * @brief  LCD1602初始化函数
  * @param  无
  * @retval 无
  */
void LCD_Init()
{
    LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
    LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
    LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
    LCD_WriteCommand(0x01);//光标复位,清屏
}

/**
  * @brief  在LCD1602指定位置上显示一个字符
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的字符
  * @retval 无
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
    LCD_SetCursor(Line,Column);
    LCD_WriteData(Char);
}

/**
  * @brief  在LCD1602指定位置开始显示所给字符串
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串
  * @retval 无
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=0;String[i]!='\0';i++)
    {
        LCD_WriteData(String[i]);
    }
}

/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
    unsigned char i;
    int Result=1;
    for(i=0;i<Y;i++)
    {
        Result*=X;
    }
    return Result;
}

/**
  * @brief  在LCD1602指定位置开始显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~65535
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i--)
    {
        LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
    }
}

/**
  * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-32768~32767
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
    unsigned char i;
    unsigned int Number1;
    LCD_SetCursor(Line,Column);
    if(Number>=0)
    {
        LCD_WriteData('+');
        Number1=Number;
    }
    else
    {
        LCD_WriteData('-');
        Number1=-Number;
    }
    for(i=Length;i>0;i--)
    {
        LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
    }
}

/**
  * @brief  在LCD1602指定位置开始以十六进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~0xFFFF
  * @param  Length 要显示数字的长度,范围:1~4
  * @retval 无
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
    unsigned char i,SingleNumber;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i--)
    {
        SingleNumber=Number/LCD_Pow(16,i-1)%16;
        if(SingleNumber<10)
        {
            LCD_WriteData(SingleNumber+'0');
        }
        else
        {
            LCD_WriteData(SingleNumber-10+'A');
        }
    }
}

/**
  * @brief  在LCD1602指定位置开始以二进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度,范围:1~16
  * @retval 无
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i--)
    {
        LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
    }
}
 

c语言预编译:

矩阵键盘(为了减少IO口的占用):

矩阵按键每一行类似于独立按键;

如果逐行扫描在51开发板中矩阵键盘的IO口会和其他外设产生引脚冲突,例如矩阵键盘的P15口就与蜂鸣器的BZ口冲突,逐行扫描后会导致蜂鸣器一直响;

矩阵键盘密码锁:

        

IO口的模式(模式可以定制):

准双向口输入配置:

弱上拉,强下拉(单片机高电平驱动能力弱)单片机的IO口可以双向输出输入,假如一个IO口给1在独路给0,也不会短路,

高电平的驱动能力弱于低电平驱动能力;

开漏输出:

扫描:

        数码管扫描(输出扫描)

原理:显示第一位——显示第二位——显示第三位——。。。快速循环这个过程,最终实现数码管同时显示的效果;

矩阵键盘(输入扫描)

原理:读取第一行(列)——读取第二行列——读取第三行列。。。快速循环这个过程,最终实现所有按键同时检测的效果;

(视频显示像素点如果不采用矩阵扫描会导致需要大量的IO口,采用矩阵扫描可以极大节约IO口数量)

以上扫描的共性:节省IO口;

定时器:

     51单片机定时器属于单片机内部资源,电路连接和运转均在单片机内部完成;

用于计时系统,软件计时,使得程序固定时间完成一项操作;

        替代长时间Delay,提高cpu运行效率和处理速度;

多任务执行:把程序切换成时间片穿插在一条时间线上;

        STC89C52有(T0,T1,T2)三个定时器,T0与T1与传统的51兼容,T2时此型号单片机增加的资源;

定时器在单片机内部根据时钟的输出信号,每隔固定时间段,计数器单元的数值就增加1,计数器单元值增加的设定的提醒时间时,计数单元就会向中断系统发出中断申请,产生提醒,使程序跳转到中断服务函数中执行;

        时钟(提供计数单元的时钟脉冲) ----------计数单元(时钟计数)---------中断系统(产生中断,执行定时任务)

定时器的工作模式:

        STC89C52的T0和T1都有的四种工作模式:

模式0:13位定时器/计数器

模式1:16位定时器/计数器(常用)

模式2:8位自动重装模式

模式3:两个8位计数器

高字节TH,低字节TL;这个计数器只能数到(0---65535);unsigned int

溢出时计数器会清零,并申请中断;只有两个字节存定时器计数情况;

定时器时钟:

该时钟可以由内部引脚提供(该计数器就是时钟),也可以从外部引脚提供(该计数器就充当计数器的功能)

        SYSclk:系统时钟,即晶振周期,本开发板12MHZ

在振荡器中采用一个特殊的元件——石英晶体,可以产生高度稳定的信号,这种采用石英晶体的振荡器称为晶体振荡器。

定时器中断系统:

        

        高优先级中断可以打断低优先级中断;

中断相当于可以同时执行多个任务;

STC89C52中断资源:

单片机通过配置寄存器来控制内部线路的连接,通过内部线路的不同连接方式来实现不同的功能;

按键控制LED控制流水灯模式:

        定时器开启,12M的晶振1微秒加一,加到最大值才产生中断;总共定时65535微秒;

64535离计数器溢出差值1000,所以计时时间为1ms,(给计数器赋值,多次产生中断,直到达到目标时间);

        1、配置TMOD(寄存器)工作模式

配置定时器0的低四位

TMOD是不可寻址寄存器,如果只给低四位赋值时,只用一个定时器的情况下没有影响,如果要用两个定时器,只赋值低四位会导致赋值刷新另一个定时器的参数IO,导致定时器功能无法正常使用;(可以用与或赋值,避免上述情况)

    TMOD = TMOD & 0xF0;//把TMOD的低四位清零,高四位保持不变

    TMOD = TMOD | 0x01;//把TMOD的低四位置一,高四位不变;

让定时器在模式1工作所以在M1给0,M0给1,C/T给0,GATE给0,

M1和M0共同决定定时器的工作模式,门控端GATE给0就是int0单独控制;

可位寻址寄存器可以对每一位单独赋值,不可位寻址的寄存器不能单独赋值,只能单独赋值;

TF0 = 0;把TF0清零防止配置好就产生中断;

TR0 = 1;定时器是否开启,TR0给1允许T0开始计数,TR0=0时禁止T0计数;(GATE = 0);

IE0  ;控制外部中断引脚,

IT0  ;控制外部中断引脚,                                                                                                                                                                                                                                                                                 

配置中断:

ET0 = 1 ;

EA =1;

PT0 =0;                                                                                                                                           

配置好中断后写入中断任务子函数(中断子程序):

                                                

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1284229.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

手把手教你做基于stm32的红外、语音、按键智能灯光控制(上)

目录&#xff1a; 1.系统实现目标2.硬件选型和软件准备2.1. 硬件选型2.2 软件准备 3. 硬件IO表4.各个模块的驱动函数4.1. 红外遥控模块4.2. 按键模块4.3. LED灯4.4. BH1750光照度传感器4.5. 红外检测模块 1.系统实现目标 本文所设计的基于单片机的灯光控制系统主要由模式选择功…

【C++】树型结构关联式容器:map/multimap/set/multisetの使用指南(27)

前言 大家好吖&#xff0c;欢迎来到 YY 滴C系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; 目录 一.键值对二.关联式容器&#xff06;序列…

国产API调试插件:Apipost-Helper

前言 Idea 是一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;它可以帮助开发人员更加高效地编写、调试和部署软件应用程序,Idea 还具有许多插件和扩展&#xff0c;可以根据开发人员的需要进行定制和扩展&#xff0c;从而提高开发效率,今天我们就来介绍一款…

uniapp-距离distance数字太长,截取保留前3为数字

1.需求 将接口返回的距离的字段&#xff0c;保留三位数显示。 2.实现效果 3.代码&#xff1a; 1.这是接口返回的数据&#xff1a; 2.调取接口&#xff0c;赋值前先处理每条数据的distance <view class"left">距你{{item.distance}}km</view>listFun() …

C语言面试之旅:掌握基础,探索深度(面试实战之ARM架构一)

从前不会回头&#xff0c;往后不会将就。 ----小新 一.ARM采用32位架构 ARM约定一个Byte是8 bits&#xff0c;一个Halfword是16 bits (2 byte)&#xff0c;一个Word是32 bits (4 byte)。大部分ARM core …

回溯法及例题(C++实现)

回溯法概念 概念&#xff1a;在包含问题所有解的解空间树中&#xff0c;按照深度优先搜索的策略&#xff0c;根据根结点&#xff08;开始节点&#xff09;出发搜索解空间树。 流程&#xff1a;首先根结点成为活节点&#xff0c;同时也成为当前的扩展结点。在当前的扩展结点处…

蓝桥杯真题:四平方和-Java版

import java.io.*;/*先找后两个数for(int i 0; 2 * i * i < n;i)for(int j i; i * i j * j < n;j ) 再找前两个数 for(int i 0;4 * i * i < n; i )for(int j i;2 * (j * j i * i) < n;j )//这样就可以让后两个数尽量大,前两个数尽量小 这样就可以确定后…

Kubernetes学习笔记-Part.07 Harbor搭建

目录 Part.01 Kubernets与docker Part.02 Docker版本 Part.03 Kubernetes原理 Part.04 资源规划 Part.05 基础环境准备 Part.06 Docker安装 Part.07 Harbor搭建 Part.08 K8s环境安装 Part.09 K8s集群构建 Part.10 容器回退 第七章 Harbor搭建 Docker-Compose是用来管理容器的…

【React 开发】增强你的React 技能:2024年要掌握的4种高级模式

React由于其简单和灵活&#xff0c;近年来已成为最受欢迎的前端库之一。然而&#xff0c;当应用程序的复杂性扩展时&#xff0c;管理状态、处理异步输入和维护可扩展的体系结构可能会变得困难。我们将在本文中介绍四种高级React模式&#xff0c;它们将帮助您克服这些困难以及如…

Unity中C#使用协程控制Shader材质变化

文章目录 前言一、协程是什么二、在Unity中使用协程1、我们在 Start 中测试一下协程的执行顺序2、我们实现一个点击按钮实现角色受击效果 三、协程中的动画过渡1、首先&#xff0c;在协程内实现中毒并且消散的效果2、在 OnGUI 内&#xff0c;给一个新按钮使用刚刚定义的协程 四…

算法基础六

搜索插入位置 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 示例 1: 输入: nums [1,3,5,6], target 5 输出: 2 示例 2: 输入: nums [1,3,5,6], target 2 输…

TCP 半连接队列和全连接队列

在 TCP 三次握手的时候&#xff0c;Linux 内核会维护两个队列&#xff0c;分别是&#xff1a; 半连接队列&#xff0c;也称 SYN 队列&#xff1b; 全连接队列&#xff0c;也称 accept 队列&#xff1b; 服务端收到客户端发起的 SYN 请求后&#xff0c;内核会把该连接存储到半连…

创新零售巨头:揭开山姆与Costco蓬勃发展背后的秘密

会员制商店这个冷门的业态突然之间硝烟弥漫&#xff0c;更多的资本开始涌向付费会员商店这一业态&#xff0c;本文即将探讨的是付费会员制的成功秘诀和零售企业可行的发展路径。Costco的发展经验对国内超市巨头的崛起具有显著的借鉴意义&#xff0c;以优质低价商品服务为中心&a…

辛普森距离(SD,Sampson Distance)

定义 Sampson误差是复杂性介于代数误差和几何误差之间&#xff0c;但非常近似于几何误差的一种误差。 应用 SLAM对极几何中使用到SD来筛选内点&#xff1a; 1.随机采样8对匹配点 2.8点法求解基础矩阵 ​&#xff1b; 3.奇异值约束获取基础矩阵F&#xff1b; 4.计算误差&…

前端开发_CSS

CSS定义 层叠样式表 (Cascading Style Sheets&#xff0c;缩写为 CSS&#xff09;&#xff0c;是一种 样式表 语言&#xff0c;用来描述 HTML 文档的呈现&#xff08;美化内容&#xff09; 书写位置&#xff1a;title 标签下方添加 style 双标签&#xff0c;style 标签里面书…

【华为OD题库-064】最小传输时延I-java

题目 某通信网络中有N个网络结点&#xff0c;用1到N进行标识。网络通过一个有向无环图.表示,其中图的边的值表示结点之间的消息传递时延。 现给定相连节点之间的时延列表times[]{u&#xff0c;v&#xff0c; w)&#xff0c;其中u表示源结点&#xff0c;v表示目的结点&#xff0…

Windows本地搭建WebDAV服务并使用内网穿透远程访问【无公网IP】

windows搭建WebDAV服务&#xff0c;并内网穿透公网访问【无公网IP】 文章目录 windows搭建WebDAV服务&#xff0c;并内网穿透公网访问【无公网IP】1. 安装IIS必要WebDav组件2. 客户端测试3. cpolar内网穿透3.1 打开Web-UI管理界面3.2 创建隧道3.3 查看在线隧道列表3.4 浏览器访…

Unity Meta Quest 一体机开发(八):【手势追踪】实现 Hand Grab 扔物体功能

文章目录 &#x1f4d5;教程说明&#x1f4d5;设置刚体和碰撞体&#x1f4d5;给物体添加 Physics Grabbable 脚本&#x1f4d5;给手部添加 Hand Velocity Calculator 物体 此教程相关的详细教案&#xff0c;文档&#xff0c;思维导图和工程文件会放入 Spatial XR 社区。这是一…

SAS聚类分析介绍

1 聚类分析介绍 1.1基本概念 聚类就是一种寻找数据之间一种内在结构的技术。聚类把全体数据实例组织成一些相似组&#xff0c;而这些相似组被称作聚类。处于相同聚类中的数据实例彼此相同&#xff0c;处于不同聚类中的实例彼此不同。聚类技术通常又被称为无监督学习&#xff0…

2023博思高科技智慧车行、人行专项研讨会成功召开

来源&#xff1a;智安物联网 11月30日&#xff0c;深圳市博思高科技有限公司&#xff08;以下简称“博思高科技”&#xff09;在其总部成功举办了智慧车行、人行专项研讨会议。本次会议邀请了来自国家发改委综合运输研究所的程世东主任&#xff0c;中国安全防范产品行业协会原…