文章目录
前言
本笔记用于记录STC89C51单片机开发板入门学习,此部分为基础实验例程。开始实验前建议学习《10天学会51单片机-郭天祥》,另外还需要一定的C语言基础。
准备环境:
- 笔记本一台;
- STC89C51开发板一套(我选用的是普中51-单核-A2开发板,入手价格56元,因为便宜买的);
- 串口助手软件STC-ISP(用于程序下,也可用商家自带的程序下载软件);
- KeiluVision5软件(用于程序开发,安装和教程自行百度)。
1. 点亮第一个LED
本条所要实现的功能是:点亮D1发光二极管,即让P2.0管脚输出一个低电平。
1.1 代码
/*********************
点亮第一个LED灯实验
实验现象:下载程序后D1指示灯点亮
日期:2020-04-11
作者:lixs
**********************/
#include <reg52.h>
sbit led=P2^0;//将单片机P2.0端口定义为led
void main()
{
led=0;//p2.0端口设置为低电平
while(1);//循环语句
}
1.2 编译
编译前需要在KeiluVision5软件进行设置:1)options选项;2)output选项;3)勾选create HEX file;4)命名Name of Executable。如下图所示:
设置完成后进行编译。如下图所示:
编译完成后会生成.hex文件。如下图所示:
至此编译工作完成。
1.3 程序下载
编译生成.hex文件后,打开STC-ISP软件,将此.hex文件下载到单片机中。
STC-ISP软件设置。如下图所示:
软件设置完成后,开始下载程序:1)点击打开程序文件;2)选择.hex文件;3)点击下载/编程。如下图所示:
点击下载程序后会出现:正在检测目标单片机…,此时检查单片机是否上电。如已上电,请关闭电源,重新上电,即可完成程序下载。如下图所示:
单片机正常连接后,会完成程序下载,STC-ISP软件会提示程序下载结果。如下图所示:
1.4 结果展示
1.5 常见问题及解决办法
无
2. LED灯闪烁
本条所要实现的功能是:让D1发光二极管固定周期闪烁,即让P2.0管脚先输出一个低电平点亮D1,然后固定周期后输出一个高电平熄灭D1。这就需要增加一个延时,我们利用c语言中的循环函数,让CPU不断循环执行即可实现延时功能。
2.1 代码
/*********************
LED灯闪烁实验
实验现象:下载程序后D1指示灯闪烁
日期:2020-04-11
作者:lixs
**********************/
#include <reg52.h>
typedef unsigned int uint16;
sbit led=P2^0;//将单片机P2.0端口定义为led
void delay(uint16 x);
void main()
{
while(1)
{
led=0;//p2.1端口设置为低电平,即点亮D1
delay(50000);//循环50000次,即大约延时500ms
led=1;//p2.1端口设置为高电平,即熄灭D1
delay(50000);//循环50000次,即大约延时500ms
}
}
void delay(uint16 x)//延时函数,当x=1时,大约延时10us
{
while(x--);
}
2.2 编译
编译过程同1.2一致。
2.3 程序下载
程序下载过程同1.3一致。
2.4 结果展示
2.5 常见问题及解决办法
问题1:为什么如果将延时函数中的形参x赋值超过65535即LED灯延时间隔即呈现非正常状态?
解决办法:因为x数据类型为unsigned int类型,最大值为65535,因此x会溢出,导致非正常状态出现,x的赋值一定要严格在数据类型的取值范围内,否则不会得到预期结果。
3. LED流水灯
3.1 代码
/*********************
LED流水灯实验
实验现象:下载程序后D1-D8指示灯循环逐个点亮
日期:2020-04-11
作者:lixs
**********************/
#include <reg52.h>
#include <intrins.h> //左右移函数头文件
#define led P2 //定义P2端口为led,即可用led代替P2端口
typedef unsigned int uint16;//对数据类型进行声明定义
typedef unsigned char uchar8;//对数据类型进行声明定义
uchar8 i;//初始化变量i
void delay(uint16);//声明延时函数
//主函数:实现led灯流水效果(采用<<左移运算符实现)
/*void main()
{
led=~0x01;
delay(50000);
while(1)
{
for(i=0;i<8;i++)
{
led=~(0x01<<i);//将1左移i位,然后将结果赋值到led中
delay(50000);//循环50000次,即大约延时500ms
}
}
}*/
//主函数:实现led灯流水效果(采用左移函数实现)
void main()
{
led=~0x01;//0x01取反即为0xFE,也可直接写led=0xFE
delay(50000);//循环50000次,即大约延时500ms
while(1)
{
for(i=0;i<8;i++)//循环8次,即与D1-D8一一对应
{
led=_crol_(led,1);//左移函数,将led的值左移1位,然后将结果赋值到led中
delay(50000);//循环50000次,即大约延时500ms
}
}
}
//延时函数,x=1时,大约延时10us
void delay(uint16 x)
{
while(x--);
}
3.2 编译
编译过程同1.2一致。
3.3 程序下载
程序下载过程同1.3一致。
3.4 结果展示
3.5 常见问题及解决办法
问题1: 为什么LED流水灯点亮的同时,数码管也会跟着流动点亮?
解决办法:经查看开发板原理图得知,此现象是由于硬件电路导致,非程序影响。
由于工作原因,无法保证定期更新实验例程,还请谅解。以下实验例程会不定期更新,欢迎随时光临指导。
4. 蜂鸣器
4.1 代码
/*********************
蜂鸣器发声实验
实验现象:下载程序后蜂鸣器模块发声
日期:2020-04-11
作者:lixs
**********************/
#include <reg52.h>
sbit buzzer=P1^5;//将单片机P1.5端口定义为buzzer
typedef unsigned int uint16;//对数据类型进行声明定义
void delay(uint16 x);//声明延时函数
void main()
{
while(1)
{
//通过给P1.5端口赋值方式使蜂鸣器发生
/*buzzer=0;//将P1.5端口置0,即蜂鸣器端输入低电平
delay(1000);
buzzer=1;//将P1.5端口置1,即蜂鸣器端输入高电平
delay(1000);*/
//通过取反方式使蜂鸣器发生
buzzer=~buzzer;//buzzer刚开始是0x01,然后循环取反,即可达到0/1切换的效果
delay(100);//循环100次,即大约延时1ms
}
}
void delay(uint16 x)//延时函数,当x=1时,大约延时10us
{
while(x--);
}
4.2 编译
编译过程同1.2一致。
4.3 程序下载
程序下载过程同1.3一致。
4.4 结果展示
- 待上传视频
4.5 常见问题及解决办法
无
5. 动态数码管显示
5.1 代码
/*********************
动态数码管实验
实验现象:下载程序后动态数码管依次显示数字0-7
日期:2020-04-13
作者:lixs
**********************/
#include <reg52.h>
sbit LSA=P2^2;//将单片机P2.2端口定义为LSA
sbit LSB=P2^3;//将单片机P2.3端口定义为LSB
sbit LSC=P2^4;//将单片机P2.4端口定义为LSC
typedef unsigned int uint16;//对数据类型进行声明定义
typedef unsigned char uchar8;//对数据类型进行声明定义
uchar8 code duanxuan[17]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//段选显示0-F的值
void delay(uint16);//声明延时函数
void DigDisplay();//声明数码管显示函数
void main()
{
//发送位选
while(1)
{
DigDisplay();
}
}
void DigDisplay()//位选、段选函数,即选择点亮第几个数码管,并显示数字几
{
uchar8 i;
for(i=0;i<8;i++)
{
switch(i)
{
case(0):LSA=1;LSB=1;LSC=1;break;//显示第0位,即点亮LED8,左1
case(1):LSA=0;LSB=1;LSC=1;break;//显示第1位,即点亮LED7,左2
case(2):LSA=1;LSB=0;LSC=1;break;//显示第2位,即点亮LED6,左3
case(3):LSA=0;LSB=0;LSC=1;break;//显示第3位,即点亮LED5,左4
case(4):LSA=1;LSB=1;LSC=0;break;//显示第4位,即点亮LED4,左5
case(5):LSA=0;LSB=1;LSC=0;break;//显示第5位,即点亮LED3,左6
case(6):LSA=1;LSB=0;LSC=0;break;//显示第6位,即点亮LED2,左7
case(7):LSA=0;LSB=0;LSC=0;break;//显示第7位,即点亮LED1,左8
}
P0=duanxuan[i];//发送段选,即选择显示数字几
delay(100);//延时函数,大约延时1ms
P0=0x00;//消隐
}
}
void delay(uint16 x)//延时函数,x=1时大约延时10us
{
while(x--);
}
5.2 编译
编译过程同1.2一致。
5.3 程序下载
程序下载过程同1.3一致。
5.4 结果展示
- 待上传视频
5.5 常见问题及解决办法
无
6. 独立按键
6.1 代码
/*********************
独立按键实验
实验现象:下载程序后按下K1按键可以对D1灯状态取反
日期:2020-04-13
作者:lixs
**********************/
#include <reg52.h>
sbit led=P2^0;//将单片机P2.0端口定义为led
sbit k1=P3^1;//将单片机P3.1端口定义为k1
typedef unsigned int uint16;//对数据类型进行声明定义
typedef unsigned char uchar8;//对数据类型进行声明定义
void delay(uint16);//声明延时函数
void keypros();
void main()
{
led=1;
while(1)
{
keypros();
}
}
void keypros() //按键处理函数
{
if(k1==0) //检测按键是否按下
{
delay(1000);//延时10ms,消除抖动
if(k1==0)
{
led=~led;//led状态取反
}
while(!k1); /*!k1 = !k1==1 = k1==0 检测按键是否松开,
如k1=0则表示还没松开,保持在当前循环,
k1=1则表示松开,跳出当前循环等待下次状态变化*/
}
}
void delay(uint16 x)//延时函数,x=1时大约延时10us
{
while(x--);
}
6.2 编译
编译过程同1.2一致。
6.3 程序下载
程序下载过程同1.3一致。
6.4 结果展示
- 待上传视频
6.5 常见问题及解决办法
无
7. 矩阵按键
7.1 代码
/*********************
矩阵按键实验
实验现象:下载程序后数码管显示0,按下矩阵按键上的按键显示对应的数字
日期:2020-04-13
作者:lixs
**********************/
#include <reg52.h>
#define GPIO_DIG P0//将单片机P0端口定义为GPIO_DIG,即可用GPIO_DIG代替P0
#define GPIO_KEY P1//将单片机P1端口定义为GPIO_KEY,即可用GPIO_DIG代替P1
typedef unsigned int uint16;//对数据类型进行声明定义
typedef unsigned char uchar8;//对数据类型进行声明定义
uchar8 code duanxuan[17]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//段选显示0-F的值
uchar8 KeyValue;
void delay(uint16);//声明延时函数
void KeyDown();
void main()
{
while(1)
{
KeyDown();
GPIO_DIG=duanxuan[KeyValue];
}
}
void KeyDown()
{
char a=0;
GPIO_KEY=0x0f;
if(GPIO_KEY!=0x0f)
{
delay(1000);
if(GPIO_KEY != 0x0f)
{
GPIO_KEY=0x0f;
switch(GPIO_KEY)
{
case(0x07):KeyValue=0;break;
case(0x0b):KeyValue=1;break;
case(0x0d):KeyValue=2;break;
case(0x0e):KeyValue=3;break;
}
GPIO_KEY=0xf0;
switch(GPIO_KEY)
{
case(0x70):KeyValue=KeyValue;break;
case(0xb0):KeyValue=KeyValue+4;break;
case(0xd0):KeyValue=KeyValue+8;break;
case(0xe0):KeyValue=KeyValue+12;break;
}
}
}
while((a<50)&&(GPIO_KEY != 0xf0))
{
delay(100);
a++;
}
}
void delay(uint16 x)//延时函数,x=1时大约延时10us
{
while(x--);
}
7.2 编译
编译过程同1.2一致。
7.3 程序下载
程序下载过程同1.3一致。
7.4 结果展示
- 待上传视频
7.5 常见问题及解决办法
无
8. 单片机IO扩展–74HC595
8.1 代码
/*********************
点阵LED实验
实验现象:下载程序后,
点阵LED灯从左往右依次点
亮,类似流水灯效果
日期:2020-04-14
作者:lixs
**********************/
#include <reg51.h>
#include <intrins.h>
typedef unsigned int uint16;//对数据类型进行声明定义
typedef unsigned char uchar8;//对数据类型进行声明定义
uchar8 ledNum;
//**定义IO口**//
sbit SRCLK=P3^6;
sbit RCLK=P3^5;
sbit SER=P3^4;
sbit LED=P0^7;
//**声明函数**//
void Hc595SendByte(uchar8 dat);//声明发送数据函数
void delay(uint16);//声明延时函数
void main()
{
LED = 0;
ledNum = 0x01;//0000 0001
while(1)
{
Hc595SendByte(ledNum);
ledNum = _crol_(ledNum,1);//0000 0010
delay(50000);
}
}
void Hc595SendByte(uchar8 dat)//向74H595发送一个字节数据
{
uchar8 a;
SRCLK = 1;
RCLK = 1;
for (a = 0; a < 8; a++)
{
SER = dat >>