1 点亮第一个LED

1.1 两种电平类型

电平类型
TTL +5V 0V
RS232 -12V +12V

TTL <——>RS232,使用电平转换芯片max232

1.2 了解二、八、十、十六进制及其转换

1.3 逻辑电路

备注
均1出1
与非 均1出0 即将 “与” 取 非
均0出0
或非 均0出1
异或 不同出1
同或 相同出1

1.4 关于的说明

  • 作用:定义特殊功能寄存器和位寄存器

  • 类型说明

    | 声明类型 | 说明 |
    | ———— | ——————————— |
    | sfr | 特殊功能寄存器声明 |
    | sfr16 | 16位特殊功能寄存器声明 |
    | sbit | 特殊功能位声明 |
    | bit | 位变量声明 |

1.5 单片机结构

  • 内部结构
    image-20240326164714235

    关于总线:总线(BUS)是计算机各部件之间传送信息的公共通道。微机中有内部总线和外部总线两类。

    • 内部总线是CPU内部之间的连线。
    • 外部总线是指CPU与其它部件之间的连线。
      • 外部总线有三种:数据总线DB(Data Bus)、地址总线 AB(Address Bus)和控制总线CB(Control Bus)
  • tx开发板外观
    image-20240326165450988

1.6 P3第二功能说明

image-20240326164647132

1.7 单片机主要需要掌握

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

1.8 实验:点亮第一个led灯

51单片机IO口默认高电平

1.8.1 操作P0_0为点亮第一个led灯

1
2
3
4
5
6
7
8
9
10
/**
* 操作P0_0为点亮第一个led灯
*/
#include <reg52.h>

sbit D0 = P1^0;

void main(){
D0 = 0;
}

为什么sbit D0 = P1^0;要在main函数之外?

sbit声明的部分是编译器预处理的部分,就是为了给寄存器(位或字节)取个别名,是在函数没有编译之前必须完成的,放在主函数中就是编译中要处理的内容了,对于那些符号地址,C编译器不认识,有的名字也不允许(如P1.1),必须在编译之前进行替代,就是sbit声明,替代的内容为相应单片机寄存器的头文件里边定义的,如REG51.H

1.8.2 操作总线为点亮第一个led灯

1
2
3
4
5
6
7
8
/**
* 操作总线为点亮第一个led灯
*/
#include <reg52.h>

void main(){
P1 = 0xfe; //1111 1110
}

1.8.3 结果

image-20240326161919076

1.9 硬件补充知识

LED电路展示

image-20240326191751980

1.9.1 如何计算排阻的阻值?

  • 计算排阻值
    • 上图的P2即排阻,内部其实就是并联的一堆电阻如下图所示。
    • 下图中展示了如何根据电阻大小来控制通过led的电流,进而控制led的亮度。
    • 如图
      image-20240326193115416
  • 电阻的分类:

    • 限流电阻
      image-20240326194305877

    • 上拉电阻

    • 下拉电阻

1.9.2 74HC573锁存器

image-20240326193830074

image-20240326193934617

$\overline{\text{OE}}$(output enable):上划线表示只有低电平时,芯片才有效。

D:输入端

Q:输出端

LE:锁存器的锁存端

Z:高阻态

$Q_0$ :上一次的值

X:任意值

1.9.3 STC-ISP的用法

image-20240326195307951

com口要求5以下,如何修改设备的com口?

image-20240330160303473

勾上“显示隐藏的设备”

image-20240330160445200

image-20240330160705354

1.9.4 单片机的命名

STC89C5240CPDIP0721CV4336

89:系列

C:cmos

52:2*4k存储空间

40:最高40Mhz

C:商用级

PDIP:双列直插式封装

0721:生产日期

2 流水灯&蜂鸣器&继电器控制

2.1 keil调试功能

2.1.1 打开debug模式

需要先保存文件并编译后,点击调试按钮:

2.1.2 端口监视功能

需要先切换到debug模式

image-20240330170943479

2.1.3 查看某一变量的实时变化

view -> watch & call stack window

2.1.4 硬件仿真

keil直接连通实验板进行在线调试

如何切换到硬件调试?

image-20240330173142090

2.2 单片机工作的时序

image-20240330184627131

2.3 如何查看演示程序的延时时间

Debug->左侧->Register->sec->看value(单位:秒)

WPS拼图0

2.4 如何查看51帮助文档

help->uVision help

2.5 流水灯实验

2.5.1 _crol_循环左移

Summary

1
2
3
4
5
#include <intrins.h>

unsigned char _crol_ (
unsigned char c, /* character to rotate left */
unsigned char b); /* bit positions to rotate */

Description

The _crol_ routine rotates the bit pattern for the character c left b bits. This routine is implemented as an intrinsic function.

Return Value

The crol routine returns the rotated value of c.

See Also

_cror_, _irol_, _iror_, _lrol_, _lror_

Example

1
2
3
4
5
6
7
8
9
#include <intrins.h>

void test_crol (void) {
char a;
char b;

a = 0xA5;
b = _crol_(a,3); /* b now is 0x2D */
}

2.5.2 代码

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
/**
* 流水灯,每0.5秒流一个灯
*/

#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int


/**
* 延时d毫秒
*/
void delay(uint d){
uint x,y; // 总时间x*y
for(x = d; x > 0; x--)
for(y = 100; y > 0; y--);
}

void main(){
P1 = 0xfe;
delay(500);
while(1){
P1 = _crol_(P1,1);
delay(500);
}
}

2.5.3 实验结果

202403301705638

2.6 蜂鸣器

2.6.1 蜂鸣器接法

FM=0时,蜂鸣器响

image-20240401181306898

3 数码管静态显示

3.1 引脚知识补充

RST:复位,24个时钟周期的高电平。

VSS:地

$\overline{\text{PSEN}}$:

ALE:正常工作时输出1/6时钟周期的方波

$\overline{\text{EA}}$​:1(访问内部存储器,满后访问外部)/0(只访问外部存储器)

XTAL1/2:外部晶振

3.2 复位电路 & 晶振接法

3.2.1 晶振

image-20240403190503958

两个电容的作用:上电时帮助晶振起震

  • 12MHz——30pF
  • 6MHz——20pF

3.2.2 复位电路

image-20240403191418200

3.3 P0口的特殊性

  • P0是双向三态IO:高、低和高阻态,内无上拉电阻。因此认为添加上拉电阻,P0一上电就是高电平。

  • P1,2,3:准双向、内有上拉电阻;要输入数据,先写1

补充:

  • P0,1,2,3各有一个寄存器,内部数据是在这四个寄存器中交换

3.4数码管静态显示

3.4.1 静态数码管的两种接法

image-20240403193028204

本文使用共阴极,并提供编码表(在程序中,编码表要声明为code

3.4.2 共阴极的接法

image-20240402115733352

  • 为何使用上拉电阻:单片机io输出的电流非常小,不够点亮LED
  • 段选:控制一个数码管的某一段亮。如上图,所有’a’连到一起。
  • 位选:控制某一个数码管亮。共阴极时,低电平亮。

3.5 锁存器应用

利用锁存器,使单片机的一个端口控制多个数码管。

74HC573高电平直通,低电平锁存。

  • 先将位选置为高电平,通过P0传输位选信号,控制哪一个数码管亮。最后将位选置为低电平,将该信号锁存,在之后位选锁存器一直输出该信号。
  • 接着将段选置为高电平,通过P0传输段选信号,控制一个数码管的哪一段亮。最后将位选置为低电平,将该信号锁存,在之后位选锁存器一直输出该信号。

3.6 实验

3.6.1 电路图

image-20240403194715502

image-20240403194406004

3.6.2 代码

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
/**
* 八位数码管每隔1秒轮流显示0~F
*/
#include <reg52.h>

#define uchar unsigned char
#define uint unsigned int

/**
* 定义变量
*/
sbit dula = P2^6; // 控制led段的 锁存器使能端
sbit wela = P2^7; // 控制led位的 锁存器使能端
uint num;

/**
* code: 告诉编译器将table放进ROM,否则将占用宝贵的RAM资源
*/
uchar code table[] = {
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};

/**
* 延时d毫秒
*/
void delay(uint d){
uint x,y; // 总时间x*y (ms)
for(x = d; x > 0; x--)
for(y = 110; y > 0; y--);
}

void main(){
/*位选*/
wela = 1; // 锁存器高电平直通
P0 = 11000000/*0xc0*/; // 所有数码管都亮;共阴极“位选”理解成“地”?;11000000顺序: P0^7 -> P0^0
wela = 0; // 低电平锁存
while(1){
num = 0;
for( ; num < 16; num++){
/*段选*/
P0 = 0x00;
dula = 1;
P0 = table[num];
dula = 0;
delay(1000);
}
}
}

4 中断 & 数码管动态显示

4.1 8051中断系统的结构

5个中断源,2个优先级,可实现二级嵌套。

补充:单片机上电后所有寄存器默认都是0,所有引脚默认都是1

image-20240416174848659

4.2 中断请求标志

TCON

  • 低四位控制 外部中断
  • 高四位控制 定时计数器 启动、中断申请以及设置溢出标志
    • TF0/1由单片机自动控制(溢出时自动置1,引起定时器中断后,自动清0),因此只需要关注TR1和TR0即可

image-20240416175122633

image-20240416195745874

TMOD(定时计数器工作方式寄存器)

字节地址:89H

image-20240416194728688

对于各位的解释

image-20240416195144104

M0M1设置工作方式

image-20240416195318210

SCON(串行口中断标志)

image-20240416175406235

IE中断允许控制

image-20240416175214713

IP优先级控制

image-20240416175518779

默认优先级表

image-20240416175742077

4.3 中断服务程序的写法

image-20240416203103286

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//以外部中断0举例

void main(){
EA=1;//开总中断
EX0=1;//开外部中断0
IT0=1; //设置为下降沿触发方式
//...
}

//中断函数不需要声明
void exter0() interrupt 0 /*void 中断函数名 interrupt 第几个中断源(按默认优先级顺序编号0~4)*/
{
//...
}
// 当P3.2有低电平的时候出发点中断

4.4 定时器中断

image-20240416194643619

方式1

image-20240416195902873

计数个数和计数初值的关系:$X(计数初值)=2^{16}-N(计数个数)$

如何计算TH0和TL0?

  • 法1

  • 法2
    $2^{16}-N$ 直接转为十六进制数,高两位填入TH0,低两位填入TL0

4.5 定时、计数器中断程序的写法

image-20240416202947475

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

void main(){
TMOD=0X01;//设置定时器0的工作方式
TH0=(65536-50000)/256; //设置计数(定时)初值
TL0=(65536-50000)%256;
EA=1;//开总中断
ET0=1;//开定时器中断
TR0=1;//启动定时器0
// ...
}

void exter() interrupt 1{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256; // 因为被清零,所以恢复初值

//...
}

4.6 数码管动态显示

所谓动态扫描显示,即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示,而实际上多位数码管是一位一位轮流显示的,只是轮流的速度非常快,人眼已经无法分辨出来。

代码参考第四讲:数码管的动态显示原理和应用实现(郭天祥)-CSDN博客

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
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={ //段选编码表
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
uchar code table2[]={ //位选编码表
0xfe,0xfd,0xfb,
0xf7,0xef,0xdf};
sbit wela = P2^7;
sbit dula = P2^6;
uchar count,num1,num2;
void main()
{
count = 0; //计数
num1 = 0;
num2 = 0;
TMOD = 0x01;
TH0 = (65536 - 50000)/256;
TL0 = (65536 - 50000)%256;
EA = 1;
ET0 = 1;
TR0 = 1;
while(1); //等待中断产生
}

void timer0() interrupt 1
{
TH0 = (65536 - 50000)/256;
TL0 = (65536 - 50000)%256;
count++; //每次中断,计数值加1
if(count == 20)//每过1s
{
count = 0;//计数值清0
num1++; //段选值加1
if(num1 == 7)//将段选范围限制在1~6
num1 = 1;
dula = 1;
P0 = table[num1];
dula = 0;
P0 = 0xff; // 消影
wela = 1;
P0 = table2[num2];
wela = 0;
num2++; //位选值加1
if(num2 == 6)//将位选范围限制在1~6
num2 = 0;
}
}

其中,关于“消影”,在书P53

例 3.3.1的程序中需要注意:在每次送完段选数据后、送入位选数据前,需要加上语句“P0=0xff”,这条语句的专业名称叫做“消影”

解释如下:在刚送完段选数据后,P0 口仍然保持着上次的段选数据,若不加“P0=0xff;”语句再执行接下来的打开位选锁存器命令后,原来保持在P0口的段选数据将立即通过位选锁存器直接加在数码管上,接下来才是再次通过 P0口给位选锁存器送入位选数据。虽然这个过程非常短暂,但是在数码管高速显示状态下,我们仍然可以看见数码管出现显示混乱的现象,加上“消影”后,在开启位选锁存器后,P0口数据全为高电平,所以哪个数码管都不会亮,因此这个“消影”动作是很重要的。

5 键盘

参考51单片机学习笔记(郭天祥版)(5)——作业讲解、独立键盘、矩阵键盘_郭天祥stc89c51单片机笔记-CSDN博客

5.1 独立键盘

image-20240418155935053

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
/**
* 独立按键按下计数及消抖
*/


#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int

uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00};

sbit btn = P3^4;
sbit led0 = P1^0;
sbit wela = P2^7;
sbit dula = P2^6;
uint num = 0;


/*>>>延时函数>>>*/
void Delay1ms() //@12.000MHz
{
unsigned char i, j;

i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
void delay(int n)
{
while(n--)
{
Delay1ms();
}
}

/*<<<*/


void main(){
P3 = 0xff; // P3初始化


wela = 1;//打开位选
P0 = 0xfe; //打开第一个数码管
wela = 0;//锁存

dula = 1;//打开段选
P0 = table[0];//初始化
dula = 0;//关闭段选

while(1){
if(btn == 0){
/* btn按下 */


//消抖
delay(10); //等待10ms检测是否还是低电平
if(btn!=0) continue;

//led0亮
led0 = 0;

//显示按下此时
++num;
if(num>9){
num = 0;
}

dula = 1;
P0 = 0xff; // 消隐
dula = 0;

dula = 1;//打开段选
P0 = table[num];
dula = 0;//关闭段选

while(!btn);//松手检测,如果一直按下则阻断在这里
delay(10); //松手消抖
while(!btn);
}
else{
// btn抬起
led0 = 1;
}
}

}

5.2 矩阵键盘

逐行扫描:过程参考章节开头的链接,节选如下。

其实和独立键盘都是一样的,都是检测低电平,但是四行四列全部连得IO口,没有接地的,所以低电平由你写程序给予。

image-20240418202654041

先给P3.0~3.3这样赋值,然后读取P3.4~3.7的数据,如果第一个键按下去了,那么P3.4就是0(线与的关系,没忘吧?),同一时刻你只能按下一个键,检测时都是有先后顺序的。那么P3的值就是如下:

image-20240418202712005

如果是按下的第1行第2列的键,那么就会如下:

image-20240418202729547

以此类推。如果都没按下去,那么P3.4~P3.7都是1。我们就根据每一次读取的值判断按下去的是哪一个键。这就是第一行的检测,矩阵键盘的检测要依次对四行进行扫描,第一次P3.0=0,然后读取四列,如果没有按下去,那么下一次就是把P3.1=0,其它三个为1,也是这样判断。只要有任何一个键被按下,就跳出整个大循环,直接退出扫描程序。如果你是两个一起按下去的,也是有先后顺序的,那么后面的也检测不到。

先让P3=0xfe,在定义一个变量temp,保存P3的值(temp=P3),接下来我们要读的实际上是P3的高4位,只想知道高4位什么状态,然后再让temp&0xf0(按位与),如果一个都没按下,那么高4位全是1,低4位不管(任何数和0与都是0),那么temp&0xf0的结果还是0xf0,如果不是0xf0就是有键按下,如果第一个键按下了,那么P3.7~3.4就是1110,后面低4位不管,那么和0xf0与的时候就是1110 0000,不等于0xf0(1111 0000),就知道有键按下了,之后延时一下,再检测一遍,如果还是这个数,0xe0,那么就知道第一个键按下去了,用一个变量num,num=1,标记第一个键。一共扫描16次(第一行赋值0,扫描4列,第二行0,扫描4列……)。

再举一下例子:

例如按下去的是第一行第二列的键。

那么第一次赋值P3=1111 1110后,temp就会为1101 1110,temp&0xfe=1101 0000,然后和0xfe比较即可,之后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
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/**
* 对按键从上到下,从左到右编号,
* 按第一个键在七段数码管显示1,
* 按第二个键在七段数码管显示2,...
* 以此类推
*/
#include<reg51.h>

#define uchar unsigned char
#define uint unsigned int

sbit WEI=P2^7;
sbit DUAN=P2^6;

sbit led0=P1^0;
sbit key0=P3^0;

uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
// 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
uchar num=0,temp;

/*>>> 延时 >>>*/
void Delay1ms() //@12.000MHz
{
unsigned char i, j;

i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
void delay(int n)
{
while(n--)
{
Delay1ms();
}
}
/* <<< <<< */

void main()
{
DUAN=1;
P0=0x00;
DUAN=0;

WEI=1;
P0=0xfe;
WEI=0;

while(1)
{
//第一行
P3=0xfe;
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5); // 消除抖动
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee:num=1;break;
case 0xde:num=2;break;
case 0xbe:num=3;break;
case 0x7e:num=4;break;
}

/*松手检测
* 没有这里的话,如果按下某一行,就会一直进入上面这个while循环,即使松手也出不来,
* 有了它,不松手就一直在下面的循环,松手后就会改变temp的值,变为0xf0
*/
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
DUAN=1;
P0=Table[num-1];
DUAN=0;
}
}

//第二行
P3=0xfd;
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xed:num=5;break;
case 0xdd:num=6;break;
case 0xbd:num=7;break;
case 0x7d:num=8;break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
DUAN=1;
P0=Table[num-1];
DUAN=0;
}
}

//第三行
P3=0xfb;
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb:num=9;break;
case 0xdb:num=10;break;
case 0xbb:num=11;break;
case 0x7b:num=12;break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
DUAN=1;
P0=Table[num-1];
DUAN=0;
}
}

//第四行
P3=0xf7;
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xe7:num=13;break;
case 0xd7:num=14;break;
case 0xb7:num=15;break;
case 0x77:num=16;break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
DUAN=1;
P0=Table[num-1];
DUAN=0;
}
}
}
}


6 DA & AD

6.1 DA

6.1.1 主要性能指标

模拟量随着数字量的变化而变化

image-20240618162250812

分辨率

分辨率计算公式

其中,FS表示满量程输入值,n表示二进制位数。

例如,采样8位DAC时,分辨率为$5V/256=19.5mV$,即每次变化±19.5mV。

线性度

也称为非线性误差,即实际转换特性曲线与理想直线特性曲线之间的最大偏差(百分比)。

绝对精度和相对精度

绝对精度:类型线性度,只不过不是百分比;

  • 由增益误差,零点误差、非线性误差和噪声误差引起。

    • 增益误差(当输入数码为全1时,实际输出值与理想输出值之差);
    • 零点误差(数码输入为全0时,DAC的非零输出值)、
    • 非线性误差和噪声等引起的。
  • 绝对精度(即最大误差)应小于1个LSB.

相对精度:与绝对精度表示同一含义,用最大误差相对于满刻度的百分比表示。

建立时间

D/A的转换速率

6.1.2 DAC0832

内部结构及引脚

image-20240425145304415

image-20240425145706155

补充:说明文档中的原理图
7489679012b015a70b3c12195d008ae2

工作方式

  • 单缓冲工作方式

  • 双极性模拟输入电压

  • 双缓冲工作方式

  • 直通工作方式(视频课主要介绍了该方式)

    当DAC0832芯片的片选信号、写信号、及传送控制信号的引脚全部接地,允许输入锁存信号LE脚接+5V时,DAC0832芯片就处于直通工作方式,数字量一旦输入,就直接进入DAC寄存器,进行DIA转换。

    • DAC0832与89c52在直通方式下的连接方式

      image-20240618153022933

在实验时,将P5的2、3引脚短路,通过观察发光二极管D12的亮度变化,理解输出电压强弱的变化

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <reg52.h>

sbit csda = P3^2;
sbit wr = P3^6;

int main()
{
csda = 0;
wr = 0;
P1 = 0xff;
while(1);
return 0;
}

6.2 AD

8 $I^{2}C$总线

8.2 单片机模拟$I^{2}C$总线通信