07_PHAM XUAN HOANG_TRAN QUOC PHU_STM32F103C8 HIỂN THỊ LCD 16X2.pdf

DongNgo14 32 views 73 slides Oct 29, 2024
Slide 1
Slide 1 of 73
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47
Slide 48
48
Slide 49
49
Slide 50
50
Slide 51
51
Slide 52
52
Slide 53
53
Slide 54
54
Slide 55
55
Slide 56
56
Slide 57
57
Slide 58
58
Slide 59
59
Slide 60
60
Slide 61
61
Slide 62
62
Slide 63
63
Slide 64
64
Slide 65
65
Slide 66
66
Slide 67
67
Slide 68
68
Slide 69
69
Slide 70
70
Slide 71
71
Slide 72
72
Slide 73
73

About This Presentation

STM32F103C8 HIỂN THỊ LCD 16X2


Slide Content

TRƯỜNG ĐẠI HỌC THỦ DẦU MỘT
VIỆN KỸ THUẬT – CÔNG NGHỆ
KHOA ĐIỆN – ĐIỆN TỬ





ĐỀ TÀI BÁO CÁO MÔN HỌC LẬP TRÌNH HỆ THỐNG
NHÚNG

TÊN ĐỀ TÀI: STM32F103C8 hiển thị LCD 16x2



GVGD: ThS. Ngô Thanh Đông
SVTH: 1. Phạm Xuân Hoàng - MSSV: 2225202160237
2. Trần Quốc Phú - MSSV: 2225202160207




Bình Dương, tháng 09 năm 2024

2

Chương 1: Giới thiệu lập trình hệ thống nhúng ...................................................................................7
1.1. Giới thiệu lập trình hệ thống nhúng: ....................................................................................7
1.2. Lập trinh hệ thống nhúng với STM32: ..................................................................................7
1.2.1. Cấu Trúc Hệ Thống Nhúng ..............................................................................................7
1.2.2. Ngôn Ngữ Lập Trình ........................................................................................................8
1.2.3. Công Cụ Phát Triển .........................................................................................................8
1.2.4. Giao Tiếp với Phần Cứng .................................................................................................8
1.2.5. Tài Nguyên Học Tập ........................................................................................................8
1.2.6. Thực Hành Dự Án ............................................................................................................8
1.3. Các ứng dụng lập trình hệ thống nhúng của STM32: .............................................................9
1.3.1. Thiết bị IoT (Internet of Things) ......................................................................................9
1.3.2. Tự động hóa công nghiệp .................................................................................................9
1.3.3. Điện tử tiêu dùng ............................................................................................................ 10
1.3.4. Y tế ................................................................................................................................. 10
1.3.5. Giao thông vận tải .......................................................................................................... 10
1.3.6. Hệ thống điều khiển tự động .......................................................................................... 10
1.3.7. Thiết bị giáo dục ............................................................................................................. 10
1.3.8. Thiết bị đo lường ............................................................................................................ 11
1.3.9. Hệ thống an ninh ............................................................................................................ 11
1.3.10. Thiết bị chơi game ........................................................................................................ 11
1.4. Cấu trúc STM32F103: ......................................................................................................... 11
1.4.1. Kiến trúc tổng thể .......................................................................................................... 11
1.4.2. Cổng giao tiếp ................................................................................................................ 11
1.4.3. Bộ điều khiển ................................................................................................................. 12
1.4.4. Hệ thống điện ................................................................................................................. 12
1.4.5. Hỗ trợ và phát triển ....................................................................................................... 12
1.4.6. Tính năng bảo mật ......................................................................................................... 12
Chương 2: Khảo sát chức năng xuất nhập dữ liệu số ......................................................................... 13
2.1. Giới thiệu về GPIO của STM32: ............................................................................................... 13
2.1.1. Chức năng Đầu vào và Đầu ra: ...................................................................................... 13
2.1.2. Chế độ Hoạt động: ......................................................................................................... 13
2.1.3. Tốc độ và Điện áp: ......................................................................................................... 13
2.1.4. Interrupts:...................................................................................................................... 13

3

2.1.5. Thư viện và Hỗ trợ: ........................................................................................................ 14
2.1.6. Số lượng Chân GPIO: .................................................................................................... 14
2.1.7. Ứng dụng: ...................................................................................................................... 14
2.2. Cấu trúc các thanh ghi xuất nhập dữ liệu số của STM32F103C8T6: ........................................... 14
1. Cấu trúc Thanh ghi GPIO ................................................................................................... 14
2. Ví dụ Cấu trúc Thanh ghi .................................................................................................... 15
3. Tóm tắt ................................................................................................................................ 16
2.3. Lệnh nhập dữ liệu số: ............................................................................................................. 16
Cấu hình Chân GPIO .............................................................................................................. 16
2.3.2. Đọc Dữ liệu từ Chân GPIO ............................................................................................ 17
2.3.3. Ví dụ Hoàn Chỉnh .......................................................................................................... 18
Tóm tắt .................................................................................................................................... 19
2.4. Lệnh xuất dữ liệu số: .............................................................................................................. 19
Cấu hình Chân GPIO .............................................................................................................. 19
2.4.2. Xuất Dữ liệu ra Chân GPIO ........................................................................................... 20
2.4.3. Ví dụ Hoàn Chỉnh .......................................................................................................... 20
Tóm tắt .................................................................................................................................... 22
2.5. Bài tập 01: ............................................................................................................................. 22
Chương 3: UART của STM32F103 ..................................................................................................... 28
3.1. Giới thiệu về UART của STM32: .............................................................................................. 28
3.1.1. Chức năng chính: ........................................................................................................... 28
3.1.2. Các thanh ghi chính: ...................................................................................................... 28
3.1.3. Cấu hình: ....................................................................................................................... 28
3.1.4. Chế độ hoạt động: .......................................................................................................... 28
3.1.5. Ứng dụng: ...................................................................................................................... 29
3.1.6. Hỗ trợ phần mềm: .......................................................................................................... 29
3.2. Cấu trúc các thanh ghi UART của STM32F103C8T6: ................................................................. 29
3.2.1. Cấu trúc thanh ghi USART ............................................................................................ 29
3.2.2. Giải thích các thanh ghi .................................................................................................. 30
3.2.3. Địa chỉ cơ sở ................................................................................................................... 30
3.2.4. Tóm tắt........................................................................................................................... 30
3.3. Các chế độ truyền nhập UART của STM32F103C8T6: ............................................................... 31
3.3.1. Chế độ truyền đơn (Full Duplex) .................................................................................... 31

4

3.3.2. Chế độ truyền bán đối xứng (Half Duplex) ..................................................................... 31
3.3.3. Chế độ truyền không đồng bộ ........................................................................................ 31
3.3.4. Chế độ truyền đồng bộ ................................................................................................... 32
3.3.5. Chế độ truyền bằng ngắt (Interrupt Mode) .................................................................... 32
3.3.6. Chế độ truyền DMA (Direct Memory Access) ................................................................ 32
3.3.7. Tóm tắt........................................................................................................................... 32
3.4. Bài tập 02: ............................................................................................................................. 32
Chương 4: Ngắt STM32 .................................................................................................................... 36
4.1. Giới thiệu về ngắt trong STM32: ............................................................................................. 36
Các loại ngắt trong STM32: .................................................................................................... 36
4.2. Các trúc các thanh ghi ngắt của STM32F103C8T6: ................................................................... 36
1. NVIC (Nested Vectored Interrupt Controller) ..................................................................... 36
4.3. Các lệnh về ngắt STM32F103: ................................................................................................. 37
1. Kích hoạt ngắt ..................................................................................................................... 37
2. Cấu hình ngắt cho EXTI ...................................................................................................... 37
3. Viết hàm xử lý ngắt (ISR) .................................................................................................... 38
4. Vô hiệu hóa ngắt .................................................................................................................. 38
5. Thiết lập độ ưu tiên cho ngắt ............................................................................................... 38
6. Kiểm tra trạng thái ngắt ...................................................................................................... 38
7. Kích hoạt ngắt từ phần mềm ............................................................................................... 39
8. Cấu hình ngắt thời gian (Timer Interrupt) .......................................................................... 39
9. Hàm xử lý ngắt cho Timer ................................................................................................... 39
Kết luận ................................................................................................................................... 39
4.4. Bài tập 03: ............................................................................................................................. 39
Chương 5: PWM STM32 ................................................................................................................... 42
5.1. Giới thiệu về PWM STM32F103: ............................................................................................. 42
1. Nguyên lý hoạt động của PWM............................................................................................ 42
2. Cấu hình PWM trong STM32F103 ...................................................................................... 42
3. Thay đổi Duty Cycle ............................................................................................................ 43
4. Kết luận ............................................................................................................................... 43
5.2. Các thanh ghi PWM của STM32F103C8T6: .............................................................................. 43
1. Cấu trúc của thanh ghi TIM ................................................................................................ 44
2. Các thanh ghi chính cho PWM ............................................................................................ 44

5

3. Cấu hình PWM .................................................................................................................... 45
Ví dụ cấu hình ......................................................................................................................... 45
4.Kết luận ................................................................................................................................ 46
5.3. Các lệnh về PWM của STM32F103C8T6: .................................................................................. 46
1. Cấu hình RCC (Clock Control) ........................................................................................... 46
2. Cấu hình GPIO .................................................................................................................... 47
3. Cấu hình Timer ................................................................................................................... 47
4. Điều chỉnh Duty Cycle ......................................................................................................... 47
5. Khởi động Timer và kiểm tra .............................................................................................. 48
Lưu ý: ...................................................................................................................................... 48
5.4. Bài tập 04: ............................................................................................................................. 48
Chương 6: Ngắt timer STM32 ........................................................................................................ 52
6.1. Giới thiệu Timer của STM32F103C8T6 ............................................................................... 52
1. Các loại Timer ..................................................................................................................... 52
2. Tính năng nổi bật................................................................................................................. 52
3. Ứng dụng ............................................................................................................................. 53
4. Cấu trúc ............................................................................................................................... 53
5.Kết luận ................................................................................................................................ 53
6.2. Các thanh ghi Timer của STM32F103C8T6 ............................................................................... 53
1. Thanh ghi điều khiển ........................................................................................................... 54
2. Thanh ghi cấu hình .............................................................................................................. 54
3. Thanh ghi Capture/Compare ............................................................................................... 54
4. Thanh ghi cấu hình chế độ ................................................................................................... 54
5. Thanh ghi điều khiển đầu ra ................................................................................................ 54
6. Thanh ghi trạng thái và ngắt ............................................................................................... 55
7. Thanh ghi bộ đếm ................................................................................................................ 55
8.Tóm tắt ................................................................................................................................. 55
6.3. Các lệnh về timer của STM32F103C8T6 ................................................................................... 55
1. Bật đồng hồ cho Timer ........................................................................................................ 56
2. Cấu hình chân GPIO ........................................................................................................... 56
3. Cấu hình Timer ................................................................................................................... 56
4. Điều chỉnh Duty Cycle ......................................................................................................... 56
5. Khởi động Timer và kiểm tra .............................................................................................. 57

6

6. Ngắt Timer .......................................................................................................................... 57
7. Hàm xử lý ngắt .................................................................................................................... 57
6.4. Bài tập 05 .............................................................................................................................. 58
Chương 7: Đề tài ứng dụng STM32F103 tự chọn ............................................................................... 62
7.1. Giới thiệu đề tài: STM32F103C8 hiển thị LCD 16x2 .................................................................. 62
7.2. Cơ sở lý thuyết: ..................................................................................................................... 62
1. Hàm đổi trạng thái output: .................................................................................................. 62
2. Hàm set/ reset output: .......................................................................................................... 62
3. Hàm input: .......................................................................................................................... 63
4. Hàm Delay ms: .................................................................................................................... 63
5. Thanh ghi GPIOx_ODR datasheet ...................................................................................... 63
7.3. Phương án thực hiện: ............................................................................................................ 64
7.5. Kết quả đề tài: ....................................................................................................................... 66

7



Chương 1: Giới thiệu lập trình hệ thống nhúng

1.1. Giới thiệu lập trình hệ thống nhúng:
Lập trình hệ thống nhúng (Embedded Systems Programming) là lĩnh vực
nghiên cứu và phát triển phần mềm cho các thiết bị nhúng, tức là những
thiết bị có phần cứng và phần mềm được tích hợp chặt chẽ để thực hiện
các chức năng cụ thể. Những thiết bị này thường có tài nguyên hạn chế về
bộ nhớ, bộ xử lý và nguồn năng lượng, và chúng được sử dụng rộng rãi
trong nhiều lĩnh vực, từ điện tử tiêu dùng đến công nghiệp, ô tô và y tế.
1.2. Lập trinh hệ thống nhúng với STM32:
Lập trình hệ thống nhúng với STM32 là một trong những lựa chọn phổ
biến cho các kỹ sư và lập trình viên, nhờ vào khả năng linh hoạt, hiệu suất
cao và giá thành hợp lý của dòng vi điều khiển STM32.
Lập trình hệ thống nhúng là một lĩnh vực quan trọng trong kỹ thuật điện
tử và phần mềm. Hệ thống nhúng thường được sử dụng trong các thiết bị
như điện thoại, máy giặt, ô tô, và nhiều sản phẩm điện tử khác. Dưới đây
là một số thông tin cơ bản và hướng dẫn để bạn bắt đầu:
1.2.1. Cấu Trúc Hệ Thống Nhúng
• Phần cứng: Gồm vi điều khiển (microcontroller), cảm biến, thiết bị
đầu ra (motor, LED, màn hình...).
• Phần mềm: Gồm mã nguồn điều khiển phần cứng, thường viết bằng
C, C++, hoặc Python.

8

1.2.2. Ngôn Ngữ Lập Trình
• C/C++: Ngôn ngữ phổ biến nhất cho lập trình nhúng nhờ tính hiệu
quả và khả năng điều khiển phần cứng.
• Assembly: Đôi khi được sử dụng cho các ứng dụng yêu cầu hiệu
suất tối ưu.
• Python: Sử dụng trong các hệ thống nhúng có khả năng xử lý tốt
hơn như Raspberry Pi.
1.2.3. Công Cụ Phát Triển
• IDE: Sử dụng các môi trường phát triển như Arduino IDE, Keil,
hoặc MPLAB.
• Compiler: Các trình biên dịch như GCC cho C/C++.
• Board: Arduino, Raspberry Pi, ESP32, STM32 là những nền tảng
phổ biến.
1.2.4. Giao Tiếp với Phần Cứng
• GPIO: General Purpose Input/Output cho phép điều khiển các thiết
bị ngoại vi.
• Serial Communication: Giao tiếp qua UART, SPI, I2C.
• Interrupts: Sử dụng để xử lý các sự kiện thời gian thực.
1.2.5. Tài Nguyên Học Tập
• Sách: "Programming Embedded Systems in C and C++" là một tài
liệu hữu ích.
• Khóa Học Trực Tuyến: Coursera, Udemy có nhiều khóa học về lập
trình nhúng.
• Diễn Đàn: Tham gia các cộng đồng như Stack Overflow, Reddit để
giải quyết vấn đề và học hỏi từ người khác.
1.2.6. Thực Hành Dự Án
• Bắt Đầu Với Arduino: Làm các dự án đơn giản như đèn LED nhấp
nháy, cảm biến nhiệt độ.

9

• Phát Triển Dự Án Thực Tế: Tạo ra các sản phẩm như hệ thống
giám sát môi trường, điều khiển từ xa.
1.2.7. Giới thiệu về STM32
STM32 là dòng vi điều khiển 32-bit do STMicroelectronics phát triển, với
nhiều model và cấu hình khác nhau. Các vi điều khiển này thường được
sử dụng trong các ứng dụng nhúng nhờ vào:
• Hiệu suất cao: Với kiến trúc ARM Cortex-M.
• Tính năng phong phú: Các giao tiếp như UART, SPI, I2C, ADC,
và GPIO.
• Tiêu thụ điện năng thấp: Phù hợp với các ứng dụng yêu cầu tiết
kiệm năng lượng.
Lập trình hệ thống nhúng với STM32 mở ra nhiều cơ hội sáng tạo và phát
triển ứng dụng phong phú, phù hợp với nhu cầu của thị trường công nghệ
hiện đại.

1.3. Các ứng dụng lập trình hệ thống nhúng của STM32:
STM32 là một trong những vi điều khiển phổ biến nhất trong lập trình hệ
thống nhúng, nhờ vào tính linh hoạt và khả năng xử lý mạnh mẽ. Dưới
đây là một số ứng dụng thực tế của lập trình hệ thống nhúng với STM32:
1.3.1. Thiết bị IoT (Internet of Things)
• Cảm biến thông minh: Giám sát nhiệt độ, độ ẩm, ánh sáng, chất
lượng không khí, và gửi dữ liệu qua giao thức như MQTT hoặc
HTTP.
• Bộ điều khiển từ xa: Điều khiển thiết bị qua smartphone hoặc giao
diện web.
1.3.2. Tự động hóa công nghiệp

10

• Robot công nghiệp: Điều khiển động cơ và cảm biến trong dây
chuyền sản xuất.
• Hệ thống SCADA: Giám sát và điều khiển quy trình công nghiệp
từ xa.
1.3.3. Điện tử tiêu dùng
• Thiết bị gia dụng thông minh: Như máy giặt, tủ lạnh, máy nướng
bánh có thể điều khiển từ xa.
• Hệ thống giải trí: Máy phát nhạc, thiết bị điều khiển âm thanh.
1.3.4. Y tế
• Thiết bị theo dõi sức khỏe: Như máy đo huyết áp, máy theo dõi
nhịp tim, hoặc thiết bị theo dõi hoạt động thể chất.
• Thiết bị chẩn đoán: Các máy móc y tế như máy siêu âm hoặc máy
nội soi.
1.3.5. Giao thông vận tải
• Hệ thống điều khiển ô tô: Quản lý động cơ, hệ thống phanh ABS,
và cảm biến an toàn.
• Hệ thống giám sát và điều khiển giao thông: Thiết bị thu thập dữ
liệu lưu lượng giao thông và điều khiển tín hiệu đèn.
1.3.6. Hệ thống điều khiển tự động
• Drones (máy bay không người lái): Quản lý điều khiển bay, thu
thập dữ liệu từ cảm biến.
• Robot hút bụi: Tự động hóa quy trình làm sạch, điều hướng qua
cảm biến.
1.3.7. Thiết bị giáo dục
• Bảng mạch phát triển: Như STM32 Nucleo hoặc Discovery
boards, cho học sinh và sinh viên học lập trình nhúng.
• Dự án DIY: Thiết kế các sản phẩm nhúng từ cơ bản đến nâng cao.

11

1.3.8. Thiết bị đo lường
• Máy đo đa năng: Đo điện áp, dòng điện, tần số, và các thông số
khác.
• Thiết bị phân tích dữ liệu: Lưu trữ và phân tích dữ liệu từ các cảm
biến.
1.3.9. Hệ thống an ninh
• Camera an ninh: Quản lý thu hình, phát hiện chuyển động và gửi
thông báo.
• Hệ thống báo động: Giám sát và phát hiện xâm nhập.
1.3.10. Thiết bị chơi game
• Máy chơi game đơn giản: Xây dựng các trò chơi trên nền tảng
nhúng với màn hình hiển thị và điều khiển.
1.4. Cấu trúc STM32F103:
Cấu trúc của STM32F103 là một phần quan trọng để hiểu về khả năng và
chức năng của vi điều khiển này. Dưới đây là cái nhìn tổng quan về cấu
trúc của STM32F103:
1.4.1. Kiến trúc tổng thể
• Nhân ARM Cortex-M3: STM32F103 sử dụng kiến trúc ARM
Cortex-M3, cho phép xử lý hiệu quả, tốc độ cao với tiêu thụ điện
năng thấp.
• Bộ nhớ:
o Flash Memory: Lưu trữ chương trình (từ 16KB đến 128KB,
tùy model).
o SRAM: Bộ nhớ tạm (từ 20KB đến 64KB, tùy model).
o EEPROM: Một số model có hỗ trợ EEPROM nội bộ.
1.4.2. Cổng giao tiếp

12

• GPIO (General Purpose Input/Output): Nhiều chân GPIO cho
phép kết nối với cảm biến, thiết bị ngoại vi.
• Giao tiếp ngoại vi:
o USART/UART: Giao tiếp nối tiếp cho truyền thông dữ liệu.
o SPI (Serial Peripheral Interface): Giao tiếp nhanh với các
thiết bị ngoại vi.
o I2C (Inter-Integrated Circuit): Giao tiếp với cảm biến và
thiết bị ngoại vi khác.
o CAN (Controller Area Network): Giao tiếp cho các ứng
dụng ô tô (trong một số model).
1.4.3. Bộ điều khiển
• ADC (Analog to Digital Converter): Chuyển đổi tín hiệu analog
sang tín hiệu số, hỗ trợ nhiều kênh.
• DAC (Digital to Analog Converter): Chuyển đổi tín hiệu số sang
tín hiệu analog (trong một số model).
• Timers: Nhiều bộ đếm và bộ định thời cho các tác vụ điều khiển
thời gian.
1.4.4. Hệ thống điện
• Nguồn cung cấp: Chạy từ nguồn 2.0V đến 3.6V.
• Watchdog Timer: Giám sát hoạt động của hệ thống, tự động khởi
động lại nếu phát hiện lỗi.
1.4.5. Hỗ trợ và phát triển
• Peripheral Libraries: STM32F103 hỗ trợ thư viện HAL và CMSIS
giúp lập trình viên dễ dàng truy cập và điều khiển các thiết bị ngoại
vi.
• STM32CubeMX: Công cụ cấu hình và tạo mã nguồn tự động cho
phần cứng.
1.4.6. Tính năng bảo mật

13

• Một số model hỗ trợ bảo mật phần cứng, giúp bảo vệ dữ liệu và ngăn
chặn truy cập trái phép.
Chương 2: Khảo sát chức năng xuất nhập dữ liệu số

2.1. Giới thiệu về GPIO của STM32:
GPIO (General Purpose Input/Output) của STM32 là một phần quan trọng
trong vi điều khiển STM32, cho phép người dùng giao tiếp với các thiết
bị ngoại vi và cảm biến. Dưới đây là một số điểm nổi bật về GPIO của
STM32:
2.1.1. Chức năng Đầu vào và Đầu ra:
• GPIO có thể được cấu hình làm đầu vào (input) hoặc đầu ra (output)
tùy theo nhu cầu của ứng dụng.
• Đầu vào có thể đọc tín hiệu từ cảm biến hoặc thiết bị khác.
• Đầu ra có thể điều khiển đèn LED, động cơ, hoặc thiết bị ngoại vi.
2.1.2. Chế độ Hoạt động:
• Input Mode: Đọc trạng thái tín hiệu, có thể là chế độ pull-up, pull-
down.
• Output Mode: Gồm chế độ push-pull và open-drain.
• Alternate Function: Cho phép chân GPIO thực hiện các chức năng
khác như UART, I2C, SPI.
2.1.3. Tốc độ và Điện áp:
• Các chân GPIO có thể hoạt động ở nhiều tốc độ khác nhau (low,
medium, high, very high).
• Thường hoạt động ở mức điện áp 3.3V, nhưng có thể chịu đựng
được mức điện áp cao hơn trong một số trường hợp.
2.1.4. Interrupts:

14

• GPIO hỗ trợ ngắt (interrupt), cho phép ứng dụng phản ứng nhanh
với sự kiện (ví dụ: nhấn nút).
2.1.5. Thư viện và Hỗ trợ:
• STM32 cung cấp các thư viện phần mềm như HAL (Hardware
Abstraction Layer) và LL (Low Layer) giúp lập trình GPIO dễ dàng
hơn.
• STM32CubeMX cũng hỗ trợ cấu hình GPIO thông qua giao diện đồ
họa.
2.1.6. Số lượng Chân GPIO:
• Tùy vào dòng vi điều khiển STM32, số lượng chân GPIO có thể từ
vài chục đến vài trăm chân.
2.1.7. Ứng dụng:
• Sử dụng trong các ứng dụng như điều khiển LED, đọc cảm biến,
giao tiếp với các thiết bị ngoại vi, và nhiều ứng dụng nhúng khác.
GPIO của STM32 cung cấp một nền tảng linh hoạt và mạnh mẽ cho việc
phát triển ứng dụng nhúng, giúp dễ dàng tích hợp các thiết bị và cảm biến
khác nhau.
2.2. Cấu trúc các thanh ghi xuất nhập dữ liệu số của
STM32F103C8T6:
Thanh ghi xuất nhập dữ liệu số (GPIO) của STM32F103C8T6 được tổ
chức theo cách cho phép người dùng điều khiển các chân GPIO một cách
dễ dàng. Dưới đây là cấu trúc các thanh ghi liên quan đến GPIO:
1. Cấu trúc Thanh ghi GPIO
Mỗi cổng GPIO (ví dụ: GPIOA, GPIOB, ...) có các thanh ghi chính sau
đây:

15

1.1. Cổng cấu hình (CRL/CRH)
• CRL (Configuration Register Low): Cấu hình cho các chân 0-7.
• CRH (Configuration Register High): Cấu hình cho các chân 8-15.
Cấu hình từng chân bao gồm:
• Mode: Chế độ hoạt động (input, output, alternate function).
• CNF: Cấu hình đầu vào hoặc đầu ra (floating, pull-up, push-pull,
open-drain).
1.2. Thanh ghi dữ liệu (IDR/ODR)
• IDR (Input Data Register): Đọc trạng thái của các chân GPIO (0
hoặc 1).
• ODR (Output Data Register): Ghi giá trị ra các chân GPIO (0 hoặc
1).
1.3. Thanh ghi bit kiểm soát (BSRR/BRR)
• BSRR (Bit Set/Reset Register): Đặt hoặc xóa một chân cụ thể mà
không ảnh hưởng đến các chân khác.
• BRR (Bit Reset Register): Chỉ có tác dụng xóa các chân GPIO.
1.4. Thanh ghi khóa (LCKR)
• LCKR (Lock Register): Khóa các cài đặt của các chân GPIO để
tránh thay đổi không mong muốn.
2. Ví dụ Cấu trúc Thanh ghi
Cấu trúc thanh ghi cho GPIOA có thể được định nghĩa như sau (tùy thuộc
vào tài liệu tham khảo):
Mã code :

16

typedef struct {
__IO uint32_t CRL; // Cấu hình cho chân 0-7
__IO uint32_t ODR; // Dữ liệu đầu ra
__IO uint32_t IDR; // Dữ liệu đầu vào
__IO uint32_t BRR; // Dữ liệu reset
__IO uint32_t BSRR; // Dữ liệu set/reset
__IO uint32_t CRH; // Cấu hình cho chân 8-15
__IO uint32_t LCKR; // Khóa cấu hình
} GPIO_TypeDef;

#define GPIOA ((GPIO_TypeDef *) 0x40010800) // Địa chỉ cơ sở của
GPIOA
3. Tóm tắt
Các thanh ghi của GPIO trên STM32F103C8T6 cho phép lập trình viên
cấu hình, đọc, và ghi dữ liệu đến các chân GPIO một cách linh hoạt. Việc
hiểu cấu trúc này giúp bạn phát triển ứng dụng nhúng hiệu quả hơn.

2.3. Lệnh nhập dữ liệu số:
Để nhập dữ liệu số từ chân GPIO trên STM32F103C8T6, bạn sẽ sử dụng
thanh ghi IDR (Input Data Register). Dưới đây là hướng dẫn và ví dụ cụ
thể về cách thực hiện điều này:
Cấu hình Chân GPIO

17

Trước khi bạn có thể đọc dữ liệu từ chân GPIO, bạn cần cấu hình chân đó
là đầu vào.
2.3.1. Cấu hình chân GPIO là đầu vào
Giả sử bạn muốn đọc dữ liệu từ chân PA0. Dưới đây là cách cấu hình nó:
Mã code:

#include "stm32f10x.h" // Thư viện cho STM32F103C8T6

void GPIO_Config(void) {
// Bật đồng hồ cho GPIOA
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;

// Cấu hình PA0 là đầu vào với pull-up
GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0); //
Xóa cấu hình hiện tại
GPIOA->CRL |= (GPIO_CRL_CNF0_1); // Cấu hình chế độ pull-up
GPIOA->ODR |= (1 << 0); // Kích hoạt pull-up (đặt PA0 = 1)
}
2.3.2. Đọc Dữ liệu từ Chân GPIO
Sau khi đã cấu hình, bạn có thể đọc dữ liệu từ chân PA0 bằng cách kiểm
tra bit tương ứng trong thanh ghi IDR:
Mã code:
uint8_t read_GPIOA0(void) {

18

return (GPIOA->IDR & (1 << 0)) != 0; // Kiểm tra PA0
}
2.3.3. Ví dụ Hoàn Chỉnh
Dưới đây là một ví dụ hoàn chỉnh, bao gồm cấu hình GPIO và đọc giá trị
từ PA0:
Mã code:
#include "stm32f10x.h"
void GPIO_Config(void) {
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Bật đồng hồ cho
GPIOA
GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0); //
Xóa cấu hình hiện tại
GPIOA->CRL |= (GPIO_CRL_CNF0_1); // Cấu hình chế độ pull-up
GPIOA->ODR |= (1 << 0); // Kích hoạt pull-up
}
uint8_t read_GPIOA0(void) {
return (GPIOA->IDR & (1 << 0)) != 0; // Đọc trạng thái PA0
}
int main(void) {
GPIO_Config(); // Cấu hình GPIO

while (1) {
if (read_GPIOA0()) {

19

// Xử lý khi PA0 có mức HIGH
} else {
// Xử lý khi PA0 có mức LOW
}
}
}
Tóm tắt
• Cấu hình: Sử dụng CRL/CRH để cấu hình chân là đầu vào.
• Đọc dữ liệu: Sử dụng thanh ghi IDR để kiểm tra trạng thái của chân.
Như vậy, bạn có thể dễ dàng nhập dữ liệu số từ các chân GPIO của
STM32F103C8T6.
2.4. Lệnh xuất dữ liệu số:
Để xuất dữ liệu số từ chân GPIO trên STM32F103C8T6, bạn sẽ sử dụng
thanh ghi ODR (Output Data Register). Dưới đây là hướng dẫn và ví dụ
cụ thể về cách thực hiện điều này:
Cấu hình Chân GPIO
Trước khi bạn có thể xuất dữ liệu, bạn cần cấu hình chân GPIO là đầu ra.
Dưới đây là cách thực hiện:
2.4.1. Cấu hình chân GPIO là đầu ra
Giả sử bạn muốn xuất dữ liệu ra chân PA1. Dưới đây là cách cấu hình nó:
Mã code:
#include "stm32f10x.h" // Thư viện cho STM32F103C8T6
void GPIO_Config(void) {

20

// Bật đồng hồ cho GPIOA
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
// Cấu hình PA1 là đầu ra
GPIOA->CRL &= ~(GPIO_CRL_MODE1 | GPIO_CRL_CNF1); //
Xóa cấu hình hiện tại
GPIOA->CRL |= (GPIO_CRL_MODE1_0); // Chế độ output, max
speed 2 MHz
}
2.4.2. Xuất Dữ liệu ra Chân GPIO
Sau khi đã cấu hình, bạn có thể xuất dữ liệu đến chân PA1 bằng cách ghi
giá trị vào thanh ghi ODR:
Mã code:
void set_GPIOA1(uint8_t state) {
if (state) {
GPIOA->ODR |= (1 << 1); // Đặt PA1 = HIGH
} else {
GPIOA->ODR &= ~(1 << 1); // Đặt PA1 = LOW
}
}
2.4.3. Ví dụ Hoàn Chỉnh
Dưới đây là một ví dụ hoàn chỉnh, bao gồm cấu hình GPIO và xuất giá trị
ra PA1:
Mã code:

21

#include "stm32f10x.h"
void GPIO_Config(void) {
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Bật đồng hồ cho
GPIOA
GPIOA->CRL &= ~(GPIO_CRL_MODE1 | GPIO_CRL_CNF1); //
Xóa cấu hình hiện tại
GPIOA->CRL |= (GPIO_CRL_MODE1_0); // Chế độ output, max
speed 2 MHz
}
void set_GPIOA1(uint8_t state) {
if (state) {
GPIOA->ODR |= (1 << 1); // Đặt PA1 = HIGH
} else {
GPIOA->ODR &= ~(1 << 1); // Đặt PA1 = LOW
}
}

int main(void) {
GPIO_Config(); // Cấu hình GPIO

while (1) {
set_GPIOA1(1); // Xuất HIGH ra PA1
for (volatile int i = 0; i < 100000; i++); // Delay
set_GPIOA1(0); // Xuất LOW ra PA1

22

for (volatile int i = 0; i < 100000; i++); // Delay
}
}
Tóm tắt
• Cấu hình: Sử dụng CRL/CRH để cấu hình chân là đầu ra.
• Xuất dữ liệu: Sử dụng thanh ghi ODR để ghi giá trị cho chân.
Với hướng dẫn này, bạn có thể dễ dàng xuất dữ liệu số từ các chân GPIO
của STM32F103C8T6.
2.5. Bài tập 01: STM32F103 TRUYỀN DỮ LIỆU UART_ĐIỀU
KHIỂN ĐỘNG CƠ ENCODER DC_P2

23

24

25

26

27

28

Chương 3: UART của STM32F103

3.1. Giới thiệu về UART của STM32:
UART (Universal Asynchronous Receiver-Transmitter) của STM32 là
một giao thức truyền thông phổ biến dùng để giao tiếp giữa vi điều khiển
và các thiết bị ngoại vi. Dưới đây là một số điểm nổi bật về UART trên
STM32:
3.1.1. Chức năng chính:
• Truyền và nhận dữ liệu: Hỗ trợ truyền dữ liệu đồng bộ và không
đồng bộ giữa các thiết bị.
• Chế độ 8-bit: Hỗ trợ truyền dữ liệu 8-bit với các tùy chọn cho bit
dừng và bit kiểm tra lỗi.
3.1.2. Các thanh ghi chính:
• SR (Status Register): Cung cấp thông tin về trạng thái của UART,
bao gồm các cờ như TXE (Transmit Data Register Empty) và RXNE
(Receive Data Register Not Empty).
• DR (Data Register): Dùng để gửi và nhận dữ liệu.
• BRR (Baud Rate Register): Cấu hình tốc độ truyền dữ liệu.
3.1.3. Cấu hình:
• Tốc độ baud: Có thể được cấu hình từ 300 đến 115200 bps (hoặc
cao hơn, tùy vào dòng STM32).
• Bit dừng: Có thể chọn 1 hoặc 2 bit dừng.
• Kiểm tra lỗi: Hỗ trợ các phương pháp kiểm tra như parity.
3.1.4. Chế độ hoạt động:
• Giao tiếp đầy đủ: Hỗ trợ cả truyền và nhận đồng thời.

29

• Interrupt: Hỗ trợ ngắt để xử lý dữ liệu nhận hoặc gửi mà không cần
polling.
3.1.5. Ứng dụng:
• Thích hợp cho các ứng dụng như giao tiếp với cảm biến, module
GSM, GPS, và thiết bị ngoại vi khác.
3.1.6. Hỗ trợ phần mềm:
• STM32 cung cấp thư viện HAL và LL giúp lập trình UART dễ dàng
hơn.
• STM32CubeMX hỗ trợ cấu hình UART qua giao diện đồ họa.
UART trên STM32 là một công cụ mạnh mẽ và linh hoạt cho việc giao
tiếp giữa các thiết bị, giúp đơn giản hóa quá trình phát triển ứng dụng
nhúng.
3.2. Cấu trúc các thanh ghi UART của STM32F103C8T6:
Cấu trúc các thanh ghi UART trên STM32F103C8T6 (cụ thể là USART1)
bao gồm nhiều thanh ghi chính giúp điều khiển và quản lý việc truyền
nhận dữ liệu. Dưới đây là cấu trúc cơ bản của các thanh ghi này:
3.2.1. Cấu trúc thanh ghi USART

Mã code:

typedef struct {
__IO uint32_t SR; // Status Register
__IO uint32_t DR; // Data Register
__IO uint32_t BRR; // Baud Rate Register
__IO uint32_t CR1; // Control Register 1
__IO uint32_t CR2; // Control Register 2

30

__IO uint32_t CR3; // Control Register 3
__IO uint32_t GTPR; // Guard Time and Prescaler Register
} USART_TypeDef;

3.2.2. Giải thích các thanh ghi
• SR (Status Register): Chứa các cờ trạng thái.
o TXE: Cờ cho biết thanh ghi dữ liệu truyền (DR) đã sẵn sàng
để gửi.
o RXNE: Cờ cho biết có dữ liệu đã nhận trong thanh ghi nhận.
• DR (Data Register): Chứa dữ liệu sẽ được gửi đi hoặc dữ liệu đã
nhận.
• BRR (Baud Rate Register): Cấu hình tốc độ truyền (baud rate).
• CR1 (Control Register 1): Cấu hình các chức năng như bật ngắt,
chọn chế độ 8-bit, và chế độ truyền/nhận.
• CR2 (Control Register 2): Cấu hình các tùy chọn liên quan đến bit
dừng và khác.
• CR3 (Control Register 3): Cấu hình các chức năng bổ sung như
điều khiển luồng dữ liệu.
• GTPR (Guard Time and Prescaler Register): Cấu hình thời gian
bảo vệ và bộ chia cho tốc độ truyền.
3.2.3. Địa chỉ cơ sở
Địa chỉ cơ sở của USART1 trong bộ nhớ là:
Mã code:

#define USART1_BASE 0x40013800
#define USART1 ((USART_TypeDef *) USART1_BASE)
3.2.4. Tóm tắt
Các thanh ghi UART trên STM32F103C8T6 cho phép lập trình viên cấu
hình và quản lý việc truyền nhận dữ liệu một cách linh hoạt và hiệu quả.

31

Việc hiểu rõ cấu trúc này sẽ giúp phát triển ứng dụng giao tiếp nhanh
chóng và chính xác hơn.

3.3. Các chế độ truyền nhập UART của STM32F103C8T6:
UART trên STM32F103C8T6 hỗ trợ nhiều chế độ truyền nhận dữ liệu,
cho phép linh hoạt trong việc giao tiếp. Dưới đây là các chế độ chính của
UART:
3.3.1. Chế độ truyền đơn (Full Duplex)
• Mô tả: Cả việc truyền và nhận dữ liệu đều có thể diễn ra đồng thời.
Điều này có nghĩa là thiết bị có thể gửi và nhận dữ liệu cùng một
lúc.
• Ứng dụng: Giao tiếp với các thiết bị như modem hoặc cảm biến cần
phản hồi ngay lập tức.
3.3.2. Chế độ truyền bán đối xứng (Half Duplex)
• Mô tả: Dữ liệu có thể được truyền hoặc nhận tại một thời điểm,
nhưng không thể cả hai cùng lúc. Thiết bị phải chuyển đổi giữa chế
độ truyền và nhận.
• Ứng dụng: Thích hợp cho các ứng dụng như điều khiển từ xa hoặc
giao tiếp qua các kênh truyền chia sẻ.
3.3.3. Chế độ truyền không đồng bộ
• Mô tả: UART hoạt động theo chế độ không đồng bộ, nghĩa là không
có tín hiệu đồng hồ riêng cho việc truyền và nhận dữ liệu. Dữ liệu
được truyền trong các khung, mỗi khung bao gồm bit bắt đầu, bit dữ
liệu, bit dừng và có thể có bit kiểm tra.
• Tùy chọn: Có thể cấu hình số lượng bit dữ liệu (thường là 8 hoặc 9
bit), số bit dừng (1 hoặc 2), và loại kiểm tra (none, even, odd).

32

3.3.4. Chế độ truyền đồng bộ
• Mô tả: Mặc dù không phải là chế độ chính được sử dụng trong
UART, STM32 cho phép cấu hình chế độ đồng bộ trong một số
trường hợp. Trong chế độ này, một tín hiệu đồng hồ được sử dụng
để đồng bộ hóa việc truyền và nhận dữ liệu.
• Ứng dụng: Thích hợp cho các ứng dụng yêu cầu tốc độ truyền cao
và độ chính xác trong thời gian.
3.3.5. Chế độ truyền bằng ngắt (Interrupt Mode)
• Mô tả: UART có thể được cấu hình để sử dụng ngắt khi có dữ liệu
nhận vào hoặc khi thanh ghi truyền rỗng. Điều này giúp xử lý dữ
liệu hiệu quả hơn mà không cần phải liên tục kiểm tra trạng thái.
• Ứng dụng: Thích hợp cho các ứng dụng cần tiết kiệm năng lượng
hoặc tối ưu hóa tài nguyên CPU.
3.3.6. Chế độ truyền DMA (Direct Memory Access)
• Mô tả: UART có thể hoạt động với DMA để truyền dữ liệu mà
không cần can thiệp của CPU. Điều này giúp tăng tốc độ truyền dữ
liệu và giảm tải cho vi điều khiển.
• Ứng dụng: Thích hợp cho việc truyền dữ liệu lớn hoặc trong các
ứng dụng yêu cầu tốc độ cao.
3.3.7. Tóm tắt
UART của STM32F103C8T6 cung cấp nhiều chế độ truyền nhận linh
hoạt, từ chế độ truyền đơn cho đến hỗ trợ ngắt và DMA, giúp các ứng
dụng giao tiếp trở nên đa dạng và hiệu quả. Việc chọn chế độ phù hợp sẽ
tùy thuộc vào yêu cầu cụ thể của ứng dụng mà bạn đang phát triển.
3.4. Bài tập 02: STM32F103 ĐIỀU KHIỂN ĐỘNG CƠ ENCODER
DC P3

33

34

35

36


Chương 4: Ngắt STM32
4.1. Giới thiệu về ngắt trong STM32:
Ngắt (interrupt) trong STM32 là một cơ chế cho phép vi điều khiển tạm
dừng chương trình đang thực thi để xử lý một sự kiện khẩn cấp. Điều này
rất hữu ích để quản lý các tác vụ thời gian thực mà không cần phải thường
xuyên kiểm tra trạng thái của thiết bị.
Các loại ngắt trong STM32:
1. Ngắt ngoại vi (External Interrupts):
o Được kích hoạt bởi các tín hiệu bên ngoài như nút bấm, cảm
biến, v.v.
o Sử dụng các chân GPIO để nhận tín hiệu.
2. Ngắt thời gian (Timer Interrupts):
o Được tạo ra bởi các bộ đếm thời gian (timer) khi đạt đến giá
trị nhất định.
o Hữu ích cho các tác vụ định kỳ.
3. Ngắt từ các thiết bị ngoại vi (Peripheral Interrupts):
o Ngắt từ các thiết bị như UART, I2C, SPI, ADC, v.v.
o Thường dùng để xử lý dữ liệu khi nhận hoặc gửi.
4.2. Các trúc các thanh ghi ngắt của STM32F103C8T6:
Trên STM32F103C8T6, các thanh ghi ngắt được cấu hình qua các thành
phần chính như NVIC (Nested Vectored Interrupt Controller) và các thanh
ghi điều khiển ngắt của các thiết bị ngoại vi. Dưới đây là cấu trúc chính
của các thanh ghi liên quan đến ngắt:
1. NVIC (Nested Vectored Interrupt Controller)
Thanh ghi NVIC:
• NVIC_ISER (Interrupt Set-Enable Register): Cho phép các ngắt.

37

• NVIC_ICER (Interrupt Clear-Enable Register): Vô hiệu hóa các
ngắt.
• NVIC_ISPR (Interrupt Set-Pending Register): Đánh dấu ngắt là
chờ xử lý.
• NVIC_ICPR (Interrupt Clear-Pending Register): Xóa cờ chờ
cho ngắt.
• NVIC_IABR (Interrupt Active Bit Register): Kiểm tra trạng thái
ngắt (đang hoạt động hay không).
• NVIC_IPR (Interrupt Priority Register): Đặt độ ưu tiên cho từng
ngắt.
4.3. Các lệnh về ngắt STM32F103:
Dưới đây là một số lệnh và hàm thường dùng để cấu hình và xử lý ngắt
trong STM32F103:
1. Kích hoạt ngắt
Để kích hoạt ngắt cho một thiết bị hoặc chân GPIO, bạn cần sử dụng các
thanh ghi NVIC và EXTI:
Kích hoạt ngắt trong NVIC

Sao chép mã
NVIC_EnableIRQ(EXTI0_IRQn); // Kích hoạt ngắt cho EXTI0
2. Cấu hình ngắt cho EXTI
Cấu hình cổng GPIO làm ngắt

Sao chép mã
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Kích hoạt đồng hồ
cho GPIOA
GPIOA->CRL &= ~GPIO_CRL_CNF0; // Xóa cài đặt CNF cho PA0
GPIOA->CRL |= GPIO_CRL_CNF0_1; // Thiết lập PA0 làm ngắt
(Floating input)

38

EXTI->IMR |= EXTI_IMR_MR0; // Kích hoạt ngắt cho dòng 0
EXTI->FTSR |= EXTI_FTSR_TR0; // Kích hoạt ngắt khi tín hiệu
giảm
3. Viết hàm xử lý ngắt (ISR)
Cấu trúc một hàm xử lý ngắt cho EXTI0 có thể như sau:
Sao chép mã
void EXTI0_IRQHandler(void) {
// Xử lý ngắt
// ...

// Xóa cờ ngắt
EXTI->PR |= EXTI_PR_PR0; // Xóa cờ cho EXTI0
}
4. Vô hiệu hóa ngắt
Để vô hiệu hóa ngắt, bạn có thể sử dụng:
Sao chép mã
NVIC_DisableIRQ(EXTI0_IRQn); // Vô hiệu hóa ngắt EXTI0
5. Thiết lập độ ưu tiên cho ngắt
Để thiết lập độ ưu tiên cho một ngắt:

Sao chép mã
NVIC_SetPriority(EXTI0_IRQn, 2); // Thiết lập độ ưu tiên cho EXTI0 là
2
6. Kiểm tra trạng thái ngắt
Để kiểm tra xem một ngắt có đang chờ xử lý hay không:

Sao chép mã
if (EXTI->PR & EXTI_PR_PR0) {

39

// Cờ ngắt EXTI0 đang chờ xử lý
}
7. Kích hoạt ngắt từ phần mềm
Để kích hoạt ngắt bằng phần mềm:
Sao chép mã
EXTI->SWIER |= EXTI_SWIER_SWIER0; // Kích hoạt ngắt EXTI0 từ
phần mềm
8. Cấu hình ngắt thời gian (Timer Interrupt)
Để sử dụng ngắt từ một timer, bạn cần cấu hình timer và ngắt như sau:
Sao chép mã
TIM2->PSC = 7200 - 1; // Thiết lập prescaler
TIM2->ARR = 10000 - 1; // Thiết lập auto-reload
TIM2->DIER |= TIM_DIER_UIE; // Kích hoạt ngắt khi timer tràn

NVIC_EnableIRQ(TIM2_IRQn); // Kích hoạt ngắt cho TIM2
9. Hàm xử lý ngắt cho Timer
Sao chép mã
void TIM2_IRQHandler(void) {
if (TIM2->SR & TIM_SR_UIF) { // Kiểm tra cờ tràn
// Xử lý ngắt
TIM2->SR &= ~TIM_SR_UIF; // Xóa cờ tràn
}
}
Kết luận
Các lệnh và cấu hình trên giúp bạn thiết lập và quản lý ngắt hiệu quả trên
STM32F103. Hãy tham khảo tài liệu kỹ thuật để tìm hiểu thêm chi tiết về
từng chức năng và thanh ghi.
4.4. Bài tập 03: STM32F103 ĐIỀU KHIỂN ĐỘNG CƠ ENCODER
DC P4

40

41

42

Chương 5: PWM STM32
5.1. Giới thiệu về PWM STM32F103:
PWM (Pulse Width Modulation) trên STM32F103 là một kỹ thuật điều
chế độ rộng xung được sử dụng để điều khiển công suất, tốc độ động cơ,
độ sáng LED, và nhiều ứng dụng khác. STM32F103 có các bộ đếm thời
gian (timers) hỗ trợ chế độ PWM, giúp bạn dễ dàng cấu hình và điều
khiển.
1. Nguyên lý hoạt động của PWM
PWM điều chỉnh công suất trung bình bằng cách thay đổi độ rộng của
xung trong một chu kỳ cố định. Tần số và độ rộng của xung quyết định
lượng năng lượng được cung cấp cho tải. Tỷ lệ giữa thời gian bật và tắt
xung gọi là Duty Cycle.
2. Cấu hình PWM trong STM32F103
STM32F103 sử dụng các bộ đếm thời gian (TIM) để tạo ra tín hiệu PWM.
a. Kích hoạt đồng hồ cho Timer và GPIO

Sao chép mã
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // Kích hoạt đồng hồ
cho TIM2
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Kích hoạt đồng hồ
cho GPIOA
b. Cấu hình chân GPIO
Thiết lập chân GPIO để hoạt động ở chế độ PWM:

Sao chép mã
GPIOA->CRL &= ~GPIO_CRL_CNF1; // Xóa cài đặt CNF cho PA1
GPIOA->CRL |= GPIO_CRL_CNF1_1; // Chế độ Alternate Function
Push-Pull

43

GPIOA->CRL |= GPIO_CRL_MODE1_1; // Tốc độ 2 MHz
c. Cấu hình Timer
Cấu hình Timer để tạo PWM:

Sao chép mã
TIM2->PSC = 7200 - 1; // Thiết lập prescaler (giảm tần số)
TIM2->ARR = 100 - 1; // Thiết lập giá trị tự động (100 là giá trị max)
TIM2->CCR1 = 50; // Thiết lập Duty Cycle (50% ở đây)
TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;
// Chế độ PWM mode 1
TIM2->CCMR1 |= TIM_CCMR1_OC1PE; // Kích hoạt preload register
TIM2->CR1 |= TIM_CR1_CEN; // Kích hoạt Timer
3. Thay đổi Duty Cycle
Để thay đổi Duty Cycle của tín hiệu PWM, bạn có thể thay đổi giá trị CCR
(Capture/Compare Register):

Sao chép mã
TIM2->CCR1 = new_value; // new_value trong khoảng 0 đến ARR
4. Kết luận
PWM là một công cụ mạnh mẽ trong STM32F103 cho các ứng dụng điều
khiển công suất và điều khiển động cơ. Việc sử dụng các thanh ghi Timer
và GPIO để cấu hình PWM rất đơn giản và hiệu quả. Bạn có thể tùy chỉnh
tần số và Duty Cycle theo yêu cầu cụ thể của ứng dụng. Hãy tham khảo
tài liệu kỹ thuật của STM32F103 để tìm hiểu thêm chi tiết.

5.2. Các thanh ghi PWM của STM32F103C8T6:
Trên STM32F103C8T6, PWM được tạo ra chủ yếu thông qua các bộ đếm
thời gian (timers). Các thanh ghi chính liên quan đến cấu hình và điều

44

khiển PWM bao gồm các thanh ghi của từng bộ đếm. Dưới đây là các
thanh ghi quan trọng của TIM2, một trong những bộ đếm thường được sử
dụng để tạo PWM.
1. Cấu trúc của thanh ghi TIM

Sao chép mã
typedef struct
{
__IO uint32_t CR1; // Control Register 1
__IO uint32_t CR2; // Control Register 2
__IO uint32_t SMCR; // Slave Mode Control Register
__IO uint32_t DIER; // DMA/Interrupt Enable Register
__IO uint32_t SR; // Status Register
__IO uint32_t EGR; // Event Generation Register
__IO uint32_t CCMR1; // Capture/Compare Mode Register 1
__IO uint32_t CCMR2; // Capture/Compare Mode Register 2
__IO uint32_t CCER; // Capture/Compare Enable Register
__IO uint32_t CNT; // Counter
__IO uint32_t PSC; // Prescaler
__IO uint32_t ARR; // Auto-Reload Register
__IO uint32_t RCR; // Repetition Counter Register
__IO uint32_t CCR1; // Capture/Compare Register 1
__IO uint32_t CCR2; // Capture/Compare Register 2
__IO uint32_t CCR3; // Capture/Compare Register 3
__IO uint32_t CCR4; // Capture/Compare Register 4
__IO uint32_t BDTR; // Break and Dead-Time Register
__IO uint32_t DCR; // DMA Control Register
__IO uint32_t DMAR; // DMA Address for Full Transfer
} TIM_TypeDef;
2. Các thanh ghi chính cho PWM
• CR1 (Control Register 1): Cấu hình chế độ hoạt động của bộ đếm
(kích hoạt, hướng, chế độ đếm).

45

• PSC (Prescaler): Thiết lập giá trị phân chia tần số cho tín hiệu đầu
vào.
• ARR (Auto-Reload Register): Đặt giá trị tự động tái nạp, xác định
chu kỳ của PWM.
• CCR1, CCR2, CCR3, CCR4 (Capture/Compare Registers): Xác
định giá trị cho độ rộng xung (Duty Cycle) cho các kênh PWM
(timers thường có tối đa 4 kênh).
• CCMR1, CCMR2 (Capture/Compare Mode Registers): Thiết
lập chế độ hoạt động cho các kênh PWM, có thể cấu hình chế độ
PWM (PWM mode 1, PWM mode 2, v.v.).
• CCER (Capture/Compare Enable Register): Kích hoạt các kênh
PWM.
• SR (Status Register): Thông báo trạng thái của bộ đếm và các cờ
ngắt liên quan.
• EGR (Event Generation Register): Tạo sự kiện (reset, update,
etc.).
3. Cấu hình PWM
Để cấu hình PWM, bạn sẽ cần thiết lập các thanh ghi này theo các bước
sau:
1. Kích hoạt đồng hồ cho TIM2.
2. Cấu hình chân GPIO cho chế độ Alternate Function.
3. Thiết lập PSC, ARR để xác định tần số PWM.
4. Cấu hình CCR để xác định Duty Cycle.
5. Cấu hình CCMR để chọn chế độ PWM.
6. Kích hoạt Timer.
Ví dụ cấu hình

Sao chép mã
// Kích hoạt đồng hồ cho TIM2
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;

46

// Cấu hình GPIOA cho TIM2_CH1 (PA0)
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
GPIOA->CRL &= ~GPIO_CRL_CNF0; // Xóa cài đặt CNF cho PA0
GPIOA->CRL |= GPIO_CRL_CNF0_1; // Chế độ Alternate Function
Push-Pull
GPIOA->CRL |= GPIO_CRL_MODE0_1; // Tốc độ 2 MHz

// Cấu hình TIM2
TIM2->PSC = 7200 - 1; // Thiết lập prescaler
TIM2->ARR = 100 - 1; // Thiết lập giá trị auto-reload
TIM2->CCR1 = 50; // Thiết lập Duty Cycle (50%)
TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;
// Chế độ PWM mode 1
TIM2->CCMR1 |= TIM_CCMR1_OC1PE; // Kích hoạt preload register
TIM2->CCER |= TIM_CCER_CC1E; // Kích hoạt kênh 1
TIM2->CR1 |= TIM_CR1_CEN; // Kích hoạt Timer
4.Kết luận
Các thanh ghi PWM trong STM32F103C8T6 cho phép bạn điều chỉnh độ
rộng xung và tần số PWM một cách linh hoạt. Việc sử dụng chúng một
cách hiệu quả có thể giúp bạn tạo ra các tín hiệu PWM cho nhiều ứng
dụng khác nhau, từ điều khiển động cơ đến điều chỉnh độ sáng LED. Hãy
tham khảo tài liệu kỹ thuật để hiểu rõ hơn về từng thanh ghi và tính năng
của chúng.

5.3. Các lệnh về PWM của STM32F103C8T6:
Để điều khiển PWM trên STM32F103C8T6, bạn sẽ sử dụng Timer và cấu
hình nó để phát tín hiệu PWM. Dưới đây là các bước cơ bản và các lệnh
cần thiết:
1. Cấu hình RCC (Clock Control)
Bạn cần bật đồng hồ cho Timer bạn sẽ sử dụng, ví dụ: Timer 1.

47


Sao chép mã
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Bật đồng hồ cho Port
A
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // Bật đồng hồ cho
Timer 2
2. Cấu hình GPIO
Thiết lập chân GPIO cho chế độ Alternate Function.

Sao chép mã
GPIOA->CRL &= ~(GPIO_CRL_MODE1 | GPIO_CRL_CNF1); // Xóa
cài đặt
GPIOA->CRL |= (GPIO_CRL_MODE1_1 | GPIO_CRL_CNF1_1); //
Output 2 MHz, AF push-pull
3. Cấu hình Timer
Cấu hình Timer để phát tín hiệu PWM.

Sao chép mã
TIM2->PSC = 72 - 1; // Prescaler (1 MHz)
TIM2->ARR = 1000 - 1; // Auto-reload register (tần số PWM)
TIM2->CCR1 = 500; // Duty cycle 50%
TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;
// Cấu hình PWM mode 1
TIM2->CCMR1 |= TIM_CCMR1_OC1PE; // Enable preload register
TIM2->CCER |= TIM_CCER_CC1E; // Enable output on Channel 1
TIM2->CR1 |= TIM_CR1_CEN; // Bật Timer
4. Điều chỉnh Duty Cycle
Để điều chỉnh độ rộng xung (duty cycle), bạn có thể thay đổi giá trị CCR.

Sao chép mã

48

TIM2->CCR1 = new_value; // new_value trong khoảng 0 đến 999
5. Khởi động Timer và kiểm tra
Sau khi cấu hình, hãy khởi động Timer và kiểm tra xem tín hiệu PWM có
hoạt động đúng không.
Lưu ý:
• Chọn timer và chân GPIO phù hợp với ứng dụng của bạn.
• Tần số PWM sẽ được tính từ Timer Clock / (PSC + 1) / (ARR + 1).
5.4. Bài tập 04: STM32F103 ĐIỀU KHIỂN ĐỘNG CƠ ENCODER
DC P5

49

50

51

52


Chương 6: Ngắt timer STM32
6.1. Giới thiệu Timer của STM32F103C8T6
Timer trên STM32F103C8T6 là một phần quan trọng trong vi điều khiển
này, cho phép thực hiện nhiều chức năng khác nhau như tạo tín hiệu
PWM, đo thời gian, và tạo ra các sự kiện định kỳ. Dưới đây là một số
điểm nổi bật về các loại timer và tính năng của chúng:
1. Các loại Timer
• Basic Timer: Dùng để tạo ra các sự kiện đơn giản. Chúng không có
khả năng tạo PWM hoặc đo xung.
• General-purpose Timer (TIM2, TIM3, TIM4, TIM5): Các timer
này có khả năng tạo PWM, đo thời gian, và thực hiện các nhiệm vụ
khác. Chúng hỗ trợ nhiều chế độ hoạt động như:
o PWM Mode: Tạo tín hiệu PWM cho điều khiển động cơ,
LED, v.v.
o Input Capture: Đo độ dài xung hoặc tần số.
o Output Compare: So sánh giá trị đếm và thực hiện hành động
khi đạt được giá trị đó.
• Advanced-control Timer (TIM1): Thích hợp cho các ứng dụng
điều khiển động cơ với nhiều chức năng hơn, như điều khiển vị trí
và tốc độ.
2. Tính năng nổi bật
• Prescaler: Cho phép điều chỉnh tốc độ đếm của timer, từ đó thay
đổi tần số của các tín hiệu đầu ra.
• Auto-reload register (ARR): Thiết lập giá trị tối đa mà timer có thể
đếm, cho phép tạo các chu kỳ thời gian khác nhau.
• Capture/Compare register (CCR): Dùng để xác định độ rộng
xung (duty cycle) trong chế độ PWM hoặc lưu trữ giá trị xung đầu
vào.

53

• Interrupts: Tất cả các timer có khả năng phát sinh ngắt khi đạt giá
trị đếm nhất định, cho phép xử lý sự kiện theo thời gian thực.
3. Ứng dụng
• Điều khiển động cơ: Sử dụng PWM để điều chỉnh tốc độ và hướng
quay.
• Đo thời gian: Sử dụng timer để tạo các delay hoặc đo thời gian giữa
các sự kiện.
• Tạo tín hiệu: Sử dụng các chế độ khác nhau để tạo ra các tín hiệu
số cho các ứng dụng khác nhau.
4. Cấu trúc
Các thanh ghi quan trọng liên quan đến timer thường gồm:
• TIMx_CR1: Cấu hình điều khiển timer.
• TIMx_PSC: Prescaler.
• TIMx_ARR: Auto-reload register.
• TIMx_CCR1-4: Capture/compare registers cho các kênh khác
nhau.
• TIMx_CCMR1-2: Cấu hình chế độ hoạt động của các kênh.
5.Kết luận
Timer trên STM32F103C8T6 cung cấp nhiều tính năng mạnh mẽ cho các
ứng dụng điều khiển và đo lường, giúp bạn dễ dàng triển khai các giải
pháp khác nhau trong hệ thống nhúng. Nếu bạn cần thêm thông tin chi tiết
về từng loại timer hoặc cách sử dụng, hãy cho tôi biết!
6.2. Các thanh ghi Timer của STM32F103C8T6
Các thanh ghi Timer trên STM32F103C8T6 rất quan trọng trong việc cấu
hình và điều khiển các timer. Dưới đây là một số thanh ghi chính mà bạn
sẽ thường xuyên sử dụng khi làm việc với các timer (ví dụ TIM2, TIM3,
TIM4, TIM5) trong STM32F103C8T6:

54

1. Thanh ghi điều khiển
• TIMx_CR1:
o Điều khiển các tính năng cơ bản của timer (chẳng hạn như
bật/tắt timer, chế độ đếm lên/xuống, v.v.).
• TIMx_CR2:
o Cung cấp thêm các tùy chọn điều khiển, chẳng hạn như kích
hoạt các ngắt hoặc cấu hình các chế độ hoạt động nâng cao.
2. Thanh ghi cấu hình
• TIMx_PSC:
o Prescaler, dùng để chia tần số xung đồng hồ của timer. Giá trị
này sẽ làm giảm tần số đếm của timer.
• TIMx_ARR:
o Auto-reload register, xác định giá trị tối đa mà timer có thể
đếm tới. Khi giá trị đếm đạt đến ARR, timer sẽ reset về 0.
3. Thanh ghi Capture/Compare
• TIMx_CCR1, TIMx_CCR2, TIMx_CCR3, TIMx_CCR4 :
o Capture/Compare registers, được sử dụng để cấu hình độ rộng
xung (duty cycle) trong chế độ PWM hoặc để lưu trữ giá trị
đếm trong chế độ input capture.
4. Thanh ghi cấu hình chế độ
• TIMx_CCMR1 và TIMx_CCMR2 :
o Cấu hình chế độ hoạt động cho các kênh capture/compare. Bạn
có thể cấu hình chế độ PWM, input capture hoặc output
compare tại đây.
5. Thanh ghi điều khiển đầu ra
• TIMx_CCER:
o Điều khiển việc kích hoạt hoặc tắt các đầu ra của timer (các
kênh). Ví dụ: bật hoặc tắt chế độ PWM cho các kênh.

55

6. Thanh ghi trạng thái và ngắt
• TIMx_SR:
o Status register, dùng để kiểm tra trạng thái hiện tại của timer
(các cờ ngắt).
• TIMx_EGR:
o Event generation register, dùng để tạo ra sự kiện cho timer.
• TIMx_DIER:
o Interrupt enable register, cho phép kích hoạt các ngắt cho các
sự kiện khác nhau (như update, capture, v.v.).
7. Thanh ghi bộ đếm
• TIMx_CNT:
o Counter register, chứa giá trị hiện tại của bộ đếm timer.
8.Tóm tắt
Các thanh ghi trên cho phép bạn điều khiển timer theo nhiều cách khác
nhau, từ việc tạo ra tín hiệu PWM cho đến đo thời gian hoặc xử lý sự kiện.
Việc hiểu rõ về các thanh ghi này là rất quan trọng để triển khai các ứng
dụng sử dụng timer trên STM32F103C8T6.
Nếu bạn cần thêm thông tin cụ thể về từng thanh ghi hoặc cách sử dụng
chúng, hãy cho tôi biết!

6.3. Các lệnh về timer của STM32F103C8T6
Dưới đây là các lệnh cơ bản để cấu hình và sử dụng timer trên
STM32F103C8T6, cụ thể cho Timer 2 (TIM2). Bạn có thể áp dụng các
lệnh này cho các timer khác (TIM1, TIM3, TIM4, TIM5) với các điều
chỉnh phù hợp.

56

1. Bật đồng hồ cho Timer
Trước khi sử dụng timer, bạn cần bật đồng hồ cho nó và các chân GPIO
liên quan.
Sao chép mã
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // Bật đồng hồ cho
TIM2
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Bật đồng hồ cho Port
A
2. Cấu hình chân GPIO
Cấu hình chân GPIO cho chế độ Alternate Function (AF) để sử dụng
PWM
Sao chép mã
GPIOA->CRL &= ~(GPIO_CRL_MODE1 | GPIO_CRL_CNF1); // Xóa
cài đặt
GPIOA->CRL |= (GPIO_CRL_MODE1_1 | GPIO_CRL_CNF1_1); //
Output 2 MHz, AF push-pull
3. Cấu hình Timer
Thiết lập các thanh ghi của timer để tạo PWM.
Sao chép mã
TIM2->PSC = 72 - 1; // Chia tần số, với tần số 1 MHz
TIM2->ARR = 1000 - 1; // Đặt ARR để có tần số PWM
TIM2->CCR1 = 500; // Duty cycle 50%
TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;
// Chế độ PWM mode 1
TIM2->CCMR1 |= TIM_CCMR1_OC1PE; // Enable preload register
TIM2->CCER |= TIM_CCER_CC1E; // Bật đầu ra cho Channel 1
TIM2->CR1 |= TIM_CR1_CEN; // Bật Timer
4. Điều chỉnh Duty Cycle
Để thay đổi độ rộng xung (duty cycle), chỉ cần thay đổi giá trị của CCR.

57

Sao chép mã
TIM2->CCR1 = new_value; // new_value trong khoảng 0 đến 999
5. Khởi động Timer và kiểm tra
Sau khi cấu hình xong, Timer sẽ tự động hoạt động. Bạn có thể kiểm tra
giá trị trong thanh ghi CNT để theo dõi.
Sao chép mã
uint32_t timer_value = TIM2->CNT; // Lấy giá trị đếm hiện tại
6. Ngắt Timer
Nếu bạn muốn sử dụng ngắt, bạn có thể cấu hình như sau:
Sao chép mã
TIM2->DIER |= TIM_DIER_UIE; // Bật ngắt update
NVIC_EnableIRQ(TIM2_IRQn); // Bật ngắt cho TIM2
7. Hàm xử lý ngắt
Cần tạo hàm xử lý ngắt để thực hiện hành động khi timer phát sinh ngắt.
Sao chép mã
void TIM2_IRQHandler(void) {
if (TIM2->SR & TIM_SR_UIF) { // Kiểm tra cờ ngắt update
TIM2->SR &= ~TIM_SR_UIF; // Xóa cờ ngắt
// Thực hiện hành động ở đây
}
}
8. Kết luận
Đây là các lệnh cơ bản để cấu hình và sử dụng timer trên
STM32F103C8T6. Bạn có thể điều chỉnh các tham số và cấu hình theo
yêu cầu của ứng dụng của mình. Nếu bạn cần thêm thông tin chi tiết hoặc
có câu hỏi cụ thể hơn, hãy cho tôi biết!

58

6.4. Bài tập 05: STM32F103 ĐIỀU KHIỂN ĐỘNG CƠ ENCODER
DC_STM32 control DC motor

59

60

61

62


Chương 7: Đề tài ứng dụng STM32F103 tự chọn

7.1. Giới thiệu đề tài: STM32F103C8 hiển thị LCD 16x2
Sử dụng STM32D103C8 để hiển thị LCD 16x2 chạy trên phần mềm
Proteus
7.2. Cơ sở lý thuyết:
7.2.1 : Một số code hiển thị LCD 16x2
1. Hàm đổi trạng thái output:
Cú pháp: HAL_GPIO_TogglePin(GPIOx, GPIO_Pin);
Chức năng: Đảo trạng thái ngõ ra
Tham số:
GPIOx: Là port thao tác: GPIOA, GPIOB …
GPIO_PIN: là chân thao tác: GPIO_PIN_0, GPIO_PIN_1, …
Return: không


2. Hàm set/ reset output:
Cú pháp: HAL_GPIO_WritePin (GPIOx, GPIO_Pin, PinState);
Chức năng: Đặt trạng thái chân thao tác lên mức HIGH (1) hoặc LOW
(0)
Tham số:
GPIOx: Là port thao tác: GPIOA, GPIOB …
GPIO_PIN: là chân thao tác: GPIO_PIN_0, GPIO_PIN_1, …
PinState: Trạng thái của chân: GPIO_PIN_SET : đặt lên mức
HIGH(1).

63

GPIO_PIN_RESET : đặt lên mức
LOW(0).
Return: không

3. Hàm input:
Cú pháp: HAL_GPIO_ReadPin (GPIOx, GPIO_Pin);
Chức năng: Đọc tín hiệu số từ chân thao tác
Tham số:
GPIOx: Là port thao tác: GPIOA, GPIOB …
GPIO_PIN: là chân thao tác: GPIO_PIN_0, GPIO_PIN_1, …
Return: true hoặc false (giá trị số của chân Input)


4. Hàm Delay ms:
Cú pháp: HAL_Delay (Delay);
Chức năng: Delay ms
Tham số: Delay: số ms cần delay
Return: không
5. Thanh ghi GPIOx_ODR datasheet

ODRy[15:0]: Port output data (y= 0 .. 15)

64

Các bit này có thể đọc và ghi bằng phần mềm và được truy cập chế độ
word.
Ví dụ:
GPIOB có bit ODR0 = 0 thì chân PB0 = 0 (chân PB0 xem như là ngõ vật
lý)
GPIOB có bit ODR0 = 1 thì chân PB0 = 1 (chân PB0 xem như là ngõ vật
lý)
Truy cập chế độ Word: GPIOB->ODR = 0xFFFF;
Ví dụ:
uint16_t portB=0;

portB = portB <<1
| 0x01;
GPIOB->ODR =
portB;
Lệnh portB <<1 là dịch portB sang trái 1 bit
portB <<1 | 0x01: Sau khi dịch portB sang trái 1
bit rồi OR với 0x01.
GPIOB->ODR = portB: gán dữ liệu portB cho
thanh ghi ORD của GPIOB.

7.3. Phương án thực hiện:
Dưới đây là một kế hoạch chi tiết cho việc phát triển một dự án với vi
điều khiển STM32F401VE, bao gồm các bước từ lên ý tưởng cho đến
triển khai và kiểm tra.
1. Lên ý tưởng dự án
• Xác định ứng dụng: Quyết định loại ứng dụng sẽ phát triển (ví dụ:
thiết bị IoT, hệ thống điều khiển động cơ, hoặc thiết bị y tế).
• Chọn các cảm biến/thiết bị ngoại vi: Lựa chọn các cảm biến và
thiết bị cần thiết cho ứng dụng (ví dụ: cảm biến nhiệt độ, cảm biến
độ ẩm, động cơ servo).
2. Thiết kế phần cứng

65

• Schematic Design: Vẽ sơ đồ mạch điện sử dụng phần mềm như
KiCAD hoặc Altium Designer. Bao gồm kết nối giữa
STM32F401VE và các cảm biến, module giao tiếp.
• PCB Layout: Thiết kế PCB dựa trên sơ đồ đã tạo, đảm bảo tính khả
thi và hiệu suất của mạch.
3. Cung cấp nguồn điện
• Chọn nguồn: Đảm bảo nguồn điện đáp ứng yêu cầu của vi điều
khiển (thường là 3.3V).
• Tích hợp mạch ổn định: Sử dụng các tụ điện và mạch ổn định để
bảo đảm nguồn điện ổn định cho STM32F401VE.
4. Phát triển phần mềm
• Chọn IDE: Sử dụng STM32CubeIDE hoặc bất kỳ IDE nào hỗ trợ
lập trình cho STM32.
• Tạo dự án mới: Thiết lập dự án trong IDE, chọn vi điều khiển
STM32F401VE.
• Sử dụng thư viện HAL/LL: Sử dụng thư viện phần mềm để tương
tác với các phần cứng, giúp giảm thời gian phát triển.
• Lập trình logic điều khiển: Viết mã cho các chức năng như đọc dữ
liệu từ cảm biến, điều khiển thiết bị ngoại vi, xử lý tín hiệu.
5. Kiểm tra và gỡ lỗi
• Sử dụng Debugger: Sử dụng công cụ gỡ lỗi (như ST-Link) để kiểm
tra và sửa lỗi trong mã.
• Kiểm tra từng module: Đảm bảo từng phần của phần mềm hoạt
động đúng (kiểm tra cảm biến, giao tiếp, và các tính năng khác).
• Thực hiện kiểm tra tích hợp: Đảm bảo tất cả các phần hoạt động
cùng nhau trong hệ thống.
6. Triển khai và thử nghiệm
• Lắp ráp hệ thống: Kết nối tất cả các phần cứng lại với nhau và lắp
đặt vào vỏ nếu cần.

66

• Chạy thử nghiệm: Tiến hành các thử nghiệm thực tế để đảm bảo
hệ thống hoạt động theo yêu cầu.
• Điều chỉnh và tối ưu hóa: Dựa trên kết quả thử nghiệm, thực hiện
các điều chỉnh cần thiết để cải thiện hiệu suất hoặc độ tin cậy.
7. Tài liệu hóa
• Tài liệu kỹ thuật: Ghi chép lại toàn bộ quá trình phát triển, từ thiết
kế phần cứng đến mã nguồn và hướng dẫn sử dụng.
• Hướng dẫn người dùng: Viết hướng dẫn sử dụng cho người dùng
cuối, mô tả cách thức vận hành và bảo trì sản phẩm.
7.5. Kết quả đề tài:
Sau khi chúng ta chạy code trên STM32CubeID 1.16.0 không có lỗi thì
áp dụng code đó vào phần mềm Proteus để chạy:
Một số hình ảnh khi làm bài:

67

68

69

Code bài làm :
#include "main.h"

#include <stdio.h>

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
#define LCD_RS_Pin GPIOB,GPIO_PIN_14
#define LCD_E_Pin GPIOB,GPIO_PIN_13
#define LCD_D4_Pin GPIOB,GPIO_PIN_12
#define LCD_D5_Pin GPIOB,GPIO_PIN_11
#define LCD_D6_Pin GPIOB,GPIO_PIN_10
#define LCD_D7_Pin GPIOB,GPIO_PIN_9
#define LCD_Set_Pin(LCD_Pin) HAL_GPIO_WritePin(LCD_Pin,GPIO_PIN_SET)
#define LCD_Reset_Pin(LCD_Pin)
HAL_GPIO_WritePin(LCD_Pin,GPIO_PIN_RESET)
#define LCD_Write_Pin(LCD_Pin,value) HAL_GPIO_WritePin(LCD_Pin,value)
#define LCD_Delay_ms(time) HAL_Delay(time)
#define LCD_GetBit(value,bit) ((value>>bit) & 1)
/////=== END DEFINE THEO PHAN CUNG MOI MCU


#define LCD_Send_cmd(Value) LCD_Write_8bit(Value,0)
#define LCD_Send_cmd_4bit(Value) LCD_Write_4bit(Value,0)
#define LCD_Send_data(Value) LCD_Write_8bit(Value,1)
#define LCD_SetCursor(row,col) LCD_Send_cmd(0x80+(row*64)+col)
#define LCD_clear() LCD_Write_8bit(0x01,0)


void LCD_Write_4bit(uint8_t value, uint8_t cmd_data) {
LCD_Write_Pin(LCD_RS_Pin, cmd_data);
LCD_Set_Pin(LCD_E_Pin);
LCD_Delay_ms(1);
LCD_Write_Pin(LCD_D4_Pin, LCD_GetBit(value,0));
LCD_Write_Pin(LCD_D5_Pin, LCD_GetBit(value,1));
LCD_Write_Pin(LCD_D6_Pin, LCD_GetBit(value,2));
LCD_Write_Pin(LCD_D7_Pin, LCD_GetBit(value,3));
LCD_Delay_ms(1);
LCD_Reset_Pin(LCD_E_Pin);
LCD_Delay_ms(1);
}
void LCD_Write_8bit(uint8_t value, uint8_t cmd_data) {
LCD_Write_4bit((value >> 4) & 0x0F, cmd_data);
LCD_Write_4bit(value & 0x0F, cmd_data);
}
// Định nghĩa hàm _write để sử dụng printf
int _write(int file, char *ptr, int len) {
int i;
(void) file; // Tránh cảnh báo về biến chưa sử dụng


for (i = 0; i < len; i++) {
LCD_Write_8bit(ptr[i], 1); // Gửi từng ký tự lên LCD
}
return len;

70

}
void LCD_init() {
LCD_Send_cmd_4bit(0x03);
LCD_Delay_ms(5);
LCD_Send_cmd_4bit(0x03);
LCD_Delay_ms(1);
LCD_Send_cmd_4bit(0x03);
LCD_Delay_ms(1);
LCD_Send_cmd_4bit(0x02);
LCD_Delay_ms(1);
LCD_Send_cmd(0x28);
LCD_Delay_ms(1);
LCD_Send_cmd(0x0C);
LCD_Delay_ms(1);
}


int main(void)
{

HAL_Init();

SystemClock_Config();

MX_GPIO_Init();

LCD_init();
printf("DH TDMU\n");
LCD_SetCursor(1,0);
printf("PHAM XUAN HOANG\n");

while (1)
{

}

}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};


RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI ;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT ;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI ;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

71

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}

static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOB_CLK_ENABLE ();
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13
|GPIO_PIN_14|GPIO_PIN_9, GPIO_PIN_RESET);

GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13
|GPIO_PIN_14|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}

#ifdef USE_FULL_ASSERT

void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif /* USE_FULL_ASSERT */

7.6. Kết luận:
Qua quá trình thực hiện dự án, chúng ta đã thành công trong việc điều
khiển vi điều khiển STM32F103C8 để hiển thị thông tin lên màn hình
LCD 16x2. Các dữ liệu được hiển thị một cách rõ ràng và ổn định, chứng
tỏ hiệu quả của việc cấu hình các thanh ghi và sử dụng thư viện HAL.
Trong quá trình thực hiện, chúng tôi gặp một số khó khăn liên quan đến
việc cấu hình đúng chân GPIO và viết các hàm điều khiển LCD. Tuy
nhiên, bằng cách tham khảo tài liệu và các ví dụ có sẵn, chúng tôi đã giải
quyết được các vấn đề này.

72

Dự án này đã giúp chúng tôi làm quen với việc sử dụng STM32F103C8
và các ngoại vi cơ bản. Trong tương lai, chúng tôi có thể mở rộng dự án
bằng cách thêm vào các cảm biến khác như cảm biến nhiệt độ, độ ẩm và
hiển thị các giá trị đo được lên màn hình. Ngoài ra, chúng tôi cũng có thể
tích hợp giao diện người dùng đơn giản bằng cách sử dụng các nút nhấn
để điều khiển các thông số hiển thị.

73

TÀI LIỆU KHAM KHẢO
(7) Bài 2.01: STM32F103C8 hiển thị LCD 16x2 - YouTube
Hướng dẫn sử dụng Các hàm HAL STM Cube IDE.docx - Google Tài liệu
Tags