Giáo trình Hệ thống nhúng (Phần 2)

Lập trình nhúng hiện nay không xa lại gì với chúng ta, STM32 là chip của

ST, dựa trên nền lõi ARM Cortex-M. Dòng ARM Cortex™-M là thế hệ mới, thiết

lập các tiêu chuẩn mới về hiệu suất, chi phí, ứng dụng cho các thiết bị cần tiêu thụ

năng lượng thấp, và đáp ứng yêu cầu thời gian thực khắc khe.

Một số tính năng có sử dụng STM32 như: từ điện tử dân dụng (tivi, đầu máy,

máy giặt ), xe hơi đời mới, game, mobile, laptop chỗ nào ARM cũng có mặt.

TÍNH NĂNG NỔI BẬT:

 Hiệu suất cao

 Tiêu thụ năng lượng thấp

 Code cũng tương đối dễ vì được support gần như hết: ngoại vi (GPIO, I2C,

SPI, ADC, USB, Ethernet, CAN .), ST cung cấp cho chúng ta các thư viện trực

tiếp cho mỗi dòng ARM (gọi là CMSIS – Cortex

Microcontroller Software Interface Standard ), nhiệm vụ của chúng ta không thể

dễ dàng hơn: khai báo và sử dụng mà thôi

 Giá rẻ: STM32F1x khoảng 29000 đồng. STM32F1x chạy với tốc đọ

24Mhz.

 Flash 16.128K

 37/51/80 chân I/O

 2 bộ USART

 12 Timers

 16 kênh ADC -12bit

 2 bộ I2C

 2 bộ SPI

 2 bộ Watchdog

 16 bộ ngắt lập trình được

 RTC (đồng hồ thời gian thực tích hợp)

pdf 39 trang kimcuc 10060
Bạn đang xem 20 trang mẫu của tài liệu "Giáo trình Hệ thống nhúng (Phần 2)", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

Tóm tắt nội dung tài liệu: Giáo trình Hệ thống nhúng (Phần 2)

Giáo trình Hệ thống nhúng (Phần 2)
Chương 4. Lập trình nhúng trên ARM 
 34 
CHƯƠNG 4. LẬP TRÌNH NHÚNG TRÊN ARM 
4.1. GIỚI THIỆU ARM STM32 
Lập trình nhúng hiện nay không xa lại gì với chúng ta, STM32 là chip của 
ST, dựa trên nền lõi ARM Cortex-M. Dòng ARM Cortex™-M là thế hệ mới, thiết 
lập các tiêu chuẩn mới về hiệu suất, chi phí, ứng dụng cho các thiết bị cần tiêu thụ 
năng lượng thấp, và đáp ứng yêu cầu thời gian thực khắc khe. 
Hình 4.1 Hiệu năng ARM Cortex™-M 
Một số tính năng có sử dụng STM32 như: từ điện tử dân dụng (tivi, đầu máy, 
máy giặt), xe hơi đời mới, game, mobile, laptop  chỗ nào ARM cũng có mặt. 
TÍNH NĂNG NỔI BẬT: 
 Hiệu suất cao 
Hình 4.2 Performance DMIP S/MHz 
 Tiêu thụ năng lượng thấp 
Chương 4. Lập trình nhúng trên ARM 
 35 
Hình 4.3 So sánh tiêu thụ năng lượng giữa ARM và VĐK 16 bit hoặc 8 bit 
 Code cũng tương đối dễ vì được support gần như hết: ngoại vi (GPIO, I2C, 
SPI, ADC, USB, Ethernet, CAN.), ST cung cấp cho chúng ta các thư viện trực 
tiếp cho mỗi dòng ARM (gọi là CMSIS – Cortex 
Microcontroller Software Interface Standard ), nhiệm vụ của chúng ta không thể 
dễ dàng hơn: khai báo và sử dụng mà thôi  
 Giá rẻ: STM32F1x khoảng 29000 đồng. STM32F1x chạy với tốc đọ 
24Mhz. 
 Flash 16..128K 
 37/51/80 chân I/O 
 2 bộ USART 
 12 Timers 
 16 kênh ADC -12bit 
 2 bộ I2C 
 2 bộ SPI 
 2 bộ Watchdog 
 16 bộ ngắt lập trình được 
 RTC (đồng hồ thời gian thực tích hợp) 
Hình 4.4 so sánh 1 cách trực quan nhất giữa các dòng VXL 8 bit - 16 bit và 
Cortex™-M qua hàm "nhân 2 số 16 bit" (Cortex™-M có thể nhân 2 số 32 bit chỉ 
bằng 1 lệnh): 
Hình 
4.4 Comparing 16-bit multiply operations across processor architectures 
Chương 4. Lập trình nhúng trên ARM 
 36 
4.2. GIỚI THIỆU KIT 
 Vi xử lý ARM Cortex-M3 là thế hệ mới nhất của dòng vi xử lý ARM cho hệ 
thống nhúng. Nó được phát triển để cung cấp cho các hệ thống giá thành thấp và 
nó gần giống với MCU, với việc cắt giàm chân và năng lượng thấp, trong khi vẫn 
đảm bảo khả năng tính toán và đáp ứng ngắt được năng cao hơn. ARM Cotext M3 
dự trên kiến trúc vi xử lý RISC nhưng tối ưu hiệu quả mã lệnh, nhưng năng lực 
được đảm bảo từ nhân ARM trong kích thước bộ nhớ thường kết hợp với 8 hoặc 
16 bit . 
Dòng STM32F103 có nhân ARM vì vậy tương thích với tất cả công cụ và 
phần mền dành cho ARM. Nó là sự kết hợp hiệu năng cao từ ARM Cortex-M3 
CPU với nhiều thiết bị ngoại vi cũng như nâng cao tính năng I/O. STM32-103 Dev 
1.0 cho phép bạn khám phá hoàn toàn nhưng tính năng mới của vi điều khiển ARM 
Cortex M3 STM32F103RDT6 được phát triển từ ST Microelectronics Inc. Một vài 
ứng dụng như: USB Mass Storage device, Audio class device, HID mouse device, 
CDC Virtual com port device  
Hình 4.5 Kit STM32F103RDT6 
4.2.1. Đặc tính của kit 
1. MCU: STM32F103RDT6 ARM 32 bit CORTEX M3™ with 384K 
2. Program Flash, 64K Bytes RAM, USB, CAN, x2 I2C, x16 ADC, x2 
DAC 
3. x5 UART, x2 SPI, x12 TIMERS, up to 72Mhz operation 
4. JTAG connector tiêu chuan v_i ARM 2x10 pin dành cho viec lập trình 
và gỡ rối 
5. USB connector 
6. SD-MMC card, Audio, Microphone 
7. user buttions x3 
8. user leds x3 
9. RS-232 connector 
Chương 4. Lập trình nhúng trên ARM 
 37 
10. RESET button 
11. status LED 
12. 8 Mhz crystal oscillator 
13. 32768 Hz crystal and RTC backup battery 
14. extension headers for all uC ports 
15. Kích thước: 90.67 x 73.54mm (3.56 x 2.89") 
Yêu cầu từ board phát triển : 
 Cáp USB 1.8m để nới với PC ( dành cho việc cấp nguồn hoặc giao tiếp 
 USB trong trường hợp dùng đến tính năng USB ) 
 Phần cứng : ARM-JTAG, ARM-USB-OCD, ARM-USB-TINY or other 
ARM JTAG compatible tool. 
 Phần mềm : 
+ free open source platform: GNU C compiler + OpenOCD and Eclipse 
(support all low cost Olimex JTAG debuggers) 
+ commercial solution EW-ARM from IAR Systems AB, require 
expensive J-LINK debugger 
+ CrossWorks from Rowley (supports all Olimex low cost JTAG 
debuggers). 
4.2.2 Đặc tính STM32F103RDT6 
- CPU clock up to 72Mhz 
- FLASH 384KB 
- RAM 64KB 
- DMA x12 channels 
- RTC 
- WDT 
- Timers x11+1 
- SPI x2 
- I2C x2 
- USART x5 
- USB x1 
- CAN x1 (multiplexed with USB so both can't be used in same 
time) 
- GPIO up to 51 (multiplexed with peripherials) 
- 16 kênh ADC 12-bit, DAC x2 
- operating voltage 2.0-3.6V 
- temperature -40C +85C 
RS232: 
STM32F103RDT6 have 3 USARTs which are available on the extension 
headers. One of them can operate up to 4.5 Mbit/s, the other two up to 2.25 Mbit/s. 
They provide hardware management of the CTS and RTS signals, IrDA SIR 
ENDEC support, are ISO 7816 compliant and have LIN Master/Slave 
capability.All USART interfaces can be served by the DMA controller. 
SPI: 
STM32F103RDT6 have 2 SPIs which able to communicate up to 18 Mbits/s 
in slave and master modes in fullduplex and simplex communication modes. The 
Chương 4. Lập trình nhúng trên ARM 
 38 
3-bit prescaler gives 8 master mode frequencies and the frame is configurable from 
8-bit to 16-bit. The hardware CRC generation/verification supports basic SD 
Card/MMC modes. Both SPIs can be served by the DMA controller. 
I2C: 
STM32F103RDT6 have two I²C bus interfaces which can operate in multi-
master and slave modes. They can supportstandard and fast modes. They support 
dual slave addressing (7-bit only) and both 7/10-bit addressing in master mode. A 
hardware CRC generation/verification is embedded. They can be served by DMA 
and they support SM Bus 2.0/PM Bus. 
CAN: 
The STM32F103RDT6 CAN is compliant with specifications 2.0A and B 
(active) with a bit rate up to 1 Mbit/s. It can receive and transmit standard frames 
with 11-bit identifiers as well as extended frames with 29-bit identifiers. It has 
three transmit mailboxes, two receive FIFOs with 3 stages and 14 scalable filter 
banks.The CAN and USB share same pins PA11 and PA12, so you can’t use both 
CAN and USB on same time. 
USB: 
The STM32F103RDT6 embeds a USB device peripheral compatible with the 
USB Fullspeed 12 Mbs. The USB interface implements a full speed (12 Mbit/s) 
function interface. It has software configurable endpoint setting and 
suspend/resume support. The dedicated 48 MHz clock source is generated from 
the internal main PLL.The CAN and USB share same pins PA11 and PA12, so 
you can’t use both CAN and USB on same time. 
ADC: 
STM32F103RDT6 have two 12-bit Analog to Digital Converters which share 
up to 16 external channels, performing conversions in singleshot or scan modes. 
In scan mode, automatic conversion is performed on a selected group of analog 
inputs. Additional logic functions embedded in the ADC interface allow: 
- Simultaneous sample and hold 
- Interleaved sample and hold 
- Single shunt 
The ADC can be served by the DMA controller.An analog watchdog feature 
allows very precise monitoring of the converted voltage of one, some or all 
selected channels. An interrupt is generated when the converted voltage is outside 
the programmed thresholds. The events generated by the standard timers (TIMx) 
and the Advanced Control timer (TIM1) can be internally connected to the ADC 
start trigger, injection trigger, and DMA trigger respectively, to allow the 
application to synchronize A/D conversion and timers. 
Lưu ý: Tham khảo thêm tính năng của chíp ở tài liệu datasheet và User 
Manual. 
Chương 4. Lập trình nhúng trên ARM 
 39 
4.2.3. Sơ đồ nguyên lý board 
Chương 4. Lập trình nhúng trên ARM 
 40 
Chương 4. Lập trình nhúng trên ARM 
 41 
4.2.4 Hướng dẫn set jump cho board 
Nguồn cung cấp cho mạch 
Chương 4. Lập trình nhúng trên ARM 
 42 
Cấp nguồn ngoài 
( DC 5V ) 
Cấp nguồn từ USB 
Chương 4. Lập trình nhúng trên ARM 
 43 
Chương 4. Lập trình nhúng trên ARM 
 44 
Nút Reset 
Nút WKUP 
Nút thoát khỏi trạng thái ngủ của STM32 
Giao tiếp trực tiếp RS232 của ARM QUA USART1 
Chương 4. Lập trình nhúng trên ARM 
 45 
Thẻ nhớ SD giao tiếp trực tiếp SPI của ARM 
Header nạp và gỡ lỗi chương trình qua JTAG 
Hướng dẫn cấu hình DIP SW1 để nạp chương trình qua 
cổng USART1 với FLASH LOADER DEMOSTRATOR 
trên board OPENCMX-STM3210D 
Chức năng BOOT0 
Nạp qua 
bootloader 
Chạy chương 
trình trong 
ARM 
Chương 4. Lập trình nhúng trên ARM 
 46 
4.3. TẠO DỰ ÁN VỚI KEIL ARM 
 Giới thiệu cách tạo mới dự án cho vi xử lý ARM Cortex-M3 STM32F103RC 
bằng Keil ARM. Cùng với đó là cách tích hợp bộ thư viện chuẩn CMSIS của ST 
dành cho dòng ARM này. 
4.3.1. Bộ thư viện CMSIS 
 ST cung cấp cho người dùng bộ thư viện chuẩn lập trình giao tiếp với thiết 
bị ngoại vi tương thích với chuẩn CMSIS. Thông qua bộ thư viện này, lập trình 
viên dễ dàng giao tiếp với các thiết bị phần cứng chuẩn của các dòng Cortex-M3 
của ST. 
 Thư viện được chia làm 2 phần: 
 + phần hỗ trợ nhân Cortex-M3: bao gồm mã giao tiếp với nhân CPU, và đoạn 
mã start up code. 
 + phần hỗ trợ các thiết bị ngoại vi: chứa toàn bộ các hàm thư viện điều khiển 
thiết bị ngoại vi của ST. 
 Cấu trúc thư viện CMSIS như sau: 
 * Lưu ý: Các hàm được viết và đặt tên theo chuẩn CMSIS, lập trình viên cần 
tuân theo các quy tắc của CMSIS khi sử dụng hàm, tránh viết lại các hàm truy cập 
thẳng vào phần cứng khi không cần thiết. 
4.3.2. Khởi tạo dự án mới 
 + Mở Keil IDE, chọn menu “Project->New uVision Project” để tạo dự án 
mới. Giả dụ đặt tên dự án mới này là 24h_Led. 
 * Lưu ý: Thường khi tạo project mới hệ thống file quản lý dự án của Keil hay 
bố trí ở thư mục dự án, điều này dễ bị lẫn lộn với các file nguồn, ta nên tạo một 
thư mục con để quản lý các file dự án này. 
 Chọn chip STM32F103RC cho board 
Chương 4. Lập trình nhúng trên ARM 
 47 
Hình 4.6 Khởi tạo dự án 
 + Sau khi dự án mới được tạo, ta nên tổ chức lại hệ thống mã nguồn để dễ 
dàng theo dõi. 
Hình 4.7 Tổ chức thư mục mã nguồn 
 Như hình 2 ở trên ta tạo 4 nhóm file, các nhóm “CMSIS”, 
“StdPeriph_Driver” và “Start up” sẽ là các files từ thư viện CMSIS của ST. 
 * Lưu ý: Khi tạo mới dự án, Keil sẽ hỏi người dùng có sử dụng "start up 
code" sẵn có không. Chúng ta không sử dụng "start up code" này của Keil mà sẽ 
dùng của ST có trong bộ thư viện chuẩn. 
 + Tích hợp thư viện CMSIS vào chương trình 
Chương 4. Lập trình nhúng trên ARM 
 48 
 Chúng ta sẽ lần lượt tích hợp các thư mục trong thư viện vào dự án như sau: 
 + Nhóm “CMSIS”: thêm file core_cm3.c ở thư mục 
“\Libraries\CMSIS\CM3\CoreSupport” và system_stm32f10x.c ở thư mục 
“\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x” 
 + Nhóm “StdPeriph_Driver”: thêm các file liên quan đến điều khiển ngoạI 
vi, ở dự án này chúng ta cần điều khiển cổng GPIO, UART nên cần thêm các 
file: stm32f10x_gpio.c, stm32f10x_usart.c và stm32f10x_rcc.c ở thư mục 
“\Libraries\STM32F10x_StdPeriph_Driver\src”. 
 + Nhóm “Start up”: thêm file startup_stm32f10x_hd.s ở thư mục 
“Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm”. 
+ Nhóm “User”: chứa file của người dùng, giả sử thêm file main.c của ta vào 
đây. 
Chương 4. Lập trình nhúng trên ARM 
 49 
 * Lưu ý: Đối với nhóm StdPeriph_Driver, nên căn cứ vào nhu cầu điều khiển 
ngoại vi để thêm vào các file tương ứng, tránh thêm các file dư thừa vì làm tăng 
thời gian biên dịch và tốn tài nguyên hệ thống. 
 + Khai báo thư mục thư viện cho dự án. Sau khi thêm các file cần thiết cho 
dự án, chúng ta chưa thể biên dịch thành công được vì còn thiếu đường dẫn tới các 
file khai báo thư viện CMSIS. 
Mở khung điều khiển cấu hình dự án 
 Chọn tab “C/C++” 
 Thêm các đường dẫn thư mục sau vào dự án: 
 + \Libraries: thư mục chứa Libraries CMSIS 
 + \Libraries\CMSIS\CM3\CoreSupport 
 + \Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x 
 + \Libraries\STM32F10x_StdPeriph_Driver\inc 
 * Lưu ý : Người dùng có thể thêm vào các đường dẫn thư mục khác của dự 
án 
4.3.3. Cấu hình project 
 Sau khi đã thêm các file cần thiết cho dự án, chúng ta phải thiết lập các thông 
số cơ bản để Keil có thể biên dịch ra file thực thi. 
 + Để nạp chương trình xuống board , chúng ta cần cấu hình Keil biên dịch ra 
file hex (hoặc bin). 
 Mở khung cấu hình dự án, chọn tab “Output”, check và ô “Create HEX File” 
Chương 4. Lập trình nhúng trên ARM 
 50 
 + Để tiện sắp xếp tài nguyên của dự án, ta nên xếp các file tạm được sinh ra 
bởI Keil vào các thư mục riêng 
 Tương ứng với các file object (tab Output) và linker (tab Listing) ta lưu trong 
thư mục “Obj” và “Lst” cho tiện theo dõi sau này. 
 + Cần lưu ý là với bộ thư viện CMSIS, chúng ta sử dụng khá nhiều kỹ thuật 
“macro” trong lập trình. Có một số “macro” cần khai báo “define” sẵn trong dự án 
để có thể biên dịch thành công. 
Chương 4. Lập trình nhúng trên ARM 
 51 
 * Lưu ý: Nếu sử dụng bộ thư viện chuẩn cho thiết bị ngoại vi, nên khai báo 
macro: USE_STDPERIPH_DRIVER. 
4.3.4. Trình diễn 
 + Nếu có sẵn board , chúng ta có thể nạp trực tiếp file .hex sau khi biên dịch 
xuống chíp thông qua Flash Downloader của ST bằng cổng COM. 
 + Nếu không có board, chúng ta có thể xem bằng cách dùng Debug Simulator 
của Keil 
 + Chạy Debug chương trình, mở cửa sổ theo dõi các thiết bị ngoại vi ở menu 
“Peripherals” chọn ngoại vi tương ứng, giả sử đó là Port C của GPIO. 
 Bấm F10 (hoặc F11) để chạy debug từng dòng lệnh đồng thời theo dõi giá trị 
của Port C thay đổi. 
4.4. CÁC BƯỚC NẠP CHƯƠNG TRÌNH 
B1: chuyển STM32 qua chế độ nạp bằng cổng USART1 nhờ vào DIP SW1 
B2: Chạy chương trình nạp FLASH LOADER DEMOSTRATOR và thiết lập 
thông số như trong hình 
Bấm chọn Next 
NẾU HIỆN RA THÔNG BÁO NHƯ SAU 
Chương 4. Lập trình nhúng trên ARM 
 52 
Chú ý làm các bước như sau : 
1. Rút nguồn cấp ra khỏi boad chờ sau 5s rùi cấp nguồn lại 
2. Kiểm tra lại cáp COM 
3. Kiếm tra lại DIP SW1 thiết lập STM32 ở bootloader đã đúng chưa? 
Nếu như bạn đã làm như các bước trên mà vẫn hiện ra thông báo đó thì có thể 
STM32 của bạn không vào được bootloarder hoặc chíp ARM của bạn đã fuse 
“WRITE PROTECT : ENABLE 
B2 : Nếu chương trình nhận ra bootloader từ ARM, lúc đó chương hiện ra thông 
báo như sau: 
Bạn bấm vào button “Next” 
Hoặc gặp thông báo cảnh báo Remove protection, khi đó bạn bấm vào button 
“Remove protection” Chờ cho chương trình xóa xong, bạn Nhấn “Close “ bạn 
chạy lại chương trình và làm lại như Bước 1 
B3 : Khi bạn gặp thông báo 
Chương 4. Lập trình nhúng trên ARM 
 53 
Bạn bấm “Next” 
B4 : Bạn thiết lập thông số như trong hình dưới 
Bạn chọn file nạp bằng cách bấm vào nút “” Khi đó bạn trỏ tới file hex mà 
bạn muốn nạp cho STM32. Xong bạn bấm button “Open”. Khi đó chương trình 
sẽ ra trở lại màn hình như sau. Nếu bạn muốn chương trình kiểm tra lại nội 
dung file nạp có đúng với nội dung của STM32 hay không bạn click chọn “Verify 
after download” 
B4: Bạn tiếp tục bấm “Next” 
Khi nạp xong chương trình thông báo: 
Chương 4. Lập trình nhúng trên ARM 
 54 
Bạn chọn “Close” để đóng chương trình 
B5: Thiết lập lại DIP SW1 để chạy chương trình trong ARM. 
4.5. LẬP TRÌNH NHÚNG TRÊN ARM 
4.5.1. Điều khiển LED đơn 
Trước khi bắt đầu chúng ta cần mở file stm32f10x.h lên và xem phần sau: 
/* #define STM32F10X_LD */ /*!< STM32F10X_LD: STM32 Low density devices 
*/ 
/* #define STM32F10X_LD_VL */ /*!< STM32F10X_LD_VL: STM32 Low density 
Value Line devices */ 
/* #define STM32F10X_MD */ /*!< STM32F10X_MD: STM32 Medium density 
devices */ 
/* #define STM32F10X_MD_V ... h 4 số Anode chung 
Sau khi khởi tạo thành công Project, các bạn thêm các File.c cần thiết vào các 
Folder, cụ thể: 
-FWlib: stm32f10x_gpio.c, stm32f10x_rcc.c, stm32f10x_tim.c, misc.c 
-Main: main.c 
-User: led7.c 
-UserSTM32: user_delay.c, user_gpio.c, user_interrupt.c, user_nvic.c, 
user_timer.c 
-StartUp: core_cm3.c, startup_stm32f10x_md.s, system_stm32f10x.c 
Trong hàm main.c các bạn cần sử dụng: 
-Hàm SystemInit(): Đây là hàm khởi tạo nguồn Clock cho vi điều khiển (các bạn 
có thể tham khảo thêm nguồn Clock cho STM32 tại đây, trong bài toán này mình 
sử dụng nguồn Clock có tần số 72MHz. 
-Hàm NVIC_Configuration(): Đây là hàm cấu hình ngắt (nằm trong 
File user_nvic thuộc Folder UserSTM32), vì bài toán sử dụng ngắt tràn TIM2 để 
tạo khoảng thời gian 1ms: 
void NVIC_Configuration(void) 
{ 
 NVIC_InitTypeDef NVIC_InitStructure; 
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); 
 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; 
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
 NVIC_Init(&NVIC_InitStructure); 
} 
Chương 4. Lập trình nhúng trên ARM 
 61 
- Hàm GPIO_Configuration(): Đây là hàm khởi tạo và cấu hình chức năng GPIO 
(nằm trong File user_gpio thuộc Folder UserSTM32), đối với bài toàn này, các 
bạn cần cấu hình: 
+ các chân PA0 – PA7 là chân Output Push Pull, tốc độ trung bình 50MHz. 
+ các chân PB12 – PB15 là chân Output Push Pull, tốc độ trung bình 50MHz. 
void GPIO_Configuration(void) 
{ 
 GPIO_InitTypeDef GPIO_InitStructure; 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 
 GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE); 
/******************************* PORTA ***********************************/ 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); 
/*___________________________ OUTPUT_______________________*/ 
 GPIO_InitStructure.GPIO_Pin = 
GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|G
PIO_Pin_7; 
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
 GPIO_Init(GPIOA, &GPIO_InitStructure); 
/*___________________________ INPUT ________________________*/ 
/**************************** PORTB *************************/ 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); 
/*___________________________ OUTPUT _______________________*/ 
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15; 
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
 GPIO_Init(GPIOB, &GPIO_InitStructure); 
/*___________________________ INPUT _________________________*/ 
} 
-Hàm TIMER2_Configuration(): Đây là hàm cấu hình cho TIM2. Các bạn cấu 
hình cho TIM2 xảy ra ngắt sau thời gian 1ms: 
void TIMER2_Configuration(void) 
{ 
 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); 
 TIM_TimeBaseStructure.TIM_Prescaler = 35999; 
 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
 TIM_TimeBaseStructure.TIM_Period = 1; 
 TIM_TimeBaseStructure.TIM_ClockDivision = 0; 
 TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; 
 TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); 
 TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); 
 TIM_Cmd(TIM2,ENABLE); 
} 
Chương 4. Lập trình nhúng trên ARM 
 62 
- Hàm delay_init(72): Đây là hàm khởi tạo để sử dụng các hàm delay_ms(), 
delay_us() (nằm trong File user_delay thuộc Folder UserStm32), 72 là tần số 
nguồn Clock sử dụng. 
Sau 1 ms, ngắt tràn TIM2 xảy ra, các bạn thực hiện quét Led ở trình phục vụ ngắt 
TIM2 void TIM2_IRQHandler(void) (nằm trong File user_interrupt thuộc 
Folder UserStm32): 
void TIM2_IRQHandler(void) 
{ 
 if(TIM_GetITStatus(TIM2,TIM_IT_Update)) 
 { 
 TIM_ClearITPendingBit(TIM2,TIM_IT_Update); 
 LED7_Display(Value_Display); 
 } 
} 
Trong trình phục vụ ngắt mình sử dụng hàm hiển thị giá trị số lên Led 7 thanh void 
LED7_Display(uint16_t Value) (nằm trong File led7 thuộc Folder User): 
void LED7_Display(uint16_t Value) 
{ 
 LED7_CacuCode(Value); 
 LED7_PowerOff(); 
 LED7_DataOut(Led7_BufferData[Led7_Index]); 
 LED7_PowerOn(Led7_Index); 
 Led7_Index++; 
 if(Led7_Index>=NUMBER_LED7)Led7_Index=0; 
} 
Thực hiện thay đổi giá trị hiển thị lên Led 7 thanh trong vòng while(1): 
while(1) 
{ 
 Value_Display++; 
 if(Value_Display > 9999) Value_Display = 0; 
 delay_ms(500); 
} 
Biên dịch chương trình và nạp chạy demo trên KIT STM32 START 
4.5.4. LCD 16X2 4 bit 
a) Sơ đồ phần cứng 
Chương 4. Lập trình nhúng trên ARM 
 63 
Hình 4.9. Sơ đồ kết nối board với LCD 16x2 
Trong đó, các chân kết nối với STM32F103C8T: 
-Các chân điều khiển LCD16x2 LCD_RS, LCD_RW, LCD_EN kết nối thứ tự 
với các chân PORTB[12 – 14]. 
-Các chân dữ liệu của LCD16x2 LCD_D[4 – 7] kết nối thứ tự với các 
chân PORTA[4 – 7]. 
b) Lập trình phần mềm 
Sau khi khởi tạo thành công Project, các bạn thêm các File.c cần thiết vào các 
Folder, cụ thể: 
-FWlib: stm32f10x_gpio.c, stm32f10x_rcc.c 
-Main: main.c 
-User: lcd16x2.c 
-UserSTM32: user_delay.c, user_gpio.c 
-StartUp: core_cm3.c, startup_stm32f10x_md.s, system_stm32f10x.c 
Trong hàm main.c các bạn cần sử dụng: 
-Hàm SystemInit(): Đây là hàm khởi tạo nguồn Clock cho vi điều khiển, trong 
bài toán này mình sử dụng nguồn Clock có tần số 72MHz. 
-Hàm GPIO_Configuration(): Đây là hàm khởi tạo và cấu hình chức năng GPIO 
(nằm trong File user_gpio thuộc Folder UserSTM32), đối với bài toàn này, các 
bạn cần cấu hình: 
+ các chân PA[4 – 7] là chân Output Push Pull, tốc độ trung bình 50MHz. 
+ các chân PB[12 – 14] là chân Output Push Pull, tốc độ trung bình 50MHz. 
Chương 4. Lập trình nhúng trên ARM 
 64 
void GPIO_Configuration(void) 
{ 
 GPIO_InitTypeDef GPIO_InitStructure; 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 
 GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE); 
/***************************** PORTA ***********************/ 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); 
/*____________________________ OUTPUT _____________________*/ 
 GPIO_InitStructure.GPIO_Pin =GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; 
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
 GPIO_Init(GPIOA, &GPIO_InitStructure); 
/*___________________________ INPUT _________________________*/ 
/**************************** PORTB ***********************************/ 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); 
/*___________________________ OUTPUT ________________________*/ 
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14; 
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
 GPIO_Init(GPIOB, &GPIO_InitStructure); 
/*___________________________ INPUT ________________________*/ 
} 
- Hàm delay_init(72): Đây là hàm khởi tạo để sử dụng các hàm delay_ms(), 
delay_us() (nằm trong File user_delay thuộc Folder UserStm32), 72 là tần số 
nguồn Clock sử dụng. 
- Các bạn khởi tạo LCD16x2 và lập trình hiển thị các chuỗi ký tự: 
LCD16X2_Init(); 
LCD16X2_Gotoxy(0,0); 
LCD16X2_Puts((uint8_t*)" MinhHaGroup "); 
LCD16X2_Gotoxy(0,1); 
LCD16X2_Puts((uint8_t*)"KIT STM32 START "); 
while(1) 
{ 
} 
Các hàm Driver cho LCD16x2 các bạn xem ở File lcd16x2 thuộc Folder User. 
Biên dịch chương trình và nạp chạy demo trên KIT STM32 
4.5.5. Lập trình UART giao tiếp PC 
a) Lập trình UART cho ARM STM32 
- Tạo một Project tương tự như với lập trình GPIO , chúng ta thêm driver 
stm32f10x_uart.c trong thư viện CMIS vào để có thể lập trình truyền nhận dữ liệu 
UART 
Chương 4. Lập trình nhúng trên ARM 
 65 
- Viết code cho chương trình chính trong hàm maic.c 
Khai báo IO cho UART: 
 GPIO_Init(GPIOA, &GPIO_InitStructure); 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //USART1 TX 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
GPIO_Init(GPIOA, &GPIO_InitStructure); 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_8; //USART1 RX 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_Init(GPIOA, &GPIO_InitStructure); 
Cấu hình UART: 
void USART1_Configuration(void) 
{ 
USART_InitTypeDef USART_InitStructure; 
//Kich hoat Clock USART1 
RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1, ENABLE); 
//Chon BaudRate 
USART_InitStructure.USART_BaudRate = 115200; 
//Chon do dai khung truyen 
USART_InitStructure.USART_WordLength = USART_WordLength_8b; 
//Chon stop bit 
USART_InitStructure.USART_StopBits = USART_StopBits_1; 
//Chon Parity 
USART_InitStructure.USART_Parity = USART_Parity_No; 
//Chon che do dieu khien 
USART_InitStructure.USART_HardwareFlowControl = 
USART_HardwareFlowControl_None; 
//Chon phuong thuc truyen nhan 
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;// 
Chương 4. Lập trình nhúng trên ARM 
 66 
//Cau hinh cac thong so vua lua chon 
USART_Init(USART1, &USART_InitStructure); 
//Kich hoat hoat dong cua USART 
USART_Cmd(USART1, ENABLE); 
} 
Hàm ghi dữ liệu 
Hàm đọc dữ liệu từ cổng UART: 
USART_ReceiveData(USART1); 
Hàm gửi chuỗi dữ liệu ra cổng UART: 
USART_SendString(USART1,"demo") 
b) Lập trình giao diện truyền nhận dữ liệu UART dùng Visual Basic 
- Khởi động chương trình 
- Cửa sổ khởi động chọn StandardEXE để tạo một form mới 
- Giao diện chương trình 
Chương 4. Lập trình nhúng trên ARM 
 67 
- Click chuột vào form1 để đổi tên cho project trong mục caption 
Nhấp chuột vào biểu tượng textbox để lấy textbox ra màn hình 
Trong phần thuộc tính của textbox xóa chữ text1 trong caption đi 
- Tiếp tục chọn label để kéo label vào chương trình, thay đổi tên label trong thuộc 
tính caption 
- Tiếp tục với button 
29 
- Chỉnh sửa và thêm một số thành phần để có form như hình dưới 
Chương 4. Lập trình nhúng trên ARM 
 68 
Như vậy ta đã tạo ra một Form các tham số a,b hiển thị với các textbox1,2. Nút 
truyền là Command1 nút nhận là Command2, nút thoát là Command3 
Form hoạt động như sau : Nhập các thông số trong text1, nhấn nút truyền để gửi 
dữ liệu trong text1 ra cổng COM. Nhấn nút nhận thì dữ liệu nhận được sẽ hiển thị 
lên text2. Phím Exit để thoát khỏi chương trình 
Vì Control để điều khiển cổng COM-MSCOM không phải control cơ bản nên nó 
không hiển thị trên tool, chúng ta phải lấy ra trong thư viện như sau 
- Kéo thả MSCOM vào form 
- Để soạn thảo code cho chương trình VB, ta click chuột vào vị trí bất kỳ trong 
form 
Chương 4. Lập trình nhúng trên ARM 
 69 
- Giao diện chính 
- Khai báo sử dụng cổng COM 
- Để viết mã cho nút truyền ta click vào nút truyền và code như sau. Khai báo 
thêm biến s để chứa giá trị của text 
- Tương tự cho nút nhận 
- Và nút Exit 
- Lưu form vừa tạo, chọn Run để chạy chương trình 
32 
- Kết quả: 
Chương 4. Lập trình nhúng trên ARM 
 70 
- Chọn file – Make tut.exe để tạo file thực thi và chạy như một phần mềm thông 
thường 
4.6. CÂU HỎI VÀ BÀI TẬP 
1. Trình bày các thành phần và mô hình lập trình của vi điều khiển ARM 
2. Trình bày được một số lệnh cơ bản trong tập lệnh của ARM 
3. Hàm và các bước thực hiện khi gọi một hàm 
4. Khái niệm ngắt và chương trình phục vụ ngắt 
5. Các bước thực thi khi thực hiện một ngắt. 
6. Viết CT Quét ma trận bàn phím. Chống dội 
7. Viết CT đếm 00-99 hiển thị trên LCD 16x2 
8. Viết CT hiển thị phút và giây trên Led 7 đoạn 
9. Viết CT điểu khiển 8 led đơn sáng dần sau đó tắt dần 
10. Viết chương trình cho vi điều khiển để giải phương trình bậc một ax + b = 0. 
Trong đó a và b nhập từ port A và B. Kết quả hiển thị trên LCD. 
11. Viết chương trình C cho vi điều khiển để giải phương trình bậc hai ax^2 + bx + c = 0. 
Trong đó, a, b và c nhập vào từ port B, C, và D. Kết quả được hiển thị trên serial LCD. 
Hãy mô phỏng hệ thống bằng phần mềm Proteus. 
12. Cho một hệ thống nhúng sử dụng vi điều khiển được mô tả như sau: 
 Port A (PA0, PA1, PA2) nối với 3 nút nhấn tích cực mức thấp, có tên là UP, 
DOWN, CLEAR 
 Port B (PB0, PB1  PB6) nối với một LED 7 đoạn Anode chung, có các chân A, 
B, C, D, E, F, G. 
 Sau khi RESET, LED 7 đoạn hiển thị số 0 
 Khi nhấn nút UP, số hiển thị sẽ tăng 1 (tối đa tăng đến số 9). 
 Khi nhấn nút DOWN thì số hiển thị sẽ giảm 1 (tối thiểu giảm đến số 0). 
 Khi nhấn nút CLEAR, số hiển thị về 0. 
 Khi không nhấn nút thì số hiển thị giữ nguyên 
a) Hãy vẽ sơ đồ mạch chi tiết cho hệ thống trên 
b) Hãy viết chương trình C để thực hiện chức năng điều khiển hệ thống trên. 
13. Cho một hệ thống nhúng điều khiển khóa cửa sử dụng PIC16F84 được mô tả 
như sau: 
 RB0, RB1, RB2, RB3, RB4: nối với 5 nút nhấn 1, 2, 3, 4, 5 (tích cực mức 
thấp). 
Chương 4. Lập trình nhúng trên ARM 
 71 
 RB5: nối với nút nhấn tích cực mức thấp, có tên là ENTER 
 RB6: điều khiển RELAY tích cực mức cao thông qua transistor. 
 RB7: điều khiển đèn LED cảnh báo tích cực mức cao. 
 Nguyên lý hoạt động: 
o Người đi vào cửa bấm vào mã số (gồm 5 số) và sau đó bấm ENTER 
 Nếu đúng mật mã 54321, RB6 sẽ tích cực mức cao để mở cửa. 
 Nếu sai mật mã, đèn LED cảnh báo sáng. 
o Các nút nhấn có chức năng chống rung phím. 
14. Thiết kế một hệ thống nhúng điều khiển nhiệt độ lò điện đơn giản. Hệ thống 
sử dụng cảm biến nhiệt độ lò LM35, PIC16F877A, led 7 đoạn và relay bật tắt lò. 
Cho điện áp tham khảo của ADC Vref = 5V, độ phân giải của cảm biến LM35 là 
tuyến tính với 10mV/oC. 
 Cảm biến nhiệt độ được nối vào AN0 của PIC 
 Relay bật tắt lò được nối vào chân RE2 của port E 
 Hai led 7 đoạn anode chung nước nối vào 2 port B, C 
 Sau khi RESET, hai led 7 đoạn hiển thị nhiệt độ hiện tại của lò 
 Khi nhiệt độ trong lò nhỏ hơn 80oC thì RE2 được cài đặt bằng 1 để bật lò. 
 Khi nhiệt độ lớn hơn 120oC thì RE2 được cài đặt bằng 0 để tắt lò. 
a) Hãy vẽ sơ đồ mạch chi tiết cho hệ thống trên 
b) Hãy viết chương trình C để thực hiện chức năng điều khiển hệ thống trên. 
15. Hãy viết chương trình điều khiển cho 16F877A để tạo xung ở ngõ ra B0 bao 
gồm xung 10kHz và 1kHz lồng vào nhau mô tả như hình dưới. Chu kỳ nhiệm vụ 
của xung 10kHz và 1kHz là 50%. 
 ___||_||_||_||_||_________________||_||_||_||_||_______________ 
16. Hãy viết chương trình C cho PIC16F877A tạo xung vuông ở 2 ngõ ra RC0 và 
RC1, với tần số xung clock lần lượt là 0.5KHz và 1KHz, duty cycle là 50%. Hãy 
sử dụng ngắt Timer1 với thạch anh 4MHz. 
17. Hãy viết chương trình cho vi điều khiển PIC16F877A sử dụng thạch anh 
20MHz tạo sóng sin có tần số 1 KHz bằng phương pháp có điều chế ở 10 KHz. 
18. Lập trình giao tiếp KIT STM32 với máy tính qua USART, lập trình truyền thông KIT với điện 
thoại Android qua Bluetooth. 
 72 
TÀI LIỆU THAM KHẢO 
[1]. Andrew Sloss, Dominic Symes, Chris Wright, ARM System Developer's 
Guide: Designing and Optimizing System Software, Morgan Kaufmann, 2004 
[2]. RajKamal, Embedded Systems-Architecture, Programming and Design, 
McGraw Hill, 2003 
[3]. Steve Heath, Embedded Systems Design, Second Edition, Newnes, 2002. 
[4]. Tammy Noergaard, Embedded Systems Architecture: A Comprehensive 
Guide for Engineers and Programmers, Newnes, 2005. 
[5]. Đinh Công Đoan, Bài Giảng Hệ Thống Nhúng, Khoa CNTT Đại học SPKT 
TP.HCM 

File đính kèm:

  • pdfgiao_trinh_he_thong_nhung_phan_2.pdf