本文最后更新于 2024-01-14,文章内容可能已经过时。

2024.1.10工作出现的知识问题

ADC

数字电子的模拟世界

多年前,我们使用的电子设备,如电话、电脑、电视等,本质上都是模拟的。然后慢慢地,固定电话被现代手机取代,CRT 电视和显示器被 LED 显示器取代,带有真空管的计算机演变为更强大的微处理器和微控制器等等。

在数字时代的今天,我们被先进的数字电子设备所包围,让我们认为我们周围的一切本质上都是数字的,这是不正确的。

世界在本质上一直是模拟的,例如,我们人类感觉和经历的一切,如速度、温度、空气速度、阳光、声音等,在本质上都是模拟的。但是我们在微控制器和微处理器上运行的电子设备不能直接读取/解释这些模拟值,因为它们只在0和1上运行。所以我们需要一种能将这些模拟值转换成0和1的东西,以便我们的微控制器和微处理器能够理解它们。这就是所谓的模数转换器或简称ADC。在本文中,我们将学习有关ADC的知识以及如何使用它们。

什么是 ADC 以及如何使用它?

如前所述,ADC 代表模数转换,它用于将模拟值从现实世界转换为数字值,如 1 和 0。那么这些模拟值是什么?这些是我们在日常生活中看到的,比如温度、速度、亮度等。但是等等!ADC 能否将温度和速度直接转换为 0 和 1 等数字值?

不,当然不是。ADC只能将模拟电压值转换为数字值。因此,无论我们想要测量哪个参数,都应该先将其转换为电压,这种转换可以在传感器的帮助下完成。例如,为了将温度值转换为电压,我们可以使用热敏电阻,同样,为了将亮度转换为电压,我们可以使用LDR。一旦转换成电压,我们就可以在ADC的帮助下读取。

为了了解如何使用 ADC,我们首先应该熟悉一些基本术语,例如通道、分辨率、范围、参考电压等。

ADC 中的分辨率(位)和通道

当您阅读任何微控制器或ADC IC的参数规格时,ADC的参数信息将使用“通道”和“分辨率(位)”等术语给出。

例如,Arduino UNO的ATmega328有一个8通道10位ADC。术语“8通道”意味着ATmega328微控制器上有8个引脚可以读取模拟电压,每个引脚可以读取10位分辨率的电压。并非微控制器上的每个引脚都可以读取模拟电压,这因不同型号的微控制器而异。

假设我们的 ADC 范围是从 0V 到 5V,并且我们有一个 10 位 ADC,这意味着我们的输入电压 0-5 伏将被分成 1024 级离散模拟值(0000000000—1111111111,2^10 = 1024)。1024 是 10 位 ADC 的分辨率,类似地,8 位 ADC 的分辨率为 512 (2^8 ),16 位 ADC 的分辨率为 65536 (2^16 )。

这样,如果实际输入电压为 0V,则 MCU 的 ADC 会将其读取为 0,如果为 5V,则 MCU 将读取为 1024,如果是2.5V,则 MCU 将读取为 512。我们可以使用以下公式根据 ADC 的分辨率和参考电压计算 MCU 读取的数字值。

(ADC 分辨率 / 参考电压) = (ADC 数字值 / 实际电压值)

ADC 的参考电压

您应该了解的另一个重要术语是“参考电压”。在 ADC 转换过程中,通过将其与已知电压进行比较来找到未知电压的值,这个已知电压,称为参考电压。

通常所有 MCU 都有一个设置内部参考电压的选项,这意味着您可以使用软件(程序)在内部将此电压设置为某个可用值。

在 Arduino UNO 板中,参考电压在内部默认设置为 5V,如果需要,用户也可以在软件中进行所需的更改,再通过 Vref 引脚在外部设置此参考电压。

需要注意的是,测量的模拟电压值应始终小于参考电压值,并且参考电压值应始终小于单片机的工作电压值。

例子

这里我们以具有 3 位分辨率和 2V 参考电压的 ADC 为例。由上所述,它可以将 0-2v 模拟电压映射为 8 (2^3 ) 个不同的电平,如下图所示:

从上图得出,如果模拟电压为 0.25,那么数字值是十进制的 1 和二进制的 001。同样,如果模拟电压为 0.5,则数字值为十进制的 2 和二进制的 010。

一些微控制器具有内置 ADC,如 Arduino、MSP430、PIC16F877A,但有些微控制器没有,如 8051、Raspberry Pi 等,对于没有ADC的微控制器,我们必须用一些外部模数转换器 IC来帮助完成模拟信号的读取,如ADC0804、ADC0808。

ADC 类型和工作原理

ADC 的类型很多,最常用的有 Flash ADC、双斜率 ADC、逐次逼近ADC。它们相当复杂,如果解释每个 ADC 的工作原理以及它们之间的区别,将超出本文的范围。但粗略地说,ADC 有一个内部电容器,要测量的模拟电压对该电容器充电。然后我们通过在一段时间内对电容器放电来测量电压值。

关于 ADC 的一些常见问题

如何使用我的 ADC 测量超过 5V 的电压?

如前所述,ADC 模块无法测量超过微控制器工作电压的电压值。也就是说,一个工作电压为5V 的微控制器,只能通过其 ADC 引脚测量最大的电压值为 5V。

如前所述,ADC 模块无法测量超过微控制器工作电压的电压值。也就是说,一个 工作电压为5V 的微控制器,只能通过其 ADC 引脚测量最大的电压值为 5V。如果您想测量更大的范围,例如 0-12V,那么您可以使用分压器或分压器电路来辅助测量。如将两个一个 1K 电阻串联到电压源,并测量电阻之间的电压,当然实际中还要考虑ADC的输入阻抗。

如何将 ADC 的数字值转换为实际的电压值?

当使用 ADC 转换器测量模拟电压时,MCU 获得的结果是数字的。例如,在 10 位 5V 微控制器中,当要测量的实际电压为 4V 时,MCU 会将其读取为 820,我们可以再次使用上面讨论的公式将 820 转换为 4V,以便我们可以在我们的计算。让我们验证一下。

(ADC 分辨率 / 参考电压) = (ADC 数字值 / 实际电压值)

实际电压值 = ADC 数字值 * (参考电压 / ADC 分辨率)

= 820 * (5/1024)

= 4.003

=4V

C语言关键字

关键字

说明

auto

声明自动变量

break

跳出当前循环

case

开关语句分支

char

声明字符型变量或函数返回值类型

const

定义常量,如果一个变量被 const 修饰,那么它的值就不能再被改变

continue

结束当前循环,开始下一轮循环

default

开关语句中的"其它"分支

do

循环语句的循环体

double

声明双精度浮点型变量或函数返回值类型

else

条件语句否定分支(与 if 连用)

enum

声明枚举类型

extern

声明变量或函数是在其它文件或本文件的其他位置定义

float

声明浮点型变量或函数返回值类型

for

一种循环语句

goto

无条件跳转语句

if

条件语句

int

声明整型变量或函数

long

声明长整型变量或函数返回值类型

register

声明寄存器变量

return

子程序返回语句(可以带参数,也可不带参数)

short

声明短整型变量或函数

signed

声明有符号类型变量或函数

sizeof

计算数据类型或变量长度(即所占字节数)

static

声明静态变量

struct

声明结构体类型

switch

用于开关语句

typedef

用以给数据类型取别名

unsigned

声明无符号类型变量或函数

union

声明共用体类型

void

声明函数无返回值或无参数,声明无类型指针

volatile

说明变量在程序执行中可被隐含地改变

while

循环语句的循环条件

一、数据类型关键字

A基本数据类型(5个)

  • void:声明函数无返回值或无参数,声明无类型指针,显式丢弃运算结果

  • char:字符型类型数据,属于整型数据的一种

  • int:整型数据,通常为编译器指定的机器字长

  • float:单精度浮点型数据,属于浮点数据的一种

  • double:双精度浮点型数据,属于浮点数据的一种

B类型修饰关键字(4个)

  • short:修饰int,短整型数据,可省略被修饰的int。

  • long:修饰int,长整形数据,可省略被修饰的int。

  • signed:修饰整型数据,有符号数据类型

  • unsigned:修饰整型数据,无符号数据类型

C复杂类型关键字(5个)

  • struct:结构体声明

  • union:共用体声明

  • enum:枚举声明

  • typedef:声明类型别名

  • sizeof:得到特定类型或特定类型变量的大小

D存储级别关键字(6个)

  • auto:指定为自动变量,由编译器自动分配及释放。通常在栈上分配

  • static:指定为静态变量,分配在静态变量区,修饰函数时,指定函数作用域为文件内部

  • register:指定为寄存器变量,建议编译器将变量存储到寄存器中使用,也可以修饰函数形参,建议编译器通过寄存器而不是堆栈传递参数

  • extern:指定对应变量为外部变量,即在另外的目标文件中定义,可以认为是约定由另外文件声明的对象的一个“引用“

  • const:与volatile合称“cv特性”,指定变量不可被当前线程/进程改变(但有可能被系统或其他线程/进程改变)

  • volatile:与const合称“cv特性”,指定变量的值有可能会被系统或其他进程/线程改变,强制编译器每次从内存中取得该变量的值

二、流程控制关键字

A跳转结构(4个)

  • return:用在函数体中,返回特定值(或者是void值,即不返回值)

  • continue:结束当前循环,开始下一轮循环

  • break:跳出当前循环或switch结构

  • goto:无条件跳转语句

B分支结构(5个)

  • if:条件语句

  • else:条件语句否定分支(与if连用)

  • switch:开关语句(多重分支语句)

  • case:开关语句中的分支标记

  • default:开关语句中的“其他”分治,可选。

C循环结构(3个)

  • for:for循环结构,for(1;2;3)4;的执行顺序为1->2->4->3->2...循环,其中2为循环条件

  • do:do循环结构,do 1 while(2);的执行顺序是1->2->1...循环,2为循环条件

  • while:while循环结构,while(1) 2;的执行顺序是1->2->1...循环,1为循环条件

进制转换【单片机常用十六进制】

1.如何将二进制数转换十六进制数?

下表将每 4 个二进制数(从 0 位开始)转换为 1 个十六进制数字:

二进制数

十六进制数

0000

0

0001

1

0010

2

0011

3

0100

4

0101

5

0110

6

0111

7

1000

8

1001

9

1010

A

1011

B

1100

C

1101

D

1110

E

1111

F

实例

将二进制数 11011002 转换为十六进制数:

将每 4 个二进制数字(从 0 位开始)转换为十六进制数:

11011002 = 110 1100 = 6 C = 6C16

2.二,八,十,十六进制转换列表

二进制

八进制

十进制

十六进制

0

0

0

0

1

1

1

1

10

2

2

2

11

3

3

3

100

4

4

4

101

5

5

5

110

6

6

6

111

7

7

7

1000

10

8

8

1001

11

9

9

1010

12

10

A

1011

13

11

B

1100

14

12

C

1101

15

13

D

1110

16

14

E

1111

17

15

F

10000

20

16

10

10001

21

17

11

10010

22

18

12

10011

23

19

13

10100

24

20

14

10101

25

21

15

10110

26

22

16

10111

27

23

17

11000

30

24

18

11001

31

25

19

11010

32

26

1A

11011

33

27

1B

11100

34

28

1C

11101

35

29

1D

11110

36

30

1E

11111

37

31

1F

100000

40

32

20

100001

41

33

21

100010

42

34

22

100011

43

35

23

100100

44

36

24

100101

45

37

25

100110

46

38

26

100111

47

39

27

101000

50

40

28

101001

51

41

29

101010

52

42

2A

101011

53

43

2B

101100

54

44

2C

101101

55

45

2D

101110

56

46

2E

101111

57

47

2F

110000

60

48

30

110001

61

49

31

110010

62

50

32

110011

63

51

33

110100

64

52

34

110101

65

53

35

110110

66

54

36

110111

67

55

37

111000

70

56

38

111001

71

57

39

111010

72

58

3A

111011

73

59

3B

111100

74

60

3C

111101

75

61

3D

111110

76

62

3E

111111

77

63

3F

1000000

100

64

40

1000001

101

65

41

1000010

102

66

42

1000011

103

67

43

1000100

104

68

44

1000101

105

69

45

1000110

106

70

46

1000111

107

71

47

1001000

110

72

48

1001001

111

73

49

1001010

112

74

4A

1001011

113

75

4B

1001100

114

76

4C

1001101

115

77

4D

1001110

116

78

4E

1001111

117

79

4F

1010000

120

80

50

1010001

121

81

51

1010010

122

82

52

1010011

123

83

53

1010100

124

84

54

1010101

125

85

55

1010110

126

86

56

1010111

127

87

57

1011000

130

88

58

1011001

131

89

59

1011010

132

90

5A

1011011

133

91

5B

1011100

134

92

5C

1011101

135

93

5D

1011110

136

94

5E

1011111

137

95

5F

1100000

140

96

60

1100001

141

97

61

1100010

142

98

62

1100011

143

99

63

1100100

144

100

64