我是靠谱客的博主 醉熏唇彩,这篇文章主要介绍单片机STC89C51入门学习笔记--基础实验例程(一)前言1. 点亮第一个LED2. LED灯闪烁3. LED流水灯4. 蜂鸣器5. 动态数码管显示6. 独立按键7. 矩阵按键8. 单片机IO扩展–74HC5959. LED点阵(点亮一个点)10. LED点阵(显示数字)11. 直流电机12. 外部中断013. 定时器0中断14. 串口通信15. EEPROM-IIC16. DS18B20温度传感器17. DS1302时钟18. AD模数转换19. DA数模转换20. LCD1602液晶,现在分享给大家,希望可以做个参考。

文章目录

  • 前言
  • 1. 点亮第一个LED
    • 1.1 代码
    • 1.2 编译
    • 1.3 程序下载
    • 1.4 结果展示
    • 1.5 常见问题及解决办法
  • 2. LED灯闪烁
    • 2.1 代码
    • 2.2 编译
    • 2.3 程序下载
    • 2.4 结果展示
    • 2.5 常见问题及解决办法
  • 3. LED流水灯
    • 3.1 代码
    • 3.2 编译
    • 3.3 程序下载
    • 3.4 结果展示
    • 3.5 常见问题及解决办法
  • 4. 蜂鸣器
    • 4.1 代码
    • 4.2 编译
    • 4.3 程序下载
    • 4.4 结果展示
    • 4.5 常见问题及解决办法
  • 5. 动态数码管显示
    • 5.1 代码
    • 5.2 编译
    • 5.3 程序下载
    • 5.4 结果展示
    • 5.5 常见问题及解决办法
  • 6. 独立按键
    • 6.1 代码
    • 6.2 编译
    • 6.3 程序下载
    • 6.4 结果展示
    • 6.5 常见问题及解决办法
  • 7. 矩阵按键
    • 7.1 代码
    • 7.2 编译
    • 7.3 程序下载
    • 7.4 结果展示
    • 7.5 常见问题及解决办法
  • 8. 单片机IO扩展--74HC595
    • 8.1 代码
    • 8.2 编译
    • 8.3 程序下载
    • 8.4 结果展示
    • 8.5 常见问题及解决办法
  • 9. LED点阵(点亮一个点)
    • 9.1 代码
    • 9.2 编译
    • 9.3 程序下载
    • 9.4 结果展示
    • 9.5 常见问题及解决办法
  • 10. LED点阵(显示数字)
    • 10.1 代码
    • 10.2 编译
    • 10.3 程序下载
    • 10.4 结果展示
    • 10.5 常见问题及解决办法
  • 11. 直流电机
    • 11.1 代码
    • 11.2 编译
    • 11.3 程序下载
    • 11.4 结果展示
    • 11.5 常见问题及解决办法
  • 12. 外部中断0
    • 12.1 代码
    • 12.2 编译
    • 12.3 程序下载
    • 12.4 结果展示
    • 12.5 常见问题及解决办法
  • 13. 定时器0中断
    • 13.1 代码
    • 13.2 编译
    • 13.3 程序下载
    • 13.4 结果展示
    • 13.5 常见问题及解决办法
  • 14. 串口通信
    • 14.1 代码
    • 14.2 编译
    • 14.3 程序下载
    • 14.4 结果展示
    • 14.5 常见问题及解决办法
  • 15. EEPROM-IIC
    • 15.1 代码
    • 15.2 编译
    • 15.3 程序下载
    • 15.4 结果展示
    • 15.5 常见问题及解决办法
  • 16. DS18B20温度传感器
    • 16.1 代码
    • 16.2 编译
    • 16.3 程序下载
    • 16.4 结果展示
    • 16.5 常见问题及解决办法
  • 17. DS1302时钟
    • 17.1 代码
    • 17.2 编译
    • 17.3 程序下载
    • 17.4 结果展示
    • 17.5 常见问题及解决办法
  • 18. AD模数转换
    • 18.1 代码
    • 18.2 编译
    • 18.3 程序下载
    • 18.4 结果展示
    • 18.5 常见问题及解决办法
  • 19. DA数模转换
    • 19.1 代码
    • 19.2 编译
    • 19.3 程序下载
    • 19.4 结果展示
    • 19.5 常见问题及解决办法
  • 20. LCD1602液晶
    • 20.1 代码
    • 20.2 编译
    • 20.3 程序下载
    • 20.4 结果展示
    • 20.5 常见问题及解决办法

前言

本笔记用于记录STC89C51单片机开发板入门学习,此部分为基础实验例程。开始实验前建议学习《10天学会51单片机-郭天祥》,另外还需要一定的C语言基础。
准备环境:

  1. 笔记本一台;
  2. STC89C51开发板一套(我选用的是普中51-单核-A2开发板,入手价格56元,因为便宜买的);
  3. 串口助手软件STC-ISP(用于程序下,也可用商家自带的程序下载软件);
  4. KeiluVision5软件(用于程序开发,安装和教程自行百度)。

1. 点亮第一个LED

本条所要实现的功能是:点亮D1发光二极管,即让P2.0管脚输出一个低电平。

1.1 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/********************* 点亮第一个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文件。如下图所示:
生成.hex文件
至此编译工作完成。

1.3 程序下载

编译生成.hex文件后,打开STC-ISP软件,将此.hex文件下载到单片机中。

STC-ISP软件设置。如下图所示:
STC-ISP软件设置
软件设置完成后,开始下载程序:1)点击打开程序文件;2)选择.hex文件;3)点击下载/编程。如下图所示:
程序下载
点击下载程序后会出现:正在检测目标单片机…,此时检查单片机是否上电。如已上电,请关闭电源,重新上电,即可完成程序下载。如下图所示:
检测目标单片机
单片机正常连接后,会完成程序下载,STC-ISP软件会提示程序下载结果。如下图所示:
在这里插入图片描述

1.4 结果展示

点亮第一个LED灯结果展示

1.5 常见问题及解决办法

2. LED灯闪烁

本条所要实现的功能是:让D1发光二极管固定周期闪烁,即让P2.0管脚先输出一个低电平点亮D1,然后固定周期后输出一个高电平熄灭D1。这就需要增加一个延时,我们利用c语言中的循环函数,让CPU不断循环执行即可实现延时功能。

2.1 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/********************* 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 结果展示

LED闪烁实验

2.5 常见问题及解决办法

问题1:为什么如果将延时函数中的形参x赋值超过65535即LED灯延时间隔即呈现非正常状态?
解决办法:因为x数据类型为unsigned int类型,最大值为65535,因此x会溢出,导致非正常状态出现,x的赋值一定要严格在数据类型的取值范围内,否则不会得到预期结果。

3. LED流水灯

3.1 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/********************* 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 结果展示

LED流水灯实验

3.5 常见问题及解决办法

问题1: 为什么LED流水灯点亮的同时,数码管也会跟着流动点亮?
解决办法:经查看开发板原理图得知,此现象是由于硬件电路导致,非程序影响。


由于工作原因,无法保证定期更新实验例程,还请谅解。以下实验例程会不定期更新,欢迎随时光临指导。

4. 蜂鸣器

4.1 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/********************* 蜂鸣器发声实验 实验现象:下载程序后蜂鸣器模块发声 日期: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 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/********************* 动态数码管实验 实验现象:下载程序后动态数码管依次显示数字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 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/********************* 独立按键实验 实验现象:下载程序后按下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 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/********************* 矩阵按键实验 实验现象:下载程序后数码管显示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 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/********************* 点阵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 >> 7;//将dat中的最高位D7位赋给SER dat <<= 1;//左移将dat中的最高位去掉,用D6位取代D7位 SRCLK = 0;//移位时钟 _nop_(); _nop_(); SRCLK = 1;//移位时钟 } RCLK = 0;//储存寄存器的时钟 _nop_();//51中的延时指令,延时一个机器周期,大约1us _nop_();//51中的延时指令,延时一个机器周期,大约1us RCLK = 1;//储存寄存器的时钟,一个上升沿将数据存在存储寄存器内 } void delay(uint16 x)//延时函数,x=1时大约延时10us { while(x--); }

8.2 编译

编译过程同1.2一致。

8.3 程序下载

程序下载过程同1.3一致。

8.4 结果展示

  • 待上传视频

8.5 常见问题及解决办法

9. LED点阵(点亮一个点)

9.1 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/********************* 点阵LED实验 实验现象:下载程序后, 点阵LED灯第一个点亮 日期:2020-04-14 作者:lixs **********************/ #include <reg51.h> #include <intrins.h> typedef unsigned int uint16;//对数据类型进行声明定义 typedef unsigned char uchar8;//对数据类型进行声明定义 uchar8 Num; //**定义IO口**// sbit SRCLK=P3^6; sbit RCLK=P3^5; sbit SER=P3^4; sbit LED=P0^7; //**声明函数**// void Hc595SendByte(uchar8 dat);//声明发送数据函数 void main() { LED = 0; Num = 0x01; while(1) { Hc595SendByte(Num); } } void Hc595SendByte(uchar8 dat)//向74H595发送一个字节数据 { uchar8 a; SRCLK = 1; RCLK = 1; for (a = 0; a < 8; a++) { SER = dat >> 7;//将dat中的最高位D7位赋给SER dat <<= 1;//左移将dat中的最高位去掉,用D6位取代D7位 SRCLK = 0;//移位时钟 _nop_(); _nop_(); SRCLK = 1;//移位时钟 } RCLK = 0;//储存寄存器的时钟 _nop_();//51中的延时指令,延时一个机器周期,大约1us _nop_();//51中的延时指令,延时一个机器周期,大约1us RCLK = 1;//储存寄存器的时钟,一个上升沿将数据存在存储寄存器内 }

9.2 编译

编译过程同1.2一致。

9.3 程序下载

程序下载过程同1.3一致。

9.4 结果展示

  • 待上传视频

9.5 常见问题及解决办法

10. LED点阵(显示数字)

10.1 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/********************* 点阵LED(点亮数字)实验 实验现象:下载程序后, 点阵LED显示数字0 日期:2020-04-16 作者:lixs **********************/ #include <reg51.h> #include <intrins.h> typedef unsigned int uint16;//对数据类型进行声明定义 typedef unsigned char uchar8;//对数据类型进行声明定义 #define LED P0 uchar8 ledduan[]= {0x00,0x00,0x3C,0x42,0x42,0x3C,0x00,0x00};//段选,即行,数字0 //uchar8 ledduan[]= {0x38,0x7C,0x7E,0x3F,0x3F,0x7E,0x7C,0x38};//段选,即行,心形 uchar8 ledwei[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//位选,即列 //**定义IO口**// sbit SRCLK=P3^6; sbit RCLK=P3^5; sbit SER=P3^4; void Hc595SendByte(uchar8 dat); void delay(uint16 x); void main() { uchar8 i=0; while(1) { for(i=0;i<8;i++) { LED=ledwei[i]; Hc595SendByte(ledduan[i]); delay(10); Hc595SendByte(0x00);//消隐 } } } void Hc595SendByte(uchar8 dat)//向74H595发送一个字节数据 { uchar8 a; SRCLK = 1; RCLK = 1; for (a = 0; a < 8; a++) { SER = dat >> 7;//将dat中的最高位D7位赋给SER dat <<= 1;//左移将dat中的最高位去掉,用D6位取代D7位 SRCLK = 0;//移位时钟 _nop_(); _nop_(); SRCLK = 1;//移位时钟 } RCLK = 0;//储存寄存器的时钟 _nop_();//51中的延时指令,延时一个机器周期,大约1us _nop_();//51中的延时指令,延时一个机器周期,大约1us RCLK = 1;//储存寄存器的时钟,一个上升沿将数据存在存储寄存器内 } void delay(uint16 x)//延时函数,x=1时大约延时10us { while(x--); }

10.2 编译

编译过程同1.2一致。

10.3 程序下载

程序下载过程同1.3一致。

10.4 结果展示

  • 待上传视频

10.5 常见问题及解决办法

11. 直流电机

11.1 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/********************* 独立开关控制直流电机实验 实验现象:下载程序后,按 下独立按键,电机旋转 日期:2020-04-16 作者:lixs **********************/ #include <reg52.h> #include <intrins.h> typedef unsigned int uint16; typedef unsigned char uchar8; sbit k1=P3^1;//将单片机P3.1端口定义为k1 sbit moto=P1^0; void delay(uint16 x); void keypros(); void main() { moto=0;//关闭电机 while(1) { keypros(); } } void keypros() //按键处理函数 { if(k1==0) //检测按键是否按下 { delay(1000);//延时10ms,消除抖动 if(k1==0) { moto=~moto;//moto状态取反 } while(!k1); /*!k1 = !k1==1 = k1==0 检测按键是否松开, 如k1=0则表示还没松开,保持在当前循环, k1=1则表示松开,跳出当前循环等待下次状态变化*/ } } void delay(uint16 x)//延时函数,x=1时大约延时10us { while(x--); }

11.2 编译

编译过程同1.2一致。

11.3 程序下载

程序下载过程同1.3一致。

11.4 结果展示

  • 待上传视频

11.5 常见问题及解决办法

12. 外部中断0

12.1 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/********************* 外部中断0实验 实验现象:下载程序后,操 作K3按键使D1状态取反 日期:2020-04-17 作者:lixs **********************/ #include <reg52.h> typedef unsigned int uint16; typedef unsigned char uchar8; sbit k3=P3^2;//定义K3按键 sbit LED=P2^0;//定义P2.0口是LED void delay(uint16 x)//延时函数 { while(x--); } void Int0Init()//外部中断0设置 { //设置INT0 IT0=1;//跳变沿触发方式(下降沿) EX0=1;//打开INT0的中断允许 EA=1;//打开总中断 } void main()//主函数 { Int0Init();//设置外部中断0 while(1); } void Int0() interrupt 0 //外部中断0函数 { delay(1000);//延时消抖 if(k3==0)//按键触发 { LED=~LED; } }

12.2 编译

编译过程同1.2一致。

12.3 程序下载

程序下载过程同1.3一致。

12.4 结果展示

  • 待上传视频

12.5 常见问题及解决办法

13. 定时器0中断

13.1 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/********************* 定时器0中断实验 实验现象:下载程序后, D1灯循环点亮1秒,熄灭1秒 日期:2020-04-18 作者:lixs **********************/ #include <reg52.h> typedef unsigned int uint16; typedef unsigned char uchar8; sbit LED=P2^0;//定义P2.0口是LED sbit buzzer=P1^5;//将单片机P1.5端口定义为buzzer void Timer0Init() { TMOD=0x01;//选择为定时器0模式,工作方式1,仅用TR0打开启动 ET0=1; EA=1; TR0=1; } void main() { Timer0Init(); while(1); } void Timer0() interrupt 1 { static uint16 i; TH0=0xFC; TL0=0x18; i++; if(i==1000) { i=0; LED=~LED; } }

13.2 编译

编译过程同1.2一致。

13.3 程序下载

程序下载过程同1.3一致。

13.4 结果展示

  • 待上传视频

13.5 常见问题及解决办法

14. 串口通信

14.1 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <reg52.h> typedef unsigned int u16; typedef unsigned char u8; void UsartInit() { TMOD=0X20; //设置计数器工作方式2 TH1=0XFA; //初始赋值,波特率9600 TL1=0XFA; //初始赋值,波特率9600 PCON=0X80; //波特率加倍 TR1=1; //打开计数器 SCON=0X50; //串口工作方式 ES=1; //串口中断打开 EA=1; //总中断打开 } void main() { UsartInit(); while(1); } void Usart() interrupt 4 { u8 receiveData; receiveData=SBUF; //出去接收到的数据 RI = 0; //清除接收中断标志位 SBUF=receiveData; //将接收到的数据放入到发送寄存器 while(!TI); //等待发送数据完成 TI=0; //清除发送完成标志位 }

14.2 编译

编译过程同1.2一致。

14.3 程序下载

程序下载过程同1.3一致。

14.4 结果展示

  • 待上传视频

14.5 常见问题及解决办法

15. EEPROM-IIC

15.1 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/********************* i2c驱动程序 实验现象: 日期:2020-04-18 作者:lixs **********************/ #include "i2c.h" //延时函数 void Delay10us() { unsigned char a,b; for(b=1;b>0;b--) for(a=2;a>0;a--); } //i2c启动函数 void I2cStart() { SDA=1; Delay10us(); SCL=1; Delay10us(); SDA=0; Delay10us(); SCL=0; Delay10us(); } //i2c终止函数 void I2cStop() { SDA=0; Delay10us(); SCL=1; Delay10us(); SDA=1; Delay10us(); } //i2c发送数据函数 unsigned char I2cSendByte(unsigned char dat) { unsigned char a=0,b=0; for(a=0;a<8;a++) { SDA=dat>>7; dat=dat<<1; Delay10us(); SCL=1; Delay10us(); SCL=0; Delay10us(); } SDA=1; Delay10us(); SCL=1; while(SDA) { b++; if(b>200) { SCL=0; Delay10us(); return 0; } } SCL=0; Delay10us(); return 1; } //i2c读取数据函数 unsigned char I2cReadByte() { unsigned char a=0,dat=0; SDA=1; Delay10us(); for(a=0;a<8;a++) { SCL=1; Delay10us(); dat<<=1; dat|=SDA; Delay10us(); SCL=0; Delay10us(); } return dat; } //往24c02的一个地址写入一个数据 void At24c02Write(unsigned char addr,unsigned char dat) { I2cStart(); I2cSendByte(0xa0); I2cSendByte(addr); I2cSendByte(dat); I2cStop(); } //读取24c02的一个地址的一个数据 unsigned char At24c02Read(unsigned char adrr) { unsigned char num; I2cStart(); I2cSendByte(0xa0); I2cSendByte(adrr); I2cStart(); I2cSendByte(0xa1); num=I2cReadByte(); I2cStop(); return num; }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/********************* i2c头文件 实验现象: 日期:2020-04-18 作者:lixs **********************/ #ifndef _I2C_H_ #define _I2C_H_ #include <reg52.h> sbit SCL=P2^1; sbit SDA=P2^0; void I2cStart(); void I2cStop(); unsigned char I2cSendByte(unsigned char dat); unsigned char I2cReadByte(); void At24c02Write(unsigned char addr,unsigned char dat); unsigned char At24c02Read(unsigned char adrr); #endif
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/********************* i2c实验 实验现象:下载程序后, 数码管后4位显示0,按下 k1保存显示的数据,按下k2 读取上次保存的数据,按下 k3显示数据加1,按下k4显示 数据清零。最大能写入的数据 是255 日期:2020-04-18 作者:lixs **********************/ #include <reg52.h> #include "i2c.h" typedef unsigned int uint16; typedef unsigned char uchar8; sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; sbit k1=P3^1; sbit k2=P3^0; sbit k3=P3^2; sbit k4=P3^3; char num=0; uchar8 disp[4]; uchar8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; void delay(uint16 x) { while(x--); } //按键处理函数 void Keypros() { if(k1==0) { delay(1000); if(k1==0) { At24c02Write(1,num); } while(!k1); } if(k2==0) { delay(1000); if(k2==0) { num=At24c02Read(1); } while(!k2); } if(k3==0) { delay(1000); if(k3==0) { num++; if(num>255) num=0; } while(!k3); } if(k4==0) { delay(1000); if(k4==0) { num=0; } while(!k4); } } //数据处理函数 void datapros() { disp[0]=smgduan[num/1000];//千位 disp[1]=smgduan[num%1000/100];//百位 disp[2]=smgduan[num%1000%100/10];//十位 disp[3]=smgduan[num%1000%100%10];//个位 } //数码管显示函数 void DigDisplay() { uchar8 i; for(i=0;i<4;i++) { switch(i) //位选,选择点亮的数码管 { case(0):LSA=1;LSB=1;LSC=0;break;//显示第0位 case(1):LSA=0;LSB=1;LSC=0;break;//显示第1位 case(2):LSA=1;LSB=0;LSC=0;break;//显示第2位 case(3):LSA=0;LSB=0;LSC=0;break;//显示第3位 } P0=disp[i];//发送段选,即选择显示数字几 delay(100);//延时函数,大约延时1ms P0=0x00;//消隐 } } void main() { while(1) { Keypros(); datapros(); DigDisplay(); } }

15.2 编译

编译过程同1.2一致。

15.3 程序下载

程序下载过程同1.3一致。

15.4 结果展示

  • 待上传视频

15.5 常见问题及解决办法

16. DS18B20温度传感器

16.1 代码

初始化函数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include "temp.h" //延时函数 void Delay1ms(uint y) { uint x; for(;y>0;y--) { for(x=110;x>0;x--); } } //初始化函数 uchar Ds18b20Init() { uchar i; DSPORT=0;//将总线拉低 i=70; while(i--);//延时642us DSPORT=1;//然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低 i=0; while(DSPORT) { Delay1ms(1); i++; if(i>5)//等待>5ms { return 0;//初始化失败 } } return 1;//初始化成功 } //向18B20写入一个字节 void Ds18b20WriteByte(uchar dat) { uint i,j; for(j=0;j<8;j++) { DSPORT=0;//每写入一位数据之前先把总线拉低1us i++; DSPORT=dat & 0x01;//然后写入一个数据,从最低位开始 i=6; while(i--);//延时68us,持续时间最少60us DSPORT=1;//然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值 dat>>=1; } } //读取一个字节 uchar Ds18b20ReadByte() { uchar byte,bi; uint i,j; for(j=8;j>0;j--) { DSPORT=0;//先将总线拉低1us i++; DSPORT=1;//然后释放总线 i++; i++;//延时6us等待数据稳定 bi=DSPORT;//读取数据,从最低位开始读取 //将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0 byte=(byte>>1)|(bi<<7); i=4;//读取完之后等待48us再接着读取下一个数 while(i--); } return byte; } //让18b20开始转换温度 void Ds18b20ChangTemp() { Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc);//跳过ROM操作指令 Ds18b20WriteByte(0x44);//温度转换命令 //Delay1ms(100);//等待转换成功,而如果你是一只刷着的话,就不用这个延时了 } //发送读取温度命令 void Ds18b20ReadTempCom() { Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc);//跳过ROM操作指令 Ds18b20WriteByte(0xbe);//温度转换命令 } //读取温度 int Ds18b20ReadTemp() { int temp=0; uchar tmh,tml; Ds18b20ChangTemp();//先写入转换命令 Ds18b20ReadTempCom();//然后等待转换完成后发送读取温度命令 tml=Ds18b20ReadByte();//读取温度值共16位,先读低字节 tmh=Ds18b20ReadByte();//再读高字节 temp=tmh; temp<<=8; temp|=tml; return temp; }

主函数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/********************* DS18b02温度传感器实验 实验现象:下载程序后,数码管会显示检测到的温度值 日期:2020-04-20 作者:lixs **********************/ #include <reg52.h> #include "temp.h" typedef unsigned int u16; typedef unsigned char u8; sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; char num=0; u8 DisplayData[8]; u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //延时函数 void delay(u16 i) { while(i--); } //温度读取处理转换函数 void datapros(int temp) { float tp; if(temp<0)//当温度值为负 { DisplayData[0]=0x40; //因为读取的温度是实际温度的补码,所以减1,再取反求出源码 temp=temp-1; temp=~temp; tp=temp; temp=tp*0.0625*100+0.5;//留两个小数点就是*100,+0.5就是四舍五入 } else { DisplayData[0]=0x00; tp=temp; temp=tp*0.0625*100+0.5; } DisplayData[1]=smgduan[temp%10000/1000]; DisplayData[2]=smgduan[temp%1000/100]; DisplayData[3]=smgduan[temp%100/10]; DisplayData[4]=smgduan[temp%10/1]; } //数码管显示函数 void DigDisplay() { u8 i; for(i=0;i<6;i++) { switch(i) { case(0):LSA=1;LSB=1;LSC=1;break;//显示第0位 case(1):LSA=0;LSB=1;LSC=1;break;//显示第1位 case(2):LSA=1;LSB=0;LSC=1;break;//显示第2位 case(3):LSA=0;LSB=0;LSC=1;break;//显示第3位 case(4):LSA=1;LSB=1;LSC=0;break;//显示第4位 case(5):LSA=0;LSB=1;LSC=0;break;//显示第5位 } P0=DisplayData[i];//发送数据 delay(100); P0=0x00; } } //主函数 void main() { while(1) { datapros(Ds18b20ReadTemp());//数据处理函数 DigDisplay();//数码管显示函数 } }

头文件

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef _TEMP_H_ #define _TEMP_H_ #include <reg52.h> //重定义关键字 #ifndef uchar #define uchar unsigned char #endif #ifndef uint #define uint unsigned int #endif //定义使用的IO口 sbit DSPORT=P3^7; //声明全局函数 void Delay1ms(uint y); uchar Ds18b20Init(); void Ds18b20WriteByte(uchar dat); uchar Ds18b20ReadByte(); void Ds18b20ChangTemp(); void Ds18b20ReadTempCom(); int Ds18b20ReadTemp(); #endif

16.2 编译

编译过程同1.2一致。

16.3 程序下载

程序下载过程同1.3一致。

16.4 结果展示

  • 待上传视频

16.5 常见问题及解决办法

17. DS1302时钟

17.1 代码

初始化函数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include "ds1302.h" //DS1302写入和读取时分秒的地址命令 //秒分时日月周年最低位读写位 uchar code READ_RTC_ADDR[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};//读地址{秒,分,小时,日,月,星期,年} uchar code WRITE_RTC_ADDR[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};//写地址{秒,分,小时,日,月,星期,年} //DS1302时钟初始化2016年5月7日星期六12点00分00秒 //存储顺序是秒分时日月周年,存储格式是用BCD码 uchar TIME[7]={0,0,0x12,0x07,0x05,0x06,0x16};//{秒,分,时,日,月,星期,年} //单片机向DS1302发送(地址+数据) void Ds1302Write(uchar addr,uchar dat) { uchar n; RST=0; _nop_(); SCLK=0;//先将SCLK置于低电平 _nop_(); RST=1;//然后将RST(CE)置高电平 _nop_(); for(n=0;n<8;n++)//开始传送8位地址命令 { DSIO=addr & 0x01;//数据从低位开始传送 addr>>=1; SCLK=1;//数据在上升沿时,DS1302读取数据 _nop_(); SCLK=0; _nop_(); } for(n=0;n<8;n++) { DSIO=dat & 0x01; dat>>=1; SCLK=1; _nop_(); SCLK=0; _nop_(); } RST=0;//传送数据结束 _nop_(); } //读取一个地址的数据 uchar Ds1302Read(uchar addr) { uchar n,dat,dat1; RST=0; _nop_(); SCLK=0; _nop_(); RST=1; _nop_(); for(n=0;n<8;n++)//开始传送8位地址命令 { DSIO=addr & 0x01;//数据从低位开始传送 addr>>=1; SCLK=1;//数据在上升沿时,DS1302读取数据 _nop_(); SCLK=0; _nop_();//数据在下降沿时,放置数据 } _nop_(); for(n=0;n<8;n++)//读取8位数据 { dat1=DSIO;//从最低位开始接收,DISO从低位开始依次发送8位数据********* dat=(dat>>1)|(dat1<<7);//将DSIO的最低位左移7位至最高位,然后将dat右移1位, //即最高位置0,即可将DSIO的最高位放置dat中,循环8次即可将addr数据放置dat中 SCLK=1; _nop_(); SCLK=0; _nop_(); } RST=0; _nop_();//以下为DS1302复位的稳定时间 SCLK=1; _nop_(); DSIO=0; _nop_(); DSIO=1; _nop_(); return dat; } //初始化DS1302 void Ds1302Init() { uchar n; Ds1302Write(0x8e,0x00);//关闭写保护功能 for(n=0;n<7;n++) { Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]); } Ds1302Write(0x8e,0x80);//打开写保护 } //读取时钟信息 void Ds1302ReadTime() { uchar n; for(n=0;n<7;n++)//读取7个字节的时钟信号:分秒时日月周年 { TIME[n]=Ds1302Read(READ_RTC_ADDR[n]); } }

主函数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/********************* DS1302时钟实验 实验现象:下载程序后,数码管会显示时钟 日期:2020-04-21 作者:lixs **********************/ #include <reg52.h> #include "ds1302.h" typedef unsigned int u16; typedef unsigned char u8; sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; char num=0; u8 DisplayData[8]; u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //延时函数 void delay(u16 i) { while(i--); } //时间读取处理转换函数 void datapros() { Ds1302ReadTime(); DisplayData[0]=smgduan[TIME[2]/16];//时 DisplayData[1]=smgduan[TIME[2]&0x0f]; DisplayData[2]=0x40; DisplayData[3]=smgduan[TIME[1]/16];//分 DisplayData[4]=smgduan[TIME[1]&0x0f]; DisplayData[5]=0x40; DisplayData[6]=smgduan[TIME[0]/16];//秒 DisplayData[7]=smgduan[TIME[0]&0x0f]; } //数码管显示函数 void DigDisplay() { u8 i; for(i=0;i<8;i++) { switch(i) { case(0):LSA=1;LSB=1;LSC=1;break;//显示第0位 case(1):LSA=0;LSB=1;LSC=1;break;//显示第1位 case(2):LSA=1;LSB=0;LSC=1;break;//显示第2位 case(3):LSA=0;LSB=0;LSC=1;break;//显示第3位 case(4):LSA=1;LSB=1;LSC=0;break;//显示第4位 case(5):LSA=0;LSB=1;LSC=0;break;//显示第5位 case(6):LSA=1;LSB=0;LSC=0;break;//显示第6位 case(7):LSA=0;LSB=0;LSC=0;break;//显示第7位 } P0=DisplayData[i];//发送数据 delay(100); P0=0x00; } } //主函数 void main() { Ds1302Init(); while(1) { datapros();//数据处理函数 DigDisplay();//数码管显示函数 } }

头文件

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef _DS1302_H_ #define _DS1302_H_ //包含头文件 #include <reg52.h> #include <intrins.h> //重定义关键词 #ifndef uchar #define uchar unsigned char #endif #ifndef uint #define uint unsigned int #endif //定义ds1302的IO口 sbit DSIO=P3^4; sbit RST=P3^5; sbit SCLK=P3^6; //定义全局函数 void Ds1302Write(uchar addr,uchar dat); uchar Ds1302Read(uchar addr); void Ds1302Init(); void Ds1302ReadTime(); //加入全局变量 extern uchar TIME[7]; #endif

17.2 编译

编译过程同1.2一致。

17.3 程序下载

程序下载过程同1.3一致。

17.4 结果展示

  • 待上传视频

17.5 常见问题及解决办法

18. AD模数转换

18.1 代码

初始化函数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include "XPT2046.h" //使用SPI写入数据 void SPI_Write(uchar dat) { uchar i; CLK=0; for(i=0;i<8;i++) { DIN=dat>>7;//放置最高位 dat<<=1; CLK=0; CLK=1; } } //使用SPI读数据 uint SPI_Read(void) { uint i,dat=0; CLK=0; for(i=0;i<12;i++) { dat<<=1; CLK=1; CLK=0; dat|=DOUT; } return dat; } //读取电位器数据 uint Read_AD_Data(uchar cmd) { uchar i; uint AD_Value; CLK=0; CS=0; SPI_Write(cmd); for(i=6;i>0;i--);//延时等待转换结果 CLK=1;//发送一个时钟周期,清楚BUSY _nop_(); _nop_(); CLK=0; _nop_(); _nop_(); AD_Value=SPI_Read(); CS=1; return AD_Value; }

主函数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/********************* AD模数转换实验 实验现象:下载程序后, 数码管前4位显示电位器检测 的AD值,范围是0-4095 日期:2020-04-28 作者:lixs **********************/ #include <reg52.h> #include "XPT2046.h" typedef unsigned int u16; typedef unsigned char u8; sbit LSA=P2^2;//将单片机P2.2端口定义为LSA sbit LSB=P2^3;//将单片机P2.3端口定义为LSB sbit LSC=P2^4;//将单片机P2.4端口定义为LSC u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f, 0x77,0x7c,0x39,0x5e,0x79,0x71};//段选显示0-F的值 u8 disp[4]; //延时函数 void delay(u16 i) { while(i--); } //数据处理函数 void datapros() { u16 ADC_Value; float ADC_Voltage; static u8 i; if(i==50) { i=0; ADC_Value=Read_AD_Data(0x94); ADC_Voltage=(2.5*(float)ADC_Value)/4096;//将读取到的值转换为电压值 } i++; /*disp[0]=smgduan[temp/1000];//千位 disp[1]=smgduan[temp%1000/100];//百位 disp[2]=smgduan[temp%1000%100/10];//十位 disp[3]=smgduan[temp%1000%100%10];//个位*/ disp[0]=smgduan[(u8)(ADC_Voltage*100)/1000];//千位 disp[1]=smgduan[(u8)(ADC_Voltage*100)%1000/100];//百位 disp[2]=smgduan[(u8)(ADC_Voltage*100)%1000%100/10];//十位 disp[3]=smgduan[(u8)(ADC_Voltage*100)%1000%100%10];//个位 } //数码管显示函数 void DigDisplay()//位选、段选函数,即选择点亮第几个数码管,并显示数字几 { u8 i; for(i=0;i<4;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 } P0=disp[i];//发送段选数据 delay(100);//延时函数,大约延时1ms P0=0x00;//消隐 } } //主函数 void main() { while(1) { datapros(); DigDisplay(); } }

头文件

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#ifndef _XPT2046_H_ #define _XPT2046_H_ //包含头文件 #include <reg52.h> #include <intrins.h> //重定义关键词 #ifndef uchar #define uchar unsigned char #endif #ifndef uint #define uint unsigned int #endif #ifndef ulong #define ulong unsigned long #endif //定义使用的IO口 sbit DOUT = P3^7; //输出 sbit CLK = P3^6; //时钟 sbit DIN = P3^4; //输入 sbit CS = P3^5; //片选 uint Read_AD_Data(uchar cmd); uint SPI_Read(void); void SPI_Write(uchar dat); #endif

18.2 编译

编译过程同1.2一致。

18.3 程序下载

程序下载过程同1.3一致。

18.4 结果展示

  • 待上传视频

18.5 常见问题及解决办法

1、怎么把读取到的数值转为电压值?
答:ADC_Voltage=ADC_Value*2.5/4096,ADC_Value为读到的数值,2.5为参考电压,4096为2^12(根据分辨率决定)。
2、注意进行电压转换时,ADC_Voltage和ADC_Value需要为浮点型数据。

19. DA数模转换

19.1 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/********************* DA数模转换实验 实验现象:下载程序后, DA模块上的DA1指示灯呈 呼吸灯效果,由暗变亮再 由亮变暗 日期:2020-04-29 作者:lixs **********************/ #include <reg52.h> typedef unsigned int u16; typedef unsigned char u8; sbit PWM=P2^1; bit DIR; u16 count,value,timer1; //定时器1初始化 void Timer1Init() { TMOD|=0X10;//选择为定时器1模式,工作方式1,仅用TR1打开启动 TH1=0XFF; TL1=0XFF; ET1=1;//打开定时器1中断允许 EA=1;//打开总中断 TR1=1;//打开定时器 } //主函数 void main() { Timer1Init();//定时器初始化 while(1) { if(count>100) //100*1us=0.1ms 计时100次后value开始++,此时value<timer1,PWM=0; { count=0; if(DIR==1) { value++; } if(DIR==0) { value--; } } if(value==1000) { DIR=0; } if(value==0) { DIR=1; } if(timer1>1000)//PWM周期为1000*1us=1ms { timer1=0; } if(timer1<value) { PWM=1; } else { PWM=0; } } } //定时器的中断函数 void Time1(void) interrupt 3 { TH1=0XFF; TL1=0XFF; timer1++; count++; }

19.2 编译

编译过程同1.2一致。

19.3 程序下载

程序下载过程同1.3一致。

19.4 结果展示

  • 待上传视频

19.5 常见问题及解决办法

20. LCD1602液晶

20.1 代码

初始化函数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include "lcd.h" //延时函数 void Lcd1602_Delay1ms(uint c) { uchar a,b; for(;c>0;c--) { for(b=199;b>0;b--) { for(a=1;a>0;a--); } } } //向LCD写入一个字节的命令 #ifndef LCD1602_4PINS void LcdWriteCom(uchar com) { LCD1602_E=0; //使能 LCD1602_RS=0; //选择发送命令 LCD1602_RW=0; //选择写入 LCD1602_DATAPINS=com; //放入命令 Lcd1602_Delay1ms(1); //等待数据稳定 LCD1602_E=1; //写入时序 Lcd1602_Delay1ms(5); //保持时间 LCD1602_E=0; } #else void LcdWriteCom(uchar com) { LCD1602_E=0; //使能 LCD1602_RS=0; //选择发送命令 LCD1602_RW=0; //选择写入 LCD1602_DATAPINS=com; //放入命令 Lcd1602_Delay1ms(1); //等待数据稳定 LCD1602_E=1; //写入时序 Lcd1602_Delay1ms(5); //保持时间 LCD1602_E=0; LCD1602_DATAPINS=com<<4; //发送低四位 Lcd1602_Delay1ms(1); LCD1602_E=1; //写入时序 Lcd1602_Delay1ms(5); //保持时间 LCD1602_E=0; } #endif //向LCD写入一个字节的数据 #ifndef LCD1602_4PINS void LcdWriteData(uchar dat) { LCD1602_E=0; //使能 LCD1602_RS=1; //选择输入数据 LCD1602_RW=0; //选择写入 LCD1602_DATAPINS=dat; //写入数据 Lcd1602_Delay1ms(1); //等待数据稳定 LCD1602_E=1; //写入时序 Lcd1602_Delay1ms(5); //保持时间 LCD1602_E=0; } #else void LcdWriteData(uchar dat) { LCD1602_E=0; //使能 LCD1602_RS=1; //选择写入数据 LCD1602_RW=0; //选择写入 LCD1602_DATAPINS=dat; //放入命令 Lcd1602_Delay1ms(1); //等待数据稳定 LCD1602_E=1; //写入时序 Lcd1602_Delay1ms(5); //保持时间 LCD1602_E=0; LCD1602_DATAPINS=dat<<4; //发送低四位 Lcd1602_Delay1ms(1); LCD1602_E=1; //写入时序 Lcd1602_Delay1ms(5); //保持时间 LCD1602_E=0; } #endif //初始化LCD屏 #ifndef LCD1602_4PINS void LcdInit() { LcdWriteCom(0x38); //开显示 LcdWriteCom(0x0c); //开显示不显示光标 LcdWriteCom(0x06); //写一个指针加1 LcdWriteCom(0x01); //清屏 LcdWriteCom(0x80); //设置数据指针起点 } #else void LcdInit() { LcdWriteCom(0x32); //将8位总线转为4位总线 LcdWriteCom(0x28); //在四位线下的初始化 LcdWriteCom(0x0c); //开显示不显示光标 LcdWriteCom(0x06); //写一个指针加1 LcdWriteCom(0x01); //清屏 LcdWriteCom(0x80); //设置数据指针起点 } #endif

主函数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/********************* LCD1602液晶实验 实验现象:下载程序后,插 上LCD1602液晶,即可显示Hello World 日期:2020-04-29 作者:lixs **********************/ #include "reg52.h" #include "lcd.h" typedef unsigned int u16; typedef unsigned char u8; u8 Disp[]=" Hello World "; void main() { u8 i; LcdInit(); for(i=0;i<13;i++) { LcdWriteData(Disp[i]); } while(1); }

头文件

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef _LCD_H_ #define _LCD_H_ /*当使用的是4位数据传输的时候定义,使用8位取消这个定义*/ //#define LCD1602_4PINS #include <reg52.h> #ifndef uchar #define uchar unsigned char #endif #ifndef uint #define uint unsigned int #endif #define LCD1602_DATAPINS P0 sbit LCD1602_E=P2^7; sbit LCD1602_RW=P2^5; sbit LCD1602_RS=P2^6; void Lcd1602_Delay1ms(uint c); void LcdWriteCom(uchar com); void LcdWriteData(uchar dat); void LcdInit(); #endif

20.2 编译

编译过程同1.2一致。

20.3 程序下载

程序下载过程同1.3一致。

20.4 结果展示

  • 待上传视频

20.5 常见问题及解决办法

普中51-单核-A2开发板的基础实验例程分享至此结束,本来打算紧接着下一篇做中级实验教程,后来由于工作,间隔了一段时间,感觉基础知识还是没吃透,所以下一篇准备做一下郭天祥的51单片机教程的课后题,温故而知新。因为手里没有开发板,到时会用proteus仿真进行结果展示,我会尽快整理完后分享给大家!(PS:关于本文章的例程结果展示动画,我会尽快补回来!!!)

最后

以上就是醉熏唇彩最近收集整理的关于单片机STC89C51入门学习笔记--基础实验例程(一)前言1. 点亮第一个LED2. LED灯闪烁3. LED流水灯4. 蜂鸣器5. 动态数码管显示6. 独立按键7. 矩阵按键8. 单片机IO扩展–74HC5959. LED点阵(点亮一个点)10. LED点阵(显示数字)11. 直流电机12. 外部中断013. 定时器0中断14. 串口通信15. EEPROM-IIC16. DS18B20温度传感器17. DS1302时钟18. AD模数转换19. DA数模转换20. LCD1602液晶的全部内容,更多相关单片机STC89C51入门学习笔记--基础实验例程(一)前言1.内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(191)

评论列表共有 0 条评论

立即
投稿
返回
顶部