Upload
duong-vu-kien
View
926
Download
11
Embed Size (px)
Citation preview
Trang 1
MỤC LỤC
CHƢƠNG 1: CÁC KHÁI NIỆM CƠ BẢN TRONG HỆ THỐNG NHÚNG ................ 3
1.1. Hệ nhúng ........................................................................................................... 3
1.2. Hệ thời gian thực ............................................................................................... 3
1.3. Biễu diễn số và dữ liệu ...................................................................................... 3
1.4. Cấu trúc phần cứng của hệ thống nhúng ............................................................ 4
1.5. Hệ điều hành nhúng và phần mềm nhúng .......................................................... 5
1.5.1. Hệ điều hành nhúng .................................................................................... 5
1.5.2. Hệ điều hành thời gian thực –RTOS: (Realtime Operationg System ) ......... 6
1.5.3. Phần mềm nhúng ........................................................................................ 7
1.6. Quy trình thiết kế hệ thống nhúng ..................................................................... 8
1.7. Mô hình hệ thống nhúng .................................................................................. 10
CHƢƠNG 2: HỌ VI ĐIỀU KHIỂN ARM ................................................................. 11
2.1. Tổng quan ....................................................................................................... 11
2.2. Cơ chế Pipeline ............................................................................................... 12
2.3. Các thanh ghi .................................................................................................. 13
2.4. Thanh ghi trạng thái chƣơng trình hiện hành ................................................... 14
2.5. Các mode ngoại lệ ........................................................................................... 15
2.6. Tập lệnh ARM 7 .............................................................................................. 16
2.6.1. Các lệnh rẽ nhánh ..................................................................................... 18
2.6.2. Các lệnh xử lý dữ liệu ............................................................................... 18
2.6.3. Các lệnh truyền dữ liệu ............................................................................. 19
2.6.4. Lệnh SWAP ............................................................................................. 20
2.7. Ngắt mềm (SWI – Software Interrupt Instruction) ........................................... 20
2.8. Đơn vị MAC (Multiply Accumulate Unit (MAC) ............................................ 21
2.9. Tập lệnh THUMB ........................................................................................... 21
2.10. Phần mềm phát triển và công cụ phần cứng ................................................... 23
2.10.1. Cấu trúc file start up ............................................................................... 23
2.10.2. Công cụ phần cứng ................................................................................. 25
2.10.3. Cách viết chƣơng trình C với tập lệnh ARM và tập lệnh THUMB .......... 25
2.11. Cấu trúc bên trong ......................................................................................... 26
2.11.1. Bản đồ bộ nhớ ........................................................................................ 26
2.11.2. Lập trình thanh ghi ................................................................................. 27
Trang 2
2.11.3. Memory Acelerator Module (MAM) ...................................................... 27
2.11.4. PLL- Phase Locked Loop ....................................................................... 29
2.11.5. Bộ chia bus (VLSI Peripheral Bus Divider) ............................................ 32
2.12. Các cổng vào ra ............................................................................................. 33
CHƢƠNG 3: LẬP TRÌNH VI ĐIỀU KHIỂN ARM ................................................... 34
3.1. Hƣớng dẫn sử dụng phần mềm Keil C ............................................................. 34
3.2. Truy nhập các chân vào ra chung..................................................................... 42
Thí dụ 1: Viết chƣơng trình điều khiển led đơn sáng nhấp nháy ......................... 43
Thí dụ 2: Chƣơng trình hiển thị chữ trên LCD .................................................... 44
3.3. Lập trình ngắt .................................................................................................. 50
3.3.1. Chân Connect Block ................................................................................. 50
3.3.2. Các chân ngắt ngoài .................................................................................. 51
3.3.3. Cấu trúc ngắt ............................................................................................ 52
3.3.4. Ngắt FIQ .................................................................................................. 54
3.3.5. Kết thúc ngắt ............................................................................................ 56
3.3.6. Vecto IRQ ................................................................................................ 56
3.3.7. Kết thúc một ngắt IRQ .............................................................................. 57
3.3.8. Ngắt không có địa chỉ ............................................................................... 58
3.3.9. Kết thúc ngắt không địa chỉ ...................................................................... 59
3.4. Lập trình Timer ............................................................................................... 59
3.4.1. Các Timer ................................................................................................. 59
3.4.2. Đồng hồ thời gian thực (Real Time Clock - RTC) .................................... 67
3.5. Lập trình qua UART........................................................................................ 70
3.6. Giao diện I2C .................................................................................................. 78
3.7. Giao diện SPI .................................................................................................. 81
3.8. Chuyển đổi ADC và DAC ............................................................................... 83
3.8.1. Chuyển đổi ADC ...................................................................................... 83
3.8.2. Chuyển đổi D/A ........................................................................................ 85
3.9. Truyền dữ liệu qua CAN(Controller Area Network) ........................................ 85
TÀI LIỆU THAM KHẢO .......................................................................................... 92
Trang 3
CHƢƠNG 1: CÁC KHÁI NIỆM CƠ BẢN TRONG HỆ THỐNG NHÚNG
(tổng số tiết: 3T, số tiết lý thuyết: 3T, số tiết thực hành: 0)
1.1. Hệ nhúng
Hệ nhúng là một phần hệ thống xử lý thông tin nhúng trong các hệ thống
lớn, phức hợp và độc lập. Thí dụ: ôtô, tủ lạnh, các thiết bị đo lƣờng, điều khiển,
truyền thông.
Là những tổ hợp của phần cứng và phần mềm để thực hiện một hoặc một
nhóm chức năng chuyên biệt, cụ thể (Trái ngƣợc với máy tính PC là đa năng).
Một hệ thống nhúng là một máy tính với chất lượng cao, yêu cầu về độ tin cậy
cao hơn các loại máy tính khác.
Các thiết bị PDAs, Web pad không phải là hệ thống nhúng.
1.2. Hệ thời gian thực
Chia làm 2 loại:
Thời gian thực cứng là khi hệ thống hoạt động với yêu cầu thoả mãn sự ràng
buộc trong khung thời gian cứng tức là nếu vi phạm thì sẽ dẫn đến hoạt
động của toàn hệ thống bị sai hoặc bị phá huỷ. Thí dụ: Lò phản ứng hạt
nhân,…
Thời gian thực mềm là khi hệ thống hoạt động với yêu cầu thoả mãn ràng
buộc trong khung thời gian mềm, nếu vi phạm và sai lệch nằm trong khoảng
cho phép thì hệ thống vẫn có thể hoạt động được và chấp nhận được. Thí dụ
nhƣ hệ thống phát thanh truyền hình.
Hầu hết hệ nhúng là các hệ thời gian thực và hầu hết các hệ thời gian thực là hệ
nhúng-> Thuộc tính thời gian là thuộc tính tiêu biểu cho hệ thống nhúng.
1.3. Biễu diễn số và dữ liệu
Đơn vị cơ bản nhất trong biểu diễn thông tin của hệ thống số đƣợc gọi là bit,
chính là ký hiệu viết tắt của thuật ngữ binary digit.
1964, IBM đã thiết kế và chế tạo máy tính số sử dụng một nhóm 8 bit để
đánh địa chỉ bộ nhớ và định nghĩa ra thuật ngữ 8 bit = 1 byte.
Ngày nay sử dụng rộng rãi thuật ngữ word là một từ dữ liệu dùng để biểu
diễn kích thƣớc dữ liệu mà đƣợc xử lý một cách hiệu quả nhất đối với mỗi
Trang 4
loại kiến trúc xử lý số cụ thể. Chính vì vậy một từ có thể là 16 bits, 32 bits,
hoặc 64 bits…
Mỗi một byte có thể đƣợc chia ra thành hai nửa 4 bit và đƣợc gọi là các
nibble.
Nibble chứa các bít trọng số lớn đƣợc gọi là nibble bậc cao, và nibble chứa
các bit trọng số nhỏ đƣợc gọi là nibble bậc thấp.
Các hệ thống cơ số:
Một cách tổng quát một hệ biểu diễn số cơ số b và a là một số nguyên nằm
trong khoảng giá trị cơ số b đƣợc biểu diễn nhƣ sau:
n
i
i
i xbaA0
1
cơ số binary (nhị phân), cơ số decimal (thập phân), cơ số hexadecimal, cơ số
8 Octal (bát phân).
1.4. Cấu trúc phần cứng của hệ thống nhúng
Hình 1.1. Kiến trúc cơ bản của của các chip vi điều khiển nhúng
CPU: Đóng vài trò là bộ não, giả mã và thực thi lệnh, gồm khối ALU, bộ giả
mã, bộ tuần tự và các thanh ghi.
Trang 5
Xung nhịp và trạng thái tín hiệu: Hoạt động của hệ thống đƣợc thực hiện đồng bộ hoặc
dị bộ theo các xung nhịp chuẩn. Các nhịp đó đƣợc lấy trực tiếp hoặc gián tiếp từ một
nguồn xung chuẩn thƣờng là các mạch tạo xung hoặc dao động thạch anh.
Bus: có 3 loại, bus dữ liệu, địa chỉ và điều khiển (Bus điều khiển phục vụ
truyền tải các thông tin dữ liệu để điều khiển hoạt động của hệ thống).
Bộ nhớ: có 2 loại kiến trúc
- Kiến trúc von neumann: không phân biệt vùng chứa dữ liệu và mã
chƣơng trình. Cả chƣơng trình và dữ liệu đều đƣợc truy nhập theo
cùng một đƣờng.
- Kiến trúc Havard: tách/phân biệt vùng lƣu mã chƣơng trình và dữ liệu.
Mã chƣơng trình chỉ có thể đƣợc lƣu và thực hiện trong vùng chứa
ROM và dữ liệu cũng chỉ có thể lƣu và trao đổi trong vùng RAM.
Hầu hết các vi xử lý nhúng ngày nay sử dụng kiến trúc bộ nhớ Havard hoặc kiến
trúc Havard mở rộng (tức là bộ nhớ chƣơng trình và dữ liệu tách biệt nhƣng vẫn cho
phép khả năng hạn chế để lấy dữ liệu ra từ vùng mã chƣơng trình).
Bộ nhớ chƣơng trình: Eprom và Flash
Là các chíp khả trình, cấu tạo từ các transitor, eprom có thể xóa bằng tia cực tím,
trong khi Flash có thể xóa bằng các xung điện, có thể lập trình trực tiếp và không cần
tháo ra khỏi mạch.
Bộ nhớ RAM: gồm SRAM và DRAM
Bộ điều khiển ngắt: Xử lý yêu cầu ngắt
Bộ định thời chó canh (Watchdog Timer): Là một bộ định thời đặc biệt để
định nghĩa 1 khung thời gian hoạt động bình thƣờng của hệ thống. Tự động
reset lại hệ thống khi phát hiện các sự cố mềm nhƣ hệ thống bị treo hoặc chạy
quẩn.
Khung thời gian do ngƣời lập trình đặt ra.
1.5. Hệ điều hành nhúng và phần mềm nhúng
1.5.1. Hệ điều hành nhúng
- Đóng vai trò trung gian để tƣơng tác trực tiếp với phần cứng và các chƣơng trình ở
lớp trên cũng nhƣ ngƣời sử dụng: Quản lý các tiến trình, quản lý tài ngyên và bảo về
các tài nguyên khỏi sự xâm phạm.
Trang 6
- Đƣợc nạp và thực thi đầu tiên khi hệ thống khởi động
- Để nạp hệ điều hành cần sử dụng bộ nạp boot-loader, có kích thƣớc nhỏ gọn, đảm
nhiệm chức năng tiền hệ điều hành.
- Bộ nạp khởi tạo cũng có nhiệm vụ khởi tạo vùng nhớ dữ liệu và các thanh ghi hệ
thống trƣớc khi nhảy tới chƣơng trình ứng dụng chính.
- Có rất nhiều dạng khác nhau của bộ nạp khởi tạo, từ dạng đơn giản đến phức tạp.
1.5.2. Hệ điều hành thời gian thực –RTOS: (Realtime Operationg System )
- Các chức năng chính nhƣ định thời, giải quyết xung đột dữ liệu, giao tiếp giữa các
tác vụ process/task.->Ngắn gọn: RTOS là hệ điều hành đa nhiệm - multitasking dùng
cho các ứng dụng thời gian thực.
- RTOS: Cung cấp các giao tiếp giữa phần cứng và chƣơng trình ứng dụng, với các
tính năng chủ yếu sau: Đa nhiệm - Multitasking, Đồng bộ - Sync , xử lý sự kiện và
ngắt, I/O, truyền thông giữa các tách vụ process/task, quản lý Timer, Clock và bộ nhớ
(tựa chung là quản lý tài nguyên).
Hình 1.2. Cấu trúc của OSEK
Phân loại:
a. Các hệ điều hành mang tính thƣơng mại: thƣờng nhỏ và nhanh, nhƣ QNX,
PDOS, pSOS, VxWorks, Nulceus, ERCOS, EMERALDS, Windows CE, chúng có các
đặc điểm sau:
Trang 7
+ Có thời gian chuyển ngữ cảnh và thời gian đáp ứng nhanh.
+ Kích thƣớc rất nhỏ.
+ Không có bộ nhớ ảo và có thể cố định mã, dữ liệu trong bộ nhớ.
+ Hệ thống đa tác vụ và chuẩn giao tiếp liên quá trình. Các mailbox, các
sự kiện, các tín hiệu và các đèn báo đƣợc định nghĩa tốt.
Những hệ điều hành này thƣờng có các đặc tả tốt và có các công cụ tốt để phát triển
các ứng dụng nhúng thời gian thực. Nó hỗ trợ các ràng buộc thời gian thực với các
dịch vụ nhƣ:
+ Các giới hạn thời gian thực hiện.
+ Đồng hồ thời gian thực.
+ Lập lịch thứ tự ƣu tiên.
+ Cảnh báo đặc biệt và thời gian quá hạn (timeout).
+ Hỗ trợ các hàng đợi thời gian thực.
+ Cung cấp việc xử lý độ trễ, treo hay kích hoạt việc thực hiện.
b. Hệ điều hành thời gian thực mở rộng tới Unix và các hệ điều hành khác
Các hệ điều hành này nhƣ: RT-UNIX, RT-LINUX, RT-MACH, RT-POSIX. Chúng
chậm hơn và có khả năng dự đoán ít hơn so với các hệ điều hành thời gian thực thƣơng
mại ở trên nhƣng chúng lại có nhiều chức năng và môi trƣờng phát triển tốt hơn dựa
trên tập các giao tiếp chuẩn và thân thiện.
c. Các nhân cho mục đích nghiên cứu
Thí dụ nhƣ: Spring, MARS, HARTOS, MARUTI, ARTS, CHAOS, DARK.
Các hệ điều hành này có các đặc điểm sau:
+ Hỗ trợ các thuật toán lập lịch thời gian thực và việc phân tích thời gian.
+ Hỗ trợ các dịch vụ cơ bản để đồng bộ thời gian thực.
+ Nhấn mạnh khả năng dự đoán hơn là hiệu năng trung bình.
+ Hỗ trợ cho khả năng chịu lỗi.
- Đối với LPC2000 thì OS đƣợc xem là hệ điều hành tốt nhất.
1.5.3. Phần mềm nhúng
- Ngôn ngữ đƣợc sử dụng để phát triển các ứng dụng nhúng thƣờng là C hoặc
Assembler.
- Keil C là công cụ hỗ trợ viết soạn thảo, debug và biên dịch code (cả C và ASM).
Trang 8
- Simulator là một chƣơng trình phần mềm cho phép ngƣời phát triển mã chƣơng
trình chạy mô phỏng một chƣơng trình viết cho một nền VXL/VĐK (nền phần
cứng đích) trên một môi trƣờng phần cứng khác (hay còn gọi là môi trƣờng phát
triển); cho phép chạy từng bƣớc, kiểm thử, điều chỉnh với các giá trị khác nhau, sử
dụng các thuật toán khác nhau.
Hỗ trợ các chức năng giống nhƣ trên phần cứng đích, có thể kèm theo emulator.
- Emulator là một thiết bị phần cứng có khả năng thực hiện nhƣ một nền phần cứng
đích ( Còn gọi là cộng cụ phát triển thời gian thực bởi vì nó cho ta phản ứng với các
sự kiện nhƣ VĐK đích thực thi)
Các bộ Emulator thƣờng có kèm theo cả phần chƣơng trình giám sát
(monitor program) để cho phép ngƣời phát triển chƣơng trình cho VĐK đích kiểm
tra nội dung, trạng thái các thanh ghi và các khu vực bộ nhớ và thiết lập các điểm
dừng khi thực hiện chạy chƣơng trình.
1.6. Quy trình thiết kế hệ thống nhúng
Khi tiếp cập kiển trúc hệ thống nhúng dƣới góc nhìn kỹ thuật có thể sử dụng một số
mô hình để miêu tả chu kỳ thiết kế. Một số mô hình điển hình nhƣ sau:
Mô hình big-bang: Mô hình này về cơ bản là không cần có kế hoạch và quy
trình trƣớc và trong quá trình thiết kế.
Mô hình code anh fix: Đƣa ra ra các yêu cầu nhƣng không có quy trình trƣớc
khi bắt đầu phát triển dự án.
Mô hình waterfall(thác nƣớc): Phát triển hệ thống theo từng bƣớc, có đƣợc kết
quả của bƣớc trƣớc mới thực hiện bƣớc sau và lặp lại từ đầu.
Trang 9
Hình 1.3. Mô hình thác nƣớc
Mô hình spiral (xoáy ốc): Là một quy trình phát triển hệ thống theo từng bƣớc,
tại mỗi bƣớc có sự thay đổi và quay lại thiết kế bƣớc trƣớc sao cho phù hợp.
Hình 1.4. Mô hình xoán ốc
Thực tế ngƣời ta thƣờng kết hợp các mô hình, nhƣ mô hình chu kỳ thời gian sống là sự
kết hợp của mô hình waterfall và mô hình spiral
Trang 10
Hình 1.5. Mô hình phát triển hệ thống theo chu kỳ thời gian sống
1.7. Mô hình hệ thống nhúng
Mô hình hệ thống nhúng gồm 3 lớp
Hình 1.5. Mô hình tổng thể của hệ thống nhúng
Trang 11
CHƢƠNG 2: HỌ VI ĐIỀU KHIỂN ARM
2.1. Tổng quan
- Họ vi điều khiển LPC2000 là ARM7, ngƣời lập trình không cần thiết phải thành thạo
ARM 7 để sử dụng LPC2000 mà vấn đề phức tạp là ở trình biên dịch C.
- Ngƣời lập trình cần có kiến thức cơ bản về cách CPU làm việc và các đặc tính của nó
để tạo ra các thiết kế tin cậy.
- ARM 7 là một máy tính nhỏ với tập lệnh nhỏ, khả năng tính toán cao, tiêu thụ năng
lƣợng thấp.
- Vi điều khiển ARM đƣợc phát triển theo kiến trúc RISC (Reduced Instruction Set
Computer):
- Chỉ có các lệnh nạp hoặc lƣu trữ là có thể tham chiếu tới bộ nhớ,
- Tồn tại ít lệnh và kiểu định địa chỉ, khuôn dạng lệnh cố định,
- Có nhiều tập thanh ghi,
- Các lệnh thực hiện trong một chu ky máy,
- Lệnh đƣợc thực hiện trực tiếp trên phần cứng(CISC có 1 chƣơng trình thông
dịch nhỏ),
- Chƣơng trình biên dịch mã nguồn phức tạp(CISC-chƣơng trình thông dịch
phức tạp),
- Hỗ trợ cơ chế pipeline,
- Kích thƣớc chƣơng trình lớn.
Cấu trúc các chân:
Thí dụ các chân của LPC2101:
Trang 12
Hình 2.1. Cấu trúc các chân của LPC2101
2.2. Cơ chế Pipeline
- Trái tim của ARM7 là cơ chế pipeline, thực thi lệnh theo ba bƣớc: đọc lệnh, giải mã
lệnh và thực thi lệnh.
Hình 2.2. Ba bƣớc thực hiện của pipepline
- Pipeline có phần cứng độc lập để thực hiện các bƣớc, trong khi lệnh thứ nhất đang
thực thi, lệnh thứ 2 đƣợc giải mã và lệnh thứ 3 đƣợc đọc lên pipeline.
- Hầu hết các lệnh của ARM 7 đƣợc thực thi trong 1 chu kỳ máy.
Trang 13
- Pipeline làm việc rất tốt trong trƣờng hợp chƣơng trình không rẽ nhánh. ARM chỉ
cho phép thực hiện các bƣớc nhảy ngắn trong đoạn chƣơng trình.
- Pipeline là một thành phần của CPU, thanh ghi PC chạy ở 8 bytes đầu của lệnh hiện
hành sẽ đƣợc thực thi. Thí dụ: 0x4000 LDR PC,[PC,#4]-> PC=0x400C
2.3. Các thanh ghi
- ARM7 có kiến trúc kiểu load and store, bởi vậy, để thực hiện các lệnh xử lý dữ liệu
thì tất cả các dữ liệu phải đƣợc tải từ bộ nhớ vào một tập các thanh ghi trung tâm, lệnh
xử lý dữ liệu đƣợc thực hiện và lƣu trữ dữ liệu trở lại bộ nhớ.
Hình 2.3. Kiến trúc load and store của ARM 7
- ARM7 có 17 thanh ghi 32 bít:
- Các thanh ghi R0 đến R12 là các thanh ghi chung,
- Thanh ghi R13 là thanh ghi con trỏ ngăn xếp,
- R14 là thanh ghi liên kết,
- R15 là thanh ghi bộ đếm chƣơng trình (PC) và
- Thanh ghi trạng thái chƣơng trình CPSR.
- Thanh ghi R14 dùng trong chƣơng trƣờng hợp gọi đến chƣơng trình con “gần” thì nó
sẽ cất giữ địa chỉ của trả về của chƣơng trình chính, nếu trong chƣơng trình con này
gọi đến một chƣơng trình con khác thì địa chỉ của chƣơng trình chính phải đƣợc cất
giữa vào ngăn xếp.
Trang 14
Hình 2.4. Các thanh ghi của ARM7
2.4. Thanh ghi trạng thái chƣơng trình hiện hành
Hình 2.5. Thanh ghi trạng thái chƣơng trình CPSR
- CPU ARM7 thực thi 2 loại lệnh: Tập lệnh ARM 32 bít và tập lệnh đƣợc nén 16 bít.
Bít T sẽ quyết định loại lệnh nào sẽ đƣợc thực thi, ngƣời lập trình không nên set hay
xóa giá trị của bít này.
- ARM7 có 7 chế độ hoạt động khác nhau, ngƣời lập trình thƣờng chạy trong chế độ
ngƣời dùng để truy cập đến các bank thanh ghi từ R0-R15 và thanh ghi trạng thái
chƣơng trình(CPSR). Tuy nhiên khi gặp các ngoại lệ nhƣ ngắt, lỗi bộ nhớ, ngắt mềm
CPU sẽ chuyển sang chế độ khác. Mỗi chế độ các thanh ghi R13 và R14 có giá trị
Trang 15
riêng. Ở chế độ ngắt nhanh FIQ các thanh ghi R7-R12 có giá trị giống nhau (không cần
dùng stack để lƣu chữ).
Hình 2.6. 6 chế độ hoạt động của APU ARM7
2.5. Các mode ngoại lệ
- Khi có một ngoại lệ xảy ra, CPU sẽ chuyển chế độ và thanh ghi PC sẽ đƣợc đảy về
địa chỉ của vecto ngoại lệ. Bảng vecto bắt đầu từ địa chỉ 0 trùng địa chỉ vecto ngắt.
- Mỗi vecto ngoại lệ là 4 bytes.
Hình 2.6. Bảng các vecto ngắt
Trang 16
Hình 2.7. Thứ tự ƣu tiên của các ngắt
Hình 2.8. Thí dụ về trật tự xử lý khi có một ngoại lệ ngắt xảy ra
Hình 2.9. CPU trở lại trạng thái ban đầu khi kết thúc phụ vụ ngoại lệ
2.6. Tập lệnh ARM 7
- ARM7 có 2 tập lệnh: Tập lệnh mở rộng 32 bít và tập lệnh nén (THUMB) 16 bít.
- CPU ARM7 đƣợc thiết kế để hỗ trợ xử lý theo kiểu big endian hay little endian:
Trang 17
Hình 2.10. Hai kiểu xử lý của CPU ARM7
- Một đặc điểm thú vị của ARM7 là tất cả các lệnh đều có thể là các lệnh có điều
kiện, bằng cách so sánh 4 bít từ bit 28 đến bít 31 của kết quả thực hiện lệnh với các bít
điều kiện trong thanh ghi CPSR, nếu điều khiện không thỏa mãn thì lệnh sẽ không
đƣợc thực thi.
- Các lệnh xử lý dữ liệu sẽ bị ảnh hƣởng bởi các bít điều kiện trong thanh ghi
CPSR. Hai lệnh cơ bản MOV và ADD có thể đặt các tiến tố đằng trƣớc với 16 điều
kiện nhƣ sau:
Hình 2.11. 16 điều kiện đƣợc kiểm tra trƣớc khi thực thi lệnh
Trang 18
Thí dụ: EQMOV R1,#0x00800000;
Giá trị 0x00800000 chỉ đƣa vào R1 khi kết quả cuối cùng của lệnh có các bít
tƣơng ứng với 4 bít trong thanh ghi CPSR và bít cờ Z đƣợc set =1.
- Các lệnh của ARM7 có thể chia thành 6 nhóm: Các lệnh rẽ nhánh, các lệnh xử lý
dữ liệu, truyền dữ liệu, truyền khối dữ liệu, lệnh số học và ngắt mềm.
2.6.1. Các lệnh rẽ nhánh
- Cho phép nhảy tiến hoặc lùi trong phạm vi 32MB, địa chỉ của lệnh tiếp theo sẽ
đƣợc lƣu vào thanh ghi liên kết R14.
- Lệnh rẽ nhánh có 2 biến thể: Rẽ nhánh trao đổi (branch exchange) và rẽ nhánh
liên kết trao đổi (branch link exchange). Hai lệnh này cơ giống nhau nhƣng lệnh rẽ
nhánh liên kết địa chỉ của lệnh tiếp theo đƣợc cộng thêm 4 bytes rồi đƣa vào R14.
2.6.2. Các lệnh xử lý dữ liệu
Cú pháp tổng quát:
Hình 2.12. Cú pháp tổng quát của một lệnh xử lý dữ liệu có điều kiện
Mỗi lệnh đều có 2 toán hạng, trong đó toán hạng thứ nhất phải là thanh ghi, toán hạng
còn lại có thể thanh ghi hoặc giá trị cụ thể.
Bít „S‟ đƣợc sử dụng để điều khiển điều kiện của lệnh:
S=1 thì điều kiện của lệnh phụ thuộc vào kết quả của lệnh,
S=0 thì không có điều gì xảy ra
Nếu S=1 và PC là thanh ghi chứa kết quả thì SPSR của chế độ hiện hành đƣợc
copy vào CPSR.
Trang 19
Hình 2.13. Bảng các lệnh xử lý dữ liệu
2.6.3. Các lệnh truyền dữ liệu
Hình 2.14. Các lệnh truyền dữ liệu
Trang 20
Hình 2.15. Các lệnh truyền một khối dữ liệu
2.6.4. Lệnh SWAP
- ARM7 hỗ trợ các tín hiệu thời gian thực với một lệnh swap cho phép trao đổi chỗ
nội dung của hai thanh ghi.
- Lệnh này đƣợc hỗ trợ trong thƣ viện ARM chứ không trực tiếp từ ngôn ngữ C.
Hình 2.16. Mô tả lệnh swap trong ARM7
2.7. Ngắt mềm (SWI – Software Interrupt Instruction)
Trang 21
Các ngắt mềm sinh ra một ngoại lệ khi thực thi, đƣa vi xử lý vào chế độ hoạt động
giám sát và PC nhảy tới địa chỉ 0x00000008. Cũng nhƣ các lệnh ARM khác, lệnh ngắt
mềm chứa một mã điều kiện thực thi trong 4 bít thấp của toán hạng, các bít còn lại là
trống rỗng.
Hình 2.17. Điều kiện của ngắt mềm để CPU vào chế độ giám sát
Có thể giả lặp chƣơng trình con phục vụ ngắt của ngắt mềm nhƣ sau:
switch( *(R14-4) & 0x00FFFFFF) // Kiểm tra giá trị
//đƣợc lƣu trữ trong thanh ghi liên kết
{
case ( SWI-1):
…}
2.8. Đơn vị MAC (Multiply Accumulate Unit (MAC)
- MAC hỗ trợ phép nhận số nguyên kiểu integer và long integer, khi nhân kiểu
integer 2 thanh ghi 32 bít với nhau thì kết quả là 32 bít đƣợc đặt vào thanh ghi thứ 3.
Khi nhân 32 bít kiểu long integer thì kết quả là 64 bít và đƣợc đặt vào 2 thanh ghi.
- Các lệnh nhận dạng ASM:
Tên lệnh Viết tắt Kết quả
MUL Multiply 32 bit
MULA Multiply accumulate 32 bit
UMULL Unsigned multiply 64 bit
UMLAL Unsigned multiply accumulate 64 bit
SMULL Signed multiply 64 bit
SMLAL Signed multiply accumulate 64 bit
Bảng 2.1. Các lệnh nhân trong vi điều khiển ARM
2.9. Tập lệnh THUMB
- Tập lệnh ARM là tập lệnh 32 bít, ARM có tập lệnh 16 bít gọi là tập lệnh
THUMB. Tập lệnh THUMB thực chất là tập lệnh nén lại từ tập lệnh ARM.
Trang 22
Hình 2.18. Tập lệnh THUMB đƣợc nén lại từ tập lệnh ARM
- Tập lệnh THUMB cho giá trị kết quả thấp hơn tập lệnh ARM nhƣng mà các kết
quả này chiếm một tỷ lệ lớn hơn. Tập lệnh THUMB tiết kiệm đƣợc không gian nhớ
30% và chạy nhanh hơn 40% so với tập lệnh ARM.
- Tập lệnh THUMB không có điều kiện thực thi trừ các lệnh rẽ nhánh. Các lệnh xử
lý dữ liệu thì cần có một thanh ghi nguồn và một thanh ghi đích.
Thí dụ: Với lệnh cộng thanh ghi R0 và R1:
Dùng lệnh ARM: ADD R0, R0,R1 //R0 = R0+R1
Dùng lệnh THUMB: ADD R0,R1 // R0 = R0+R1
- Tập lệnh THUMB chỉ có thể truy cập đến các thanh ghi thấp từ R0-R7, các thanh
ghi cao từ R8-R12 bị giới hạn truy cập:
Hình 2.19. Mô hình lập trình tập lệnh THUMB
Trang 23
Ngƣời lập trình không thể truy cập trực tiếp vào thanh ghi CPSR và SPSR. Ngƣời lập
trình có thể sử dụng 2 lệnh BLX và BX để chuyển chế độ hoạt động với các lệnh. Khi
reset vi điều khiển làm việc với tập lệnh THUMB, khi có 1 ngoại lệ xảy ra thì sẽ
chuyển sang làm việc với tập lệnh ARM, khi kết thúc ngoại lệ thì quay trở về làm việc
với lệnh ARM.
Hình 2.20. Trao đổi giữa lệnh ARM và lệnh THUMB
2.10. Phần mềm phát triển và công cụ phần cứng
- Keil C ARM là công cụ cho phép lập trình mô phỏng vi điều khiển ARM với hệ
thống thƣ viện đƣợc hỗ trợ tƣơng đối đầy đủ về vi điều khiển core ARM 7 nhƣ: họ vi
điều khiển LPCxxxx và ARM966E-S, cortex-M0 đến cortex-M3.
- Phần mềm isp của atmel và H-jtag để biên dịch và nạp code lên board.
2.10.1. Cấu trúc file start up
- Phần đầu cung cấp bảng vecto ngắt:
Trang 24
Hình 2.21. Các định nghĩa các vecto ngắt trong file startup.s
Bảng vecto ngắt đƣợc định nghĩa tại địa chỉ 0x00000000 và cho phép bộ đếm
chƣơng trình nhảy đến chƣơng trình con phụ vụ ngắt ( ISR-interupt service routine).
Rải địa chỉ của vio điều khiển là liên tiếp, không bị ngắt quãng trong bảng vecto ngắt.
Lệnh LDR (Load Register) đƣợc sử dụng để tải hằng tƣơng ứng với vecto ngắt trong
bảng vecto ngắt.
- Bảng vecto ngắt và bảng các hằng nằm ở 64 bytes đầu tiên của bộ nhớ.
- Lệnh NOP đƣợc sử dụng để nhảy đến vị trí vecto ngắt tại địa chỉ 0x00000014, vị
trí lỗi.
- Phần tiếp trong file startup.s cấu hình con trỏ ở đỉnh ngăn xếp cho từng chế độ
hoạt động:
- Kích thƣớc Stack tính theo byte, thí dụ trong file startup của LPCxxxx nhƣ sau:
Trang 25
Hình 2.22. Cấu hình stack cho từng chế độ hoạt động
- Vùng nhớ dành cho stack đƣợc định nghĩa ở phần địa chỉ cao nhất của bộ nhớ và
lớn dần về phần địa chỉ thấp.
2.10.2. Công cụ phần cứng
- Họ LPC2000 của hãng Philips có nhiều cổng cho phép kết nối vi điều khiển với
máy tính, thƣờng đƣợc sử dụng nhất là cổng JTAG. Khi kết nối trực tiếp với máy tính
cho phép ngƣời lập trình debug trực tiếp trên mạch phần cứng:
Hình 2.23. Kết nối LPC2000 với máy tính qua cổng JTAG
- Đồng thời kèm theo module ETM cho phép debug chƣơng trình: nhƣ theo dõi
thời gian thực, theo dõi sự kiện và phân tích quá trình thực thi.
2.10.3. Cách viết chƣơng trình C với tập lệnh ARM và tập lệnh THUMB
- Để sử dụng các định nghĩa địa chỉ các ARM7, trong chƣơng trình cần khai báo
thƣ viện hợp lệ, thí dụ với họ LPC có các khai báo: #include LPC2xxx.h hoặc
LPC21xx.h hoặc LPC210x.h
- Ngƣời lập trình có thể đƣa ra các hàm đƣợc biên dịch theo lệnh tập ARM hoặc tập
THUMB. Để chỉ định một hàm sẽ đƣợc biên dịch theo tập lệnh nào dùng directive
#pragma, thí dụ:
Trang 26
#pragma ARM // khai báo các lệnh ARM
int main(void)
{
while(1){
THUMB_function(); //gọi đến hàm THUMB
}}
#pragma THUMB //Switch to THUMB instructions
void THUMB_function(void)
{
unsigned long i,delay;
for (i = 0x00010000;i < 0x01000000 ;i = i<<1){
for (delay = 0;delay<0x000100000;delay++){} //tạo vòng lặp
IOSET1 = i; //chuyển đến led tiếp theo
}}
- Có thể chỉ ra trực tiếp trên lệnh:
int ARM_FUNCTION ( int my_var) __ARM
{…}
int THUMB_FUNCTION ( int my_var) __THUMB {…}
2.11. Cấu trúc bên trong
2.11.1. Bản đồ bộ nhớ
Hình 2.24.
Trang 27
2.11.2. Lập trình thanh ghi
- Một thanh ghi chức năng đƣợc điều khiển bởi 3 thanh ghi ngƣời dùng, một thanh
ghi để đọc trạng thái, một thanh ghi để xóa và một thanh ghi để ghi dữ liệu lên.
Hình 2.25.Cấu trúc tổng quát khi truy cập thanh ghi chức năng trong ARM7
2.11.3. Memory Acelerator Module (MAM)
- Là bộ nhớ nằm giữa bộ nhớ Flash và CPU ARM, có tốc độ thực thi cao.
Hình 2.26: Mô hình bộ nhớ MAM
- CPU ARM có thể chạy ở tốc độ 80MHz, mỗi lần chíp Flash truy cập hết 50ns.
- Flash chạy ở tốc độ 20MHz
Trang 28
- MAM đƣợc tạo ra nhƣ là một cache đầy đủ cho phép CPU dễ dàng truy cập trực
tiếp vào FLASH.
Hình 2.27. Truy cập bộ nhớ FLASH qua MAM
- Khi đọc các lệnh từ bank thứ nhất thì bank thứ hai đƣợc chốt.
- MAM là trong suốt với ngƣời dùng và đƣợc cấu hình bởi 2 thanh ghi: điều khiển
(MAMCR) và định thời (MAMTIM). Thanh ghi định thời đƣợc sử dụng để điều khiển
mối quan hệ giữa CPU và FLASH bằng cách thiết lập 3 bít đầu tiên của nó để chỉ định
chu kỳ xung nhịp của CPU đƣợc yêu cầu bởi MAM để truy cập vào FLASH.
- Khi FLASH có tốc độ 20MHz và CPU có có thể có tốc độ cực đại là 60MHz, số
chu kỳ yêu cầu truy cập FLASH là 3.
Thí dụ: Cấu hình MAM
#include "LPC21xx.h"
void ChangeGPIOPinState(unsigned int state);
int main(void){
unsigned int delay,val;
unsigned int FLASHer = 0x00010000; // Khai báo cục bộ
IODIR0 = 0x00FF0000; // Thiết lập các chân ra
VPBDIV = 0x02;
ADCR = 0x00270601; // Thiết lập A/D: 10-bit AIN0 @ 3MHz
ADCR |= 0x01000000; // Khởi tạo bộ chuyển đổi A/D
while(1)
{ do {
val = ADDR; // Đọc thanh ghi dữ liệu bộ chuyển đổi A/D
Trang 29
}while ((val & 0x80000000) == 0);
val = ((val >> 6) & 0x03FF);
if (val <0x80)
{
MAMCR = 0;
MAMTIM = 0x03;
MAMCR = 0x02;
}else
{ MAMCR = 0x0; }
for(delay = 0;delay<0x100000;delay++) //tạo vòng lặp
{;}
ChangeGPIOPinState(FLASHer); //Đổi trạng thái các chân ra ở cổng
FLASHer = FLASHer <<1; //Dịch đến đèn led tiếp
if(FLASHer&0x01000000)
{
FLASHer = 0x00010000; //Lặp lại đèn đầu tiên
// overflow
}}}
void ChangeGPIOPinState(unsigned int state)
{
IOSET0 = state; //set output pins
IOCLR0 = ~state; //clear output pins
}
2.11.4. PLL- Phase Locked Loop
- Tạo ra một tần số dao động ngoài từ 10-25MHz từ mạch dao động cơ bản và có
thể tăng lên 60 MHz để cung cấp cho CPU ARM và thiết bị ngoại vi.
- Tần số đầu ra của PLL có thể thay đổi tự động, cho phép thiết bị điều chỉnh theo
tốc độ thực thi để duy trì nguồn năng lƣợng khi ở trạng thái rảnh rỗi.
Trang 30
Hình 2.28
- Hai hằng M và P phải đƣợc lập trình để quyết định xung clock (Cclk) cho CPU và
AHB.
- Hăng thứ nhất đƣợc nhân một cách tuyến tính với tần số dao động bên ngoài đƣa
vào. Tần số ra của PLL là: Cclk=M x Osc
- Ngƣợc lại PLL lại đƣợc điều khiển bởi một dao động hoạt động hiện hành (CCO)
ở dải tần 156MHz-320MHz. Hằng số thứ 2 phải đƣợc lập trình để đảm bảo sao cho
CCO đƣợc giữ một giá trị cụ thể: Fcco = Cclk x 2 x P
- Trên board phát triển thì dao động thạch anh là 12MHz, bởi vậy để CPU đạt đƣợc
tốc độ tối đa 60MHz thì: M = Cclk/Osc = 60/12 =5
và 156< Fcco <320 = 60 x 2 x P
Thực nghiệm thì P=2.
- Giao diện lập trình PLL:
Hình 2.29.
- Giá trị trong các thanh ghi PLLCON, PLLCFG và PLLSTAT sẽ đƣợc ghi sau khi
giá trị trong PLL FEED đƣợc ghi.
Trang 31
- Khi cập nhật giá trị thanh ghi PLLCON và PLLCFG thì phải ghi liên tiếp hai giá
trị 0x000000AA và 0x00000055 cho thanh ghi PLLFEED, các giá trị này phải ghi
trong các chu kỳ liên tiếp.
- Nếu lập trình cho phép các ngắt thì ngắt sẽ sinh ran gay sau khi từ đầu tiên đƣợc
ghi và các thiết lập mới cho PLL sẽ không có ảnh hƣờng.
- Để cài đặt PLL phải ghi các giá trị cho P và M tới thanh ghi PLLCFG, sau đó set
D0 của thanh ghi PLLCON để cho phép PLL khởi động.
- Giá trị của M chiếm 5 bít thấp (D4-D0), P chiếm 2 bít D6D5:
Hình 2.30. Giá trị của P và M trong thanh ghi PLLCFG
- PLL mất một khoảng thời gian xác định đủ để sử dụng nguồn xung clock. Sự khởi
động PLL có thể đƣợc kiểm tra bằng cách đọc bít LOCK (D10) trong thanh ghi trạng
thái PLLSTAT.
- Khi LOCK bít =1, PLL có thể đƣợc sử dụng nhƣ nguồn xung clock chính. Một
ngắt có thể đƣợc sinh ra khi PLL khóa, bởi vậy ngƣời lập trình có thể thực hiện các
nhiệm vụ khác khi PLL khởi động. Khi PLL bị khóa thì có thể thay thế nguồn xung
cho Cclk bằng cách điều khiển bít PLLC trong thanh ghi PLLCON.
Trang 32
Hình 2.31. Trình tự khởi động PLL
2.11.5. Bộ chia bus (VLSI Peripheral Bus Divider)
Mạch dao động ngoài hoặc đầu ra của PLL đƣợc sử dụng để tạo ra nguồn xung Cclk
cho CPU ARM hoặc hệ thống bus có tần số cao. Các thiết bị ngoại vi có thể sử dụng
bus VPB riêng biệt.
Hình 2.32. Tạo xung Pclk từ Cclk
- Bộ chia có thể chia tốc độ Cclk xuống 2 đến 24 lần. Thanh ghi trong bộ chia
VPBDIV có thể lập trình được và chứa số lần giảm tốc độ. Tại thời điểm khởi động,
giá trị cực đại đƣợc nạp và bằng ¼ giá trị Cclk lúc khởi động.
- Hiện nay tất cả các thiết bị ngoại vi của họ vi điều khiển LPC có thể chạy ở tần số
60MHz. Vì vậy, bộ chia tần VPB thƣờng đƣợc sử dụng để tiết kiệm nguồn bằng cách
tạo xung clock chấp nhận đƣợc cho các ứng dụng.
Thí du cấu hình PLL và VPB:
Trang 33
Cấu hình PLL để tạo ra tần số Cclk là 60MHz và Pclk là 30MHz với xung đầu vào là
12MHz:
void init_PLL(void)
{
PLLCFG = 0x00000024; // Thiết lập hệ số nhân và bộ chia cho PLL
// give 60.00 MHz
PLLCON = 0x00000001; // Kích hoạt PLL
PLLFEED = 0x000000AA; // Cập nhật thanh ghi PLLFEED
PLLFEED = 0x00000055;
while (!(PLLSTAT & 0x00000400)); // kiểm tra bít Lock
PLLCON = 0x00000003; // Kết nối tới PLL
PLLFEED = 0x000000AA; //Cập nhật các thanh ghi PLL
PLLFEED = 0x00000055;
VPBDIV = 0x00000002; //Thiết lập bus VLSI với tần số 30.000MHz
}
2.12. Các cổng vào ra
- Các cổng vào ra của ARM là 32 bít, vi điều khiển có thể chỉ có 1 cổng hoặc có
nhiều hơn, nhƣng các chân dùng cho cổng vào/ra cũng là các chân dùng chung cho các
mục đích khác nhƣ biến đổi AD, ngắt, giao diện SPI, I2C,…
- Các chân đƣợc sử dụng vào mục đích nào tùy vào việc cấu hình chúng cho mục
đích đó. Trong chƣơng 3 sẽ trình bày cụ thể về cách lập trình cho các chân cổng vào
ra.
Trang 34
CHƢƠNG 3: LẬP TRÌNH VI ĐIỀU KHIỂN ARM
3.1. Hƣớng dẫn sử dụng phần mềm Keil C
B1: Tạo một project mới:
B2: Tạo thƣ mục mới để chứa project mới tạo:
B3: Đặt tên cho thƣ mục là TD1 và click đúp lên thƣ mục này để mở ra và đặt tên
cho project là TD1:
Trang 35
B4: Chọn vi điều khiển với core ARM7, thí dụ LPC2101:
B5: Chọn Yes để tự động thêm code start up vào project:
Trang 36
B6: Chọn New để thêm file mới để soạn thảo mã nguồn của vi điều khiển:
B7: Soạn thảo mã nguồn và ghi với tên MAM.C
Trang 37
B8: Ghi lại với tên MAM.C
B9: Add file MAM.c vào project:
Trang 38
B10: Chọn file MAM.c:
B11: Cấu hình cho project:
Trang 39
B12: Trong tab Target chọn tần số là 12:
B13: Trong tab Output chọn create hex File:
Trang 40
B14: Biên dịch project:
B15: Trên proteus vẽ mạch mô phỏng:
Trang 41
B16: Nạp file .hex cho vi điều khiển:
B17: Chọn file TD1.hex trong thƣ mục của project tạo từ keil C:
Trang 42
3.2. Truy nhập các chân vào ra chung
Các chân vào (General purpose I/O input pins) ra đƣợc điều khiển bởi 4 thanh ghi:
Hình 3.1. Các chân vào ra đƣợc dùng cho mục đích chung
- Mỗi chân GPIO đƣợc điều khiển bởi 4 bít để điều khiển hƣớng dữ liệu, set, xóa và
trạng thái của chân.
- Mỗi bít trong thanh ghi IODIR: 0 cho phép cấu hình các chân là đầu vào
1 cho phép cấu hình các chân là đầu ra
Trang 43
- Khi các chân là đầu ra thì các bít tƣơng ứng trên các thanh ghi IOSET và IOCLR
cho phép ngƣời lập trình điều khiển trạng thái của các bít.
- Để xóa chân nào thì đƣa set bít đó =1 tƣơng ứng trong thanh ghi IOCLR
- Để đọc nội dung của chân sử dụng thanh ghi IOPIN
Thí dụ 1: Viết chƣơng trình điều khiển led đơn sáng nhấp nháy
Ghép nối một led đơn với chân P0.0 của LPC2101, Sơ đồ nối chân Proteus:
Chƣơng trình điều khiển:
//Thi du chuong trinh dieu khien led nhap nhay tai chan p0.1
//LPC 2101
#include"LPC21xx.h"
void delay(unsigned int a);
int main(void){
IODIR0=0x00000001 ;
while(1){
IOSET0=0x00000001 ;
delay(0x100000);
Trang 44
IOCLR0=0x00000001 ;
delay(0x100000);
} }
void delay(unsigned int a){
unsigned int i;
for (i=0;i<a;i++){;}
}
Thí dụ 2: Chƣơng trình hiển thị chữ trên LCD
Sơ đồ trên proteus:
Chƣơng trình điều khiển:
Tổ chức các tệp trong chƣơng trình nhƣ sau:
Trang 45
Tệp lcd.h định nghĩa địa chỉ dành cho lcd:
/***************************************/
/* LCD routines for OLIMEX LPC-MT-2106 */
/* 16x2 Character LCD 1602K */
/* 4-bit mode operation */
/***************************************/
/* DEFINE IOMASK */
#define LCD_D4 0x10 //P0.04
#define LCD_D5 0x20 //P0.05
Trang 46
#define LCD_D6 0x40 //P0.06
#define LCD_D7 0x80 //P0.07
#define LCD_EN 0x400000 //P0.22
#define LCD_RS 0x800000 //P0.23
#define LCD_RW 0x1000000 //P0.24
#define LCD_DATA (LCD_D4|LCD_D5|LCD_D6|LCD_D7)
#define LCD_IOALL
(LCD_D4|LCD_D5|LCD_D6|LCD_D7|LCD_EN|LCD_RS|LCD_RW)
#define LCD_GPIO_SEL0 0x0000FF00 //MASK for P0.04-P0.07
#define LCD_GPIO_SEL1 0x0003F000 //MASK for P0.22-P0.24
/* Functions Header */
/* internal I/O functions */
#define lcd_rs_set() IOSET |= LCD_RS
#define lcd_rs_clr() IOCLR |= LCD_RS
#define lcd_en_set() IOSET |= LCD_EN
#define lcd_en_clr() IOCLR |= LCD_EN
#define lcd_rw_set() IOSET |= LCD_RW
#define lcd_rw_clr() IOCLR |= LCD_RW
/* wait until lcd controller is free */
void lcd_wait();
void lcd_out_data4(unsigned char);
void lcd_write_nibbles(unsigned char);
void lcd_write_control(unsigned char);
/* initialize both the GPIO of lpc and LCD */
void lcd_init();
#define lcd_clear() lcd_write_control(0x01)
#define lcd_cursor_home() lcd_write_control(0x02)
#define lcd_display_on() lcd_write_control(0x0E)
#define lcd_display_off() lcd_write_control(0x08)
#define lcd_cursor_blink() lcd_write_control(0x0F)
#define lcd_cursor_on() lcd_write_control(0x0E)
Trang 47
#define lcd_cursor_off() lcd_write_control(0x0C)
#define lcd_cursor_left() lcd_write_control(0x10)
#define lcd_cursor_right() lcd_write_control(0x14)
#define lcd_display_sleft() lcd_write_control(0x18)
#define lcd_display_sright() lcd_write_control(0x1C)
/* put a character out to lcd */
void lcd_putchar(unsigned char);
/* print a string */
void lcd_print(unsigned char*);
Tệp lcd.c định nghĩa các phƣơng thức liên quan đến các thao tác trên LCD:
#include "lcd.h"
#include "lpc210x.h"
void lcd_wait(){
int loop=2800; //more than enough
//busy loop
while(loop--);
}
void lcd_out_data4(unsigned char val){
IOCLR |= (LCD_DATA);
IOSET |= (val<<4);
}
void lcd_write_nibbles(unsigned char val){
//higher-order byte
lcd_en_set();
lcd_out_data4((val>>4)&0x0F);
lcd_en_clr();
lcd_wait();
//lower-order byte
lcd_en_set();
lcd_out_data4((val)&0x0F);
lcd_en_clr();
Trang 48
lcd_wait();
}
void lcd_write_control(unsigned char val){
lcd_rs_clr();
lcd_write_nibbles(val);
}
void lcd_init(){
PINSEL0 &= (~LCD_GPIO_SEL0);
PINSEL1 &= (~LCD_GPIO_SEL1);
/* we only work on OUTPUT so far */
IODIR |= LCD_IOALL;
/* IO init complete, init LCD */
/* init 4-bit ops*/
lcd_rs_clr();
lcd_rw_clr();
lcd_en_clr();
//wait VDD raise > 4.5V
lcd_wait();
//dummy inst
lcd_write_nibbles(0x30);
lcd_write_nibbles(0x30);
lcd_write_nibbles(0x30);
//FUNCTION SET
//001DL N F XX
//DL=1: 8bit
//DL=0: 4bit
//N=0: 1 line display
//N=1: 2 line display
//F=0: 5x7 dots
//F=1: 5x10 dots
//our case:
Trang 49
//0010 1000
lcd_en_set();
lcd_out_data4(0x2);
lcd_en_clr();
lcd_wait();
lcd_write_nibbles(0x28);
//LCD ON
lcd_write_nibbles(0x0E);
//Clear Display
lcd_write_nibbles(0x01);
//Entry mode
lcd_write_nibbles(0x06);
}
void lcd_putchar(unsigned char c){
lcd_rs_set();
lcd_write_nibbles(c);
}
void lcd_print(unsigned char* str){
int i;
//limit 1 line display for prints
for (i=0;i<16 && str[i]!=0;i++){
lcd_putchar(str[i]);
}}
Tệp test.c chứa chƣơng trình chính:
#include "lpc210x.h"
#include "lcd.h"
int main(void)
{
lcd_init();
lcd_print("Trieu Dai Gia");
return 1;
Trang 50
}
3.3. Lập trình ngắt
Trong phần này sẽ trình bày 2 loại ngắt ngoài: ngắt sinh ra qua các chân vào ra
(IRQ) và ngắt nhanh (FIQ).
- Cấu trúc tổng quát của một chƣơng trình con phục vụ ngắt:
void tên_ctcpvn (void) __Kiểu_chương_trình_phục_vụ_ngắt
{
// các lệnh thân chương trình con phục vụ ngắt
}
- Có 3 kiểu chƣơng trình con phục vụ ngắt: _IRQ, _SWI, _ABORT,
- Chân EINT1 đƣợc kết nối tới một công tác trên board cho phép bầy lỗi nhanh một
ngắt và quan sát trên trình debug.
3.3.1. Chân Connect Block
- Tất cả các chân trên LPC2000 đƣợc kết nối tới một số chức năng ở bên trong qua
một bộ đa khối đa thành phần đƣợc gọi là chân select block. Chân select block cho
phép một user cấu hình một chân qua GPIO hoặc chọn 3 chân khác.
Hình 3.2. Chân I/O qua khối đa thành phần
- Khi khởi động thì tất cả các chân qua khối đa thành phần là chân GPIO, chức
năng thứ 2 sẽ đƣợc chọn nhờ thanh ghi PINSEL. Chân ngắt EINT1 vừa là chân I/O,
vừa là chân GPIO 0.14 và là đƣờng điều khiển UART1. Do vậy, để sử dụng EINT1
phải cấu hình chân chọn thanh ghi chuyển từ GPIO sang EINT1.
Trang 51
Các thanh ghi PINSEL khi đƣợc khởi động lên có giá trị mặc định là 0 và cấu hình
các chân dành cho mục đích và ra.
Các chân của thanh ghi PINSEL cấu hình cho mục đích ngắt:
PINSEL0: (Thí dụ cho LPC213x)
STT Chân Kí hiệu Giá trị Loại ngắt
1 3:2 P0.1 11 EINT0
2 7:6 P0.3 11 EINT1
3 15:14 P0.7 11 EINT2
4 19:18 P0.9 11 EINT3
5 29:28 P0.14 10 EINT1
6 31:30 P0.15 10 EINT2
PINSEL1: (Thí dụ cho LPC213x)
STT Chân Kí hiệu Giá trị Loại ngắt
1 1:0 P0.16 11 EINT0
2 9:8 P0.20 11 EINT3
3 29:28 P0.30 11 EINT3
3.3.2. Các chân ngắt ngoài
Các ngắt ngoài đƣợc điều khiển bởi 4 thanh ghi nhƣ hình dƣới. Thanh ghi
EXMODE chọn ngắt kích theo mức hoặc theo sƣờn. Nếu một ngắt ngoài đƣợc cấu
hình là kích theo sƣờn thì thanh ghi EXPOL đƣợc sử dụng để theo dõi ngắt hoạt động
tăng lên hay giảm xuống. Trong trƣờng hợp kích theo mức, ngắt ngoài có thể chỉ ở
mức logic 0. Nếu ở chế độ tiết kiệm nguồn thì thanh ghi EXWAKE có thể cho phép
một ngắt đánh thức CPU. Để cài đặt một nguồn ngắt đơn giản chƣơng trình cần cấu
hình chân EINT1 kích theo mức và kết nối tới CPU qua thanh ghi PINSEL0.
Trang 52
Hình 3.3. Chân ngắt ngoài dễ dàng đƣợc cấu hình để tạo nguồn ngắt.
3.3.3. Cấu trúc ngắt
- ARM7 có 2 chân ngắt ngoài cho yêu cầu ngắt nhanh (FIQ) và yêu cầu chế độ ngắt
đa mục đích. Tất cả các ngắt đều phải kết nối tới ngắt IRQ. Trong một hệ thống đơn
giản có thể kết nối qua cổng OR.
- VIC cho phép điều khiển ngắt một cách hiệu quả:
Hình 3.4 Bộ điều khiển ngắt VIC cho phép điều khiển ngắt hiệu quả
- Các ngắt phát sinh trong ứng dụng đƣợc đƣa đên VIC và đƣợc điều khiển nhƣ ngắt
FIQ hoặc một vecto ngắt hoặc không có vecto ngắt.
Trang 53
Hình 3.5.
Các thanh ghi điều khiển ngắt:
VICIRQStatus: Trạng thái các ngắt IRQ
VICFIQStatus: Trạng thái các ngắt FIQ
VICIntSelect: Thanh ghi chọn ngắt FIQ hay IRQ với các chân từ 14 đến 17:
Nếu các chân có giá trị 0 tƣơng ứng với ngắt IRQ đƣợc chọn, bằng 1 tƣơng ứng với
ngát FIQ đƣợc chọn:
STT Bít Loại ngắt Giá trị
1 14 EINT0
=0 loại ngắt IRQ
=1 loại ngắt FIQ
2 5 EINT1
3 16 EINT2
4 17 EINT3
VICIntEnable: Thanh ghi cho phép ngắt.
Sử dụng các bít từ bít 14 đến bít 17 để cho phép các ngắt từ EINT0 đến EINT3:
STT Bít Loại ngắt Giá trị
1 14 EINT0
=0 không cho phép ngắt
=1 cho phép ngắt
2 5 EINT1
3 16 EINT2
4 17 EINT3
VICIntEnClr: Xóa các ngắt sử dụng các bít từ 14 đến 17 tƣơng ứng với các ngắt từ
EINT0 đến EINT3:
STT Bít Loại ngắt Giá trị
1 14 EINT0
=1 cho phép xóa ngắt 2 5 EINT1
Trang 54
3 16 EINT2
4 17 EINT3
VICProtection: Thanh ghi bảo vệ ngắt, sử dụng bít 0:
Bít Ý nghĩa
0
=0: VIC cho phép truy cập các thanh ghi ở chế độ phân quyền hoặc ngƣời
dùng.
=1: VIC chỉ cho phép truy cập các thanh ghi ở chế độ phân quyền.
VICVectAddr : Chứa địc chỉ chƣơng trình con phục vụ ngắt khi xảy ra ngắt.
VICDefVectAddr: Chứa địa chỉ chƣơng trình con phục vụ ngắt đối với loại ngắt không
vecto.
VICVectAddr0 đến VICVectAddr16: Chứa địa chị chƣơng trình con phục vụ ngắt
tƣơng ứng với các slot từ 0 đến 15.
VICVectCntl0 đến VICVectCntl15: Cho phép ngắt:
Bít Ý nghĩa
5 = 1 cho phép ngắt tại slot tƣơng ứng
4:0 Chứa số lƣợng ngắt tại slot
Nguồn ngắt
Nguồn ngắt và quy định kênh ngắt trên LPC213x:
Nguồn ngắt Cờ ngắt Kênh phục
vụ qua VIC
WDT Watchdog Interrupt (WDINT) 0
- Chỉ dùng cho ngắt mềm 1
ARM Core Embedded ICE, DbgCommRx 2
ARM Core Embedded ICE, DbgCommRx 3
TIMER0 Match 0 - 3 (MR0, MR1, MR2, MR3)
Capture 0 - 3 (CR0, CR1, CR2, CR3)
4
TIMER1 Match 0 - 3 (MR0, MR1, MR2, MR3) 5
Trang 55
Capture 0 - 3 (CR0, CR1, CR2, CR3)
UART0 Rx Line Status (RLS)
Transmit Holding Register Empty (THRE)
Rx Data Available (RDA)
Character Time-out Indicator (CTI)
6
UART1
PWM0
Rx Line Status (RLS)
Transmit Holding Register Empty (THRE)
Rx Data Available (RDA)
Character Time-out Indicator (CTI)
Modem Status Interrupt (MSI)
7
PWM0 Match 0 - 6 (MR0, MR1, MR2, MR3,
MR4, MR5, MR6)
8
I2C0 SI (state change 9
SPI0 SPI Interrupt Flag (SPIF)
Mode Fault (MODF)
10
SPI1(SSP) TX FIFO at le ast half empty (TXRIS)
Rx FIFO at least half full (RXRIS)
Receive Timeout condition (RTRIS)
Receive overrun (RORRIS)
11
PLL PLL Lock (PLOCK) 12
RTC Counter Increment (RTCCIF)
Alarm (RTCALF)
13
System
Control
External Interrupt 0 (EINT0)
External Interrupt 1 (EINT1)
External Interrupt 2 (EINT2)
External Interrupt 3 (EINT3)
14
15
16
17
ADC0 A/D Converter 0 end of conversion 18
I2C1 SI (state change) 19
BOD Brown Out detect 20
ADC1 A/D Converter 1 end of conversion 21
Trang 56
3.3.4. Ngắt FIQ
- Nếu có nhiều ngắt FIQ thì tƣơng ứng với các bít trong trong thanh ghi ISR thì
thanh ghi trạnh thái VIC FIQ sẽ chọn chƣơng trình cọn phục vụ ngắt phù hợp để thực
thi.
- Khi một ngắt FIQ sinh ra, CPU sẽ chuyển sang chế độ FIQ và PC nhảy tới địa chỉ
0x0000001C và nhảy tới địa chỉ chƣơng trình con pvn.
3.3.5. Kết thúc ngắt
- Trƣớc khi kết thúc chƣơng trình con phục vu ngắt phải đảm xóa cờ ngắt ở phía
thiết bị không ngắt lại tiếp tục sinh ra.
Thí dụ ngắt FIQ:
void main (void)
{
IODIR1 = 0x00FF0000; //Thiet lap chan LED la chan ra
PINSEL0 = 0x20000000; //Chon chuc nang EINT1 tai chan connect block
VICIntSelect = 0x00008000; //Cho phep mot kenh qua VIC la FIQ
VICIntEnable = 0x00008000; //Cho phép ngat tu EINT1 vào VIC
IOCLR1 = 0x00FF0000; // Xoa LED
while(1); //Lap mai mai
}
void fiqint (void) __fiq //chuong trinh pvn
{
IOSET1 = 0x00FF0000; //thiet lap chan led
EXTINT = 0x00000002; //xoa co ngat tu phia thiet bi ngoai
}
3.3.6. Vecto IRQ
- Nếu có một nguồn ngắt là FIQ thì tất cả các nguồn con lại phải đƣợc kết nối tới
đƣờng IRQ. Để quá trình xử lý ngắt hiệu quả, VIC cung cấp một bảng tìm kiếm để
phân phát địa chỉ của các hàm C cho từng nguồn ngắt.
- VIC chứa đựng 16 khe cho địa chỉ. Mỗi khe chứa đựng một địa chỉ vecto và một
thanh ghi điều khiển vecto.
Trang 57
Hình 3.6
- Thanh ghi điều khiển ngắt chứa đựng 2 trƣờng: một trƣờng kênh và một bít cho
phép. Bằng cách lập trình trƣờng kênh, bất kỳ một kệnh ngắt nào cũng có thể đƣợc kết
nối đến một khe (slot) đƣợc đƣa ra và kích hoạt bít cho phép ngắt. Thứ tự ƣu tiên của
một vecto ngắt đƣợc đƣa ra bởi số slot,slot càng thấp thì ngắt càng đƣợc ƣu tiên.
Hình 3.7
- Một thanh ghi khác trong VIC slot là thanh ghi địa chỉ vecto (Vector Address
Register). Thanh ghi này chứa địa chỉ của một chƣơng trình con phục vụ ngắt.
3.3.7. Kết thúc một ngắt IRQ
- Khi kết thúc một ngắt thì gửi một tín hiệu đến thanh ghi địa chỉ vecto:
void main (void)
Trang 58
{
IODIR1 = 0x000FF000; //thiet lap chan ra
PINSEL0 = 0x20000000; //cho phep ngat ngoai EXTINT1
VICVectCntl0 = 0x0000002F; //chon 1 khe uu tien cho ngat
VICVectAddr0 = (unsigned)EXTINTVectoredIRQ; //lay dia chi chuong
//trinh phuc vu ngat
VICIntEnable = 0x00008000; //cho phep ngat
while(1);
}
void EXTINTVectoredIRQ (void) __irq
{
IOSET1 = 0x000FF000; //bat led
EXTINT = 0x00000002; //xoa co ngat ngoai
VICVectAddr = 0x00000000; //gui 1 tin hieu ket thuc ngat
}
3.3.8. Ngắt không có địa chỉ
VIC có thể điều khiển đƣợc 16 ngắt, nếu có nhiều hơn 16 ngắt thì phải mở rộng
ngắt. Các ngắt này đƣợc phụ bởi một ISR. Địa chỉ của ISR đƣợc lƣu trong trong một
thanh ghi địa chỉ ngắt mặc định. Nêu một ngắt đƣợc cho phép bởi VIC mà không
đƣợc cấu hình là FIQ hoặc IRQ thì sẽ đƣợc xếp vào ngắt không có địa chỉ. Khi ngắt
này xảy ra thì một địa chỉ sẽ đƣợc tải vào trong thanh ghi địa chỉ ngắt. Và CPU phải
đọc thanh ghi trạng thái IRQ để xem nguyên nhân ngắt.
Hình 3.8. Một địa chỉ mặc định đƣợc tải vào thanh ghi địa chỉ ngắt
Trang 59
3.3.9. Kết thúc ngắt không địa chỉ
- Khi kết thúc ngắt phải xóa cờ trạng thái và viết thanh ghi địa chỉ ngắt.
Thí dụ ngắt không địa chỉ:
void main (void)
{
IODIR1 = 0x000FF000; //cau hinh cac chan ra
PINSEL0 = 0x20000000; //cho phap ngat ngoai EXTINT0
VICDefVectAddr = (unsigned)NonVectoredIRQ; //dua dia chi ngat IRQ
//vao VIC slot
VICIntEnable = 0x8000; //cho phep ngat ngoai EXTINT0 trong VIC
while(1);
}
void NonVectoredIRQ (void) __irq
{
if(VICIRQStatus&0x00008000) //kiem tra nguon sinh ngat
{
IOSET1 = 0x00FF0000; //bat led
EXTINT = 0x00000002; //xoa co ngat
update++;
}
VICVectAddr = 0x00000000; //gui tin hieu ket thuc ngat
}
3.4. Lập trình Timer
3.4.1. Các Timer
- Họ vi điều khiển ARM có số lƣợng các Timer dùng cho mục đích chung là khác
nhau, tùy vào từng loại, nhƣng ít nhất là có 2 Timer.
- Mỗi Timer 32 bít và một mạch đếm 32 bít.
- Nguồn xung clock cho tất cả các Timer là một mạch tạo xung cỡ lớn VLSI.
Trang 60
Hình 3.9. Cấu trúc Timer 32 bít của ARM
Thangh ghi PINSEL0 cấu hình cho các chân của TIMER:
STT Chân Kí hiệu Giá trị Chọn chân
1 5:4 P0.2 10 Capture 0.0 (Timer 0)
2 9:8 P0.4 10 Capture 0.1 (Timer 0)
3 13:12 P0.6 10 Capture 0.2 (Timer 0)
4 21:20 P0.10 10 Capture 1.0 (Timer 1)
5 23:22 P0.11 10 Capture 1.1 (Timer 1)
6 7:6 P0.3 10 Match 0.0 (Timer 0)
7 11:10 P0.5 10 Match 0.1 (Timer 0)
8 25:24 P0.12 10 Match 1.0 (Timer 1)
9 27:26 P0.13 10 Match 1.1 (Timer 1)
Thanh ghi VICIntEnable cho phép ngắt của TIMER:
- Bít D5: cho phép ngắt của Timer 1
- Bít D4: cho phép ngắt của Timer 0
Giá trị các bít này có thể đọc hoặc ghi đƣợc.
Thanh ghi VICIntSelect cho phép chọn loại ngắt của TIMER:
- Bít D5: cho phép chọn loại ngắt của Timer 1
- Bít D4: cho phép chọn loại ngắt của Timer 0
Trang 61
Giá trị các bít này có thể đọc hoặc ghi đƣợc, nếu bằng 0-là loại ngắt IRQ, 1-loại ngắt
FIQ.
Các thanh ghi của Timer:
Thanh ghi ngắt: TxIR (T0IR, T1IR)
Bít Kí hiệu Ý nghĩa Giá trị khi
khởi động
0 MR0 Cờ ngắt cho kênh so khớp 0 0
1 MR1 Cờ ngắt cho kênh so khớp 1 0
2 MR2 Cờ ngắt cho kênh so khớp 2 0
3 MR3 Cờ ngắt cho kênh so khớp 3 0
4 CR0 Cờ ngắt cho sự khiện chụp trên kênh so khớp 0 0
5 CR1 Cờ ngắt cho sự khiện chụp trên kênh so khớp 1 0
6 CR2 Cờ ngắt cho sự khiện chụp trên kênh so khớp 2 0
7 CR3 Cờ ngắt cho sự khiện chụp trên kênh so khớp 3 0
Thanh ghi điều khiển Timer – TCR: TIMER0: T0TCR, TIMER1: T1TCR:
Bít Ý nghĩa
0 =1: Cho phép đếm
1 =1: Reset bộ đếm
7:2 Không dùng
Thanh ghi điều khiển đếm - CTCR: TIMER0: T0CTCR và TIMER1:T1CTCR:
Thanh ghi này cho phép chọn giữa chế độ định thời và chế độ đếm:
Bít Mục đích Ý nghĩa các bít
1:0 Cho phép
chọn chế
độ đếm
hoặc định
thời
00: Chọn chế độ định thời
01-Chế độ đếm: TC tăng trên chân chụp đƣợc chọn bởi bít 3:2 có
tăng theo sƣờn
10-Chế độ đếm: TC tăng trên chân chụp đƣợc chọn bởi bít 3:2 có
giảm theo sƣờn
11-Chế độ đếm: TC tăng trên chân chụp đƣợc chọn bởi bít 3:2 theo
cả sƣờn tăng và sƣờn giảm
Trang 62
3:2 Cho phép
chọn đầu
vào đếm
00-Chọn kệnh CAPn.0 (CAP0.0 cho TIMER0 và CAP1.0 cho
TIMER1)
00-Chọn kênh CAPn.1 (CAP0.1 cho TIMER0 và CAP1.1 cho
TIMER1)
00-Chọn kệnh CAPn.2 (CAP0.2 cho TIMER0 và CAP1.2 cho
TIMER1)
00-Chọn kệnh CAPn.3 (CAP0.3 cho TIMER0 và CAP1.3 cho
TIMER1)
7:4 Không dùng
Thanh ghi đếm – TC: T0TC và T1TC: Chứa giá trị đếm, giá trị trong TC sẽ tăng
lên khi bộ đếm Prescale Counter đạt tới giá trị tới hạn. Khi đạt đến giá trị
0xFFFFFFFF thì TC lại quay về 0.
Thanh ghi Prescale Register – PR: TIME R0: T0PR và TIMER1: T1PR: Là
thanh ghi 32 bít, chứa giá trị cực đại cho Prescale Counter.
Thanh ghi Prescale Counter Register –PC: TIMER0: T0PC và TIMER1: T1PC:
Là thanh ghi 32 bít, giá trị của PC sẽ tăng lên theo mỗi xung nhịp, khi PC đạt
tới giá trị lƣu trong thanh ghi PR và trở về 0 thì TC sẽ tăng lên 1.
Thanh ghi so khớp MR0 đến MR3: Giá trị liên tiếp đƣợc so sánh với giá trị của
TC trên các kênh tƣơng ứng.
Thanh ghi điều khiển so khớp - MCR, TIMER0: T0MCR và TIMER1:
T1MCR:
Điều khiển hành động xảy ra khi có sự kiện chụp trên các kênh tƣơng ứng:
Bít Kí hiệu Ý nghĩa
0 MR0I Cho phép sinh ra ngắt khi TC=MR0
1 MR0R Reset TC khi TC=MR0
2 MR0S Dừng TC và PC khi TC=MR0
3 MR1I Cho phép sinh ra ngắt khi TC=MR1
4 MR1R Reset TC khi TC=MR1
5 MR1S Dừng TC và PC khi TC=MR1
Trang 63
6 MR2I Cho phép sinh ra ngắt khi TC=MR2
7 MR2R Reset TC khi TC=MR2
8 MR2S Dừng TC và PC khi TC=MR2
9 MR3I Cho phép sinh ra ngắt khi TC=MR3
10 MR3R Reset TC khi TC=MR3
11 MR3S Dừng TC và PC khi TC=MR3
15:12 - Không dùng
Các thanh ghi chụp - CR0-CR3: Chứa giá trị chụp đƣợc trên các kênh tƣơng
ứng.
Thanh ghi điều khiển chụp – CCR: TIMER0: T0CCR và TIMER1: T1CCR:
Bít Kí hiệu Ý nghĩa
0 CAP0RE Chụp khi có tín hiệu tăng từ 0 lên 1 tại kênh CAPn.0
1 CAP0FE Chụp khi có tín hiệu giảm từ 1 lên 0 tại kênh CAPn.0
2 CAP0I Cho phép sinh ra ngắt xảy ra tại kênh CAPn.0
3 CAP1RE Chụp khi có tín hiệu tăng từ 0 lên 1 tại kênh CAPn.1
4 CAP1FE Chụp khi có tín hiệu giảm từ 1 lên 0 tại kênh CAPn.1
5 CAP1I Cho phép sinh ra ngắt xảy ra tại kênh CAPn.1
6 CAP2RE Chụp khi có tín hiệu tăng từ 0 lên 1 tại kênh CAPn.2
7 CAP2FE Chụp khi có tín hiệu giảm từ 1 lên 0 tại kênh CAPn.2
8 CAP2I Cho phép sinh ra ngắt xảy ra tại kênh CAPn.2
9 CAP3RE Chụp khi có tín hiệu tăng từ 0 lên 1 tại kênh CAPn.3
10 CAP3FE Chụp khi có tín hiệu giảm từ 1 lên 0 tại kênh CAPn.3
11 CAP3I Cho phép sinh ra ngắt ngắt xảy ra tại kênh CAPn.3
15:12 - Không dùng
Thanh ghi so khớp ngoài External Match Register – EMR: TIMER0: T0EMR
và TIMER1: T1EMR: Cung cấp cả tín hiệu điều khiển và trạng thái của các
chân so khớp ngoài, đảo trạng thái của các chân MAT.
Hoạt động của timer:
-Tốc độ của Timer đƣợc điều khiển bởi giá trị lƣu trữ trong thanh ghi prescaler
Reg (TxPR).
Trang 64
- Bộ đếm sẽ tăng lên cho đến khi đạt tới giá trị lƣu trữ trong thanh ghi thanh ghi
đếm.
- Khi đạt tới giá trị tối đa, bộ đếm sẽ đƣợc reset lại và trở lại giá trị 0.
- Thanh ghi điều khiển đếm TxTCR chỉ có 2 bít (D1D0), một bít để điều khiển
cho phép đếm(D0), một bít để reset bộ đếm(D1).
- Mỗi bộ đếm có 4 kênh cho phép chụp lại giá trị của bộ đếm tại thời điểm khi có
tín hiệu đầu vào tác động tạo ra sự dịch chuyển giá trị.
Hình 3.10.
- Thanh ghi điều khiển chụp (TxCCR) có thể đƣợc cấu hình để điều khiển chụp, khi
giá trị bộ đếm tăng lên hoặc giảm.
- Khi xảy ra sự kiện chụp, giá trị của bộ đếm đƣợc chuyển vào thanh ghi chụp
(TxCRx )và có thể sinh ra một ngắt nếu cần thiết.
Thí dụ sau cấu hình Timer 0 cho phép chụp tại 2, khi có sự kiện chụp thì sẽ sinh ra một
ngắt.
int main(void)
{
VPBDIV = 0x00000002; //thiet lap pclk co tan so 30 MHz
PINSEL0 = 0x00000020; //cho phep chân P0.2 de chup tai kenh 0
T0PR = 0x00007530; //Toc do cua timer là 1 Msec
T0TCR = 0x00000002; //reset bo dem va prescaler
T0CCR = 0x00000005; //Chup theo suon tăng 0->1 và sinh ra ngắt.
T0TCR = 0x00000001; //cho phep timer
VICVectAddr4 = (unsigned)T0isr; //Thiet lap dia chi vecto ngat cho ISR cua
time
VICVectCntl4 = 0x00000024; //Thiet lap kenh
Trang 65
VICIntEnable = 0x00000010; //Cho phep ngat
while(1);
}
void T0isr (void) __irq
{
static int value;
value = T0CR0; // Đọc giá trị chụp đƣợc tại kenh 0
T0IR |= 0x00000001; // xoa ngat
VICVectAddr = 0x00000000; //Gia ghi mot tin hieu ket thuc ngat
}
- Mỗi kênh của Timer co một thanh ghi so khớp 32 bít, giá trị chụp đƣợc sẽ đƣợc so
sánh với giá trị trong thanh ghi so khớp, khi hai giá trị trùng nhau thì Timer sẽ thực
hiện một trong các hành động nhƣ: khởi động lại, dừng hoặc sinh ra ngắt và tác động
đến chân ngắt ngoài có thể set =1 hoặc xóa bằng 0 hoặc lơ lửng.
Hình 3.11.
- Để cấu hình Timer có sự kiện so khớp và nạp giá trị của thanh ghi so khớp mong
muốn. Sự kiện so khớp có thể có thể đƣợc điều khiển bởi thanh ghi điều khiển so
khớp. Trong thanh ghi nay mỗi kênh đƣợc điều khiển bởi một nhóm bít cho phép các
sự kiện so khớp xảy ra: sinh ra ngắt, khởi động timer và dừng timer.
- Mỗi kênh so khớp đƣợc kết hợp với một chân so khớp có thể thay đổi đƣợc khi có
một sự kiện xảy ra. Các chân so khớp có thể đƣợc điều khiển bởi 4 bít đầu trong thanh
ghi so khớp ngoài.
Trang 66
Hình 3.12. Thanh ghi so khớp ngoài
- Thanh ghi so khớp ngoài chứa đựng các trƣờng cấu hình cho mỗi kênh. Lập trình
các trƣờng này để quyết định hành động sẽ xảy ra khi có sự kiện so khớp. Mỗi chân so
khớp ứng với một bít có thể lập trình trực tiếp để thay đổi mức logic.
- Thí dụ sau mô phỏng cách tạo một xung đơn giản sử dụng 2 kênh so khớp. Kệnh 0
đƣợc sử dụng để sinh ra chu kỳ tín hiệu PWM. Khi sự kiện so khớp xảy ra, timer khởi
động lại và sinh ra một ngắt. Ngắt đƣợc sử dụng để thiết lập chân Match 1 lên mức
cao. Kệnh 1 đƣợc sử dụng để điều khiển hoàn thành chu kỳ. Khi sự kiện match 1 xảy
ra, chân Match 1 đƣợc xoa về 0. Bởi vậy, sự thay đổi giá trị trong thanh ghi Match 1 để
tạo ra tín hiệu PWM.
Thí dụ:
int main(void)
{
VPBDIV = 0x00000002; // Cấu hình bộ chia tần VPB
PINSEL0 |= 0x00000800; // Match1 là đầu ra
T0PR = 0x0000001E; //Tải presaler
T0TCR = 0x00000002; //Reset counter và presale
T0MCR = 0x00000003; //Khi so khớp thì khởi động lại và sinh ra ngắt
T0MR0 = 0x00000010; //Thiết lập chu kỳ timer
T0MR1 = 0x00000008; // Thiết lập 50% chu kỳ
T0EMR = 0x00000042; //Thiết lập châp MAT1 lên 1 trong chu kỳ đầu
Trang 67
T0TCR = 0x00000001; //cho phép timer
VICVectAddr4 = (unsigned)T0isr; //Thiết lập địa chỉ ISR của timer
VICVectCntl4 = 0x00000024; //Thiết lập kệnh
VICIntEnable |= 0x00000010; //Cho phép ngắt
while(1);
}
void T0isr (void) __irq
{
T0EMR |= 0x00000002;// Thiết lệp MAT1 lên mức cao để bắt đầu chu kỳ
T0IR |= 0x00000001; // Xóa ngắt tại match 0
VICVectAddr = 0x00000000; // Giả tin hiệu kết thúc ngắt
}
3.4.2. Đồng hồ thời gian thực (Real Time Clock - RTC)
- Đồng hồ thời gian thực LPCxxx là một lịch biểu chính xác đến năm 2099 và
không hoạt động với tần sô Pclk. RTC tiêu thụ một năng lƣợng thấp. RTC có một tập
các thanh ghi cảnh báo đƣợc sử dụng để lƣu trữ ngày tháng hoặc giá trị cụ thể trong
thanh ghi đếm thời gian (time-count register).
Hinh 3.13.
- RTC hoạt động ở xung nhịp chuẩn với tần số 32.7 KHz. Để có đƣợc số này thì
Pclk cần đƣợc kết nối tới bộ chia tần tham chiếu.
Trang 68
Hình 3.14. Tạo xung clock cho RTC
- Để đảm bảo xung clock đƣợc tạo ra chính xác từ Pclk, prescaler đƣợc lập trình
bởi 2 thanh ghi PREINT và PREFRAC. Tính toán giá trị cho mỗi thanh ghi nhƣ sau:
PREINT = (int)(pclk/32768)-1
PREFRAC = pclk – ((PREINT+1) x 32768
Với một xung Pclk 30MHz thì:
PREINT = (int)( 30,000,000/32768)-1 = 914
PREFRAC = 30,000,000 – ((914+1) x 32768) = 17280
Các giá trị có thể đƣợc lập trình trực tiếp vào thanh ghi prescaler của RTC, sau đó cho
phép xung clock trong thanh ghi điều khiển clock và các bộ đếm timer sẽ bắt đầu,
PREINT = 0x00000392; //Thiết lập prescaler RTC với tần số Pclk
//là 30.000 MHz
PREFRAC = 0x00004380;
CCR = 0x00000001; //Bắt đầu RTC
Có 8 thanh ghi đếm thời gian (time-counter), mỗi thanh ghi chứa một con số thời gian
đơn có thể đƣợc đọc bất kỳ lúc nào. Ngoài ra, có một tập các thanh ghi tổng hợp biểu
diễn cùng giá trị thời gian trong 3 từ cho phép tất cả các thông tin đƣợc đọc trong 3
thao tác.
Trang 69
Hình 3.15. Các thanh ghi tổng hợp của RTC
- RTC có thể sinh ra một sự kiện ngắt. Có 2 bộ tạo ngắt, Ngƣời lập trình có thể tạo
ra ngắt khi giá trị của thanh ghi time-counter đƣợc tăng lên, hoặc khi bộ giây đƣợc cập
nhật hoặc khi năm đƣợc tăng lên. Thanh ghi ngắt cho chép 8 ngắt có thể.
- Cách thứ 2 có thể sinh ra ngắt RTC các thanh ghi cảnh báo. Mỗi thanh ghi time-
counter có một thanh ghi cảnh báo (Alarm register), và có thể cảnh báo trong khoảng
thời gian hiện tại đến năm 2099 một cách chính xác.
- Thanh ghi Alarm Mask điều khiển sự so sánh. Thanh ghi ngắt location có 2 bít
đƣợc sử dụng để cho biết nguyên nhân sinh ra ngắt.
Thí dụ minh họa:
int main(void)
{
VPBDIV = 0x00000002;
IODIR1 = 0x00FF0000; // Thiết lập các chân đầu ra nối với led
IOSET1 = 0x00020000;
PREINT = 0x00000392; //Thiết lập RTC prescaler với Pclk 30MHz
PREFRAC = 0x00004380;
CIIR = 0x00000001; //Cho phép ngắt khi đến số giây
ALSEC = 0x00000003; //Thiết lập thanh ghi cảnh báo 3
AMR = 0x000000FE; //Cho phép cảnh báo theo số giây Alarm
CCR = 0x00000001; //Khởi động RTC
VICVectAddr13 = (unsigned)RTC_isr; //Lấy địa chỉ chƣơng trình phục vụ ngắt
VICVectCntl13 = 0x0000002D; //Thiết lập kệnh
VICIntEnable = 0x00002000; //Cho phép ngắt
Trang 70
while(1);
}
void RTC_isr(void){
unsigned led;
if(ILR&0x00000001) //Kiểm tra ngắt RTC
{
led = IOPIN1; //Đọc trạng thái của các chân vào ra IO
IOCLR1 = led&0x00030000; //tắt LED
IOSET1 = ~led&0x00030000; // bật LED
ILR = 0x00000001; //xóa ngắt
}
if(ILR & 0x00000002)
{
IOSET1 = 0x00100000; //set led 0.7
ILR = 0x00000002; //xóa thanh ghi ngắt
}
VICVectAddr = 0x00000000; /*Giả lập kết thúc ngắt */
}
3.5. Lập trình qua UART
- LPCxxx có 2 chíp UARTs. UART1 có những tính năng hiện đại. Các thiết bị kết
nối phù hợp với chuẩn công nghiệp 550. 16 bytes truyền và nhận theo kiểu FIFOs.
Hình 3.16. Sơ đồ chân UART
Trang 71
Thanh ghi PINSEL0 cấu hình cho UART:
STT Chân Kí hiệu Giá trị Chọn chân
1 1:0 P0.0 01 TxD của UART0
2 3:2 P0.1 01 RxD của UART0
3 17:16 P0.8 01 TxD của UART1
4 19:18 P0.9 01 RxD của UART1
5 21:20 P0.10 01 Có thể RTS của UART1
6 23:22 P0.11 01 Có thể CTS của UART1
7 25:24 P0.12 01 Có thể DST của UART1
8 27:26 P0.13 01 Có thể DTR của UART1
9 29:28 P0.14 01 Có thể DCDcủa UART1
31:30 P0.15 01 Có thể RI của UART1
Các thanh ghi của UART:
- Thanh ghi Receiver Buffer Register – UxRBR: là thanh ghi đệm nhận dữ liệu 8 bít.
Khi bít DLAB (Divisor Latch Access Bit) trong thanh ghi UxLCR thì cho phép đọc giá
trị thanh ghi này. Thanh ghi này chỉ cho phép đọc, không đƣợc phép ghi.
- Thanh ghi Transmit Holding Register UxTHR: Là thanh ghi đệm truyền 8 bít dữ liệu.
Khi bít DLAB = 0 cho phép ghi kí tự lên thanh ghi này mà không cho phép đọc dữ liệu
từ thanh ghi.
- Thanh ghi chốt phần chia Divisor Latch Registers – UxDLL: Chứa tốc độ truyền dữ
liệu, gồm 2 thanh ghi 8 bít là DLL và DLM. Các thanh ghi này đƣợc truy cập khi bít
DLAB=1.
- Thanh ghi Fractional Divider Register –UxFDR: Là thanh ghi 31 bít dùng để điều
khiển tốc độ truyền dữ liệu theo xung nhịp hệ thống và có thể đọc ghi theo ý của ngƣời
dùng. Các bít 3:0 chứa giá trị DIVADDVAL, các bít 7:4 chứa giá trị MULVAL, với 0
<= DIVADDVAL<=15 và 0< MULVAL <=15. Khi đó tốc độ truyền đƣợc tính theo
công thức sau:
Trang 72
Thanh ghi này chir đƣợc sử dụng trong một số phiên bản của LPC từ 213x trở lên.
Tính toán tốc độ của UART:
Thí dụ 1: Tính toán tốc độ của UART0 theo PCLK của hệ thống. Khi PCLK = 20
MHz, U0DL = 130 (U0DLM = 0x00 and U0DLL = 0x82), DIVADDVAL = 0
và MULVAL = 1 sẽ cho phép UART0 đạt tới tốc độ 9615 bauds.
Example 2: Tính toán tốc độ của UART0 theo PCLK của hệ thống. Khi PCLK = 20
MHz, U0DL = 93 (U0DLM = 0x00 and U0DLL = 0x5D), DIVADDVAL = 2 và
MULVAL = 5 sẽ cho tốc độ UART0 là 9600 bauds.
- Thanh ghi cho phép ngắt Interrupt Enable Regi ster – UxIER: Hoạt động khi
DLAB=0.
Bít Ý nghĩa
0 =1 cho phép sinh ra ngắt khi nhận dữ liệu
1 =1 cho phép sinh ra ngắt khi truyền dữ liệu
2 =1 Cho phép ngắt khi thay đổi trạng thái chân Rx
- Thanh ghi điều khiển hàng đợi FIFO Control Register - UxFCR:
- Thanh ghi điều khiển đƣờng truyền: Line Control Register - U0LCR: Là thanh ghi 8
bít với chức năng cụ thể của các bít nhƣ sau:
Bít Giá trị và ý nghĩa
1:0 Chứa số bít dữ liệu
00- 5 bít
01-6 bít
10-7 bít
11-8 bít
2 Bít stop
0- 1 bít
1-2 bít (1.5 bít nếu bít 1:0=00)
3 0-Không kiểm tra chắn/lẻ
1-Cho phép kiểm tra chẵn/lẻ
5:4 00-Kiểm tra lẻ
01-Kiểm tra chắn
Trang 73
10-bắt buộc kết quả bằng 0
11-bắt buộc kết quả bằng 1
6 Cho phép ngắt khi truyền
0-không cho phép
1- chân TxD=0 khi UxLCR[6]=1
7 DLAB-bít chốt
0-Không cho phép truy cập thanh ghi tốc độc DLL và
DLM
1-Cho phép truy cập thanh ghi DLL và DLM
Thanh ghi trạng thái đƣờng truyền Line Status Register – UxLSR: Là thanh ghi chỉ
đcoj cung cấp trạng thái của quá trình nhận và gửi dữ liệu.
Bít Kí hiệu Giá trị, ý nghĩa
0 RBR 0-UxRBR rỗng
1- UxRBR có dữ liệu
1 OE 0-Không kích hoạt lỗi tràn FIFO nhận
1-Kích hoạt lỗi tràn FIFO nhận
2 PE 0-Không kích hoạt lỗi kiểm tra chẵn lẻ
1-Kích hoạt lỗi kiểm tra chẵn lẻ
3 FE 0-không kích hoạt lỗi bít stop=0
1- kích hoạt lỗi bít stop=0
4 BI 0-không kích hoạt ngắt break
1-kích hoạt ngắt break
5 THRE 0-Đệm truyền UxTHR có dữ liệu
1-Đệm truyền UxTHR rỗng
6 TEMT 0-Đệm truyền UxTHR hoặc UxTSR có dữ liệu
1-Đệm truyền UxTHR hoặc UxTSR rỗng
7 RxFE 0-UxRBR không có lỗi
1- UxRBR có ít nhất một lỗi
Cài đặt UART0 nhƣ sau:
void init_serial (void) /* khởi tạo giao dien cong uart */
Trang 74
{
PINSEL0 = 0x00050000; /* cho phep RxD1 va TxD1*/
U1LCR = 0x00000083; /* 8 bít dữ liệu, không bít Parity, 1 Stop bit */
U1DLL = 0x000000C2; /* tốc độ 9600, xung nhịp clock 30MHz VPB */
U1LCR = 0x00000003; /* DLAB = 0*/
}
- Chân chọn khối phải đƣợc lập trình để vi xử lý chuyển từ chức năng GPIO sang
UART. Thanh ghi điều khiển đƣờng truyền ( line control register ) UART đƣợc sử
dụng để định dạng khung truyền dữ liệu.
Hình 3.17. Thanh ghi điều khiển đƣờng truyền LCR của UART
- Tần số hoạt động của UART đƣợc chia từ Pclk, gấp 16 lần tốc độ truyền dữ liệu
và tính theo công thức:
Divisor = Pclk/16 x BAUD
- Giả sử Pclk=30MHz: Divisor = 30,000,000/16 x 9600 = (approx) 194 or 0xC2
Không thể lấy tốc độ chính xác của UART, tuy nhiện các cổng này có thể hoạt
động với sai số tốc độ 5%. Nếu muốn điều chỉnh Pclk để nhân đƣợc tốc độ chính xác
thì phải sử dụng đến CAN.
- Giá trị Divisor đƣợc tổ chức thành 2 thanh ghi Divisor latch MSB (DLM) và
Divisor latch LSB (DLL). 8 bít đầu tiên của cả 2 thanh ghi chứa nửa giá trị chia nhƣ
hình dƣới, cuối cùng, bít DLAB đƣợc set =0 để bảo vệ nội dung của thanh ghi chia tốc
độ:
Trang 75
Hình 3.18. Thiết lập tốc độ của UART
- Khi UART đƣợc khởi tạo, các kí tự có thể đƣợc truyền bằng cách ghi tới thanh
ghi Transmit Holding Register. Các kí tự nhận đƣợc có thể đọc đƣợc từ thanh ghi đệm
nhận (receive buffer register). Thực chất cả hai thanh ghi này là 1, và việc đọc ghi theo
cơ chế FIFO. Hai chƣơng trình con dƣới đây mô tả việc gửi và nhậ kí tự.\
int putchar (int ch) /* Ghi một ký tự tới cổng Serial */
{
if (ch == '\n') {
while (!(U1LSR & 0x20));
U1THR = CR; /* output CR */
}
while (!(U1LSR & 0x20));
return (U1THR = ch);
}
int getchar (void) /* Đọc từ cổng Serial */
{
while (!(U1LSR & 0x01));
return (U1RBR);
Trang 76
}
Trong thƣ viện STDIO của Keil C có thể sử dụng hàm printf() và scanf(). Cả hai hàm
putchar() và getchar() đều đọc thanh ghi liên kết trạng thái (LSR) để kiểm tra lỗi và
trạng thái truyền và nhận.
Hình 3.19. Thanh ghi liên kết trạng thái cho phép kiểm tra lỗi
UART có 1 ngắt tới VIC, nhƣng có 3 nguồn ngắt. Các ngắt đƣợc sinh ra khi thay đổi
trạng thái đƣờng nhận (receive line status). Nếu có một lỗi phát sinh thì một ngắt sẽ
đƣợc sinh ra và thanh ghi liên kết trạng thái sẽ đƣợc đọc để tìm nguyên nhân lỗi, Hai
loại ngắt còn lại sinh ra do nhận và truyền dữ liệu. Ngắt sinh ra sẽ đƣợc theo dõi bởi
các ký tự nhận đƣợc trong chân RX FIFO. Các ngắt đƣợc theo dõi trong thanh ghi điều
khiển UART FIFO.
Trang 77
Hình 3.20. Bảng theo dõi các ngắt
Khi truyền sinh ra ngắt khi thanh ghi đệm truyền và thanh ghi dịch truyền là rỗng:
Hình 3.21. Ngắt tạo ra khi truyền
UART1 có cấu trúc giống UART0 nhƣng có hỗ trợ thêm modem điều khiển. Có
thêm các chân mở rộng để hỗ trợ giao diện modem: CTS, DCD, DSR, DTR, RI, RTS,
có thêm 2 thanh ghi: điều khiển modem và trạng thái modem; và một nguồn ngắt để
cung cấp thêm trạng thái ngắt của modem.
Trang 78
Hình 3.22. Cấu trúc chân mở rộng của UART1
3.6. Giao diện I2C
- I2C có thể hoạt động ở chế độ chủ hoặc khách với tốc độ 400K bit/s và chế độ
chủ sẽ tự động đƣợc phân xử trong hệ thống có nhiều thiết bị chủ.
Hình 3.23. Bus I2C
Hai đƣờng Serial Clock (SCL) và Data line (SDA) phải đƣợc chuyển đổi từ chân GPIO
sang I2C qua bộ kết nối.
Trang 79
Hình 3.24. Các thanh ghi của I2C
Giao diện I2C đƣợc điều khiển bởi 7 thanh ghi. Thanh ghi điều khiển có 2 thanh ghi
riêng biệt đƣợc sử dụng để set và clear thanh ghi điều khiển (I2CONSET và
I2CONCLR). Tốc độ bít đƣợc quyết định bởi hai thanh ghi (I2SCLH và I2CLL); thanh
ghi trạng thái trả lại mã điều khiển có liện quan tới các sự kiện trên bus. Thanh ghi ghi
đệm phát và đêm truyền, khi LPC đƣợc cấu hình là thiết bị slave thì địa chỉ mạng đƣợc
lƣu trong thanh ghi I2ADR.
Các lệnh khởi tạo giao diện I2C:
VICVectCntl1 = 0x00000029; //Chọn độ ƣu tiên cho ngắt
VICVectAddr1 = (unsigned)I2CISR //Đƣa địa chỉ ngắt và vecto ngát VIC
VICIntEnable = 0x00000200; //cho phép ngắt
PINSEL0 = 0x50; //chuyển chân GPIO sang chân I2C
I2SCLH = 0x08; //Tốc độ bít to 57.6KHz
I2SCLL = 0x08
- Tốc độ bít đƣợc lƣu trong 2 thanh ghi I2SCLH và I2CSLL:
Bit Rate = Pclk/(I2SCLH+I2CSLL
- Giả sử trong ví dụ trên PLL không đƣợc sử dụng và xung nhịp bên ngoài là
14.1456MHz thì tốc độ bít là:
Bit Rate = 14.7456/B ( 8 + 8) = 937500
- Cấu hình thanh ghi điều khiển bus I2C để đọc hoặc ghi dữ liệu nhƣ là bus chủ hoặc
nhận hoặc trả lời từ bus chủ nhƣ sau:
Trang 80
Hình 3.25. Cấu hình thanh ghi điều khiển I2C
Chƣơng trình truyền dữ liệu I2C ở chế độ master nhƣ sau:
void I2CTransferByte(unsigned Addr,unsigned Data)
{
I2CAddress = Addr; //Place address and data in Globals to be used by
//the interrupt
I2CData = Data;
I2CONCLR = 0x000000FF; //Clear all I2C settings
I2CONSET = 0x00000040; //Enable the I2C interface
I2CONSET = 0x00000020; //Start condition
}
Hình 3.26. Thanh ghi trạng thái của I2C:
Chƣơng trình gửi một kí tự qua I2C:
void I2CISR (void) //I2C interrupt routine
{
switch (I2STAT) //Read result code and switch to next action{
case ( 0x08): //Start bit
Trang 81
I2CONCLR = 0x20; //Clear start bit
I2DAT = I2CAddress; //Send address and //write bit
break;
case (0x18): //Slave address+W, ACK
I2DAT = I2Cdata; //Write data to tx register
break;
case (0x20): //Slave address +W, Not ACK
I2DAT = I2CAddress; //Resend address and write bit
break;
case (0x28): //Data sent, Ack
I2CONSET = 0x10; //Stop condition
break;
default :
break;
}
I2CONCLR = 0x08; //Clear I2C interrupt flag
VICVectAddr = 0x00000000; //Clear interrupt in
}
3.7. Giao diện SPI
Cũng giống nhƣ I2C, SPI cũng là một giao diện bus cho phép truyền và nhận dữ
liệu với thiết bị bên ngoài nhƣng chƣa đủ thông minh để quản lý bus:
Trang 82
Hình 3.27. Giao diện SPI
Giao diện SPI có 4 chân: một chân clock, một chận chọn slave và hai chân dữ liệu
master in/slave out và master out/slave in. Chân clock cung cấp một xung 400kbits/s
khi ở chế độ master, hoặc nhận nguồn xung từ bên ngoài khi ở chế độ slave. Bus SPI
hoàn toàn chỉ để truyền dữ liệu nối tiếp với tốc độ cao và không giống nhƣ giao diện
I2C, nó không có sơ đồ địa chỉ đƣợc xây dựng khi truyền nối tiếp.
Một thiết bị ngoại vi ngoài đƣợc chọn qua chân slave. Thông thƣờng LPC2000 đƣợc
kích hoạt ở chế độ chủ và sử dụng các chân vào ra chung để chọn thiết bị SPI mong
muốn. Khi SPI ở chế độ slave, chân slave của nó đƣợc đẩy về mức 0 để cho phép SPI
chủ truyền thông với nó. Hai chân dữ liệu đƣợc kết nối với thiết bị SPI từ xa và chiều
truyền phụ thuộc vào thiết bị hoạt động ở chế độ chủ hay khách (master hay slave).
Lập trình qua giao diện SPI có 5 thanh ghi:
- Thanh ghi đến xung (clock counter register) quyết định tốc độ, Pclk đƣợc chia ở
giá trị trong bộ đến xung tạo tốc độ cho SPI. Thanh ghi này giữ giá trị nhỏ nhất trong 8
bít.
- Thanh ghi điều khiển đƣợc sử dụng để cấu hình hoạt động của bus SPI. Do các
thiết bị SPI chỉ để truyền dữ liệu và có giải rộng các thiết bị có thể kết nối, xung SPI và
Trang 83
đƣờng dữ liệu có thể đƣợc cấu hình để hoạt động trong chế độ cấu hình riêng. Trƣớc
hết cần tạo cực (mức thấp hay cao hoặc ở giữa) phân đoạn và xung nhƣ hình sau:
Hình 3.28. Tạo cực và phân đoạn xung clock
Cuối cùng cấu hình hƣớng dữ liệu cho biết MSB hay LSB đƣợc truyền trƣớc.
Hình 3.29. Cấu hình hƣớng dữ liệu qua SPI
- Từng bít trong thanh ghi cấu hình đƣợc cấu hình để kết nối truyền thông với từng
thiết bị qua SPI và đƣợc set bởi ngƣời lập trình.
- Dữ liệu đƣợc gửi đi sẽ đƣợc đƣa vào thanh ghi dữ liệu và truyền theo từng byte.
3.8. Chuyển đổi ADC và DAC
3.8.1. Chuyển đổi ADC
- Chuyển đổi A/D trong một số biến thể của LPC2000 là một bộ chuyển đổi 10 bít
với tốc độ chuyển đổi 2.44 uSec hoặc 410KSps. Bộ chuyển đổi A/D có 4 hoặc 8 bít
đầu ra tùy từng phiên bản.
Trang 84
Hình 3.30 Chuyển đổi A/D có 4 hoặc 8 kênh đầu ra với độ phân giải 10 bít
-Thanh ghi điều khiển A/D thiết lập cấu hình chuyển đổi và khởi động bộ chuyển
đổi.
- Trƣớc hết phải cài đặt xung clock cho thiết bị, xung clock A/D sẽ phân phối xung
clock tới tất cả các thiết bị từ nguồn xung PCLK. Xung PCLK phải đƣợc chia xuống
4.5MHz. Đây là giá trị xung cực đại, nếu PCLK không thể đƣợc chia xuống 4.5MHz
thì giá trị gần nhất với 4.5MHz sẽ đƣợc chọn.
Hình3.31. Các bít của thanh ghi điều khiển AD
PCLK đƣợc chia theo giá trị lƣu trong CLKDIV và theo công thức sau:
CLKDIV = ( PCLK/Adclk) - 1
Thí dụ: Mô phỏng chuyển đồi A/D trong chế độ phần cứng
int main(void)
{
VPBDIV = 0x00000002; //thiet lap Pclk la 30 MHz
IODIR1 = 0x00FF0000; // P1.16..23 dinh nghia cac chan ra
ADCR = 0x00270607; // khoi dong A/D: 10-bit AIN0 @ 3MHz
VICVectCntl0 = 0x00000032; //ket noi toi A/D qua slot 0
VICVectAddr0 = (unsigned)AD_ISR; //lay dia chi cua ngat IRQ dua vao
Trang 85
//VIC slot
VICIntEnable = 0x00040000; //cho phep ngat
while(1) {;}
}
void AD_ISR (void)
{
unsigned val,chan;
static unsigned result[4];
val = ADDR;
val = ((val >> 6) & 0x03FF); //Trich ket qua A/D
chan = ((ADCR >>0x18) & 0x07);
result[chan] = val;
}
3.8.2. Chuyển đổi D/A
- Biến thể LPC2132/2138 bộ chuyển đổi DA 10 bít.
- Bộ chuyển đổi này đơn giản chỉ có 1 thanh ghi.
- DAC đƣợc cho phép bằng cách ghi tới bít 18 và 19 của PINSEL1 chuyển chân
0.25 từ GPIO thành chức năng AOUT. Chú ý rằng một kênh của bộ chuyển
A/D cũng sử dụng chân này.
Hình 3.32. Thanh ghi điều khiển D/A
Bộ điều khiển D/A đƣợc khởi động bằng cách ghi giá trị tới bít VALUE trong thanh
ghi điều khiển. Thời gian chuyển đổi phụ thuộc vào bít BIAS. Nếu =1 thì thời gian
chuyển đổi là 2.5uSec nhƣng có thể đạt tới 700uA. Nếu =0 thì thời gian chuyển đổi là
1uSec nhƣng có thể đạt đến 350uA. Tuy nhiên, tổng thời gian thiết lập phụ thuộc vào
trở kháng bên ngoài.
3.9. Truyền dữ liệu qua CAN(Controller Area Network)
Trang 86
- Các biến thể của LPC có thể có 4 bộ điều khiển can độc lập trên board.
Giao thức CAN (Controller Area Network) đƣợc phát triển bởi Robert Bosch cho
mạng tự động (Automotive Networking) vào năm 1982. Trải qua 22 năm sau, CAN trở
thành một chuẩn cho mạng tự động và trở lên hấp dẫn đối với các hệ thống không tự
động mà muốn yêu cầu một số nút đƣợc nhúng vào. CAN có những đặc tính hấp dẫn
đối với những ngƣời phát triển hệ nhúng. Nó có chi phí thấp, dễ hiện thực hóa, các
mạng ngang hàng với đặc tính kiểm tra lỗi mạnh và tốc độ truyền cao, hàng Mbit/s. Mỗi
gói CAN khá nhỏ và có thể giữ một khối lƣợng cực đại là 8 byte dữ liệu. Do đó, CAN
rất phù hợp với các mạng nhúng nhỏ để truyền một lƣợng dữ liệu nhỏ giữa các nút một
cách tin cậy.
Thiết kế node CAN:
Một nút CAN điển hình đƣợc thiết kế nhƣ sau:
Hình 3.33. Cấu trúc CAN
- Một đặc tính quan trọng khi thiết kế CAN là bộ điều kiển CAN có đƣờng truyền
và nhận dữ liệu riêng biệt và từ thiết bị vật lý. Bởi vậy một nút đang ghi dữ liệu lên
bus, đồng thời cũng lắng nghe phản hồi trên bus. Do vậy cần có cơ chế phân xử và
phát hiện lỗi trên bus.
Hai mức logic đƣợc ghi lên 2 cặp cáp nhƣ hình dƣới, hai mức logic 0 thể hiện trạng
thái rỗi của bus.
Trang 87
Hình 3.34.
Cấu trúc một thông điệp CAN:
Hình 3.35. Cấu trúc thông điệp CAN
Các bít định danh dùng để dịnh danh gói tin: theo chuẩn 20A có 11 bít định danh, 20B
thụ động thì có bít định danh và 20B chủ động có 29 bít định danh.
RTR luôn bằng 0.
Bít DLC chứa độ dài dữ liệu
Bít CRC chứa mã lỗi khi truyền
Bít ACK: cho phép chấp nhận gói tin
Để truyền một thông điệp CAN, Bộ điều khiển CAN có một tập các thanh ghi điều
khiển và thanh ghi trạng thái nhƣ sau:
Trang 88
Hình 3.36 Các thanh ghi bộ điều khiển CAN
Tốc độ truyền tính theo công thức: Tốc độ baund=PCLK/(RBRx(1+Tseg1+Tseg2))
Với RBR là tốc đô prescaler.
Cấu trúc thanh ghi định thời prescaler:
Trang 89
Đoạn chƣơng trình sau mô tả khởi tạo CAN và truyền thông điệp:
C2MOD = 0x00000001; //Khoi dong bo dieu khien CAN
C2BTR = 0x001C001D; //thiet lap bi Timing la 125k
C2MOD = 0x00000000; //dung bo dieu khie CAN
if(C2SR & 0x00000004) //neu bo dem Tx Buffer 1 rong
{
C2TFI1 = 0x00040000; //thiet lap DLC la 4 byte
C2TID1 = 0x00000022; //dia chi Standard Frame la 0x22
C2TDA1 = NetworkData; //copy du lieu vao 4 byte dau tien
C2CMR = 0x00000001; //truyen thong diep
}
Nhận dữ liệu qua CAN:
Trang 90
Cấu trúc vùng đệm nhận dữ liệu
Hình 3.37. Các thanh ghi dùng khi nhận dữ liệu từ CAN
int main(void)
{
VPBDIV = 0x00000001; //thiet lap PClk la 60MHz
IODIR1 = 0x00FF0000; // thiet lap cac chan ra
PINSEL1|= 0x00040000; //cho phep chan 0.25 la CAN1 RX
C1MOD = 0x00000001; //reset CAN
C1BTR = 0x001C001D; //thiet lap bit Timing la 125k
C1IER =0x00000001; //cho phep nhan ngat
Trang 91
VICVectCntl0 = 0x0000003A; //chon thu tu uu tien ngat
VICVectAddr0 = (unsigned)CAN1IRQ; //lay dia chi ngat IRQ
//into the VIC slot
VICIntEnable = 0x04000000; //cho phep ngat
AFMR = 0x00000001; //Cam bo loc
C1MOD = 0x00000000; //ket thuc CAM
while(1){;}
}
Trang 92
TÀI LIỆU THAM KHẢO
[1]. Philips (2005), The insider‟s guide to the Philips ARM7 based microcontroller.
[2]. Jean J. Labrosse (2000), Embbeded System Building Block Second Edition:
Commplete and ready to use in module C, R&D Books
[3]. Michael Barr, Anthony Massa (2006), Programming Embedded Systems, O'Reilly