第2章 基础知识必备
2.2 点亮第一个发光二极管
2.头文件reg52.h作用
#include <reg52.h> // 直接在所在软件安装文件夹中搜索
#include “reg52.h” //先在工程文件夹中搜索
3.sfr P0=0x80
将寄存器地址赋予一个名字
4.注释
// 只注释一行的
/* */注释从开头到结束 注释自由
5.通过电阻符号来判断阻值大小
6.74HC245和74HC573的区别和相同之处
74HC245:
三态输出八路收发器。当驱动电流很小,而负载很大时,可以用此来提高io口的驱动能力。
74HC573:
OE:三态允许控制端,低电平有效,输出使能端。
D7:数据输入端
00到07数据输出端
LE锁存允许端,锁存控制端
PS:51单片机一上电时,如果没有人为的控制I/O口的状态,它所有未控制的I/O口都默认为高电平,因此我们不需要写一句让锁存端高的语句。
74hc245是八同相三态收发器,74hc573是8位三态锁存器。两者都有把一个三位二进制数进行锁存的功能,但是74hc245具有双向传输、双向锁存的功能,74hc573只能单向传输、单向锁存。
锁存器(Latch)是一种对脉冲电平敏感的存储单元电路,它们可以在特定输入脉冲电平作用下改变状态。锁存,就是把信号暂存以维持某种电平状态。锁存器的最主要作用是缓存,其次完成高速的控制器与慢速的外设的不同步问题,再其次是解决驱动的问题,最后是解决一个 I/O 口既能输出也能输入的问题。
245是传输们,bai573是锁存器。573可以锁存信号,解放IO端口,利用动态扫描245也可zhi以做到扩充IO口。dao前提是输出端接的是对信号骤变不是很敏感的器件,在这方面573优于245.但245有双向传输功能,是573不具备的。在驱动数码管,LED等情况下两个通用。
7.创建hex文件
Hex是十六进制文件,BIN是二进制文件,这两种文件可以通过软件相互转换,其实际内容是一样的。
静态控制几个二极管亮灭的方法:
- 位操作法:控制I/O口低电平。这种方法比较麻烦,想同时让几个小灯亮需要声明几个I/O口/
#include <reg52.h>
sbit led1=P1^0;
void main()
{
led1=0;
}
- 总线操作法:
#include <reg52.h>
void main ()
{
P2=0xaa;
while(1);
//表示对单片机P2口的8个I/O口同时进行操作,十六进制换算成10101010,
如果换算成十进制是170.也可以对P2直接赋值170,效果一样的。
}
8.while语句
while(1);这个语句可以让程序停止。
因为先判断表达式,因为是真,载执行内部语句。内部语句为空,所以什么都不执行,只有当等于0是才可以跳出循环,否则程序将不断地执行该语句。
2.4for语句及简单延时语句
for{i=2;i>0;i--}
无符号字符型变量,最大值是255无法起到延时的作用。
因此选择for语句的嵌套:
unsigned char i,j;
for(i=100;i>0;i--) //第一个for没有分号,编译器默认第二个for语句就是第一个for语句的内部语句,第二个for语句为空
for(j=200;j>0;j--);
2.5延时小灯程序
1.实现程序
#include <reg52.h> //52头文件
#define uint unsigned int //宏定义
sbit led1=P2^0; //声明单片机P2口的第一位
uint i,j;
void main() //主函数
{
while(1)//大循环 在这个大括号里的语句将会不断执行下去。
{
led1=0;
for(i=1000;i>0;i--)
for(j=1000;j>0;j--); //先让第一个灯灭之后延时
led1=1;
for(i=1000;i>0;i--)
for(j=1000;j>0;j--); //再让第一灯亮之后延时
}
}
2.#define宏定义
格式: #define 新名称 原内容
只要宏定义过一次,整个代码都可以直接使用他的替代名称,
对同一个内容,只能定义一次,不能重复定义。
3.单片机的几个周期介绍
- 时钟周期:振荡周期,定义为时钟频率的倒数,时钟周期是外接晶振的倒数,是单片机最基本的、最小的时间单位。时钟频率越高,单片机的工作频率就越快。STC89C系列的时钟范围在1MHZ~40MHZ.
- 状态周期:是时钟周期的两倍。
- 机器周期:单片机的基本操作周期,在一个操作周期内,单片机完成一项基本操作。它由12个时钟周期(6个状态周期)组成。
- 指令周期:CPU执行一条指令所需要的时间。一般一个指令周期含有1~4个机器周期。
2.6不带参数函数的写法与调用
有的语句不止一次用到而且语句内容不改变,可以将这些语句写成一个不带参数的子函数,当主函数需要这些语句时,直接调用这个子函数就可以了。
例如延时函数:
void delay 1s()//无返回值的函数 //delay 1s是随意起的函数名。注意不要与C语言关键字相同
//括号是表示无参数,接下来的大括号是要实现的语句。
{
for(i=1000;i>0;i--)
for(j=0;j.0;j--);
}
#include <reg52.h>
#define uint unsigned int
void delay 500ms();
sbit led1=P2^0;
void delay 500ms()
{
uint i,j;
for(i=500;i>0;i--)
for(j=110;j>0;j--);
}
void main ()
{
while(1)
{
led1=0;
delay 500ms();
led1=1;
delay 500ms();
}
}
- 局部变量,只在当前子函数中有效。当下次再调用该函数时,编译器重新为其分配内存空间。
- 每个全局变量都占据着单片机内固定的RAM,局部变量是用时随机分配,不用时立即销毁
- 89C52只有256B的RAM,写程序要坚持能用局部变量就不用全局变量的原则。
2.7带参数函数的写法及调用
#include <reg52.h>
#define uint unsigned int
sbit Led1=P2^0;
void delayms(uint); //声明子函数
void main()
{
while(1)
{
Led1=0;
delayms(500);
Led1=1;
delayms(800);
}
}
void delayms(uint xms)//带参数
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
2.8利用C51库函数实现流水灯
#include<intrins.h>
unsigned char_crol_(unsigned char c,unsigned char b);
2.8.1.移位操作
- 左移:C51操作符中<<每执行一次左移指令,被操作的数将最高位移入单片机PSW寄存器的CY位,CY位中原来的数舍弃,最低位补0,其他位次依次向左移动一位。
- 右移:C51操作符中>>每执行一次右移指令,被操作的数将最低位移入单片机PSW寄存器的CY位,CY位中原来的数舍弃,最高位补0,其他位次依次向右移动一位。
- 循环左移:最高位移入最低位,其他位次依次向左移一位。C语言没有专门的指令,通过移位命令与简单逻辑运算可以实现循环左移。或直接利用C51库中自带的函数_crol_实现。
- 循环右移:最高位移入最高位,其他位次依次向右移一位。C语言没有专门的指令,通过移位命令与简单逻辑运算可以实现循环右移。或直接利用C51库中自带的函数_cror_实现
2.8.2 PSW寄存器(待补充完善)
PSW是程序状态字标寄存器,是一个八位寄存器。
库函数实现程序
//利用自带的库函数_crol_(),以间隔500ms,实现流水灯程序左移。
#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
void delayms(uint);
uchar aa;
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
void main()
{
aa=0xfe;
while(1)
{
P2=aa;
delayms(500);
aa=_crol_(aa,1);//将aa循环左移一位之后再赋给aa
}
}
其中aa=crol(aa,1)因为其是一个带返回值的函数,先执行等号右边的表达式,将aa循环左移一位,然后将结果赋值给左边的变量