嵌入式入门教学——C51

一、前期准备

1、硬件设备

2、软件设备

  •  

二、预备知识

1、什么是单片机?

  • 在一片集成电路芯片上集成微处理器、存储器、IO接口电路,从而构成了单芯片微型计算机,及单片机。
  • STC89C52单片机:
    • STC:公司
    • 89:所属系列
    • C:工作电压(5.5V~3.8V)
    • 52:程序空间及RAM空间大小(8KB程序空间及512B的RAM空间)

2、电平特性

  • 定义单片机为TTL电平:高+5v、低0v
  • RS232电平(计算机的串口):高-12v、低+12v 
  • 故计算机与单片机之间通讯时需要加电平转换芯片max232

3、二进制数的逻辑关系

  • 与:&
  • 或:+
  • 非:!
  • 异或:⊕(相同为0,不同为1)

4、80C51系列介绍

  • 以8051为基核开发出的CMOS工艺单片机产品统称为80C51系列。
  • STC(公司名)89(系列)C(CMOS)52(2为内部存储空间大小2*4=8k)RC
  • 40(晶振频率)C(商业级-温度)-PDIP(封装格式)
  • 0721(07年21周)CV4336

5、80C51引脚封装

  • 总线型:四组,每组8位。
  • 非总线型

6、C-51数据类型扩充定义

  • sfr:特殊功能寄存器声明。
  • sfr16:sfr16位数据声明。
  • sbit:特殊功能位声明。
  • bit:位变量声明。

7、C-51包含的头文件

  • reg51.h:定义特殊功能寄存器和位寄存器。
  • math.h:定义常用数学运算。

8、C-51的运算符

  • >>:位右移
  • <<:位左移
  • &:按位与
  • |:按位或
  • ^:按位异或
  • ~:按位取反

9、单片机主要掌握一下几点

  • 最小系统能够运行起来的必要条件:电源、晶振、复位电路(程序从头执行)。
  • 对单片机任意IO口的随意操作:输出控制电平高低、输出检测电平高低。
  • 定时器:重点掌握最常用的方式2。
  • 中断:外部中断、定时器中断、串口中断。
  • 串口通信:单片机之间、单片机与计算机间。

10、电路图符号表示

  • 电阻:R
  • 电容:C
  • 电感:L
  • 集成块/芯片:U
  • 地:GND
  • 电源:VCC、AVDD、DVDD

三、LED模块

1、点亮一个LED

1.1、LED的位置
1.2、新建一个工程
  • 新建一个工程。
  • 选择存放位置,新建一个文件夹用于存放该工程。
  • 进入文件夹,输入文件名,即工程名。
  • 选择单片机的型号。选择Atmel下的AT89C52。(本单片机使用的是STC89C52)
  • 新建一个c语言程序文件。
1.3、LED原理图
  • 下图红框区域相连接。
  • LED右端接的是电源,为高电平,故左端为低电平即可导通。(单片机默认输出高电平)
  •  
1.4、单片机如何控制LED
  • P2寄存器的8位决定了LED的高低电平。1为高电平,0为低电平。
  • 当为低电平时,低于外部电压,有电流通过,点亮led。
  • 【注】51单片机所有IO口上电后默认全是高电平。
  • 例如:控制第一个灯亮,p2寄存器应为:1111 1110。
1.5、进制转换
  • c语言中,不能识别二进制,应该转换为十六进制。
  • 例如:
    • p2=1111 1110; // 错误
    • p2=0xFE; // 正确,前面0x表示十六进制。
1.6、编写代码
#include <REGX52.H> // 头文件,定义特殊功能寄存器和位寄存器
void main(){P2=0xFE; // 1111 1110while(1); // 让程序停止在这,不让main重复执行
}
1.7、设置生成.hex下载文件
  • 设置完后,编译程序,生成.hex文件。
1.8、将.hex文件下载到单片机中
  • 将单片机连接电脑串口。 
  • 打开STC-ISP程序,选择hex文件,点击下载。
  • 重启单片机,成功点亮第一个led。

2、LED闪烁

  • 新建工程和c语言程序文件,与前相同。
  • 尝试点亮一个led再熄灭它。
  • #include<REGX52.H>
    void main(){while(1){P2=0xFE; // 亮P2=0xFF; // 灭}
    }
  • 结果led常亮,并未闪烁。原因是led闪烁的频率过快,人的肉眼无法捕捉。 
  • 使用STC-ISP生成延时函数。设置要与使用的单片机一致。
  • 添加延时函数。
  • #include<REGX52.H>
    #inlcude<INTRINS.H> // 引入nop函数
    void Delay500ms() // 500ms延时函数
    {unsigned char i, j, k;_nop_();i = 4;j = 205;k = 187;do{do{while (--k);} while (--j);} while (--i);
    }
    void main(){while(1){P2=0xFE; // 亮Delay500ms(); // 延时500msP2=0xFF; // 灭Delay500ms();}
    }
  • 编译后下载程序到单片机,LED灯以500ms的时间间隔闪烁。

3、LED流水灯

  • 新建工程和c语言程序文件,设置生成hex文件。
  • 编辑代码:
  • #include<regx52.h>
    #inlcude<intrins.h> // 引入nop函数
    void Delay500ms() //500ms延时函数
    {unsigned char i, j, k;_nop_();i = 4;j = 205;k = 187;do{do{while (--k);} while (--j);} while (--i);
    }
    void main(){while(1){P2=0xFE; // 1111 1110Delay500ms(); // 延时500msP2=0xFD; // 1111 1101Delay500ms();P2=0xFB; // 1111 1011Delay500ms();P2=0xF7; // 1111 0111Delay500ms();P2=0xEF; // 1110 1111Delay500ms();P2=0xDF; // 1101 1111Delay500ms();P2=0xBF; // 1011 1111Delay500ms();P2=0x7F; // 0111 1111Delay500ms();}
    }
  • 编译后下载程序到单片机,LED灯以500ms的时间间隔流动。
  • 原延时函数不方便,不能随时更改延时时间,重新编辑延时函数。先使用STC-ISP生成一个延时1ms的函数。
  • C51数据类型
  • 为延时函数添加一个参数,控制延时时间。
  • #include<regx52.h>
    void Delay(unsigned int xms) //带参延时函数
    {unsigned char i, j;while(xms--){i = 2;j = 239;do{while (--j);} while (--i);}
    }
    void main(){while(1){P2=0xFE; // 1111 1110Delay(500); // 延时500msP2=0xFD; // 1111 1101Delay(500);P2=0xFB; // 1111 1011Delay(500);P2=0xF7; // 1111 0111Delay(500);P2=0xEF; // 1110 1111Delay(500);P2=0xDF; // 1101 1111Delay(500);P2=0xBF; // 1011 1111Delay(500);P2=0x7F; // 0111 1111Delay(500);}
    }
  •  带参数的延时函数更加灵活。

四、独立按键

1、独立按键控制LED亮灭

1.1、独立按键
  • 相当于是一种电子开关,按下时开关接通,松开时开关断开,实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通和断开。
1.2、独立按键原理图
  • 下图红框区域相连接。
 1.3、编写代码
  • 由原理图知,K1由P3.1控制。
  • #include<regx52.h>
    void main(){//P2=0xFE;while(1){if(P3_1==0){ // K1按下P2_0=0; // 按位操作,在regx52.h头文件中有声明}else{ // K1松开P2_0=1;}}
    }
  • K1按下,LED亮;K1松开,LED灭。

2、独立按键控制LED状态

2.1、按键的抖动
  • 对于机械开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动。
  • 抖动会使对按键的判断产生一些误操作,可以通过代码解决。
2.2、解决抖动并控制LED状态
  • #include<regx52.h>
    void Delay(unsigned int xms) //带参延时函数
    {unsigned char i, j;while(xms--){i = 2;j = 239;do{while (--j);} while (--i);}
    }
    void main(){while(1){if(P3_1==0){ // K1按下// 防抖Delay(20);while(P3_1==0);Delay(20);P2_0=~p2_0; // 取反}}
    }
  • 按下K1,没反应,松开K1,灯亮;按下K1,无反应,松开K1,灯灭。

3、独立按键控制LED显示二进制

  • #include<regx52.h>
    void Delay(unsigned int xms)
    {unsigned char i, j;while(xms--){i = 2;j = 239;do{while (--j);} while (--i);}
    }
    void main(){unsigned char Led_Num=0; // 8位,相当于寄存器的8位while(1){if(P3_1==0){ // K1按下// 防抖Delay(20);while(P3_1==0);Delay(20);Led_Num++;P2=~Led_Num; // 取反}}
    }
  • 每按一次按键,8个LED显示对应的二进制。 
  • 如:,表示0000 0111。

4、独立按键控制LED移位

  • #include<regx52.h>
    void Delay(unsigned int xms) // 延时函数
    {unsigned char i, j;while(xms--){i = 2;j = 239;do{while (--j);} while (--i);}
    }
    void main(){unsigned char Led_Num=0;P2=~0x01; // 初始化while(1){// K1按键,左移if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);Led_Num++;if(Led_Num>=8) // 越界判断Led_Num=0;P2=~(0x01<<Led_Num);}// K2按键,右移if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);if(Led_Num==0)Led_Num=7;else Led_Num--;P2=~(0x01<<Led_Num);}}
    }
  • 按下K1,LED左移一个;按下K2,LED右移一个。

五、数码管

1、静态数码管显示

1.1、数码管介绍
  • 数码管是一种简单、廉价的显示器,是由多个发光极管封装在一起组成“8”字型的器件。
1.1.1、一位数码管
  • 段的名称、引脚序号
  • 共阴极连接、共阳极连接
  • 例如,让共阴极数码管显示6。
    • ,应该让A、C、D、E、F、G点亮。
    • 首先需要将3,8引脚接地,即位选(让某个数码管亮)。
    • ,控制7、4、2、1、9、10输出高电平,即段选(让数码管输出6)。
1.1.2、四位一体数码管
  • 引脚序号
  • 连接方式
  • 例如,让共阴极数码管第3位显示1。
    • ,需要如下图所示。
  • 【注】同一时刻,只能有一个位被选中显示数字,或者4个位都显示相同的数字。(静态)
1.2、数码管原理图
  • 上图左边74HC573为双向数据缓冲器,来提高驱动能力。
  • 138译码器用来控制位选(3位输入,8位输出),原理如下表。
  •  
1.3、编写代码
  • 让第三位数码管显示6。
  • #include<regx52.h>void main(){// 位选P2_4=1;P2_3=0;P2_2=1;// 段选P0=0x7D; // 0111 1101while(1);
    }
 1.4、引入函数
  • #include<regx52.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, int Number){switch(Location){case 1: P2_4=1; P2_3=1; P2_2=1; break;case 2: P2_4=1; P2_3=1; P2_2=0; break;case 3: P2_4=1; P2_3=0; P2_2=1; break;case 4: P2_4=1; P2_3=0; P2_2=0; break;case 5: P2_4=0; P2_3=1; P2_2=1; break;case 6: P2_4=0; P2_3=1; P2_2=0; break;case 7: P2_4=0; P2_3=0; P2_2=1; break;case 8: P2_4=0; P2_3=0; P2_2=0; break;}P0=NixieTable[Number];
    }
    void main(){Nixie(7,2);while(1);
    }

2、动态数码管显示

2.1、数码管消影
  • 现象:数码管数字显示的位置错乱。
  • 动态数码管显示过程
    • 位选 -> 段选 -> 位选 -> 段选。。。
  • 原因:速度太快,数据串位。
  • 解决方法
    • 位选 -> 段选 -> 清零 -> 位选 -> 段选。。。
2.2、编写代码
  • #include<regx52.h>
    // 延时函数
    void Delay(unsigned int xms)
    {unsigned char i, j;while(xms--){i = 2;j = 239;do{while (--j);} while (--i);}
    }
    //段选
    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, int Number){switch(Location){case 1: P2_4=1; P2_3=1; P2_2=1; break;case 2: P2_4=1; P2_3=1; P2_2=0; break;case 3: P2_4=1; P2_3=0; P2_2=1; break;case 4: P2_4=1; P2_3=0; P2_2=0; break;case 5: P2_4=0; P2_3=1; P2_2=1; break;case 6: P2_4=0; P2_3=1; P2_2=0; break;case 7: P2_4=0; P2_3=0; P2_2=1; break;case 8: P2_4=0; P2_3=0; P2_2=0; break;}P0=NixieTable[Number];// 消影Delay(1);P0=0x00;
    }
    void main(){while(1){Nixie(1,1);//Delay(20);Nixie(2,2);//Delay(20);Nixie(3,3);//Delay(20);}
    }
2.3、数码管驱动方式
  • 单片机直接扫描:硬件设备简单,但会耗费大量的单片机CPU时间(如上代码)。
  • 专用驱动芯片:内部自带显存、扫描电路,单片机只需告诉它显示什么即可。(TM1640芯片)

六、模块化编程及LCD1602调试工具

待续。。。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【计算机网络】应用层协议 -- DNS协议

文章目录 1. DNS背景2. 域名简介3. 域名解析过程4. 使用dig查看DNS过程 1. DNS背景 DNS&#xff08;Domain Name System&#xff0c;域名系统&#xff09;协议&#xff0c;是一个用来将域名转化为IP地址的应用层协议。 TCP/IP当中通过IP地址和端口号的方式&#xff0c;来确定…

调试正在运行的程序(Keil)

大家好&#xff0c;我是惊觉。接上一篇调试正在运行的程序(STM32CubeIDE)&#xff0c;今天Keil的实现方法。调试正在运行的程序&#xff0c;属于附着调试&#xff0c;在启动调试器时不会重置单片机的运行状态&#xff0c;从而可以定位死机等问题。没看过上一篇的同学&#xff0…

SystemC的调度器

文章目录 前言调度器初始化evaluatewait updatenotify delta notificationtime notification仿真结束 前言 SystemC是基于C的库&#xff0c;主要用来对 IC 进行功能建模和性能建模。有时也被用来当做 RTL (register transfer level) 级的升级版 HLS(High Level synthesis) 直接…

力扣 416. 分割等和子集

题目来源&#xff1a;https://leetcode.cn/problems/partition-equal-subset-sum/description/ C题解&#xff08;思路来源代码随想录&#xff09; &#xff1a; 背包问题有多种背包方式&#xff0c;常见的有&#xff1a;01背包、完全背包、多重背包、分组背包和混合背包等等。…

JVM基础篇-虚拟机栈

JVM基础篇-虚拟机栈 定义 Java Virtual Machine Stacks &#xff08;Java 虚拟机栈&#xff09; 每个线程运行时所需要的内存&#xff0c;称为虚拟机栈每个栈由多个栈帧&#xff08;Frame&#xff09;组成&#xff0c;对应着每次方法调用时所占用的内存每个线程只能有一个活动…

Manim(一款强大的数学可视化动画引擎)学习历程

相逢情便深&#xff0c;恨不相逢早 第一眼看见上面这种类型的视频我就深深被它的简约清楚所折服&#xff0c;我觉得它完全符合我的审美&#xff0c;我也相信只要了解过制作这种视频的软件的人都会喜欢上它。运用这种风格比较有名的是b站里的一位up主名叫3Blue1Brown&#xff0…

C++ 模板初阶

泛型编程 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。模板是泛型编程的基础 模板分为&#xff1a;函数模板和类模板 函数模板 概念 函数模板代表了一个函数家族&#xff0c;该函数模板与类型无关&#xff0c;在使用时被参数化&a…

数据结构 | 搜索和排序——排序

目录 一、冒泡排序 二、选择排序 三、插入排序 四、希尔排序 五、归并排序 六、快速排序 排序是指将集合中的元素按照某种顺序排序的过程。 一、冒泡排序 冒泡排序多次遍历列表。它比较相邻的元素&#xff0c;将不合顺序的交换。每一轮遍历都将下一个最大值放到正确的位…

【抽水蓄能电站】基于粒子群优化算法的抽水蓄能电站的最佳调度方案研究(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f308;4 Matlab代码、数据、文章讲解 &#x1f4a5;1 概述 文献来源&#xff1a; 摘要&#xff1a;抽水蓄能电站作为当前电力系统重要的储能和调峰电源同时具有填谷、调频、调相、事故备用以…

ETHERNET/IP 转ETHERCAT连接ethercat总线伺服如何控制

捷米JM-EIP-ECAT网关连接到ETHERNET/IP总线中做为从站使用&#xff0c;连接到ETHERCAT总线中做为从站使用&#xff0c;可以同时满足多种工业生产的需求。支持广泛的设备类型&#xff0c;可以和多种不同的设备进行通讯。 技术参数 ETHERNET/IP 技术参数 网关做为 ETHERNET/IP …

记一次 HTTPS 抓包分析和 SNI 的思考

日常听说 HTTPS 是加密协议&#xff0c;那现实中的 HTTPS 流量&#xff0c;是真的完全加密吗&#xff1f; ——答案是&#xff0c;不一定。原因嘛&#xff0c;抓个包就知道了。 我们用 curl 命令触发一下&#xff1a; curl -v https://s-api.37.com.cn/api/xxx * Trying 1…

jmeter使用步骤

jmeter 使用步骤 1&#xff0c;进入jmeter目录中的bin目录&#xff0c;双击jmeter.bat 打开 2&#xff0c;右键test plan 创建线程组 3&#xff0c;配置线程组参数 4&#xff0c;右键刚刚创建的线程组&#xff0c;创建请求&#xff0c;填写请求地址 5&#xff0c;需要携带to…

ES6之Promise、Class类与模块化(Modules)

目录 PromiseClass类extendssuper Modules 模块系统export default 和对应importexport 和 import Promise Promise 是 ES6 引入的一种用于处理异步操作的对象。 它解决了传统回调函数&#xff08;callback&#xff09;模式中容易出现的回调地狱和代码可读性差的问题。 Promis…

【远程桌面软件NoMachine】

Remote Access for Everybody 特色&#xff1a;快速、安全、跨平台、免费且简单易用&#xff0c;尤其是在带宽低、速率慢的网络环境下&#xff0c;NoMachine仍能保持良好的性能。 官网地址为&#xff1a;https://www.nomachine.com/

聊聊我的故事-悲惨的童年

目录 前言一、介绍二、17年回顾1.出生2.上幼儿园3.上小学4.上初中 高中总结 前言 本人是06年生的&#xff0c;快18了&#xff0c; 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、介绍 本人已经17了&#xff0c;在这17年过的很悲惨&#xff0c;也…

使用uni-app的uniCloud 云数据库入门:实现一个简单的增删改查

官方云数据库文档 前置步骤使用uni-app新建一个uniCloud项目 [外链图片转存失败,源站可能有防盗官方云数据库文档]!链机制,建议将()https://uniapp.dcloud.net.cn/uniCloud/hellodb.html)] 新建表 这里我加了几个测试字段 createTime、remark、money // 文档教程: https://un…

[Docker实现测试部署CI/CD----相关服务器的安装配置(1)]

目录 0、CI/CD系统最终架构图规划IP地址 1、git配置Git下载pycharm配置gitidea配置git 2、GitLab安装与配置主机要求拉取镜像定义 compose.yml启动gitlab浏览器访问并修改密码查看登录密码修改密码 3、SonarQube 安装与配置拉取镜像修改虚拟内存的大小启动SonarQube登录 SonarQ…

SQL ASNI where from group order 顺序

SQL语句执行顺序&#xff1a; from–>where–>group by -->having — >select --> order 第一步&#xff1a;from语句&#xff0c;选择要操作的表。 第二步&#xff1a;where语句&#xff0c;在from后的表中设置筛选条件&#xff0c;筛选出符合条件的记录。 …

矩阵快速幂

简介 矩阵快速幂是一种高效计算矩阵幂的方法。它利用了矩阵的幂运算具有分治性质的特点&#xff0c;可以将矩阵的幂运算时间复杂度从 O(n)降低到 O(logn)。可用于解决线性递推式问题。 经典的斐波那契数列fnfn-1fn-2。当n很大时&#xff0c;你无法快速的计算第n项的值。可以构…

【RedisInsight】连入Docker容器可视化redis服务

文章目录 下载安装RedisInsight添加数据库添加docker容器内的redis数据库 下载安装RedisInsight 进入redis官网下载&#xff1a;https://redis.com/redis-enterprise/redis-insight/&#xff0c;安装过程一路Next即可。 打开桌面上的快捷方式启动&#xff1a;RedisInsight-v2…