Report

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 44

ĐẠI HỌC QUỐC GIA THÀNH PHỐ HỒ CHÍ MINH

TRƯỜNG ĐẠI HỌC BÁCH KHOA


KHOA KHOA HỌC - KỸ THUẬT MÁY TÍNH

MÔN HỌC: VI XỬ LÝ - VI ĐIỀU KHIỂN

BÁO CÁO THÍ NGHIỆM

TỔNG HỢP

Mã môn học: CO3010


GVHD: Huỳnh Phúc Nghị
SV thực hiện: Nguyễn Thành Đạt
MSSV: 1913060
Lớp: L04

TP. HỒ CHÍ MINH, THÁNG 10/2021


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

Mục lục
1 Chapter 1: LED Animations 2
1.1 Bài tập 1: Chuyển đổi led 2 led . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 Bài tập 2: Đèn giao thông . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Bài tập 3: Ngã tư đèn giao thông . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.4 Bài tập 4: Led 7 đoạn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.5 Bài tập 5: Tổng hợp 4 bài trước . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.6 Bài tập 6, 7, 8, 9: Ma trận led . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.7 Bài tập 10: Ma trận led và đồng hồ . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

2 Chapter 2: Timer 16
2.1 Bài tập 1: Làm quen với timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.2 Bài tập 2: Làm quen với timer (tt) . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.3 Bài tập 3: Hàm update7SEG và Callback . . . . . . . . . . . . . . . . . . . . . . . 19
2.4 Bài tập 4: Thay đổi tần số bằng Callback . . . . . . . . . . . . . . . . . . . . . . . 20
2.5 Bài tập 5: Hàm updateClockBuffer . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.6 Bài tập 6: Internal Timer và trả lời câu hỏi . . . . . . . . . . . . . . . . . . . . . . 20
2.7 Bài tập 7 + 8: Đồng hồ với timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.8 Bài tập 9: Timer và ma trận led: chữ A . . . . . . . . . . . . . . . . . . . . . . . . 22
2.9 Bài tập 10: Timer và chữ A di chuyển . . . . . . . . . . . . . . . . . . . . . . . . . 25

3 Chapter 3: Button and Switches 29


3.1 Thông số kĩ thuật . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
3.2 Bài tập 1: Thiết kế máy trạng thái . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.3 Bài tập 2: Protues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.4 Bài tập 3: Tạo project và thiết lập External Timer . . . . . . . . . . . . . . . . . . 30
3.5 Bài tập 4: Internal timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.6 Bài tập 5: Chống rung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.7 Bài tập 6: Chế độ led hiển thị . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.8 Bài tập 7 + 8 + 9: Các mode 2, 3, 4 . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.9 Bài tập 10: Mode 1 và hoàn thành dự án . . . . . . . . . . . . . . . . . . . . . . . . 36

4 Chapter 4: A cooperative scheduler 38


4.1 Giải quyết vấn đề: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.1.1 void SCH_Update(void) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.1.2 void SCH_Dispatch_Tasks(void) . . . . . . . . . . . . . . . . . . . . . . . . 39
4.1.3 uint32_t SCH_Add_Task(void(*pFunction)(), uint32_t DELAY, uint32_t
PERIOD) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.1.4 uint8_t SCH_Delete_Task(uint32_t taskID)) . . . . . . . . . . . . . . . . 40
4.2 Các hàm hỗ trợ: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.2.1 void SCH_Init(void) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.2.2 void HAL_TIM_PeriodElapsedCallback ( TIM_HandleTypeDef *htim ) . 41
4.3 Các task: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.4 Demonstration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

Báo cáo thí nghiệm - Học kì 211 Trang 1


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

Link overleaf report.

Link các file hex chính.

1 Chapter 1: LED Animations

1.1 Bài tập 1: Chuyển đổi led 2 led

Câu 1: Ảnh mô phỏng Proteus

Hình 1: Schematic.

Câu 2: Biểu diễn code và máy trạng thái.

Hình 2: Máy trạng thái

Báo cáo thí nghiệm - Học kì 211 Trang 2


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

Code trong hàm while(1):


1 while (1) {
2 HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_5) ;
3 HAL_Delay ( 2 0 0 0 ) ;
4 HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_6) ;
5 }

1.2 Bài tập 2: Đèn giao thông

Câu 1: Ảnh mô phỏng Proteus

Hình 3: Schematic.

Báo cáo thí nghiệm - Học kì 211 Trang 3


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

Câu 2: Biểu diễn code và máy trạng thái.

Hình 4: Máy trạng thái

Code trong hàm while(1):


1 while (1) {
2 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 0) ;
3 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 1) ;
4 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 1) ;
5 HAL_Delay ( 5 0 0 0 ) ;
6 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 1) ;
7 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0) ;
8 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 1) ;
9 HAL_Delay ( 2 0 0 0 ) ;
10 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 1) ;
11 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 1) ;
12 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0) ;
13 HAL_Delay ( 3 0 0 0 ) ;
14 }

Báo cáo thí nghiệm - Học kì 211 Trang 4


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

1.3 Bài tập 3: Ngã tư đèn giao thông

Câu 1: Ảnh mô phỏng Proteus

Hình 5: Schematic.

Câu 2: Biểu diễn code và máy trạng thái.

Hình 6: Máy trạng thái

Báo cáo thí nghiệm - Học kì 211 Trang 5


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

Code trong hàm while(1):


1 while (1) {
2 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_1, 1 ) ; // RED
3 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_2, 1 ) ; // YELLOW
4 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_3, 0 ) ; // GREEN
5 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 0 ) ; // RED
6 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 1 ) ; // YELLOW
7 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 1 ) ; // GREEN
8 HAL_Delay ( 3 0 0 0 ) ;
9

10 HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_3) ;


11 HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_2) ;
12 HAL_Delay ( 2 0 0 0 ) ;
13

14 HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_2) ;


15 HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_1) ;
16 HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_5) ;
17 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0 ) ;
18

19 HAL_Delay ( 3 0 0 0 ) ;
20 HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_7) ;
21 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0 ) ;
22 HAL_Delay ( 2 0 0 0 ) ;
23 }

1.4 Bài tập 4: Led 7 đoạn

Câu 1: Ảnh mô phỏng Proteus

Hình 7: Schematic.

Báo cáo thí nghiệm - Học kì 211 Trang 6


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

Câu 2: Biểu diễn code và máy trạng thái.

Hình 8: Máy trạng thái

Hàm hiển thị led 7 đoạn


1 i n t NUM[ 1 0 ] [ 7 ]
2 {
3 { 0 , 0 , 0 , 0 , 0 , 0 , 1 } , // 0
4 { 1 , 0 , 0 , 1 , 1 , 1 , 1 } , // 1
5 { 0 , 0 , 1 , 0 , 0 , 1 , 0 } , // 2
6 { 0 , 0 , 0 , 0 , 1 , 1 , 0 } , // 3
7 { 1 , 0 , 0 , 1 , 1 , 0 , 0 } , // 4
8 { 0 , 1 , 0 , 0 , 1 , 0 , 0 } , // 5
9 { 0 , 1 , 0 , 0 , 0 , 0 , 0 } , // 6
10 { 0 , 0 , 0 , 1 , 1 , 1 , 1 } , // 7
11 { 0 , 0 , 0 , 0 , 0 , 0 , 0 } , // 8
12 { 0 , 0 , 0 , 0 , 1 , 0 , 0 } // 9
13 };
14 v o i d display7SEG ( i n t num) {
15 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_0, NUM[ num ] [ 0 ] ) ;
16 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_1, NUM[ num ] [ 1 ] ) ;
17 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_2, NUM[ num ] [ 2 ] ) ;
18 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_3, NUM[ num ] [ 3 ] ) ; HAL_GPIO_WritePin (GPIOB,
GPIO_PIN_4, NUM[ num ] [ 4 ] ) ;
19 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_5, NUM[ num ] [ 5 ] ) ;
20 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_6, NUM[ num ] [ 6 ] ) ;
21 }

Báo cáo thí nghiệm - Học kì 211 Trang 7


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

Trong hàm while


1 while (1) {
2 i f ( c o u n t e r >= 1 0 ) c o u n t e r = 0 ;
3 display7SEG ( c o u n t e r++) ;
4 HAL_Delay ( 1 0 0 0 ) ;
5 }

1.5 Bài tập 5: Tổng hợp 4 bài trước

Câu 1: Ảnh mô phỏng Proteus

Hình 9: Schematic.

Câu 2: Source code Hàm hỗ trợ


1 v o i d d i s p l a y ( i n t time1 , i n t time2 ) {
2 display7SEG_1 ( time1 ) ;
3 display7SEG_2 ( time2 ) ;
4 }

Hàm while
1 while (1)
2 {
3 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_1, 1 ) ; // RED
4 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_2, 1 ) ; // YELLOW
5 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_3, 0 ) ; // GREEN
6 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 0 ) ; // RED
7 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 1 ) ; // YELLOW
8 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 1 ) ; // GREEN
9

10 display (3 ,5) ;
11 HAL_Delay ( 1 0 0 0 ) ;

Báo cáo thí nghiệm - Học kì 211 Trang 8


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

12

13 display (2 ,4) ;
14 HAL_Delay ( 1 0 0 0 ) ;
15

16 display (1 ,3) ;
17 HAL_Delay ( 1 0 0 0 ) ;
18

19 HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_3) ;


20 HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_2) ;
21

22 display (2 ,2) ;
23 HAL_Delay ( 1 0 0 0 ) ;
24

25 display (1 ,1) ;
26 HAL_Delay ( 1 0 0 0 ) ;
27

28 HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_2) ;


29 HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_1) ;
30 HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_5) ;
31 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0 ) ;
32

33 display (5 ,3) ;
34 HAL_Delay ( 1 0 0 0 ) ;
35

36 display (4 ,2) ;
37 HAL_Delay ( 1 0 0 0 ) ;
38

39 display (3 ,1) ;
40 HAL_Delay ( 1 0 0 0 ) ;
41

42 HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_7) ;


43 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0 ) ;
44

45 display (2 ,2) ;
46 HAL_Delay ( 1 0 0 0 ) ;
47

48 display (1 ,1) ;
49 HAL_Delay ( 1 0 0 0 ) ;
50 }

Báo cáo thí nghiệm - Học kì 211 Trang 9


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

1.6 Bài tập 6, 7, 8, 9: Ma trận led

Câu 1: Ảnh mô phỏng Proteus

Hình 10: Schematic.

Câu 2: Hàm setNumberOnClock(int num): Nguyên lý: bật/tắt thật nhanh chân điều
khiển cột để có thể hiển thị các led đồng thời.
1 v o i d setNumberOnClock ( i n t num) {
2 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_15 , 1 ) ;
3 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_9, 1 ) ;
4 s w i t c h (num) {
5 case 0:
6 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 0 ) ;
7 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 1 ) ;
8 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0 ) ;
9 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0 ) ;
10 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 0 ) ;
11 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_10 , 0 ) ;
12 HAL_Delay ( 1 ) ;
13 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_10 , 1 ) ;
14 break ;
15 case 1:
16 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 0 ) ;
17 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 0 ) ;
18 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 1 ) ;
19 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0 ) ;
20 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 0 ) ;
21 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_10 , 0 ) ;
22 HAL_Delay ( 1 ) ;
23 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_10 , 1 ) ;
24 break ;
25 case 2:
26 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 0 ) ;
27 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 0 ) ;
28 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0 ) ;

Báo cáo thí nghiệm - Học kì 211 Trang 10


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

29 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 1 ) ;


30 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 0 ) ;
31 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_10 , 0 ) ;
32 HAL_Delay ( 1 ) ;
33 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_10 , 1 ) ;
34 break ;
35 case 3:
36 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 0 ) ;
37 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 0 ) ;
38 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0 ) ;
39 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0 ) ;
40 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 1 ) ;
41 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_11 , 0 ) ;
42 HAL_Delay ( 1 ) ;
43 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_11 , 1 ) ;
44 break ;
45 case 4:
46 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 0 ) ;
47 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 0 ) ;
48 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0 ) ;
49 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0 ) ;
50 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 1 ) ;
51 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_12 , 0 ) ;
52 HAL_Delay ( 1 ) ;
53 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_12 , 1 ) ;
54 break ;
55 case 5:
56 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 0 ) ;
57 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 0 ) ;
58 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0 ) ;
59 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0 ) ;
60 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 1 ) ;
61 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_13 , 0 ) ;
62 HAL_Delay ( 1 ) ;
63 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_13 , 1 ) ;
64 break ;
65 case 6:
66 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 0 ) ;
67 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 0 ) ;
68 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0 ) ;
69 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 1 ) ;
70 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 0 ) ;
71 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_14 , 0 ) ;
72 HAL_Delay ( 1 ) ;
73 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_14 , 1 ) ;
74 break ;
75 case 7:
76 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 0 ) ;
77 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 0 ) ;
78 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 1 ) ;
79 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0 ) ;
80 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 0 ) ;
81 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_14 , 0 ) ;
82 HAL_Delay ( 1 ) ;
83 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_14 , 1 ) ;
84 break ;

Báo cáo thí nghiệm - Học kì 211 Trang 11


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

85 case 8:
86 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 0 ) ;
87 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 1 ) ;
88 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0 ) ;
89 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0 ) ;
90 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 0 ) ;
91 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_14 , 0 ) ;
92 HAL_Delay ( 1 ) ;
93 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_14 , 1 ) ;
94 break ;
95 case 9:
96 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 1 ) ;
97 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 0 ) ;
98 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0 ) ;
99 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0 ) ;
100 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 0 ) ;
101 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_13 , 0 ) ;
102 HAL_Delay ( 1 ) ;
103 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_13 , 1 ) ;
104 break ;
105 case 10:
106 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 1 ) ;
107 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 0 ) ;
108 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0 ) ;
109 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0 ) ;
110 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 0 ) ;
111 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_12 , 0 ) ;
112 HAL_Delay ( 1 ) ;
113 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_12 , 1 ) ;
114 break ;
115 case 11:
116 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 1 ) ;
117 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 0 ) ;
118 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0 ) ;
119 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0 ) ;
120 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 0 ) ;
121 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_11 , 0 ) ;
122 HAL_Delay ( 1 ) ;
123 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_11 , 1 ) ;
124 break ;
125 }
126 }

Báo cáo thí nghiệm - Học kì 211 Trang 12


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

Câu 3: Hàm kiểm tra hiển thị checkLed.


1 v o i d check_led ( i n t c ) {
2 setNumberOnClock ( 0 ) ;
3 setNumberOnClock ( 1 ) ;
4 setNumberOnClock ( 2 ) ;
5 setNumberOnClock ( 3 ) ;
6 setNumberOnClock ( 4 ) ;
7 setNumberOnClock ( 5 ) ;
8 setNumberOnClock ( 6 ) ;
9 setNumberOnClock ( 7 ) ;
10 setNumberOnClock ( 8 ) ;
11 setNumberOnClock ( 9 ) ;
12 setNumberOnClock ( 1 0 ) ;
13 setNumberOnClock ( 1 1 ) ;
14 }

Câu 4: Hàm xóa clearAllClock()


1 void c l e a r A l l C l o c k ( ) {
2 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 0) ;
3 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_5, 0) ;
4 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0) ;
5 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0) ;
6 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 0) ;
7

8 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_9, 1 ) ;


9 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_10 , 1 ) ;
10 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_11 , 1 ) ;
11 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_12 , 1 ) ;
12 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_13 , 1 ) ;
13 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_14 , 1 ) ;
14 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_15 , 1 ) ;
15 }

Câu 5: Tổng hợp sẽ dùng các nút để điều khiển tắt sáng 12 Led đồng hồ.

Hình 11: Máy trạng thái

Báo cáo thí nghiệm - Học kì 211 Trang 13


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

Hàm xử lý nút
1 v o i d h a n d l e ( i n t num) {
2 num = num%12;
3 i f ( l e d _ f l a g [ num ] == 1 ) setNumberOnClock (num) ;
4 e l s e l e d _ f l a g [ num ] == 0 ;
5 i f (HAL_GPIO_ReadPin(GPIOB, 1 << num) == 1 && f l a g _ c l e a r == 0 ) l e d _ f l a g [ num ] = 1 ;
6 e l s e l e d _ f l a g [ num ] = 0 ;
7 }

Hàm while
1 while (1) {
2 h a n d l e ( i ++) ;
3 }

1.7 Bài tập 10: Ma trận led và đồng hồ


Câu 1: Máy trạng thái

Hình 12: Máy trạng thái

Câu 2: Code
1 v o i d c a s e _ c l o c k ( i n t time ) {
2 s w i t c h ( time ) {
3 case 11:
4 setNumberOnClock ( 0 ) ;
5 break ;
6 case 12:
7 setNumberOnClock ( 1 ) ;
8 break ;
9 default :
10 setNumberOnClock ( time +1) ;
11 break ;
12 }
13 }
14 v o i d c l o c k ( i n t hour , i n t minute , i n t s e c o n d ) {
15 clearAllClock () ;
16 c a s e _ c l o c k ( hour ) ;
17 c a s e _ c l o c k ( minute / 5 ) ;
18 case_clock ( second /5) ;
19 }

Báo cáo thí nghiệm - Học kì 211 Trang 14


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

Hàm while
1 i n t hour = 0 , min = 0 , s e c = 0 ;
2 while (1)
3 {
4 s e c ++;
5 i f ( s e c == 5 9 ) {
6 sec = 0;
7 min++;
8 }
9 i f ( min == 5 9 ) {
10 min = 0 ;
11 hour++;
12 }
13 i f ( hour == 1 2 ) {
14 hour = 0 ;
15 }
16 c l o c k ( hour , min , s e c ) ;
17 }

Báo cáo thí nghiệm - Học kì 211 Trang 15


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

2 Chapter 2: Timer

2.1 Bài tập 1: Làm quen với timer


Câu 1: Chụp lại hình mạch mô phỏng trong Proteus.

Hình 13: Schematic.

Câu 2: Biểu diễn source code trong hàm HAL_TIM_PeriodElapsedCallback.


1 int display = 100;
2 v o i d HAL_TIM_PeriodElapsedCallback ( TIM_HandleTypeDef ∗ htim ) {
3 // EX1 .
4 i f ( d i s p l a y == 1 0 0 ) {
5 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0 ) ;
6 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 1 ) ;
7 display7SEG ( 1 ) ;
8 }
9 e l s e i f ( d i s p l a y == 5 0 ) {
10 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 1 ) ;
11 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0 ) ;
12 display7SEG ( 2 ) ;
13 }
14 d i s p l a y −−;
15 i f ( d i s p l a y <= 0 ) {
16 display = 100;
17 }
18 }

Câu hỏi nhỏ: Tần số quét là

• Của timer là 100Hz

• Của mỗi LED là 1Hz

Báo cáo thí nghiệm - Học kì 211 Trang 16


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

Hình 14: Máy trạng thái

2.2 Bài tập 2: Làm quen với timer (tt)


Câu 1: Chụp lại hình mạch mô phỏng trong Proteus.

Hình 15: Schematic.

Báo cáo thí nghiệm - Học kì 211 Trang 17


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

Câu 2: Biểu diễn source code trong hàm HAL_TIM_PeriodElapsedCallback.


1 int display = 200;
2 int counter = 100;
3 v o i d HAL_TIM_PeriodElapsedCallback ( TIM_HandleTypeDef ∗ htim ) {
4 c o u n t e r −−;
5 i f ( c o u n t e r <= 0 ) {
6 counter = 100;
7 HAL_GPIO_TogglePin ( GPIOA, GPIO_PIN_5) ;
8 HAL_GPIO_TogglePin ( GPIOA, GPIO_PIN_4) ;
9 }
10 i f ( c o u n t e r == 9 0 ) {
11 HAL_GPIO_TogglePin ( GPIOA, GPIO_PIN_4) ;
12 }
13 // EX2 .
14 i f ( d i s p l a y == 2 0 0 ) {
15 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0 ) ;
16 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 1 ) ;
17 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 1 ) ;
18 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_9, 1 ) ;
19 display7SEG ( 1 ) ;
20 }
21 e l s e i f ( d i s p l a y == 1 5 0 ) {
22 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 1 ) ;
23 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0 ) ;
24 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 1 ) ;
25 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_9, 1 ) ;
26 display7SEG ( 2 ) ;
27 }
28 e l s e i f ( d i s p l a y == 1 0 0 ) {
29 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 1 ) ;
30 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 1 ) ;
31 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 0 ) ;
32 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_9, 1 ) ;
33 display7SEG ( 3 ) ;
34 }
35 e l s e i f ( d i s p l a y == 5 0 ) {
36 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 1 ) ;
37 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 1 ) ;
38 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 1 ) ;
39 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_9, 0 ) ;
40 display7SEG ( 0 ) ;
41 }
42 d i s p l a y −−;
43 i f ( d i s p l a y <= 0 ) {
44 display = 200;
45 }
46 }

Câu hỏi nhỏ: Tần số quét là

• Của timer là 100Hz

• Của mỗi LED là 0.5Hz

Báo cáo thí nghiệm - Học kì 211 Trang 18


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

2.3 Bài tập 3: Hàm update7SEG và Callback


Câu 1: Biểu diễn source code trong hàm update7SEG.
1 c o n s t i n t MAX_LED = 4 ;
2 i n t index_led = 0 ;
3 i n t led_buffer [ 4 ] = {0 , 0 , 0 , 0};
4 v o i d update7SEG ( i n t i n d e x ) {
5 i n d e x = i n d e x %4;
6 switch ( index ) {
7 case 0:
8 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 0) ;
9 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 1) ;
10 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 1) ;
11 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_9, 1) ;
12 break ;
13 case 1:
14 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 1) ;
15 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 0) ;
16 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 1) ;
17 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_9, 1) ;
18 break ;
19 case 2:
20 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 1) ;
21 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 1) ;
22 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 0) ;
23 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_9, 1) ;
24 break ;
25 case 3:
26 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, 1) ;
27 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_7, 1) ;
28 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 1) ;
29 HAL_GPIO_WritePin (GPIOA, GPIO_PIN_9, 0) ;
30 break ;
31 default :
32 break ;
33 }
34 display7SEG ( l e d _ b u f f e r [ i n d e x ] ) ;
35 }

Câu 2: Biểu diễn source code trong hàm HAL_TIM_PeriodElapsedCallback.


1 int display = 100;
2 int counter = 50;
3 v o i d HAL_TIM_PeriodElapsedCallback ( TIM_HandleTypeDef ∗ htim ) {
4 c o u n t e r −−;
5 i f ( c o u n t e r <= 0 ) {
6 counter = 100;
7 HAL_GPIO_TogglePin ( GPIOA, GPIO_PIN_5) ;
8 HAL_GPIO_TogglePin ( GPIOA, GPIO_PIN_4) ;
9 }
10 i f ( c o u n t e r == 9 0 ) {
11 HAL_GPIO_TogglePin ( GPIOA, GPIO_PIN_4) ;
12 }
13 d i s p l a y −−;
14 i f ( d i s p l a y <= 0 ) {
15 update7SEG ( i n d e x _ l e d++) ;

Báo cáo thí nghiệm - Học kì 211 Trang 19


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

16 display = 50;
17 }
18 }

2.4 Bài tập 4: Thay đổi tần số bằng Callback


Câu 1: Biểu diễn source code trong hàm HAL_TIM_PeriodElapsedCallback.
1 int display = 100;
2 int counter = 25;
3 v o i d HAL_TIM_PeriodElapsedCallback ( TIM_HandleTypeDef ∗ htim ) {
4 c o u n t e r −−;
5 i f ( c o u n t e r <= 0 ) {
6 counter = 100;
7 HAL_GPIO_TogglePin ( GPIOA, GPIO_PIN_5) ;
8 HAL_GPIO_TogglePin ( GPIOA, GPIO_PIN_4) ;
9 }
10 i f ( c o u n t e r == 9 0 ) {
11 HAL_GPIO_TogglePin ( GPIOA, GPIO_PIN_4) ;
12 }
13 d i s p l a y −−;
14 i f ( d i s p l a y <= 0 ) {
15 update7SEG ( i n d e x _ l e d++) ;
16 display = 25;
17 }
18 }

2.5 Bài tập 5: Hàm updateClockBuffer


Câu 1: Biểu diễn source code trong hàm updateClockBuffer.
1 void updateClockBuffer ( ) {
2 l e d _ b u f f e r [ 0 ] = hour / 1 0 ;
3 l e d _ b u f f e r [ 1 ] = hour %10;
4 l e d _ b u f f e r [ 2 ] = minute / 1 0 ;
5 l e d _ b u f f e r [ 3 ] = minute %10;
6 }

2.6 Bài tập 6: Internal Timer và trả lời câu hỏi


Câu 1: Điều gì xảy ra khi xóa "setTimer0(1000)": Led sẽ không sáng vì cờ "timer0_flag"
sẽ luôn bằng 0.

Câu 2: Điều gì xảy ra khi đổi "setTimer0(1000)" thành "setTimer0(1)": Led sẽ không
sáng vì lúc này "timer0_counter" sẽ luôn bằng 0 do đó (timer0_counter > 0) sẽ trả về
false nên "timer0_flag" sẽ luôn bằng 0.

Câu 3: Điều gì xảy ra khi đổi "setTimer0(1000)" thành "setTimer0(10)": Đèn sẽ sáng
vì "timer0_counter" bằng 1 nên "timer0_flag" sẽ được set bằng 1.

Báo cáo thí nghiệm - Học kì 211 Trang 20


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

2.7 Bài tập 7 + 8: Đồng hồ với timer

Ý tưởng cơ bản

• Khi cờ của timer0 được set sau mỗi 1s thì second sẽ được tăng thêm 1. Code sẽ giải quyết
việc chuyển đổi minute và hour

• Khi cờ của timer1 được set sau mỗi 250ms thì sẽ có đèn sáng ở vị trí được sáng theo thứ tự.

Máy trạng thái:

Hình 16: FSM chuyển led

Hình 17: FSM đếm giờ

Câu 1: Biểu diễn source code trong hàm main và các hàm thành phần.
Hàm main
1 i n t main ( v o i d )
2 {
3 HAL_Init ( ) ;
4 SystemClock_Config ( ) ;
5 MX_GPIO_Init ( ) ;
6 MX_TIM2_Init ( ) ;

Báo cáo thí nghiệm - Học kì 211 Trang 21


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

7 HAL_TIM_Base_Start_IT (& htim2 ) ;


8 setTimer0 (10) ;
9 setTimer1 (10) ;
10 while (1)
11 {
12 i f ( t i m e r 0 _ f l a g == 1 ) {
13 s e c o n d++;
14 HAL_GPIO_TogglePin ( GPIOA, GPIO_PIN_4) ;
15 setTimer0 (1000) ;
16 }
17 i f ( t i m e r 1 _ f l a g ==1){
18 update7SEG ( i n d e x _ l e d++) ;
19 setTimer1 (250) ;
20 }
21 i f ( s e c o n d >= 6 0 ) {
22 second = 0 ;
23 minute++;
24 }
25 i f ( minute >= 6 0 ) {
26 minute = 0 ;
27 hour++;
28 }
29 i f ( hour >= 2 4 ) {
30 hour = 0 ;
31 }
32 updateClockBuffer () ;
33 }
34 }

Hàm setTimer1 và điều chỉnh hàm timer_run


1 void setTimer1 ( i n t duration ) {
2 t i m e r 1 _ c o u n t e r = d u r a t i o n /TIMER_CYCLE;
3 timer1_flag = 0;
4 }
5 v o i d timer_run ( ) {
6 i f ( timer0_counter > 0) {
7 t i m e r 0 _ c o u n t e r −−;
8 i f ( t i m e r 0 _ c o u n t e r == 0 ) t i m e r 0 _ f l a g = 1 ;
9 }
10 i f ( timer1_counter > 0) {
11 t i m e r 1 _ c o u n t e r −−;
12 i f ( t i m e r 1 _ c o u n t e r == 0 ) t i m e r 1 _ f l a g = 1 ;
13 }
14 }

2.8 Bài tập 9: Timer và ma trận led: chữ A

Ý tưởng: matrix_buffer[8] sẽ chứa giá trị Led sáng theo từng hàng từ 1 tới 8. Led từng
hàng sáng cùng lúc khi thời gian chuyển giữa các chân điều khiển theo hàng ngắn thì sẽ nhìn như
chúng đang sáng cùng lúc.

Báo cáo thí nghiệm - Học kì 211 Trang 22


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

Hình 18: FSM chuyển Led từng hàng trong khoảng thời gian ngắn

Câu hỏi 1: Chụp lại màn hình mô phỏng trong Protues.

Hình 19: Schematic.

Câu hỏi 2: Biểu diễn source code trong hàm updateLEDMatrix(int index)
1 c o n s t i n t MAX_LED_MATRIX = 8 ;
2 i n t index_led_matrix = 0 ;
3 u i n t 8 _ t m a t r i x _ b u f f e r [ 8 ] = {0 x11 , 0 x11 , 0 x11 , 0 x11 , 0 x11 , 0 x11 , 0 x11 , 0 x11 } ;
4 u i n t 8 _ t m a t r i x _ s o u r c e [ 8 ] = {0 x18 , 0 x3c , 0 x66 , 0 x66 , 0 x7e , 0 x7e , 0 x66 , 0 x66 } ;
5 v o i d updateLEDMatrix ( i n t i n d e x ) {
6 i n d e x = i n d e x %8;
7 GPIOA−>ODR = ~m a t r i x _ s o u r c e [ i n d e x ] ;

Báo cáo thí nghiệm - Học kì 211 Trang 23


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

8 switch ( index ) {
9 case 0:
10 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_0, 0 ) ;
11 HAL_Delay ( 1 ) ;
12 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_0, 1 ) ;
13 break ;
14 case 1:
15 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_1, 0 ) ;
16 HAL_Delay ( 1 ) ;
17 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_1, 1 ) ;
18 break ;
19 case 2:
20 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_2, 0 ) ;
21 HAL_Delay ( 1 ) ;
22 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_2, 1 ) ;
23 break ;
24 case 3:
25 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_3, 0 ) ;
26 HAL_Delay ( 1 ) ;
27 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_3, 1 ) ;
28 break ;
29 case 4:
30 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_4, 0 ) ;
31 HAL_Delay ( 1 ) ;
32 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_4, 1 ) ;
33 break ;
34 case 5:
35 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_5, 0 ) ;
36 HAL_Delay ( 1 ) ;
37 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_5, 1 ) ;
38 break ;
39 case 6:
40 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_6, 0 ) ;
41 HAL_Delay ( 1 ) ;
42 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_6, 1 ) ;
43 break ;
44 case 7:
45 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_7, 0 ) ;
46 HAL_Delay ( 1 ) ;
47 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_7, 1 ) ;
48 break ;
49 default :
50 break ;
51 }
52 }

Báo cáo thí nghiệm - Học kì 211 Trang 24


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

2.9 Bài tập 10: Timer và chữ A di chuyển

Ý tưởng: Sau khi hiện thực hàm hiện LED updateLEDMatrix(int index), giờ ta thiết kế
máy trạng thái để chữ A chạy từ trái sang phải vì LED có 8 cột và chữ A được biểu diễn có chiều
ngang là 6 bit nên sẽ dung máy trạng thái có 14 trạng thái để biểu diễn.

Hình 20: FSM chuyển trạng thái từ trái sang phải

Câu hỏi: Source code


1 i n t timer0_counter = 0 ;
2 int timer0_flag = 0;
3 i n t TIMER_CYCLE = 1 ;
4 void setTimer0 ( i n t duration ) {
5 t i m e r 0 _ c o u n t e r = d u r a t i o n /TIMER_CYCLE;
6 timer0_flag = 0;
7 }
8 v o i d timer_run ( ) {
9 i f ( timer0_counter > 0) {
10 t i m e r 0 _ c o u n t e r −−;
11 i f ( t i m e r 0 _ c o u n t e r == 0 ) t i m e r 0 _ f l a g = 1 ;
12 }
13 }
14 c o n s t i n t MAX_LED_MATRIX = 8 ;
15 i n t index_led_matrix = 0 ;
16 u i n t 8 _ t m a t r i x _ b u f f e r [ 8 ] = {0 x11 , 0 x11 , 0 x11 , 0 x11 , 0 x11 , 0 x11 , 0 x11 , 0 x11 } ;
17 u i n t 8 _ t m a t r i x _ s o u r c e [ 8 ] = {0 x18 , 0 x3c , 0 x66 , 0 x66 , 0 x7e , 0 x7e , 0 x66 , 0 x66 } ;
18 void s e t b u f f e r ( i n t n) {
19 n = 13−n%13;
20 switch (n) {

Báo cáo thí nghiệm - Học kì 211 Trang 25


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

21 case 0:
22 for ( int i = 0 ; i < 8 ; i ++) m a t r i x _ b u f f e r [ i ] = ( m a t r i x _ s o u r c e [ i ] >> 7 ) ;
23 break ;
24 case 1:
25 for ( int i = 0 ; i < 8 ; i ++) m a t r i x _ b u f f e r [ i ] = ( m a t r i x _ s o u r c e [ i ] >> 6 ) ;
26 break ;
27 case 2:
28 for ( int i = 0 ; i < 8 ; i ++) m a t r i x _ b u f f e r [ i ] = ( m a t r i x _ s o u r c e [ i ] >> 5 ) ;
29 break ;
30 case 3:
31 for ( int i = 0 ; i < 8 ; i ++) m a t r i x _ b u f f e r [ i ] = ( m a t r i x _ s o u r c e [ i ] >> 4 ) ;
32 break ;
33 case 4:
34 for ( int i = 0 ; i < 8 ; i ++) m a t r i x _ b u f f e r [ i ] = ( m a t r i x _ s o u r c e [ i ] >> 3 ) ;
35 break ;
36 case 5:
37 for ( int i = 0 ; i < 8 ; i ++) m a t r i x _ b u f f e r [ i ] = ( m a t r i x _ s o u r c e [ i ] >> 2 ) ;
38 break ;
39 case 6:
40 for ( int i = 0 ; i < 8 ; i ++) m a t r i x _ b u f f e r [ i ] = ( m a t r i x _ s o u r c e [ i ] >> 1 ) ;
41 break ;
42 case 7:
43 for ( int i = 0 ; i < 8 ; i ++) m a t r i x _ b u f f e r [ i ] = m a t r i x _ s o u r c e [ i ] ;
44 break ;
45 case 8:
46 for ( int i = 0 ; i < 8 ; i ++) m a t r i x _ b u f f e r [ i ] = ( m a t r i x _ s o u r c e [ i ] << 1 ) ;
47 break ;
48 case 9:
49 for ( int i = 0 ; i < 8 ; i ++) m a t r i x _ b u f f e r [ i ] = ( m a t r i x _ s o u r c e [ i ] << 2 ) ;
50 break ;
51 case 10:
52 for ( int i = 0 ; i < 8 ; i ++) m a t r i x _ b u f f e r [ i ] = ( m a t r i x _ s o u r c e [ i ] << 3 ) ;
53 break ;
54 case 11:
55 for ( int i = 0 ; i < 8 ; i ++) m a t r i x _ b u f f e r [ i ] = ( m a t r i x _ s o u r c e [ i ] << 4 ) ;
56 break ;
57 case 12:
58 for ( int i = 0 ; i < 8 ; i ++) m a t r i x _ b u f f e r [ i ] = ( m a t r i x _ s o u r c e [ i ] << 5 ) ;
59 break ;
60 case 13:
61 for ( int i = 0 ; i < 8 ; i ++) m a t r i x _ b u f f e r [ i ] = ( m a t r i x _ s o u r c e [ i ] << 6 ) ;
62 break ;
63 default :
64 break ;
65 }
66 }
67 v o i d updateLEDMatrix ( i n t i n d e x ) {
68 i n d e x = i n d e x %8;
69 GPIOA−>ODR = ~ m a t r i x _ b u f f e r [ i n d e x ] ;
70 switch ( index ) {
71 case 0:
72 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_0, 0 ) ;
73 HAL_Delay ( 1 ) ;
74 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_0, 1 ) ;
75 break ;
76 case 1:

Báo cáo thí nghiệm - Học kì 211 Trang 26


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

77 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_1, 0 ) ;


78 HAL_Delay ( 1 ) ;
79 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_1, 1 ) ;
80 break ;
81 case 2:
82 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_2, 0 ) ;
83 HAL_Delay ( 1 ) ;
84 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_2, 1 ) ;
85 break ;
86 case 3:
87 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_3, 0 ) ;
88 HAL_Delay ( 1 ) ;
89 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_3, 1 ) ;
90 break ;
91 case 4:
92 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_4, 0 ) ;
93 HAL_Delay ( 1 ) ;
94 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_4, 1 ) ;
95 break ;
96 case 5:
97 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_5, 0 ) ;
98 HAL_Delay ( 1 ) ;
99 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_5, 1 ) ;
100 break ;
101 case 6:
102 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_6, 0 ) ;
103 HAL_Delay ( 1 ) ;
104 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_6, 1 ) ;
105 break ;
106 case 7:
107 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_7, 0 ) ;
108 HAL_Delay ( 1 ) ;
109 HAL_GPIO_WritePin (GPIOB, GPIO_PIN_7, 1 ) ;
110 break ;
111 default :
112 break ;
113 }
114 }
115 i n t main ( v o i d )
116 {
117 HAL_Init ( ) ;
118 SystemClock_Config ( ) ;
119 MX_GPIO_Init ( ) ;
120 MX_TIM2_Init ( ) ;
121

122 HAL_TIM_Base_Start_IT (& htim2 ) ;


123

124 setTimer0 ( 1 ) ;
125 i n t led_run = 0 ;
126

127 while (1)


128 {
129 updateLEDMatrix ( index_led_matrix++) ;
130 i f ( t i m e r 0 _ f l a g == 1 ) {
131 s e t b u f f e r ( led_run++) ;
132 setTimer0 (250) ;

Báo cáo thí nghiệm - Học kì 211 Trang 27


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

133 }
134 }
135 }

Báo cáo thí nghiệm - Học kì 211 Trang 28


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

3 Chapter 3: Button and Switches


Bài tập và báo cáo. Đây là Video demo lab 3

3.1 Thông số kĩ thuật


Bạn được yêu cầu xây dựng một ứng dụng đèn giao thông trên ngã tư, bao gồm một số tính
năng như được mô tả bên dưới:

• Ứng dụng có 12 đèn LED bao gồm 4 đèn LED đỏ, 4 đèn LED màu vàng, 4 đèn LED xanh .

• Ứng dụng có 4 đèn LED bảy đoạn để hiển thị thời gian với 2 đèn cho mỗi con đường. Có 2
LED bảy đoạn sẽ hiển thị thời gian cho từng LED màu tương ứng với từng đường.

• Ứng dụng có ba nút được sử dụng

– để chọn các chế độ

– để sửa đổi thời gian cho từng đèn led màu một cách nhanh chóng

– để đặt giá trị đã chọn.

• Ứng dụng có ít nhất 4 chế độ được điều khiển bằng nút đầu tiên. Chế độ 1 là chế độ bình
thường, trong khi chế độ 2 3 4 là chế độ sửa đổi. Bạn có thể nhấn nút đầu tiên để thay đổi
chế độ. Các chế độ sẽ thay đổi từ 1 thành 4 và trở lại 1 lần nữa.

Chế độ 1 - Chế độ bình thường:


- Ứng dụng đèn giao thông đang chạy bình thường.
Chế độ 2 - Sửa đổi khoảng thời gian cho đèn LED đỏ: Chế độ này cho phép bạn thay đổi
khoảng thời gian của đèn LED màu đỏ trên đường chính. Các hành vi mong đợi của điều này chế
độ bao gồm:

• Tất cả các đèn LED đơn màu đỏ đang nhấp nháy ở tần số 2 Hz.

• Sử dụng hai đèn LED bảy đoạn để hiển thị giá trị.

• Sử dụng hai đèn LED bảy đoạn còn lại để hiển thị chế độ.

• Nút thứ hai được sử dụng để tăng giá trị thời lượng cho các đèn LED màu đỏ.

• Giá trị của khoảng thời gian nằm trong khoảng 1 - 99.

• Nút thứ ba dùng để đặt giá trị.

Chế độ 3 - Sửa đổi khoảng thời gian đối với đèn LED màu vàng: Tương tự đối với đèn
LED màu đỏ được mô tả ở trên với đèn LED màu hổ phách.
Chế độ 4 - Sửa đổi khoảng thời gian cho các đèn LED màu xanh: Tương tự cho các đèn
LED màu đỏ được mô tả ở trên với các đèn LED màu xanh lá cây.

Báo cáo thí nghiệm - Học kì 211 Trang 29


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

3.2 Bài tập 1: Thiết kế máy trạng thái


Thiết kế máy trạng thái để miêu tả ý tưởng giải quyết bài toán này.

Hình 21: Máy trạng thái

3.3 Bài tập 2: Protues


Mô phỏng Proteus của bài toán này.

Hình 22: Schematic.

3.4 Bài tập 3: Tạo project và thiết lập External Timer


Tạo project và thiết kế timer interupt khoảng 10m, Code được generate sau khi cấu hình
timer.

Báo cáo thí nghiệm - Học kì 211 Trang 30


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

Hình 23: Cấu hình trong file .ioc

1 s t a t i c v o i d MX_TIM2_Init ( v o i d )
2 {
3

4 /∗ USER CODE BEGIN TIM2_Init 0 ∗/


5

6 /∗ USER CODE END TIM2_Init 0 ∗/


7

8 TIM_ClockConfigTypeDef s C l o c k S o u r c e C o n f i g = { 0 } ;
9 TIM_MasterConfigTypeDef s M a s t e r C o n f i g = { 0 } ;
10

11 /∗ USER CODE BEGIN TIM2_Init 1 ∗/


12

13 /∗ USER CODE END TIM2_Init 1 ∗/


14 htim2 . I n s t a n c e = TIM2 ;
15 htim2 . I n i t . P r e s c a l e r = 7 9 9 9 ;
16 htim2 . I n i t . CounterMode = TIM_COUNTERMODE_UP;
17 htim2 . I n i t . P e r i o d = 9 ;
18 htim2 . I n i t . C l o c k D i v i s i o n = TIM_CLOCKDIVISION_DIV1 ;
19 htim2 . I n i t . AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
20 i f ( HAL_TIM_Base_Init(&htim2 ) != HAL_OK)
21 {
22 Error_Handler ( ) ;
23 }
24 s C l o c k S o u r c e C o n f i g . C l o c k S o u r c e = TIM_CLOCKSOURCE_INTERNAL;
25 i f ( HAL_TIM_ConfigClockSource(&htim2 , &s C l o c k S o u r c e C o n f i g ) != HAL_OK)
26 {
27 Error_Handler ( ) ;
28 }
29 s M a s t e r C o n f i g . M a s t e r O u t p u t T r i g g e r = TIM_TRGO_RESET;
30 s M a s t e r C o n f i g . MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
31 i f ( HAL_TIMEx_MasterConfigSynchronization(&htim2 , &s M a s t e r C o n f i g ) != HAL_OK)
32 {
33 Error_Handler ( ) ;

Báo cáo thí nghiệm - Học kì 211 Trang 31


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

34 }
35 /∗ USER CODE BEGIN TIM2_Init 2 ∗/
36

37 /∗ USER CODE END TIM2_Init 2 ∗/


38

39 }

3.5 Bài tập 4: Internal timer


Cài đặt bộ hẹn giờ để sử dụng timer interupt đã cấu hình mà không ảnh hưởng tới các tác
vụ cùng dùng chung timer.
Ý tưởng: Viết hàm setTimer0() dùng để đặt thời gian để điều khiển cờ khi, cờ được bật nó sẽ
đóng vai trò như một kích mức (giống timer) để điều khiển tác vụ đó. Và hàm timer_run() sẽ
được gọi mỗi khi bị interupt bởi timer đã cấu hình.
Code các hàm đã đề cập:
1 int timer0_flag = 0;
2 i n t timer0_counter = 0 ;
3

4 void setTimer0 ( i n t duration ) {


5 t i m e r 0 _ c o u n t e r = d u r a t i o n /TIMER_CYCLE;
6 timer0_flag = 0;
7 }
8 v o i d timer_run ( ) {
9 i f ( timer0_counter > 0) {
10 t i m e r 0 _ c o u n t e r −−;
11 i f ( t i m e r 0 _ c o u n t e r == 0 ) t i m e r 0 _ f l a g = 1 ;
12 }
13 }
14 v o i d HAL_TIM_PeriodElapsedCallback ( TIM_HandleTypeDef ∗ htim ) {
15 i f ( htim −> I n s t a n c e == TIM2 ) {
16 // b u t t o n _ r e a d i n g ( ) ;
17 timer_run ( ) ;
18 }
19 }

3.6 Bài tập 5: Chống rung


Code đọc dữ liệu nút nhấn và chống rung.
1 #i n c l u d e " main . h"
2

3 #d e f i n e NO_OF_BUTTONS 3
4

6 #d e f i n e DURATION_FOR_AUTO_INCREASING 100
7 #d e f i n e BUTTON_IS_PRESSED GPIO_PIN_RESET
8 #d e f i n e BUTTON_IS_RELEASED GPIO_PIN_SET
9

10

11 s t a t i c GPIO_PinState b u t t o n B u f f e r [NO_OF_BUTTONS] ;
12

13 s t a t i c GPIO_PinState d e b o u n c e B u t t o n B u f f e r 1 [NO_OF_BUTTONS ] ;

Báo cáo thí nghiệm - Học kì 211 Trang 32


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

14 s t a t i c GPIO_PinState d e b o u n c e B u t t o n B u f f e r 2 [NO_OF_BUTTONS ] ;
15

16 s t a t i c uint8_t f l a g F o r B u t t o n P r e s s 1 s [NO_OF_BUTTONS] ;
17

18

19 s t a t i c u i n t 1 6 _ t c o u n t e r F o r B u t t o n P r e s s 1 s [NO_OF_BUTTONS ] ;
20 void button_reading ( void ) {
21 f o r ( c h a r i = 0 ; i < NO_OF_BUTTONS; i ++){
22 debounceButtonBuffer2 [ i ] = debounceButtonBuffer1 [ i ] ;
23 d e b o u n c e B u t t o n B u f f e r 1 [ i ] = HAL_GPIO_ReadPin(GPIOA, ( 1 << (8+ i ) ) ) ;
24 \\3 b u t t o n s a s s i g n f o r p i n 8 , 9 , 10
25 i f ( d e b o u n c e B u t t o n B u f f e r 1 [ i ] == d e b o u n c e B u t t o n B u f f e r 2 [ i ] )
26 buttonBuffer [ i ] = debounceButtonBuffer1 [ i ] ;
27 i f ( b u t t o n B u f f e r [ i ] == BUTTON_IS_PRESSED) {
28 i f ( c o u n t e r F o r B u t t o n P r e s s 1 s [ i ] < DURATION_FOR_AUTO_INCREASING) {
29 c o u n t e r F o r B u t t o n P r e s s 1 s [ i ]++;
30 }
31 else {
32 flagForButtonPress1s [ i ] = 1;
33 }
34 }
35 else {
36 counterForButtonPress1s [ i ] = 0;
37 flagForButtonPress1s [ i ] = 0;
38 }
39 }
40 }
41 unsigned char is_button_pressed ( uint8_t index ) {
42 i f ( i n d e x >= NO_OF_BUTTONS) r e t u r n 0 ;
43 r e t u r n ( b u t t o n B u f f e r [ i n d e x ] == BUTTON_IS_PRESSED) ;
44 }
45

46 unsigned char is_button_pressed_1s ( unsigned char index ) {


47 i f ( i n d e x >= NO_OF_BUTTONS) r e t u r n 0 x f f ;
48 r e t u r n ( f l a g F o r B u t t o n P r e s s 1 s [ i n d e x ] == 1 ) ;
49 }

Code thay đổi Chế độ mỗi lần nhấn nút thứ nhất.
1 enum B u t t o n S t a t e {BUTTON_RELEASED, BUTTON_PRESSED,
BUTTON_PRESSED_MORE_THAN_1_SECOND} ;
2 enum B u t t o n S t a t e b u t t o n S t a t e = BUTTON_RELEASED;
3

4 void fsm_for_input_processing ( void ) {


5 switch ( buttonState ) {
6 c a s e BUTTON_RELEASED:
7 i f ( is_button_pressed (0) ) {
8 b u t t o n S t a t e = BUTTON_PRESSED;
9 mode = ( mode+1)%4;
10 // i f ( mode != 0 ) s e t L e d b u f f e r ( l e d _ l i g h t _ t i m e [ mode − 1 ] , mode ) ;
11 }
12 break ;
13 c a s e BUTTON_PRESSED:
14 i f ( ! is_button_pressed (0) ) {
15 b u t t o n S t a t e = BUTTON_RELEASED;
16 }

Báo cáo thí nghiệm - Học kì 211 Trang 33


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

17 else {
18 i f ( is_button_pressed_1s ( 0 ) ) {
19 b u t t o n S t a t e = BUTTON_PRESSED_MORE_THAN_1_SECOND;
20 }
21 }
22 break ;
23 c a s e BUTTON_PRESSED_MORE_THAN_1_SECOND:
24 i f ( ! is_button_pressed (0) ) {
25 b u t t o n S t a t e = BUTTON_RELEASED;
26 }
27 // TODO
28 break ;
29 }
30 }

3.7 Bài tập 6: Chế độ led hiển thị


Code để hiện thị chế độ trên led 7 đoạn và để nhấp nháy đèn theo mode.
1 i f ( t i m e r 1 _ f l a g == 1 ) {
2 // t h i s i f f u n c t i o n w i l l a l w a y s c a l l f o r d i s p l a y 7 s e g
3 i n d e x = i n d e x %4;
4 update7SEG_1 ( i n d e x ) ;
5 i n d e x ++;
6 setTimer1 ( 5 ) ;
7 }
8 i f ( t i m e r 0 _ f l a g == 1 ) {
9 HAL_GPIO_TogglePin (GPIOA, 1<<mode | 1<<(mode+3) ;
10 // l e d a s s i g n f o r p i n 1 , 2 , 3 and 4 , 5 , 6 ( red , amber , g r e e n )
11 setTimer0 (250) ;
12 }

Báo cáo thí nghiệm - Học kì 211 Trang 34


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

3.8 Bài tập 7 + 8 + 9: Các mode 2, 3, 4


Code cho Mode 2, 3, 4 (vì ý tưởng là giống nhau nên chỉ thêm code mode 2)

Hình 24: Máy trạng thái cho các Mode 2, 3, 4

Code cho Mode 2:


1 #i n c l u d e " main . h"
2 #i n c l u d e " d i s p l a y . h"
3

4 enum B u t t o n S t a t e {BUTTON_RELEASED, BUTTON_PRESSED,


BUTTON_PRESSED_MORE_THAN_1_SECOND} ;
5 enum B u t t o n S t a t e b u t t o n S t a t e 1 = BUTTON_RELEASED;
6 // i n t i n d e x = 0 ;
7 i n t led_light_red_new = 0 ;
8 v o i d mode1 ( ) {
9 i f ( t i m e r 1 _ f l a g == 1 ) {
10 i n d e x = i n d e x %4;
11 update7SEG_1 ( i n d e x ) ;
12 i n d e x ++;
13 setTimer1 ( 5 ) ;
14 }
15 i f ( t i m e r 0 _ f l a g == 1 ) {
16 HAL_GPIO_TogglePin (GPIOA, 1<<1 | 1<<4) ;
17 setTimer0 (250) ;
18 }
19 switch ( buttonState1 ) {
20 c a s e BUTTON_RELEASED:
21 i f ( is_button_pressed (1) ) {
22 b u t t o n S t a t e 1 = BUTTON_PRESSED;
23 led_light_red_new++;
24 s e t L e d b u f f e r ( led_light_red_new , 1 ) ;
25 }
26 break ;
27 c a s e BUTTON_PRESSED:
28 i f ( ! is_button_pressed (1) ) {
29 b u t t o n S t a t e 1 = BUTTON_RELEASED;
30 }
31 else {
32 i f ( is_button_pressed_1s ( 1 ) ) {

Báo cáo thí nghiệm - Học kì 211 Trang 35


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

33 b u t t o n S t a t e 1 = BUTTON_PRESSED_MORE_THAN_1_SECOND;
34 }
35 }
36 break ;
37 c a s e BUTTON_PRESSED_MORE_THAN_1_SECOND:
38 i f ( ! is_button_pressed (1) ) {
39 b u t t o n S t a t e 1 = BUTTON_RELEASED;
40 }
41 // TODO
42 i f ( t i m e r 2 _ f l a g == 1 ) {
43 led_light_red_new = led_light_red_new +5;
44 s e t L e d b u f f e r ( led_light_red_new , 1 ) ;
45 setTimer2 (1000) ;
46 }
47 break ;
48 }
49 i f ( is_button_pressed (2) ) {
50 // b u t t o n S t a t e 1 = BUTTON_PRESSED;
51 l e d _ l i g h t _ t i m e [ 0 ] = led_light_red_new ;
52 led_light_time [ 2 ] = led_light_time [ 0 ] − led_light_time [ 1 ] ;
53 // s e t L e d b u f f e r ( led_light_red_new , 1 ) ;
54 }
55 }

3.9 Bài tập 10: Mode 1 và hoàn thành dự án


Code cho Mode 1

Hình 25: Máy trạng thái cho Mode 1

1 v o i d mode0 ( ) {
2 i f ( t i m e r 0 _ f l a g == 1 ) {
3 i n d e x = i n d e x %4;
4 update7SEG_1 ( i n d e x ) ;
5 // update7SEG_2 ( i n d e x ) ;
6 i n d e x ++;
7 setTimer0 ( 3 ) ;
8 }
9

10 i f ( t i m e r 1 _ f l a g ==1){
11 switch ( t r a f f i c 1 ) {

Báo cáo thí nghiệm - Học kì 211 Trang 36


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

12 case red :
13 i f ( count_less < led_light_time [ 2 ] ) {
14 t u r n _ l ed _ l i g h t _ 1 (OFF, OFF, ON) ;
15 t u r n _ l ed _ l i g h t _ 2 (ON, OFF, OFF) ;
16 s e t L e d b u f f e r ( led_light_time [ 0 ] − count_less , led_light_time [2] − count_less
);
17 }
18 else {
19 t u r n _ l ed _ l i g h t _ 1 (OFF, ON, OFF) ;
20 t u r n _ l ed _ l i g h t _ 2 (ON, OFF, OFF) ;
21 s e t L e d b u f f e r ( led_light_time [ 0 ] − count_less , led_light_time [0] − count_less
);
22 }
23 c o u n t _ l e s s ++;
24 i f ( c o u n t _ l e s s >= l e d _ l i g h t _ t i m e [ 0 ] ) { t r a f f i c 1 = g r e e n ; c o u n t _ l e s s = 0 ; }
25 break ;
26 case green :
27 t u r n _ l e d _l i g h t _ 1 (ON, OFF, OFF) ;
28 t u r n _ l e d _l i g h t _ 2 (OFF, OFF, ON) ;
29 s e t L e d b u f f e r ( led_light_time [ 2 ] − count_less , led_light_time [ 0 ] − count_less
);
30 c o u n t _ l e s s ++;
31 i f ( c o u n t _ l e s s >= l e d _ l i g h t _ t i m e [ 2 ] ) { t r a f f i c 1 = amber ; c o u n t _ l e s s = 0 ; }
32 break ;
33 c a s e amber :
34 t u r n _ l e d _l i g h t _ 1 (ON, OFF, OFF) ;
35 t u r n _ l e d _l i g h t _ 2 (OFF, ON, OFF) ;
36 s e t L e d b u f f e r ( led_light_time [ 1 ] − count_less , led_light_time [ 1 ] − count_less
);
37 c o u n t _ l e s s ++;
38 i f ( c o u n t _ l e s s >= l e d _ l i g h t _ t i m e [ 1 ] ) { t r a f f i c 1 = r e d ; c o u n t _ l e s s = 0 ; }
39 break ;
40 default :
41 break ;
42 }
43 setTimer1 (1111) ;
44 }
45 }

Báo cáo thí nghiệm - Học kì 211 Trang 37


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

4 Chapter 4: A cooperative scheduler


Giải quyết vấn đề và Trình bày demo. Ý tưởng chính là sẽ có 5 task có trong hàng đợi (mảng)
và sẽ thực thi lần lượt khi đủ điều kiện và được gọi. Đồng thời sử dụng Virtual Terminal để có
thể biết được Task nào đang thực thi và còn lại bao nhiêu thời gian.

4.1 Giải quyết vấn đề:


Sẽ có một mảng kiểu dữ liệu sTask được định nghĩa như sau:
1 typedef struct {
2 v o i d ( ∗ pTask ) ( v o i d ) ;
3 u i n t 3 2 _ t Delay ;
4 uint32_t Period ;
5 u i n t 8 _ t RunMe ;
6 u i n t 3 2 _ t TaskID ;
7 } sTask ;

Hệ thống sẽ có ít nhất 4 hàm sau:

• void SCH_Update(void)

• void SCH_Dispatch_Tasks(void)

• uint32_t SCH_Add_Task(void (* pFunction)(), uint32_t DELAY, uint32_t


PERIOD)

• uint8_t SCH_Delete_Task(uint32_t taskID)

4.1.1 void SCH_Update(void)

Ý tưởng gốc: Hàm này sẽ cập nhật giá trị Delay được điều khiển bởi timer interupt, từ đó
cập nhập lại giá trị RunMe để xác định được task nào sẽ được thực thi theo thứ tự TaskID.
1 v o i d SCH_Update ( v o i d ) {
2 u n s i g n e d c h a r Index ;
3 f o r ( Index = 0 ; Index < SCH_MAX_TASKS; Index++) {
4 i f ( SCH_tasks_G [ Index ] . pTask ) {
5 i f ( SCH_tasks_G [ Index ] . Delay == 0 ) {
6 SCH_tasks_G [ Index ] . RunMe += 1 ;
7 i f ( SCH_tasks_G [ Index ] . P e r i o d ) {
8 SCH_tasks_G [ Index ] . Delay = SCH_tasks_G [ Index ] . P e r i o d ;
9 }
10 }
11 else {
12 SCH_tasks_G [ Index ] . Delay −= 10 ;
13 }
14 }
15 }
16 }

Ý tưởng 2: Sau khi cập nhập lại giá trị của Delay của Task vừa được thực thi ta sẽ kiểm tra

Báo cáo thí nghiệm - Học kì 211 Trang 38


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

lại Task nào đang giữ giá trị Delay thấp nhất, rồi set RunMe của nó lên. Từ đó ta có thể thay đổi
độ phức tạp của hàm update từ O(n) mỗi lần gọi thành O(1) khi được gọi bình thường và O(n)
khi cập nhập lại giá trị Delay của Task vừa được thực thi.
1 unsigned char index = 0 ;
2 i n t time = 0 ;
3 v o i d SCH_Update ( v o i d ) {
4 i f ( SCH_tasks_G [ i n d e x ] . Delay == time ) {
5 SCH_tasks_G [ i n d e x ] . RunMe += 1 ;
6 i f ( SCH_tasks_G [ i n d e x ] . P e r i o d ) {
7 SCH_tasks_G [ i n d e x ] . Delay += SCH_tasks_G [ i n d e x ] . P e r i o d ;
8 }
9 i n d e x = ( i n d e x +1)%SCH_MAX_TASKS;
10 i n t min = SCH_tasks_G [ i n d e x ] . Delay ;
11 f o r ( i n t i = 0 ; i < SCH_MAX_TASKS; i ++){
12 i f ( SCH_tasks_G [ i ] . pTask ) {
13 i f ( min >= SCH_tasks_G [ i ] . Delay ) {
14 min = SCH_tasks_G [ i ] . Delay ;
15 index = i ;
16 }
17 }
18 else {
19 break ;
20 }
21 }
22 }
23 time += 1 0 ;
24

25 }

4.1.2 void SCH_Dispatch_Tasks(void)

Ý tưởng: Hàm này sẽ kiểm tra lần lượt các task đang có, và sẽ thực thi nếu chúng đủ điều
kiện RunMe > 0 và có con trỏ hàm, đồng thời sẽ xóa hàm nào không có Period (chu kỳ gọi). Đây
là hàm xử lý chính của hệ thống, được gọi trong vòng while(1).
1 v o i d SCH_Dispatch_Tasks ( v o i d ) {
2 u n s i g n e d c h a r Index ;
3 f o r ( Index = 0 ; Index < SCH_MAX_TASKS; Index++) {
4 i f ( SCH_tasks_G [ Index ] . pTask ) {
5 i f ( SCH_tasks_G [ Index ] . RunMe > 0 ) {
6 ( ∗ SCH_tasks_G [ Index ] . pTask ) ( ) ;
7 i f ( SCH_tasks_G [ Index ] . P e r i o d == 0 ) {
8 SCH_Delete_Task ( Index ) ;
9 }
10 }
11 }
12 }
13 }

Báo cáo thí nghiệm - Học kì 211 Trang 39


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

4.1.3 uint32_t SCH_Add_Task(void(*pFunction)(), uint32_t DELAY, uint32_t


PERIOD)

Ý tưởng: Hàm này sẽ truyền vào địa chỉ con trỏ hàm cần thêm pFunction, thời gian Delay,
chu kỳ gọi Period. Các dữ liệu trên sẽ được cập nhập vào biến mảng kiểu sTask ở trên. Có giá
trị trả về số thứ tự của Task đã thêm vào mảng.
1 u n s i g n e d c h a r SCH_Add_Task( v o i d ( ∗ pFunction ) ( ) , u n s i g n e d i n t DELAY, u n s i g n e d i n t
PERIOD) {
2 u n s i g n e d c h a r Index = 0 ;
3 w h i l e ( ( SCH_tasks_G [ Index ] . pTask != 0 ) && ( Index < SCH_MAX_TASKS) ) {
4 Index++;
5 }
6 i f ( Index == SCH_MAX_TASKS) {
7 Error_code_G = ERROR_SCH_TOO_MANY_TASKS;
8 r e t u r n SCH_MAX_TASKS;
9 }
10 SCH_tasks_G [ Index ] . pTask = pFunction ;
11 SCH_tasks_G [ Index ] . Delay = DELAY;
12 SCH_tasks_G [ Index ] . P e r i o d = PERIOD ;
13 SCH_tasks_G [ Index ] . RunMe = 0 ;
14 r e t u r n Index ;
15 }

4.1.4 uint8_t SCH_Delete_Task(uint32_t taskID))

Ý tưởng: Hàm này sẽ xóa dữ liệu của Task ở vi trí TaskID. Còn được gọi khi khởi tạo
Scheduler. Có dữ liệu trả về để xác định Task được xóa hay có lỗi.
1 u n s i g n e d c h a r SCH_Add_Task( v o i d ( ∗ pFunction ) ( ) , u n s i g n e d i n t DELAY, u n s i g n e d i n t
PERIOD) {
2 u n s i g n e d c h a r Index = 0 ;
3 w h i l e ( ( SCH_tasks_G [ Index ] . pTask != 0 ) && ( Index < SCH_MAX_TASKS) ) {
4 Index++;
5 }
6 i f ( Index == SCH_MAX_TASKS) {
7 Error_code_G = ERROR_SCH_TOO_MANY_TASKS;
8 r e t u r n SCH_MAX_TASKS;
9 }
10 SCH_tasks_G [ Index ] . pTask = pFunction ;
11 SCH_tasks_G [ Index ] . Delay = DELAY;
12 SCH_tasks_G [ Index ] . P e r i o d = PERIOD ;
13 SCH_tasks_G [ Index ] . RunMe = 0 ;
14 r e t u r n Index ;
15 }

4.2 Các hàm hỗ trợ:


4.2.1 void SCH_Init(void)

Ý tưởng: Hàm này sẽ khởi tạo Scheduler bằng cách xóa hết các Task trước đó. Hàm này sẽ
được gọi trước vòng while.
1 v o i d SCH_Init ( v o i d ) {

Báo cáo thí nghiệm - Học kì 211 Trang 40


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

2 unsigned char i ;
3 f o r ( i = 0 ; i < SCH_MAX_TASKS; i ++) {
4 SCH_Delete_Task ( i ) ;
5 }
6 }

4.2.2 void HAL_TIM_PeriodElapsedCallback ( TIM_HandleTypeDef *htim )

Ý tưởng: Đây là hàm điều khiển các timer c̈ứng.̈ Ở đây timer 2 với tần số 100Hz (chu kỳ
10ms) sẽ điều khiển hàm void SCH_update() và cập nhập biến time_duration để xác định
thời gian làm việc của các Task - sẽ được trình bày sau.
1 i n t time_duration ;
2 v o i d HAL_TIM_PeriodElapsedCallback ( TIM_HandleTypeDef ∗ htim ) {
3 i f ( htim −> I n s t a n c e == TIM2 ) {
4 SCH_Update ( ) ;
5 t i m e _ d u r a t i o n −= 1 0 ;
6 }
7 }

4.3 Các task:

Ý tưởng: Task có thời gian thục thi được xác định bởi biến time_duration và vòng
while(time_duration > 0), biến này được cập nhập bởi timer 2 mỗi 10ms. Các task có cấu
trúc giống nhau, chỉ khác các giá trị được in ra Terminal để biết được Task nào đang được thực
thi và thời gian bắt đầu thực thi sẽ được tính bởi hàm HAL_GetTick() việc chia cho 10 rồi
nhân 10 là để có thể loại bỏ giá trị hàng milisecond để dễ theo dõi kết quả. Đây là ví dụ cho void
taskA().
1 v o i d taskA ( ) {
2 u i n t 8 _ t t x B u f f e r [ ] = { "A " };
3 HAL_UART_Transmit(& huart1 , t x B u f f e r , s t r l e n ( t x B u f f e r ) , 1 0 0 ) ;
4 i n t time = HAL_GetTick ( ) /10∗10 −20;
5 char b u f f e r [ 1 6 ] ;
6 HAL_UART_Transmit(& huart1 , ( u i n t 8 _ t ∗ ) b u f f e r , s p r i n t f ( b u f f e r , "%d" , time ) , 5 0 0 ) ;
7 HAL_UART_Transmit(& huart1 , ( u i n t 8 _ t ∗ ) " \ r " , 2 , 5 0 0 ) ;
8 time_duration = 5 0 ;
9 while ( time_duration > 0) {
10 }
11 }

Báo cáo thí nghiệm - Học kì 211 Trang 41


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

4.4 Demonstration
Mô phỏng protues.

Hình 26: Schematic.

Giả sử ta có 5 task với thời gian thực thi 50ms, và chu kỳ thực thi lần lượt là 0.5s, 1s, 1.5s,
2s, 2.5s. Các task này được thêm vào bằng hàm SCH_Add_Task trước vòng while(1). Thì
các Task.Delay lần lượt là 0, 50, 100, 150, 200 để chắc chắn rằng các thứ tự thực thi của chúng
không bị đảo lộn.
1 SCH_Add_Task( taskA , 0 , 500) ;
2 SCH_Add_Task( taskB , 50 , 1000) ;
3 SCH_Add_Task( taskC , 100 , 1500) ;
4 SCH_Add_Task( taskD , 150 , 2000) ;
5 SCH_Add_Task( taskE , 200 , 2500) ;

Với giả thuyết như trên, theo lý thuyết ta sẽ có thời gian biểu thực thi của các Task như sau:

• Task A: 0, 500, 1000, 1500, ...

• Task B: 50, 1050, 2050, 3050, ...

• Task C: 100, 1600, 3100, 4600, ...

• Task D: 150, 2150, 4150, 6150, ...

• Task E: 200, 2700, 5200, 7700, ...

Để có thể

Báo cáo thí nghiệm - Học kì 211 Trang 42


Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học và Kỹ Thuật Máy Tính

Hình 27: Mô phỏng Protues Terminal Output

Báo cáo thí nghiệm - Học kì 211 Trang 43

You might also like