文章目录
AutoLeaders控制组—51单片机学习笔记1.1单片机及开发板介绍单片机介绍单片机应用领域STC89C52单片机内部结构开发板介绍2.1点亮一个Led新建工程编程认识Led2.2LED闪烁编程改进:Delay延迟函数2.3LED流水灯写入程序打开程序的方法3.1独立按键控制LED灯亮灭独立按键介绍编程C51数据运算:3-2 独立按键控制LED状态按键的抖动如何消抖编程3-3 独立按键控制LED显示二进制编程编程改进3.4独立按键控制LED移位编程LED左移编程4.1静态数码管显示LED数码管数码管引脚数码管引脚定义原理图编程4.2动态数码管显示编程数码管驱动方式数码管驱动方式AutoLeaders控制组—51单片机学习笔记
1.1单片机及开发板介绍
单片机介绍
单片机,英文Micro Controller Unit,简称MCU
内部集成了CPU、RAM、定时器、中断系统、通信接口等常用硬件。
单片机任务是信息采集、处理和硬件设备的控制。
单片机是一个袖珍版计算机,有成本低、体积小、结构简单的优点,在生活和工业控制领域大有所用。
单片机应用领域
单片机应用领域广泛,如智能仪表、导航系统、家用电器等。各种产品一旦用上单片机就能起到产品升级换代的效果,被冠以“智能化”的形容词。
STC89C52单片机
所属系列:51单片机系列
公司:STC公司
位数:8位
RAM:512字节(短期存储,相当于运行内存,关机后清零)
ROM:8K(长期存储,相当于手机内存跟电脑硬盘,能长期保存)
工作频率:12MHz
命名规则:
1、stc为公司名,89为系列
2、89表示系列(这里表示STC的12T/6T 的8051单片机)
3、C代表工作电压(C表示5.5~3.8V)
4、52代表程序空间大小(这里的程序空间大小为8K字节)
5、RC表示RAM的空间大小(RC为512字节)
6、40表示工作频率(最大可达40MHZ)
内部结构
开发板介绍
整体
1、拉杆上掰取下单片机
2、单片机引脚(缺口下方为一号引脚)
3、Led灯
4、矩阵按键
5、独立按键
6、红外接收头(接收遥控器的信号,可实现遥控)
7、无线模块(实现一个单片机控制到另一个单片机)
8、USB下载模块
9、时钟芯片(产生时间,读取时间,可制作闹钟、小时钟。)
10、复位系统
11、AD\DA(模/数转换器)(将模拟信号转换为数字信号给单片机,或者将数字信号转换为模拟信号给外部使用)
12、步进电机模块
13、蜂鸣器(根据单片机所给的各种频率输出来响动)
14、138译码器(可以拓展I/O口,驱动数码管)
15、24C02(一种ROM)
16、温度传感器
17、74HC245芯片
18、电位器和排座
19、点阵屏
20、动态数码管模块
2.1点亮一个Led
新建工程
打开Keil uVision5,点击project,再点击new uVision Project
在桌面新建文件夹,再在文件夹中新建文件夹,命名为点亮一个Led,再将程序命名,保存。
在弹出的框中选择Atmel中的89c52
点击Target,右键source group1,选择Add new item。弹出窗口选否。
选择c语言,将文件命名为main
编程
如何调节代码字体大小:点击上方扳手图标,在window栏选择c/c++,Element栏选择text,点击Font,即可选择字体大小。
点击类似魔法棒的图标,点击Output,将Create勾选,创建文件,目的:为了烧录时能找到程序文件
单片机程序在cpu中执行,直接给寄存器写值(1和0),通过驱动器执行引脚给高电平还是低电平
P2直接控制8个LED灯,通过二进制控制,1为灭,0为亮。不能直接写二进制,要用十六进制,如0001 0001=0x11,0x为十六进制标志,四个二进制数用一个十六进制数代替。进制转换如下:
写编程要有头文件#include <REGX52.H>
编程如下;
#include <REGX52.H>void main(){P2=0xFE;}
打开软件stc,在单片机型号选STC89C52RC,点击打开程序文件,找到保存文件,打开object里的文件,点击下载/编程,重启单片机即可
认识Led
中文名:发光二极管
英文名:light emitting diode,简称Led
用途:照明、广告灯
单片机Led模块:
如图,单片机Led有8个,右边表示正极,经过8个电阻调节电流,左端连接单片机引脚,通过单片机控制左端电极正负,控制LED亮灭
电阻大小计算(根据电阻上数字):
102=10 00=1k;473=47*10^3=47k
2.2LED闪烁
编程改进:
为使程序能够一直重复执行,可添加while
#include <REGX52.H>void main(){while(1){P2=0xFE;}}
Delay延迟函数
若函数如下:
#include <REGX52.H>void main(){while(1){P2=0xFE;P2=0xFF;}}
用于闪烁太快,人眼看不见,因此需要Dealy延迟函数
在STC软件中上方找到软件延时计算器,在定时长度输入500,生成函数。复制函数,粘贴到程序中。在头文件中加#include <INTRINS.H>
结果如下:
#include <REGX52.H#include <INTRINS.H>void Delay500ms()//@11.0592MHz{unsigned char i, j, k;_nop_();i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);}void main(){while(1){P2=0xFE;Delay500ms();P2=0xFF;Delay500ms();}}
改进:在定时长度输入1,定义unsigned char xms;让函数在while(xms)中,结尾xms–,如下:
void Delay(unsigned int xms){unsigned char i, j;while(xms){_nop_();i = 2;j = 199;do{while (--j);} while (--i);xms--;}}
2.3LED流水灯
写入程序
由上一节内容,通过对照进制表,让LED灯挨个闪烁
#include <REGX52.H>#include <INTRINS.H>void Delay500ms()//@11.0592MHz{unsigned char i, j, k;_nop_();i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);}void main(){while(1){P2=0xFE;Delay500ms();P2=0xFD;Delay500ms();P2=0xFB;Delay500ms();P2=0xF7;Delay500ms();P2=0xEF;Delay500ms();P2=0xDF;Delay500ms();P2=0xBF;Delay500ms();P2=0x7F;Delay500ms();}}
打开程序的方法
找到打开程序的文件的位置,找到main文件,右键,用记事本或Dev打开
3.1独立按键控制LED灯亮灭
独立按键介绍
相当于是一种电子开关,按下时开关接通,松开时开关断开,原理是按键内部金属弹片受力弹动来实现接通和断开
内部结构:
对应单片机引脚
编程
右键可打开头文件,点击open
通过下划线“_“精确控制某一个单元,如:
P2_0,P2_1……分别代表一个LED灯,用1和0控制灭和亮。
P3_1,P3_0……分别代表一个独立按键用1和0控制关和开。
用if语句即可写出程序,用独立按键控制LED灯亮灭
#include <REGX52.H>void main(){while(1){if(P3_1==0){P2_0=1;}else{P2_0=0;}}}
然而,一旦松开按键,LED就会熄灭
C51数据运算:
按位左移<< : 0011 1100<<1=0111 1000
按位右移>> : 0011 1100>>1=0001 1110
按位与&:0001 1000 & 0010 1010=0000 1000
相同数字&后不变,不同数字&后为0
按位或|:0001 1000 | 0010 1010=0011 1010
1“或”1和0都为1,0“或”0为0
按位异或^:0001 1000^0010 1010=0011 0010
相同数字为0,不同数字为1
按位取反:0001 1000=1110 0111
3-2 独立按键控制LED状态
按键的抖动
对于机械开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动。
由于按键的抖动,单片机在刚刚按下按键时,会在一瞬间读取多个结果,造成误差,因此需要消抖
如何消抖
1、加入硬件,使经过电路,途径触发器之类的硬件,过滤后再传输给单片机处理。
2、通过软件处理,写入延时程序,度过抖动时间后再进行操作。
编程
1、加入延迟函数Delay
2、判断是否按下按键if(P3_1==0)
3、接着Delay(20)用于消除抖动
4、用while(P3_1==0)卡住程序,实现按住按键没有生效,松开按键生效的效果。接着再次用Delay(20)用于消除抖动
5、通过P2_0=~P2_0实现按下开关后LED灯状态改变
如下:
#include <REGX52.H>#include <INTRINS.H>void Delay(unsigned int xms){unsigned char i, j;while(xms){_nop_();i = 2;j = 199;do{while (--j);} while (--i);xms--;}}void main(){while(1){if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);P2_0=~P2_0;}}}
正常下载即可
3-3 独立按键控制LED显示二进制
编程
1、由上节课可知加入Delay函数消抖,然后通过if,while函数实现独立按键控制Led状态
2、不能直接P2++,因为单片机默认高电平,所以P2++呈现的效果是相反的,即灯全亮,灭灯进位
3、不能直接对P2取反,因为P2在不断改动,取反是它,加一还是它,最终会卡在1111 1111与0000 0000不断徘徊
4、因此要定义一个变量Led=0,让Led++,再让P2=~Led,从而实现独立按键控制LED显示二进制
代码如下:
#include <REGX52.H>#include <INTRINS.H>void Delay(unsigned int xms){unsigned char i, j;while(xms){_nop_();i = 2;j = 199;do{while (--j);} while (--i);xms--;}}void main(){unsigned char Led=0;while(1){if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);Led++;P2=~Led;}}}
编程改进
因为P2++实现的是反向操作,于是我们可以通过P2–来实现正向操作。
代码如下:
#include <REGX52.H>#include <INTRINS.H>void Delay(unsigned int xms){unsigned char i, j;while(xms){_nop_();i = 2;j = 199;do{while (--j);} while (--i);xms--;}}void main(){unsigned char Led=0;while(1){if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);P2--;}}}
3.4独立按键控制LED移位
编程
1、与上节课相同,加入Delay函数消抖,然后通过if,while函数实现独立按键控制Led状态,定义一个变量Led=0,让Led++,
2、因为单片机LED只有8个而Led值到8时,移位越界,因此加入if(Led==8)时,令Led=0。
3、通过P2~(0x01<<Led)完成操作
代码如下:
#include <REGX52.H>#include <INTRINS.H>void Delay(unsigned int xms){unsigned char i, j;while(xms){_nop_();i = 2;j = 199;do{while (--j);} while (--i);xms--;}}void main(){unsigned char Led;P2=~0x01;while(1){if(P3_2==0&&P2==~0){Delay(20);while(P3_2==0);Delay(20);Led++;if(Led==8)Led=0;P2=~(0x01<<Led);}}}
LED左移编程
上述代码为LED右移,以下为LED左移
1、if函数移至前面,先判断if(Led0)时,Led7;
2、用else表示Led不为0时的操作,Led–
代码如下:
#include <REGX52.H>#include <INTRINS.H>void Delay(unsigned int xms){unsigned char i, j;while(xms){_nop_();i = 2;j = 199;do{while (--j);} while (--i);xms--;}}void main(){unsigned char Led;P2=~0x01;while(1){if(P3_2==0&&P2==~0){Delay(20);while(P3_2==0);Delay(20);if(Led==0)Led=7;elseLed--;P2=~(0x01<<Led);}}}
4.1静态数码管显示
LED数码管
定义:数码管是一种简单、廉价的显示器,是由多个发光二极管封装在一起组成“8”字型的器件。
生活中的数码管:
数码管引脚
1、一位数码管
2、连接方式
共阴极
共阳极
3、数码管排序(顺时针)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bACURD6q-1668432317529)(C:\Users\86136\AppData\Roaming\Typora\typora-user-images\image-111448334.png)]
数码管引脚定义
1、数码管是四位一体的
2、连接方式
根据上面连接方式,可见通过更改位选(即上方的12、9、8、6对应口)的数值,来控制其是否连通。
由于共用引脚,一次只能显示一个数字
3、动态数码管显示
通过快速扫描程序,极快的显示数字,人眼就会看到多个数字
4、共用引脚的原因
减少引脚数量,便于单片机控制
原理图
1、控制LED的I/O口
根据上面的动态数码管模块图,可知P00P07控制LED的段选(下面的多个引脚),而位选(公共端)接在LED1LED8。
接着看138译码器可以发现,位选端的LED1LED8在其右侧,左侧由P22P24控制,即所谓3个口控制8位。
2、74HC245芯片
3、牌组电阻
从上图的动态数码管原理图中,这一部分负责保护电路,防止数码管电流过大。
编程
1、建立Switch函数,使对应选位选中
switch(L){case 8:P2_4=0;P2_3=0;P2_2=0;break;case 7:P2_4=0;P2_3=0;P2_2=1;break;case 6:P2_4=0;P2_3=1;P2_2=0;break;case 5:P2_4=0;P2_3=1;P2_2=1;break;case 4:P2_4=1;P2_3=0;P2_2=0;break;case 3:P2_4=1;P2_3=0;P2_2=1;break;case 2:P2_4=1;P2_3=1;P2_2=0;break;case 1:P2_4=1;P2_3=1;P2_2=1;break;}
2、建立数组,使能显示对应数字
unsigned char n[]={0x3F,0x06,0x5B,0x4F,0x66,0x7D,0x07,0x7F,0X6F,0x3E};
3、建立函数smg,使对应选位选中且能显示对应数字
void smg(unsigned char L,q){switch(L){case 8:P2_4=0;P2_3=0;P2_2=0;break;case 7:P2_4=0;P2_3=0;P2_2=1;break;case 6:P2_4=0;P2_3=1;P2_2=0;break;case 5:P2_4=0;P2_3=1;P2_2=1;break;case 4:P2_4=1;P2_3=0;P2_2=0;break;case 3:P2_4=1;P2_3=0;P2_2=1;break;case 2:P2_4=1;P2_3=1;P2_2=0;break;case 1:P2_4=1;P2_3=1;P2_2=1;break;}P0=n[q];Dealy(1);}
最终代码如下:
#include <REGX52.H>#include <INTRINS.H>unsigned char n[]={0x3F,0x06,0x5B,0x4F,0x66,0x7D,0x07,0x7F,0X6F,0x3E};void Dealy(unsigned char xms)//@11.0592MHz{while(xms){unsigned char i, j;_nop_();i = 2;j = 199;do{while (--j);} while (--i);xms--;}}void smg(unsigned char L,q){switch(L){case 8:P2_4=0;P2_3=0;P2_2=0;break;case 7:P2_4=0;P2_3=0;P2_2=1;break;case 6:P2_4=0;P2_3=1;P2_2=0;break;case 5:P2_4=0;P2_3=1;P2_2=1;break;case 4:P2_4=1;P2_3=0;P2_2=0;break;case 3:P2_4=1;P2_3=0;P2_2=1;break;case 2:P2_4=1;P2_3=1;P2_2=0;break;case 1:P2_4=1;P2_3=1;P2_2=1;break;}P0=n[q];Dealy(1);}void main(){while(1){if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);smg(1,1);Delay(1);}}}
即实现了静态数码管显示
4.2动态数码管显示
编程
1、由上节课时所学,打出基本代码
2、让1位显示1,2位显示2,3位显示3
3、中间间隔2ms
代码如下:
#include <REGX52.H>#include <INTRINS.H>unsigned char n[]={0x3F,0x06,0x5B,0x4F,0x66,0x7D,0x07,0x7F,0X6F,0x3E};void Dealy(unsigned char xms)//@11.0592MHz{while(xms){unsigned char i, j;_nop_();i = 2;j = 199;do{while (--j);} while (--i);xms--;}}void smg(unsigned char L,q){switch(L){case 8:P2_4=0;P2_3=0;P2_2=0;break;case 7:P2_4=0;P2_3=0;P2_2=1;break;case 6:P2_4=0;P2_3=1;P2_2=0;break;case 5:P2_4=0;P2_3=1;P2_2=1;break;case 4:P2_4=1;P2_3=0;P2_2=0;break;case 3:P2_4=1;P2_3=0;P2_2=1;break;case 2:P2_4=1;P2_3=1;P2_2=0;break;case 1:P2_4=1;P2_3=1;P2_2=1;break;}P0=n[q];Dealy(1);}void main(){while(1){if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);smg(1,1);Delay(2);smg(2,2);Delay(2);smg(3,3);Delay(2);}}}
如果闪烁太快,会有重影,因此需要2ms延迟,称为消影
数码管驱动方式
1、单片机直接扫描:硬件设备简单,但会耗费大量单片机CPU时间
2、专用驱动芯片:内部自带显存、扫描电路,单片机只需告诉它显示什么即可
d char n[]={0x3F,0x06,0x5B,0x4F,0x66,0x7D,0x07,0x7F,0X6F,0x3E};
#include <REGX52.H>#include <INTRINS.H>unsigned char n[]={0x3F,0x06,0x5B,0x4F,0x66,0x7D,0x07,0x7F,0X6F,0x3E};void Dealy(unsigned char xms)//@11.0592MHz{while(xms){unsigned char i, j;_nop_();i = 2;j = 199;do{while (--j);} while (--i);xms--;}}void smg(unsigned char L,q){switch(L){case 8:P2_4=0;P2_3=0;P2_2=0;break;case 7:P2_4=0;P2_3=0;P2_2=1;break;case 6:P2_4=0;P2_3=1;P2_2=0;break;case 5:P2_4=0;P2_3=1;P2_2=1;break;case 4:P2_4=1;P2_3=0;P2_2=0;break;case 3:P2_4=1;P2_3=0;P2_2=1;break;case 2:P2_4=1;P2_3=1;P2_2=0;break;case 1:P2_4=1;P2_3=1;P2_2=1;break;}P0=n[q];Dealy(1);}void main(){while(1){if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);smg(1,1);Delay(2);smg(2,2);Delay(2);smg(3,3);Delay(2);}}}
数码管驱动方式
1、单片机直接扫描:硬件设备简单,但会耗费大量单片机CPU时间
2、专用驱动芯片:内部自带显存、扫描电路,单片机只需告诉它显示什么即可