0
1
00:00:03,370 --> 00:00:12,340
現在讓我們探索如何同時而不是按順序切換藍色和橙色LED
1

2
00:00:12,340 --> 00:00:15,190
方式，但有點平行。
2

3
00:00:15,460 --> 00:00:22,540
因此，要做到這一點，我們必須為橙色和綠色創建主要功能，現在我要做的是
3

4
00:00:22,540 --> 00:00:30,530
將先創建橙色主線，然後創建綠色主線，然後在這些函數中將存在無限個
4

5
00:00:30,590 --> 00:00:32,970
循環就像我們擁有的主要功能一樣。
5

6
00:00:33,170 --> 00:00:39,120
但這一次是橙色，然後是綠色，我要開始，常規的主要功能是
6

7
00:00:39,120 --> 00:00:45,700
int main，但這次我們要使用橙色main，int橙色main。不用
7

8
00:00:45,740 --> 00:00:46,520
論點。
8

9
00:00:52,400 --> 00:00:54,270
我要打開，我要關閉。
9

10
00:00:54,270 --> 00:00:57,130
當然，我將在其中有一個循環。
10

11
00:00:57,280 --> 00:01:01,660
這才真正使它成為主要功能。
11

12
00:01:02,840 --> 00:01:07,670
我將有一個類似的藍色。
12

13
00:01:15,310 --> 00:01:21,320
當然，我將在循環的一個循環中填充藍色LED的切換代碼
13

14
00:01:21,320 --> 00:01:23,830
藍色，然後對橙色執行相同操作。
14

15
00:01:24,020 --> 00:01:29,840
因此，我將在此處剪切我們測試過的藍色代碼，然後將其放入主藍色
15

16
00:01:29,950 --> 00:01:37,410
或藍色主體，然後我將其變成橙色，然後將其重命名為橙色，我將
16

17
00:01:37,460 --> 00:01:40,200
過來這裡橙色
17

18
00:01:40,310 --> 00:01:50,600
那當然是橙色
18

19
00:01:50,790 --> 00:01:51,330
讓我們來看看
19

20
00:01:51,350 --> 00:01:53,560
為什麼這有問題？
20

21
00:01:53,990 --> 00:01:57,070
讓我們看看，當然這裡有一個錯誤。
21

22
00:01:57,140 --> 00:01:57,690
好。
22

23
00:01:59,630 --> 00:02:06,340
因此，我們現在有兩個主要功能。讓我們保留原始的main函數，然後調用
23

24
00:02:06,390 --> 00:02:07,990
藍色主體和橙色主體
24

25
00:02:08,050 --> 00:02:09,790
在這個主要功能內
25

26
00:02:12,700 --> 00:02:20,560
我只在這裡叫藍色總管。藍色強調底線，然後強調橙色。
26

27
00:02:25,880 --> 00:02:32,110
實際上，不僅僅是關閉端口D中藍色LED的位。
27

28
00:02:32,410 --> 00:02:38,150
讓我們關閉整個端口，以免在實驗過程中陷入困境
28

29
00:02:38,390 --> 00:02:45,350
在這裡我們關閉了藍色LED，但是由於我們沒有明確關閉橙色，我們找到了橙色
29

30
00:02:45,350 --> 00:02:46,310
on.
30

31
00:02:46,310 --> 00:02:49,370
我的意思是，這會使實驗有些混亂。
31

32
00:02:49,370 --> 00:02:58,010
因此，我要做的是，與其使用該運算符關閉藍色，不如將其關閉
32

33
00:02:58,010 --> 00:03:05,360
的所有引腳都熄滅，所以當我說藍色熄滅時，所有LED都熄滅。
33

34
00:03:05,390 --> 00:03:13,790
當我說橙色時，所有LED也會熄滅。這將簡化我們的查看方式。
34

35
00:03:14,060 --> 00:03:23,440
所以當我將這些功能帶入此處，何時
35

36
00:03:23,440 --> 00:03:31,270
我把這些功能帶到這裡，我不得不在原始主要功能中保留一會兒，以便
36

37
00:03:31,270 --> 00:03:34,990
使代碼不終止。
37

38
00:03:34,990 --> 00:03:40,200
如果我們不把這根線放在這裡，這個主要功能將運行，並且將終止。
38

39
00:03:40,240 --> 00:03:46,570
但是，當我們將其放置在此處時，它仍然存在，它使我們有時間在藍色主電源和藍色主電源之間進行切換。
39

40
00:03:46,570 --> 00:03:47,490
橙色的手。
40

41
00:03:47,590 --> 00:03:55,940
另一件事是，為了能夠到達代碼的這一部分，請記住這裡的藍色主體。
41

42
00:03:55,960 --> 00:03:56,810
我剛到這裡
42

43
00:03:56,890 --> 00:03:59,780
如您所見，這裡有一個無限循環。
43

44
00:03:59,800 --> 00:04:01,530
此函數不返回。
44

45
00:04:01,690 --> 00:04:08,780
因此，當編譯器編譯所執行的操作時，通常會忽略此代碼
45

46
00:04:08,800 --> 00:04:15,760
因為它知道第一個藍色主函數不會返回，所以此後的任何內容都無法訪問
46

47
00:04:15,820 --> 00:04:17,730
因為這裡有一個無限循環。
47

48
00:04:18,040 --> 00:04:24,880
因此，要使其他代碼，藍色主體代碼之後的代碼，無限循環之後的代碼可以訪問，我們可以
48

49
00:04:25,210 --> 00:04:32,350
創建一個像這樣的volatile變量並設置一個if條件，如果啟動則執行此操作，否則執行該操作
49

50
00:04:32,410 --> 00:04:36,860
我們可以在此處初始化變量，以便有一個起點。
50

51
00:04:36,940 --> 00:04:41,920
因此，當我們轉到調試器時，我們嘗試操作內存中的值。
51

52
00:04:41,920 --> 00:04:44,730
我們實際上可以在這裡找到此代碼。
52

53
00:04:46,110 --> 00:04:54,360
現在繼續進行操作，更改目標選項。我將點擊此處，然後禁用
53

54
00:04:54,360 --> 00:04:55,760
浮點硬件。
54

55
00:04:55,800 --> 00:05:02,200
這將使我們能夠正確觀察內存中的變化。
55

56
00:05:02,220 --> 00:05:09,430
因此，默認情況下表示使用單精度。我要說不使用，然後單擊“確定”。
56

57
00:05:09,630 --> 00:05:12,740
一旦完成，我將仔細檢查。
57

58
00:05:12,850 --> 00:05:15,890
這是主要功能，這是常規的主要功能。
58

59
00:05:15,900 --> 00:05:19,810
在main函數內部，我們有藍色main，還有橙色main。
59

60
00:05:19,950 --> 00:05:25,030
我在這裡有此volatile變量，它已初始化為零。
60

61
00:05:25,050 --> 00:05:31,500
表示是否為其他，表示運行代碼的else部分，因為else為零。
61

62
00:05:31,530 --> 00:05:36,190
因此，當我們運行代碼時，我們應該看到橙色的LED閃爍。
62

63
00:05:36,770 --> 00:05:41,150
但是我將從調試視圖運行它，所以我將首先單擊此處。
63

64
00:05:45,290 --> 00:05:50,540
我將關閉它，然後要做的是，我將單擊此處運行代碼。
64

65
00:05:53,980 --> 00:05:57,450
如您所見，橙色LED閃爍。
65

66
00:05:57,700 --> 00:06:05,720
所以我接下來要做的是，我將一個斷點放置在systick中，以便當我們進入
66

67
00:06:05,780 --> 00:06:09,730
中斷服務程序我們可以手動進行某些更改。
67

68
00:06:09,740 --> 00:06:14,100
因此，我將像這樣在此處放置一個斷點，然後停止。
68

69
00:06:14,150 --> 00:06:22,760
完成此操作後，我將在此處向我的視圖添加內存視圖，並在此處查看內存窗口並選擇一個內存
69

70
00:06:23,240 --> 00:06:28,230
我將導航到堆棧指針的地址，該地址為六四零。
70

71
00:06:28,310 --> 00:06:29,180
這就是這個價值
71

72
00:06:29,280 --> 00:06:31,340
因此，如果我只是在此處輸入此值。
72

73
00:06:31,520 --> 00:06:37,390
然後按Enter鍵，它將帶我到堆棧指針的地址。
73

74
00:06:37,540 --> 00:06:39,820
因此，我將稍微調整一下視圖。
74

75
00:06:39,890 --> 00:06:46,870
因此，當皮質M處理器中發生中斷時，皮質M中某些寄存器的內容
75

76
00:06:47,220 --> 00:06:55,390
寄存器組保存到堆棧中。請記住，堆棧只是存在於其中的特定內存區域
76

77
00:06:55,390 --> 00:06:56,210
RAM。
77

78
00:06:56,320 --> 00:07:00,990
因此，這些內容將保存到堆棧中。
78

79
00:07:01,000 --> 00:07:07,410
這樣處理器就可以返回堆棧並恢復之前保存的內容
79

80
00:07:07,430 --> 00:07:09,430
完成之後
80

81
00:07:09,440 --> 00:07:12,150
為中斷服務程序提供服務。
81

82
00:07:12,190 --> 00:07:20,280
這使進程可以在中斷發生時準確地繼續到停止的位置。
82

83
00:07:20,310 --> 00:07:25,030
讓我們看一下ARM cortex M4設備通用使用指南。
83

84
00:07:25,110 --> 00:07:31,650
首先，我將退出調試器，以便可以在此處選擇書籍。我會選書
84

85
00:07:31,680 --> 00:07:34,650
然後選擇這本特殊的書
85

86
00:07:34,800 --> 00:07:35,600
對。
86

87
00:07:35,640 --> 00:07:42,290
因此，在ARM cortex M4設備通用用戶指南中，在異常模型中，
87

88
00:07:42,300 --> 00:07:49,330
在這裡它說當有一個待處理的異常時發生異常輸入
88

89
00:07:49,330 --> 00:07:52,990
足夠的優先權
89

90
00:07:52,990 --> 00:07:59,030
不必擔心細節，更重要的是，我們想學習什麼
90

91
00:07:59,030 --> 00:08:00,230
在這裡
91

92
00:08:00,230 --> 00:08:07,630
它還說，當處理器發生異常時，處理器會將信息壓入堆棧。
92

93
00:08:07,650 --> 00:08:15,730
此操作稱為堆棧，八個數據字的結構稱為堆棧幀。
93

94
00:08:16,050 --> 00:08:19,540
請記住，單詞是指32位數據類型。
94

95
00:08:19,590 --> 00:08:24,190
因此，這意味著八個寄存器的結構稱為堆棧幀。
95

96
00:08:24,210 --> 00:08:32,160
繼續說，��用浮點例程時，Cortex M4處理器會自動
96

97
00:08:32,180 --> 00:08:39,810
還將異常條目上的浮點狀態堆棧起來，並在此處提供了一個圖表
97

98
00:08:39,850 --> 00:08:42,490
描繪他在說什麼。
98

99
00:08:42,870 --> 00:08:49,750
因此，這是使用未啟用浮點的處理器的堆棧幀。
99

100
00:08:49,920 --> 00:08:55,320
這是使用啟用了浮點的處理器的堆棧幀，您可以看到它有多長時間
100

101
00:08:55,320 --> 00:08:55,860
is.
101

102
00:08:55,860 --> 00:09:01,350
因此，這就是為什麼我禁用了浮點硬件的浮點單元的原因。
102

103
00:09:01,470 --> 00:09:03,810
這樣我們就得到了這個堆棧框架。
103

104
00:09:03,810 --> 00:09:12,420
因此，當處理器處理異常（例如systick中斷）時，
104

105
00:09:12,810 --> 00:09:16,560
這些寄存器保存到堆棧中。
105

106
00:09:16,680 --> 00:09:22,260
如果我們沒有禁用硬件浮點單元，我們會將所有這些寄存器保存到
106

107
00:09:22,260 --> 00:09:24,090
堆棧，但我們禁用了它。
107

108
00:09:24,210 --> 00:09:26,900
因此，這些寄存器將保存到堆棧中。
108

109
00:09:27,210 --> 00:09:34,680
因此，當處理器完成對中斷服務程序的服務後，它將恢復
109

110
00:09:34,770 --> 00:09:42,270
這些寄存器以及這些寄存器的內容會告訴處理器確切的停止位置
110

111
00:09:42,270 --> 00:09:47,160
發生中斷，以便它可以從停止的地方開始。
111

112
00:09:47,160 --> 00:09:53,550
因此，是的，只是在這裡再次回顧一下這種安排，我們可以知道當一個中斷異常時
112

113
00:09:53,640 --> 00:09:58,570
發生八個寄存器會自動保存到堆棧中。
113

114
00:09:58,700 --> 00:10:11,280
PSR，PC，LR，R12，R3，R2，R1然後是R0。首先保存XPSR，然後保存R0
114

115
00:10:11,340 --> 00:10:12,840
最後保存。
115

116
00:10:12,840 --> 00:10:19,860
因此，我們在堆棧頂部找到了R0。 cortex M堆棧從最高內存地址增長
116

117
00:10:19,860 --> 00:10:21,060
到最低。
117

118
00:10:21,120 --> 00:10:25,040
因此，我們找到了最後一個要壓入堆棧的元素。
118

119
00:10:25,260 --> 00:10:29,270
在這種情況下，R0具有最低的存儲器地址。
119

120
00:10:29,340 --> 00:10:31,150
現在讓我們回到uVision。
120

121
00:10:31,190 --> 00:10:37,960
請記住，堆棧指針寄存器SP始終指向堆棧的頂部。
121

122
00:10:38,160 --> 00:10:42,240
因此，堆棧指針在皮質M寄存器組中進行寄存器。
122

123
00:10:42,270 --> 00:10:47,840
如果要獲取此堆棧指針寄存器的地址並轉到該內存位置。
123

124
00:10:47,910 --> 00:10:52,590
然後，我們實際上可以說出這些寄存器的所有內容。
124

125
00:10:52,590 --> 00:10:58,370
因為它存儲在堆棧中，並且堆棧指針寄存器指向堆棧的頂部。
125

126
00:10:58,380 --> 00:11:04,240
現在，我們轉到uVision，看看是否可以在內存中找到這種相似的排列。
