Hướng dẫn lập trinh AVR hay Vi điều khiển AVR do hãng Atmel sản xuất được gới thiệu lần đầu năm 1996. AVR có rất nhiều dòng khác nhau bao gồm dòng Tiny AVR (như AT tiny 13, AT tiny 22…) có kích thước bộ nhớ nhỏ, ít bộ phận ngoại vi, rồi đến dòng AVR (chẳn hạn AT90S8535, AT90S8515,…) có kích thước bộ nhớ vào loại trung bình và mạnh hơn là dòng Mega (như ATmega32, ATmega128,…) với bộ nhớ có kích thước vài Kbyte đến vài trăm Kb cùng với các bộ ngoại vi đa dạng được tích hợp trên chip, cũng có dòng tích hợp cả bộ LCD trên chip (dòng LCD AVR).[1] Tốc độ của dòng Mega cũng cao hơn so với các dòng khác. Sự khác nhau cơ bản giữa các dòng chính là cấu trúc ngoại vi, còn nhân thì vẫn như nhau. Năm 2008, Atmel lại tiếp tục cho ra đời dòng AVR mới là megaAVR, với những tính năng mạnh mẽ chưa từng có ở các dòng AVR trước đó. Có thể nói XXmegaAVR là dòng MCU 8 bit mạnh mẽ nhất hiện nay.
Trang 1Mục lục
Mở đầu 2
1 Giới thiệu vi xử lý AVR 3
2 Một số phần mềm, thiết bị hỗ trợ cho việc lập trình AVR 5
2.1 Phần mềm CodeVision 5
2.2 Phần mềm mô phỏng Proteus 5
2.3 Mạch nạp và phần mềm nạp 6
3 Ứng dụng của vi xử lý ATmega16 7
3.1 Điều khiển I/O (In/Out) 7
3.2 Ngắt ngoài (Interrupt) 8
3.3 Timer/Counter 9
3.4 Điều khiển độ rộng xung – PWM 11
3.4.1 Khái niệm độ rộng xung 11
3.4.2 Tạo PWM bằng ATmega16 11
3.5 Chuyển đổi ADC 14
3.6 Giao tiếp USART 16
3.6.1 Các thuật ngữ được dùng trong giao tiếp USART 16
3.6.2 Giao tiếp USART trên ATmega16 17
4 Các bài tập ví dụ 19
4.1 Lập trình điều khiển thiết bị ngoài (Led, động cơ…) 19
4.1.1 Phân tích mạch điện 19
4.1.2 Xây dựng nguyên lý điều khiển 19
4.1.3 Mô phỏng trên Proteus 21
4.1.4 Lập trình cho vi xử lý 22
4.1.5 Chạy thử trên mạch mô phỏng 29
4.2 Lập trình ngắt ngoài (INT) 31
4.2.1 Phân tích mạch điện 31
4.2.2 Nguyên lý điều khiển và xây dựng mạch mô phỏng trên Proteus 31
4.2.3 Lập trình cho vi xử lý 32
4.3 Lập trình Timer/Counter 35
4.3.1 Phân tích, xây dựng nguyên lý điều khiển và mạch mô phỏng 35
4.3.2 Lập trình cho vi xử lý 35
4.4 Điều khiển độ rộng xung PWM 42
4.4.1 Phân tích mạch điện 42
4.4.2 Nguyên lý điều khiển 42
4.4.3 Xây dựng mạch mô phỏng trên Proteus 43
4.4.4 Lập trình cho vi xử lý 43
4.5 Chuyển đổi ADC 46
4.5.1 Phân tích mạch điện 46
4.5.2 Nguyên lý điều khiển và mạch mô phỏng trên Proteus 47
4.5.3 Lập trình cho vi xử lý 49
4.6 Truyền nhận dữ liệu với máy tính 58
4.6.1 Phân tích mạch điện 58
4.6.2 Nguyên lý điều khiển và mạch mô phỏng 58
4.6.3 Lập trình cho vi xử lý 59
Phụ lục 64
Trang 2Mở đầu
Hiện nay các vi xử lý, hay vi điều khiển (MCU – Micro Controller Unit) đang được sử dụng rộng rãi trong nhiều kĩnh vực như: điều khiển, tự động hóa, đo đạc, truyền thông… So với các phương pháp điều khiển, đo đạc truyền thống (cơ khí, điện tử tương tự…), thì sử dụng vi xử lý có các ưu điểm như: nhỏ gọn, ít tốn năng lượng, thời gian đáp ứng nhanh, có thể lập trình được…
Vi xử lý họ AVR của hãng ATMEL hiện đang được sử dụng tương đối phổ biến Vi xử
lý họ AVR là các vi xử lý lập trình được Sau khi được lập trình, vi xử lý sẽ hoạt động theo thuật toán được viết trong lập trình của người dùng Như vậy người dùng có thể lập trình cho
vi điều khiển hoạt động theo ý đồ của mình để giải quyết một các bài toán (điều khiển, đo đạc…)
Trong lập trình cho vi điều khiển, thường sử dụng ngôn ngữ lập trình C và có liên quan tới cấu trúc của vi xử lý, để người đọc chưa được học về ngôn ngữ lập trình C hoặc cấu trúc
vi xử lý có thể dễ dàng theo dõi, những phần đó sẽ được diễn giải theo cách càng đơn giản càng tốt Như vậy người đọc có thể theo dõi tài liệu mà không thấy quá khó hiểu, tuy nhiên cũng vì thế nên các kiến thức được trình bày không đầy đủ và chỉ ở mức cơ bản nhất, để người đọc có thể nhanh chóng tự lập trình được một số ứng dụng cơ bản với vi điều khiển AVR
Trang 31 Giới thiệu vi xử lý AVR
AVR là tên gọi chung các vi xử lý của hãng ATMEL Hãng ATMEL sản xuất các vi xử
lý với các chức năng, khả năng tính toán khác nhau, được đặt tên khác nhau: ATtiny25, ATtiny48…,ATmega8, ATmega16, ATmega128…
Các vi xử lý khác nhau thì khác nhau về dung lượng bộ nhớ ROM, RAM, các khối chức năng, số lượng chân… Trong tài liệu này, các hướng dẫn và ví dụ được viết cho vi xử lý ATmega16 Sơ đồ chân, các khối chức năng và cách sử dụng, đặc tính làm việc… của vi lý được nhà sản xuất ghi trong file “datasheet” kèm theo, có thể tìm trên internet
Hình 2:Sơ đồ chân của Atmega16
Tất cả các chân của ATmega16 được đánh số thứ tự từ 1 đến 40 như hình vẽ, chiều của
vi xử lý được lấy theo đầu lõm hoặc chấm tròn trên vi xử lý
Khi làm việc, các chân của vi điều khiển có hai mức trạng thái là 0 và 1 Trạng thái 0 ứng với mức điện áp 0 V còn trạng thái 1 ứng với mức điện áp +5V
Trang 4Chức năng của các chân trên vi xử lý ATmega16 như sau:
Chân 10 – VCC: Là chân cấp nguồn +5V cho vi xử lý
Chân 11 và 31 – GND: Là hai chân nối với nguồn âm Khi thiết kế mạch, phải nối cả hai chân 11 và 31 với nguồn âm
Chân 9 – RESET: Bình thường chân 9 ở trạng thái 0, khi cấp điện +5V vào chân RESET, trạng thái của nó từ 0 lên 1, và reset lại toàn bộ hoạt động của vi xử lý, tương đương với việc ngắt nguồn nuôi vi xử lý rồi cấp nguồn lại
Chân 12 – XTAL1 và 13 – XTAL2: Là hai chân nối với thạch anh Thạch anh là một linh kiện có tác dụng tạo dao động điện, vi xử lý sẽ hoạt động theo các dao động này (ví dụ 4Mhz, 12 Mhz…) Trong một số trường hợp có thể dùng thạch anh được gắn sẵn trong vi xử lý, hai chân XTAL1 và XTAL2 được bỏ trống
Chân 30 – AVCC: Là chân cấp nguồn cho khối chuyển đổi ADC (Analog to Digital Converter) ACD là một chức năng của vi xử lý, cho phép đo điện áp đặt tại chân 33, 34, …, 40 của vi xử lý Xem thêm mục Chuyển đổi ADC
Chân 32 – AREF: Điện áp tham chiếu Chân AREF được sử dụng khi cần dùng chức năng ADC của vi điều khiển Khi cần dùng chức năng ADC, người dùng cần đặt vào chân AREF một điện áp, gọi là điện áp tham chiếu Xem thêm mục
Sử dụng ADC
Các chân 1 … 8: Được nhóm chung thành một “cổng”, gọi là PORT B, từng chân trong Port B được ký hiệu PB0, PB1, …, PB7 ứng với các chân từ 1 đến 8 Các chân này có thể đảm nhiệm các chức năng khác nhau, tùy vào thiết lập của người dùng khi lập trình
Các chân 14 … 21: Được nhóm chung thành một “cổng”, gọi là PORT D, từng chân trong Port D được ký hiệu PD0, PD1, …, PD7 ứng với các chân từ 14 đến
21 Các chân này có thể đảm nhiệm các chức năng khác nhau, tùy vào thiết lập của người dùng khi lập trình
Các chân 22 … 29: Được nhóm chung thành một “cổng”, gọi là PORT C, từng chân trong Port C được ký hiệu PC0, PC1, …, PC7 ứng với các chân từ 22 đến
29 Các chân này có thể đảm nhiệm các chức năng khác nhau, tùy vào thiết lập của người dùng khi lập trình
Các chân 33 … 40: Được nhóm chung thành một “cổng”, gọi là PORT A, từng chân trong Port A được ký hiệu PA0, PA1, …, PA7 ứng với các chân từ 1 đến 8 Các chân này có thể đảm nhiệm các chức năng khác nhau, tùy vào thiết lập của người dùng khi lập trình
Trang 52 Một số phần mềm, thiết bị hỗ trợ cho việc lập trình AVR
2.1 Phần mềm CodeVision
Phần mềm CodeVision là phần mềm hỗ trợ lập trình cho vi xử lý AVR bằng ngôn ngữ
C Cách sử dụng cụ thể CodeVision được viết trong các ví dụ trong tài liệu
Hình 3: Giao diện CodeVision
2.2 Phần mềm mô phỏng Proteus
Hình 4: Giao diện Proteus
Proteus là phần mềm mô phỏng mạch điện trên máy tính, có giao diện trực quan, với các linh kiện điện tử được sắp xếp trên màn hình và được nối dây, đặt các thông số để có thể chạy thử mạch điện trên máy tính
Proteus có sẵn rất nhiều các linh kiện điện tử có thể tìm thấy trên thị trường, bao gồm cả các vi xử lý AVR Các lệnh theo ngôn ngữ C sau khi được viết bằng CodeVision có thể được đưa vào Proteus để chạy vi xử lý AVR tương ứng Dùng Proteus ta có thể kiểm tra xem lập trình viết trong CodeVision đã đúng hay chưa, như vậy không cần thiết phải thử trên mạch thật, tiết kiệm thời gian, tiền bạc
Tuy nhiên do là mô phỏng trên máy tính, nên một số phần quan trọng trong mạch thực (nguồn điện, sự tương thích về công suất giữa các phần tử…) không được tính đến, dẫn tới mạch điện mô phỏng chỉ có giá trị tham khảo, kiểm tra nguyên lý hoạt động trước khi tiến hành làm mạch thật
Trang 62.3 Mạch nạp và phần mềm nạp
Sau khi thử trên Proteus, và làm một mạch điện thật bên ngoài có vi xử lý AVR, để cho
vi xử lý AVR chạy được những gì đã lập trình, phải nạp chương trình cho nó (gần giống như cài phần mềm cho máy tính), muốn làm điều đó chúng ta cần mạch nạp và phần mềm nạp Mạch nạp là một mạch điện nối giữa vi xử lý và máy tính, còn phầm mềm nạp được cài trên máy tính để điều khiển mạch nạp Sau khi nạp, chương trình chúng ta viết bằng AVRStudio sẽ được nhớ trong bộ nhớ của vi xử lý, và vi xử lý sẽ hoạt động theo như chương trình đó
Tóm tắt 2
Lập trình bằng ngôn ngữ C cho vi điều khiển AVR bằng phần mềm CodeVision hoặc AVRStudio
Chạy mô phỏng vi xử lý trên máy tính để kiểm tra bằng phần mềm Proteus
Nạp chương trình cho vi xử lý bằng mạch nạp và phần mềm Khazama
Trang 73 Ứng dụng của vi xử lý ATmega16
Các chức năng cơ bản của vi xử lý ATmega16 sẽ được trình bày trong tài liệu gồm có:
Chức năng I/O (In/Out)
Ngắt ngoài (INT – INTerrupt)
Đếm thời gian (Timer/Counter)
Điều khiển độ rộng xung (PWM – Pulse Width Module)
Chuyển đổi ADC (Analog to Digital Converter)
Truyền nhận dữ liệu với máy tính (USART – Universal Synchronous and Asynchronous serial Receiver and Transmitter)
Còn các chức năng khác của ATmega16 như SPI, … sẽ không được trình bày ở đây
3.1 Điều khiển I/O (In/Out)
Điều khiển I/O, hay còn gọi là điều khiển Vào/Ra, là một chức năng cơ bản nhất của vi
xử lý Chức năng I/O cho phép người lập trình gán trạng thái 0 hoặc 1 (ứng với mức điện áp 0V và +5V tương ứng) cho một hoặc nhiều chân trong các Port A, B, C hoặc D Nói cách khác, người lập trình có thể điều khiển điện áp tại một chân bất kỳ trong số 4 port ở mức 0V hoặc +5V
Với chức năng In/Out, vi xử lý có thể điều khiển bật/tắt trực tiếp hoặc gián tiếp các thiết
bị ngoài như đèn Led, động cơ điện…
Nếu muốn sử dụng một chân nào đó trong số các port A, B, C hoặc D (chẳng hạn như chân PB6), khi lập trình người dùng phải thiết lập chức năng I/O cho chân PB6 Cách thiết lập sẽ được trình bày trong ví dụ Lập trình điều khiển thiết bị ngoài
Tóm tắt 3.1
Dùng chức năng I/O điều khiển trạng thái các chân vi xử lý
Trang 83.2 Ngắt ngoài (Interrupt)
Ngắt (Interrupt) trong AVR, bao gồm cả ngắt ngoài, là một tín hiệu khẩn cấp gửi đến bộ
xử lý, yêu cầu bộ xử lý dừng các công việc hiện tại (A) để thực hiện một việc nào đó (B) Sau khi khi kết thúc B, bộ xử lý sẽ quay về làm tiếp việc A đang dang dở Tín hiệu khẩn cấp đó
có thể đến từ bên trong vi xử lý (từ bộ Timer, USART…) hoặc từ bên ngoài (nhấn một nút bấm…)
Ngắt ngoài là loại ngắt duy nhất độc lập với các thiết bị của vi xử lý, vì tín hiệu ngắt đến
từ bên ngoài, ví dụ như khi người dùng bấm một nút bấm ở bên ngoài…
Trên Atmega16 có ba bộ ngắt ngoài, ứng với các chân 16 (PD2), 17 (PD3) và chân 3 (PB2), ký hiệu lần lượt là INT0, INT1 và INT2
Hình sau thể hiện một tín hiệu ngắt tạo ra bằng một button (nút bấm) tới ngắt INT0
Hình 5: Tín hiệu ngắt
Với mạch điện button như hình trên, khi chưa nhấn nút, điện áp đặt trên chân INT0 gần bằng +5V Khi nhấn nút, chân INT0 được nối với GND nên điện áp chân INT0 lúc này là 0V Sau khi nhả nút, điện áp chân INT0 lại trở về +5V
Quá trình điện áp chân INT0 giảm nhanh tử gần +5V xuống 0V gọi là Falling Edge (cạnh xuống), còn quá trình điện áp tăng từ 0V lên +5V gọi là Rising Edge (cạnh lên) Người dùng có thể lập trình cho ngắt INT0 hoạt động khi xảy ra Falling Edge, Rising Edge hoặc cả hai
Nếu chọn Falling Edge, ngắt xảy ra khi vừa nhấn xong nút
Nếu chọn Rising Edge, ngắt xảy ra khi nhả xong nút
Nếu chọn cả Falling Edge và Rising Edge, ngắt sẽ xảy ra 2 lần khi vừa nhấn xong nút và sau khỉ nhả xong nút
Cách kích hoạt chức năng ngắt ngoài INT0, INT1 hoặc INT2 và cách lựa chọn cạnh xuống/cạnh lên được hướng dẫn trong ví dụ Lập trình ngắt ngoài
Ngắt ngoài thường dùng để thực hiện giao tiếp giữa người và vi xử lý (thông qua thao tác nhấn nút), hoặc có thể dùng để đếm sự kiện bên ngoài (ví dụ như số sản phẩm đi qua cảm biến)…
Tóm tắt 3.2
ATmega16 có 3 ngắt
Ngắt theo cạnh xuống, cạnh lên hoặc cả hai
Trang 93.3 Timer/Counter
Timer/Counter, hay còn gọi là bộ đếm thời gian, bộ định thời… có chức năng đếm, hoặc định ra một khoảng thời gian và cả đếm sự kiện Trên một số vi xử lý, timer/counter còn có thêm chức năng điều chỉnh độ rộng xung (PWM) Trên ATmega16 có 3 bộ timer/counter, gọi tắt là T/C0, T/C1,T/C2
Các bộ T/C hoạt động bằng cách đếm số xung dao động của thạch anh nuôi vi xử lý theo
tỉ lệ (Prescale) 1:1 hoặc 1:8, Thạch anh, như đã nói ở phần 1, tạo ra dao động để vi xử lý hoạt động Mỗi linh kiện thạch anh có một tần số dao động nhất định (ví dụ 4 Mhz, 12Mhz…) Mỗi chu kỳ dao động ứng với một khoảng thời gian Δt nhỏ, bằng cách đếm các dao động này, các bộ T/C có thể định ra các khoảng thời gian khác nhau Ví dụ với thạch anh 1Mhz, thì chu kỳ dao động là:
6 6
1
10 ( ) 1( )1.10
Nếu muốn xác định một khoảng thời gian 1 s 1000m s, bộ T/C sẽ phải dùng một biến đếm để đếm đủ 1000 lần Các biến đếm đó được đặt tên là TCNT0, TCNT1 hoặc TCNT2 tùy theo bộ T/C0, T/C1, T/C2 tương ứng
Các biến đếm TCNT được lưu trong vi xử lý bằng 8 hoặc 16 bit (bit là các ô nhớ trong vi
xử lý và chỉ có hai trạng thái 0 hoặc 1, tổ hợp của các bit này sẽ tương ứng với giá trị của biến TCNT theo hệ nhị phân) Thường dùng tên gọi T/C 8 bit hoặc T/C 16 bit chính là nói tới
số bit dùng để lưu giá trị của biến TCNT
Vì số bit bị giới hạn, nên khả năng đếm của biến TCNT bị giới hạn (với 8 bit, có thể đếm tối đa từ 0 đến 255), dẫn tới khoảng thời gian xác định được nếu đếm trực tiếp số dao dộng của thạnh anh cũng bị giới hạn
Giải pháp đưa ra là đếm theo tỉ lệ (prescale) đã nói ở trên Thay vì đếm mỗi dao động một lần, nếu đếm theo tỉ lệ, ví dụ 1:8, thì cứ 8 dao động của thạnh anh, T/C mới đếm một lần, tức là giá trị TCNT tăng thêm 1
255 (đủ 125 lần đếm) Khi biến TCNT tới giá trị 255, thì sẽ được reset về giá trị ban đầu để đếm tiếp, đồng thời xảy ra ngắt Do vậy tín hiệu ngắt của T/C là khi biến TCNT tới giá trị cực đại, và ngắt có T/C tạo ra gọi là ngắt trong
Trang 10Cách chọn tỉ lệ, giá trị ban đầu, giá trị tối đa và các thiết lập liên quan khác của T/C sẽ
được trình bày trong ví dụ Lập trình Timer/Counter
Tóm tắt 3.3
Timer/Counter (T/C) tạo ngắt trong theo các quãng thời gian định trước
ATmega16 có 2 T/C 8 bit và 1 T/C 16 bit
Biến đếm TCNT và tỉ lệ Prescale
Trang 113.4 Điều khiển độ rộng xung – PWM
3.4.1 Khái niệm độ rộng xung
Để hiểu khái niệm độ rộng xung, ta xét mạch điện đơn giản sau đây:
Hình 7: Mạch điện ví dụ độ rộng xung
Một động cơ được mắc nối tiếp với một nút bấm như hình vẽ Nếu ta bấm nút, động cơ
sẽ chạy, nhả nút, động cơ sẽ dừng Điện áp giữa hai đầu động cơ có dạng xung như trên hình
7 Nếu nhấn, nhả nút bấm theo chu kỳ, thì điện áp hai đầu động cơ cũng thay đổi theo chu kỳ, lúc này sẽ có khái niệm Time Period và Duty Cycle Duty Cycle là thời gian điện áp ở mức +5V, còn Time Period là chu kỳ của xung, bao gồm Duty Cycle và thời gian điện áp bằng 0V còn lại
Nếu giảm Duty Cycle, thì động cơ chạy chậm lại Ngược lại, nếu tăng Duty Cycle thì động cơ chạy nhanh lên Duty Cycle giảm tối thiểu bằng 0 và tăng tối đa bằng Time Period Điều chỉnh độ rộng xung chính là điều chỉnh Duty Cycle, và đôi khi là cả Time Period
Hình 8: Vị trí các chân có thể dùng để tạo tín hiệu PWM
Trong đó PWM0 do T/C0 tạo ra, PWM1A và PWM1B dó T/C1 tạo ra, PWM2 do T/C2 tạo ra Muốn tạo PWM nào thì ta cần phải thiết lập T/C tương ứng
Trang 12Để dễ hiểu hãy lấy ví dụ muốn tạo tín hiệu PWM tại chân PD4 (PWM1B), ta phải dùng T/C1 và thiết lập cho T/C1 ở chế độ tạo PWM T/C1 là timer/counter 16 bit, do đó biến TCNT1 có thể đếm tới giá trị MAX là 65535
Ý tưởng ở đây là biến TCNT1 chạy từ 0 tới giá trị OCR1B, sau đó chạy tiếp tới giá trị ICR1 Trong đó OCR1B là một giá trị do người dùng đặt trước ứng với khoảng thời gian Duty Cycle Giá trị ICR1 cũng là một giá trị do người dùng đặt trước nhưng ứng với Time Period Như vậy khi biến TCNT1 chạy từ 0 qua OCR1B tới ICR1, điện áp trên chân OC1B sẽ thay đổi theo Duty Cycle và Time Period tương ứng
T/C1 có 3 chế độ hoạt động để tạo PWM là:
Fast PWM (PWM tần số cao)
Phase correct PWM (PWM với pha chính xác)
Phase correct and frequency correct PWM (PWM với pha và tần số chính xác)
Ba chế độ trên khác nhau ở cách tính Duty Cycle và sai số điều khiển Trong tài liệu này
sẽ giới thiệu hai chế độ thông dụng nhất là Fast PWM
Ở chế độ Fast PWM biến TCNT1 đếm xung thạch anh theo tỉ lệ Prescale định trước, chạy từ 0 tới OCR1B, lúc này điện áp trên chân OC1B là +5V Khi TCNT1 chạy từ OCR1B tới ICR1, điện áp chân OC1B là 0V Đồng thời khi TCNT1 chạm mốc ICR1, biến TCNT1 được reset về 0 để tiếp tục đếm cho chu kỳ tiếp theo
Như vậy thời gian biến TCNT1 chạy từ 0 tới OCR1B ứng với Duty Cycle, thời gian biến TCNT1 chạy từ 0 tới ICR1 ứng với Time Period
Trang 13Chẳng hạn muốn tạo một xung PWM có Time Period là 2ms, Duty Cycle là 1 ms với thạch anh 4 Mhz, tỉ lệ Prescale = 8, ta có:
Mỗi dao động thạch anh ứng với khoảng thời gian là:
Tương tự, để tạo được Duty Cycle của PWM là 1 ms, thì giá trị OCR1B = 500
Thông thường khi lập trình, người ta cố định giá trị ICR1 ngay từ đầu (Time Period cố định), còn giá trị OCR1B được thay đổi khi vi xử lý hoạt động, nhằm tạo ra PWM có Duty Cycle thay đổi
Cách kích hoạt chế độ Fast PWM, chọn các giá trị OCR1B, ICR1 và các thông số khác
sẽ được trình bày trong ví dụ Điều khiển độ rộng xung PWM
Tóm tắt 3.4
PWM tạo ra do bộ T/C, ATmega16 có 4 kênh PWM (tại chân OC0; OC1A; OC1B; OC2)
PWM dùng điều chỉnh tốc độ động cơ, động cơ bước và động cơ servo
Tạo PWM nhờ biến TCNT và các giá trị OCR và ICR Điều chỉnh độ rộng xung bằng cách điều chỉnh giá trị OCR
Trang 143.5 Chuyển đổi ADC
Trong các ứng dụng đo lường và điều khiển bằng vi xử lý, bộ chuyển đổi tương tự-số (ADC) là một thành phần rất quan trọng Các đại lượng vật lý như nhiệt độ, áp suất, dòng điện,… đều có thể dùng cảm biến và các mạch xử lý để chuyển về dạng tín hiệu điện áp Trên
vi xử lý ATmega16, có thể đo 8 điện áp khác nhau đặt trên các 8 chân thuộc PORT A, gọi là
8 kênh ADC, được ký hiệu là ADC0, …, ADC7 Điện áp cấp cho bộ chuyển đổi ADC là +5V
và được cấp qua chân AVCC
Hình 10: 8 kênh ADC của ATmega16
Điện áp đặt tại một trong số các kênh ADC, ví dụ ADC0, sẽ được bộ chuyển đổi ADC của ATmega16 đo và trả lại một giá trị tương ứng Để hiểu rõ hơn về hoạt động của ADC ta cần hiểu một số khái niệm sau:
Điện áp tham chiếu - V ref : Là giá trị lớn nhất mà bộ ADC có thể đo được Trong đo đạc
truyền thống, với các thiết bị đo, chúng ta cũng gặp khái niệm “giá trị lớn nhất mà thiết bị có thể đo được” Ví dụ như một đồng hồ đo áp suất có thể đo được tối đa 70 bar, có nghĩa là đồng hồ này chỉ dùng để đo áp suất nhỏ hơn 70 bar
Với ADC trên ATmega16, Vref (điện áp tham chiếu) được người lập trình đặt trước khi kích hoạt chức năng ADC Có 3 cách chọn điện áp tham chiếu như sau:
Chọn điện áp so sánh bằng điện áp trên chân VREF
Chọn điện áp so sánh bằng +5V, nối chân VREF với chân AVCC
Chọn điện áp tham chiếu nội – Vref = 2,56 V Điện áp tham chiếu nội này được tạo ra bên trong vi xử lý, người dùng không cần cấp điện áp qua chân VREF
Độ phân giải: Cho biết mức độ chính xác của phép đo bằng chuyển đổi ADC, cũng là số
bit dùng để chứa giá trị đầu ra của bộ chuyển đổi ADC Chuyển đổi ADC trên ATmega16 là
bộ ADC 10 bit, giá trị bộ ADC trả về sau khi đo có giá trị từ 0 đến 1023, ứng với 1023 khoảng chia
Hoạt động của ADC có thể giải thích đơn giản như sau, đầu tiên vi xử lý chia nhỏ điện
áp tham chiếu Vref làm 1023 khoảng, sau đó so sánh giá trị điện áp đặt tại chân đầu vào ADC xem điện áp cần đo đó nằm ở khoảng bao nhiêu Giá trị ADC đo được chính là số thứ tự của khoảng điện áp tương ứng
Hình 11: Hoạt động của ADC
Trang 15Như hình trên, Vref được chia làm 1023 khoảng, từ 0 đến 1023 Điện áp cần đo Vin đặt vào chân ADC0, sau khi đo, bộ ADC sẽ trả về giá trị i, là khoảng điện áp ứng với Vin Như vậy giá trị điện áp Vin cần đo là:
ef1023
Các cách kích hoạt bộ chuyển đổi ADC, chọn kênh đo, điện áp tham chiếu và đo bằng ADC sẽ được trình bày trong ví dụ Chuyển đôi ADC
Trang 163.6 Giao tiếp USART
USART được trình bày trong tài liệu này là một chuẩn truyền thông nối tiếp không đồng
bộ giữa các thiết bị digital Chức năng USART trên vi xử lý ATmega16 là một trong số các chức năng vi xử lý dùng để truyền/nhận dữ liệu với các thiết bị khác (máy tính, vi xử lý khác…)
3.6.1 Các thuật ngữ được dùng trong giao tiếp USART
Truyền thông nối tiếp không đồng bộ: Trong nhiều bài toán cần sử dụng vi xử lý và
máy tính kết nối với nhau Trong quá trình làm việc đó vi xử lý cần trao đổi dữ liệu với máy tính, ví dụ như vi xử lý gửi giá trị đo đạc bằng ADC về máy tính và máy tính gửi tín hiệu điều khiển xuống vi xử lý…
Giả sử dữ liệu cần trao đổi là các mã có chiều dài 8 bit, cách đơn giản nhất là kết nối 1 PORT (8 bit) của vi điều khiển với máy tính, mỗi dây nối sẽ chịu trách nhiệm truyền/nhận 1 bit dữ liệu Đây gọi là cách giao tiếp song song, cách này là cách đơn giản nhất, nhưng nhược điểm của cách truyền này là số đường truyền quá nhiều, giá trị càng lớn thì số đường truyền cũng sẽ nhiều thêm
Trong truyền thông nối tiếp dữ liệu được truyền từng bit trên 1 (hoặc một ít) đường truyền, vì thế tiết kiệm đường truyền dữ liệu Hình sau mô tả sự so sánh giữa 2 cách truyền song song và nối tiếp trong việc truyền con số 187 thập phân (tức 10111011 nhị phân)
Hình 12: Phương pháp truyền song song (a) và nối tiếp (b)
Vì dữ liệu cần được “chia nhỏ” thành từng bit khi truyền/nhận, tốc độ truyền nối tiếp sẽ
bị giảm Mặt khác, để đảm bảo tính chính xác của dữ liệu, bộ truyền và bộ nhận cần có những
“thỏa hiệp” hay những tiêu chuẩn nhất định
Khái niệm “đồng bộ” để chỉ sự “báo trước” trong quá trình truyền Lấy ví dụ thiết bị 1 (tb1) kết với với thiết bị 2 (tb2) bởi 2 đường, một đường dữ liệu và 1 đường xung nhịp Cứ mỗi lần tb1 muốn gửi 1 bit dữ liệu, tb1 điều khiển đường xung nhịp chuyển từ mức thấp lên mức cao báo cho tb2 sẵn sàng nhận một bit Bằng cách “báo trước” này tất cả các bit dữ liệu
có thể truyền/nhận dễ dàng với ít “rủi ro” trong quá trình truyền Tuy nhiên, cách truyền này đòi hỏi ít nhất 2 đường truyền cho 1 quá trình (gửi hoặc nhận dữ liệu)
Khác với cách truyền đồng bộ, truyền thông “không đồng bộ” chỉ cần một đường truyền cho một quá trình “Khung dữ liệu” đã được chuẩn hóa bởi các thiết bị nên không cần đường xung nhịp báo trước dữ liệu đến Ví dụ 2 thiết bị đang giao tiếp với nhau theo phương pháp này, chúng đã được thỏa thuận với nhau rằng cứ 1ms thì sẽ có 1 bit dữ liệu truyền đến, như thế thiết bị nhận chỉ cần kiểm tra và đọc đường truyền mỗi mili-giây để đọc các bit dữ liệu và sau đó kết hợp chúng lại thành dữ liệu có ý nghĩa Truyền thông nối tiếp không đồng bộ vì thế hiệu quả hơn truyền thông đồng bộ (không cần nhiều đường truyền) Tuy nhiên, để quá trình truyền thành công thì việc tuân thủ các tiêu chuẩn truyền là hết sức quan trọng
Baud rate (tốc độ Baud): như trong ví dụ trên về việc truyền 1 bit trong 1ms, bạn thấy
rằng để việc truyền và nhận không đồng bộ xảy ra thành công thì các thiết bị tham gia phải
“thống nhất” nhau về khoảng thời dành cho 1 bit truyền, hay nói cách khác tốc độ truyền phải
Trang 17được cài đặt như nhau trước, tốc độ này gọi là tốc độ Baud Theo định nghĩa, tốc độ baud là
số bit truyền trong 1 giây Ví dụ nếu tốc độ baud được đặt là 19200 thì thời gian dành cho 1 bit truyền là 1/19200 ~ 52.083us
Frame (khung truyền): Khung truyền bao gồm các quy định về số bit trong mỗi lần
truyền, các bit “báo” như bit Start và bit Stop, các bit kiểm tra như Parity, ngoài ra số lượng các bit trong một data cũng được quy định bởi khung truyền Hình dưới là một ví dụ của một khung truyền theo UART, khung truyền này được bắt đầu bằng một start bit, tiếp theo là 8 bit data, sau đó là 1 bit parity dùng kiểm tra dữ liệu và cuối cùng là 1 bits stop
Hình 13: Khung truyền theo USART
Start: start là bit đầu tiên được truyền trong một frame truyền, bit này có chức năng báo
cho thiết bị nhận biết rằng có một gói dữ liệu sắp được truyền tới Start là bit bắt buộc phải có trong khung truyền
Data: data hay dữ liệu cần truyền là thông tin chính mà chúng ta cần gửi và nhận
Thường data gồm 8 bit
Parity bit: parity là bit dùng kiểm tra dữ liệu truyền đúng không (một cách tương đối)
Parity bit không phải là bit bắt buộc và vì thế chúng ta có thể loại bit này khỏi khung truyền (các ví dụ trong tài liệu này không dùng bit parity)
Stop bits: stop bits là một hoặc các bit báo cho thiết bị nhận rằng một gói dữ liệu đã
được gởi xong Stop bits là các bits bắt buộc xuất hiện trong khung truyền
3.6.2 Giao tiếp USART trên ATmega16
Vi điều khiển Atmega16 có 1 module truyền thông nối tiếp USART Với chế độ truyền nối tiếp không đồng bộ (cụ thể trong tài liệu này là giao tiếp với máy tính), chúng ta sử dụng
2 chân của Atmega16 để phục vụ cho truyền nhận dữ liệu là: chân truyền dữ liệu – TxD (Transmitted Data) và chân nhận dữ liệu – RxD (Reveived Data)
Hình 14: Hai chân RXD và TXD dùng trong giao tiếp với máy tính
Mô-đun USART trên chip Atmega16 hoạt động theo chế độ quá trình truyền và nhận dữ liệu có thể xảy ra đồng thời
Khi sử dụng USART để giao tiếp với máy tính, phải thiết lập các thông số hoạt động ở vi
xử lý và trên máy tính giống nhau, bao gồm:
Trang 18 Baud rate: Baud rate càng cao, tốc độ truyền càng nhanh, tuy nhiên xác suất xảy
ra lỗi trong quá trình truyền/nhận cũng lớn hơn Thường chọn Baud rate = 9600 với các ứng dụng không đòi hỏi tốc độ cao
Frame: Khung truyền bao gồm start bit, data, parity bit và stop bit, trong đó start bit là cố định và không thay đổi Ví dụ trong tài liệu này sẽ lấy khung truyền có 8 bit data, không dùng parity bit và 1 bit stop
USART của ATmega16 cũng có tính năng ngắt Ngắt của USART xảy ra khi hoàn tất gửi xong một dữ liệu, hoặc nhận xong một dữ liệu Tính năng ngắt khi nhận xong một dữ liệu
sẽ được dùng trong ứng dụng truyền dữ liệu từ vi xử lý về máy tính
Cách kích hoạt mô-đun USART, thiết lập các thông số Baud rate, Frame… và cách sử dụng USART sẽ được trình bày trong ví dụ Giao tiếp USART
Tóm tắt 3.6
Kết nối với máy tính dùng chức năng USART
Baud rate = 9600; khung truyền có 8 bit data, 1 bit stop, không dùng
parity
Ngắt khi truyền/nhận dữ liệu hoàn tất
Trang 194 Các bài tập ví dụ
Tất cả các mạch điện sử dụng vi xử lý lập trình được đều được thiết kế theo trình tự:
Phân tích mạch: Yêu cầu, đặc điểm làm việc, …
Xây dựng nguyên lý điều khiển
sơ đồ nguyên lý và sơ đồ đi dây kèm theo
4.1 Lập trình điều khiển thiết bị ngoài (Led, động cơ…)
Đây là ví dụ đầu tiên và đơn giản nhất trong các ví dụ ứng dụng vi xử lý, vì vậy sẽ được viết kỹ từng bước và giải thích thật đơn giản
Bài ví dụ “Lập trình điều khiển thiết bị ngoài” đang nói tới thực ra là điều khiển ngắt các thiết bị ngoài (đèn Led, động cơ…) thay cho công-tắc điện, và là dạng điều khiển đơn giản nhất trong các ứng dụng của vi điều khiển
đóng-Mạch điện trong ví dụ này sẽ làm việc như sau: Điều khiển đèn Led sáng/tắt theo chu kỳ 0,5 giây
4.1.1 Phân tích mạch điện
Với bất cứ một dự án (Project) thiết kế mạch điện nào, công việc đầu tiên cũng đều là phân tích mạch điện cần thiết kế Dựa vào yêu cầu và đặc điểm làm việc, chúng ta có thể xây dựng được nguyên lý làm việc của các khối cơ bản của mạch (khối điều khiển, khối công suất…) và lập trình cho vi xử lý
Với ví dụ điều khiển Led như trên, yêu cầu và đặc điểm làm việc như sau:
Led sáng rồi tắt theo chu kỳ 0,5 giây
Giữa các lần sáng/tắt của Led, không điều khiển thêm thiết bị nào khác
Led có công suất bé (cỡ 0,1 W)
4.1.2 Xây dựng nguyên lý điều khiển
Như ở phần 1 đã nói, người dùng có thể lập trình để điều khiển điện áp tại một hay một
số chân của vi điều khiển Có hai mức điện áp là 0V và +5V, và được gán với trạng thái 0 và
1 tương ứng Ví dụ chân số 6 (PB5) của vi điều khiển ở trạng thái 1, tức là tại chân đó có điện
áp +5V, còn nếu ở trạng thái 0, tức là tại chân đó có điện áp bằng 0 (nối đất – GND)
Ý tưởng đưa ra là ta có thể dùng điện áp này để chạy một thiết bị nào đó nối trực tiếp với chân của vi điều khiển Tuy nhiên với điện áp +5V, đồng thời dòng điện cho phép nhỏ (vài chục mA), nên ta chỉ có thể nối trực tiếp vào vi điều khiển những thiết bị có công suất rất nhỏ, ví dụ như: đèn LED
Trang 20Hình 15: Nối trực tiếp vi xử lý với thiết bị có công suất nhỏ
Thực tế, để có thể điều khiển những thiết bị có công suất lớn hơn (hoặc làm cho Led sáng hơn), người ta không nối trực tiếp vi điều khiển với thiết bị, mà qua một mạch công suất Có thể hiểu mạch công suất như một rơ-le trong mạch điện dân dụng
Hình 16: Sơ đồ dùng điện thế 5V công suất nhỏ để điều khiển Mo-tơ 12V công suất lớn
Có nhiều linh kiện điện tử có thể thay thế cho một rơ-le, điển hình là các transistor Hình sau thể hiện nguyên lý hoạt động của mạch:
Hình 17: Vi xử lý điều khiển đóng/mở transistor để điều khiển tải
Một mạch tương tự như mạch transistor trình bày ở trên được gọi là mạch công suất, còn khối vi xử lý được gọi là mạch điều khiển
Bình thường khi chân 6 của vi điều khiển (nối với chân B của transistor) ở trạng thái 0 (0V), thì transistor đóng, tức là E và C không thông nhau
Khi vi điều khiển chuyển trạng thái chân 6 sang 1 (+5V), transistor mở, tức là dòng điện
từ nguồn có thể chạy từ E sang C, qua tải rồi về âm
Như vậy thay đổi trạng thái chân 6 sẽ điều khiển bật/tắt được Led
Trang 214.1.3 Mô phỏng trên Proteus
Mô phỏng trên Proteus tức là xây dựng mạch nguyên lý và chạy thử nghiệm trên máy tính bằng phần mềm Proteus
Trình tự tiến hành mô phỏng mạch nguyên lý đóng/mở transistor bằng Proteus như sau:
Hình 18: Mở thư viện Proteus
Mở phần mềm Proteus, click vào các biểu tượng “1” và “2” để chọn lịnh kiện Sau khi click vào “2”, một của sổ mới sẽ hiện ra, cho phép chọn linh kiện
Hình 19: Thư viện Proteus
Gõ tên linh kiện vào ô Keywords, ví dụ “mega16”, các linh kiện tìm được sẽ hiện bên ô Result, click chuột để chọn linh kiên ATMEGA16 như trên hình 2
Gõ tiếp “npn” để tìm linh kiện transistor loại PNP, gõ “led” để tìm linh kiện LED Sau
đó sắp xếp và nối dây cho các linh kiện như trong hình 3
Trang 22Hình 20: Mạch mô phỏng ví dụ Điều khiển thiết bị ngoài
4.1.4 Lập trình cho vi xử lý
Lập trình chi vi xử lý AVR, cũng như với các vi xử lý khác, nên tiến hành theo các bước như sau, để tạo thuận lợi trong việc xây dựng thuật toán, kiểm tra và sửa lỗi lập trình
Xác định yêu cầu làm việc của vi xử lý
Xây dựng thuật toán điều khiển
Chuẩn bị lập trình và viết chương trình điều khiển
Kiểm tra và sửa lỗi
a) Xác định yêu cầu làm việc của vi xử lý
Trong ví dụ này, vi xử lý chỉ cần điều khiển trạng thái của chân số 6 của vi xử lý (có ký hiệu PB5/MOSI trên Proteus) thay đổi giữ mức 0 (0V) và 1 (+5V) theo chu kỳ 0,5 giây
b) Xây dựng thuật toán điều khiển
Thuật toán điều khiển ở trong bài ví dụ này khá đơn giản, theo sơ đồ sau:
Hình 21: Sơ đồ thuật toán điều khiển vi xử lý
Sơ đồ được giải thích như sau:
Khi được cấp điện, vi xử lý chuẩn bị cho bước “Bắt đầu”, bao gồm thiết lập chân PB5 (ứng với chân số 6 của vi xử lý) là chân điều khiển, có trạng thái ban đầu là
Trang 23c) Chuẩn bị lập trình bằng phần mềm CodeVision
Mở phần mềm CodeVision, nhấn Ctrl+N để tạo Project (dự án) mới, trong hộp thoại
“Create New File” chọn “Project” rồi nhấn “OK” “Yes”
Hình 22: Tạo project mới
Hình 23: Sử dụng CodeWizardAVR
Hộp thoại “CodeWizardAVR” hiện ra, chọn tên chip là ATmega16, và chọn tần số hoạt động của chip (ví dụ 4000000 Hz = 4Mhz)
Hình 24: Chọn vi xứ lý và tần số hoạt động
Hộp thoại “CodeWizardAVR còn có nhiểu mục khác, ứng với các chức năng của vi xử
lý như USART, ADC, External IRQ (ngắt) đã nói trong phần giới thiệu Nhưng nếu chỉ cần điều khiển trạng thái các chân của vi xử lý, ta chỉ cần vào mục Ports để quy định chức năng vào/ra của chân vi xử lý
Trang 24Hình 25: Thiết lập các Port
Trên Proteus chúng ta muốn dùng chân số 6 của vi xử lý, có ký hiệu PB5, tức là chân ứng với Bit 5 của Port B, vì vậy chúng ta set Bit 5 thành “Out” như trên hình
Sau khi thiết lập ban đầu cho Atmega16 xong, click “File” “Generate, Save and Exit”
Hình 26: Tạo và lưu project
Sau đó sẽ có 3 hộp thoại hiện ra để lưu các file cần thiết Đặt tên và lưu các file đó vào cùng một thư mục như trong hình
Trang 25Hình 27: Chọn thư mục lưu project
Sau khi lưu xong ta sẽ thấy một ô để viết các lệnh lập trình theo ngôn ngữ C Các dòng lệnh chúng ta viết sẽ được lưu trong file “bai1.c”
Hình 28: Nơi viết các dòng lệnh
d) Viết chương trình điều khiển
Khi mới tạo ra file bai1.c đã được ghi rất nhiều dòng lệnh, do phần mềm tự tạo ra theo các thiết lập ở phần “CodeWizardAVR” chúng ta vừa làm Tuy nhiên với bài này, chúng ta chỉ cần theo tác ở một vài vị trí trong file “bai1.c” Trình tự tiến hành được trình bày như sau: Include các file header: Viết thêm dòng lệnh #include <delay.h> vào vị trí như trong hình dưới File delay.h là một file có sẵn của phần mềm Codevision, dùng khi muốn delay (trì hoãn, tạm dừng) quá trình làm việc của vi xử lý trong một khoảng thời gian định trước, trong ví dụ ta dùng để tạm dừng 0,5 s
Trang 26Hình 29: “Include” các file *.h cần thiết
CodeVision có nhiều file *.h khác nhau (h là viết tắt của header), mỗi file *.h đó được tạo sẵn cho các ứng dụng của vi xử lý Tên một số file *.h và chức năng của các file đó được cho như bảng
Tên file Chức năng liên quan delay.h Tạm dừng vi xử lý
stdio.h Giao tiếp với máy tính
LCD.h Ghi các ký tự ra LCD Một số file *.h và chức năng liên quan
Khi muốn sử dụng tính năng nào có liên quan, thì ta thêm dòng lệnh
#include <*.h>
vào vị trí đã nói ở trên
Vòng lặp while chính: Trong file bai1.c vừa tạo ra cũng đã có sẵn một vòng lặp while liên tục (vòng lặp while chính), đây là nơi viết các dòng lệnh (code) cho bài tập Điều khiển thiết bị ngoài
Hình 30: Vòng lặp while liên tục được tạo sẵn
Các dòng chữ sau ký hiệu “//” chỉ có ý nghĩa chú thích, không ảnh hưởng tới lập trình
Vòng lặp while có cú pháp:
while (x) {
Các dòng lệnh
}
Trong đó x gọi biến logic (chỉ nhận giá trị đúng hoặc sai tương ứng với 1 hoặc 0), vòng
lặp while có nghĩa là chừng nào biến x có giá trị đúng, vi xử lý sẽ thực hiện lặp đi lặp lại các
dòng lệnh viết trong vòng lặp
Trang 27Như trên hình ta thấy while (1), có nghĩa là x luôn bằng 1, và vòng lặp này xảy ra
mãi trong suốt quá trình hoạt động có vi xử lý
Nhắc lại thuật toán điều khiển đơn giản đã được trình bày ở trên:
Hình 31: Thuật toán điều khiển đơn giản cho ví dụ
Quá trình lặp đi lặp lại các bước trên hình có thể được thực hiện bằng một vòng lặp while, ở đây ta dùng vòng lặp while mà phân mềm Code vision đã tạo sẵn
Như vậy có thể hình dung các lệnh trong vòng lặp while chính như sau:
- Đưa trạng thái (set trạng thái) chân PB5 về 1 hoặc 0:
Với phần mềm CodeVision, có thể set trạng thái cho các chân bằng lệnh:
PORTx.y = z;
Trong đó: x là tên PORT tường ứng, ví dụ chân PB5 thì x là B
Y là thứ tự chân (từ 0 đến 7), ví chân PB5 thì y là 5
Z là trạng thái muốn set, ví dụ 0 hoặc 1
Như vậy để set trạng thái chân PB5 lên 1, ta dùng lệnh:
Trong đó x là số ms hoặc µs tương ứng ta muốn chương trình đợi Trong ví dụ
ta muốn dừng chương trình trong khoảng thời gian là 0,5 s = 500 ms = 500 000 µs, thì dùng lệnh sau:
Trang 28while (1) {
Hình 32: Đoạn code trong vòng lặp while
e) Kiểm tra lỗi cú pháp và complie
Sau khi viết hết các code, nhấn CTRL+F9 để tiến hành complie (biên dịch từ ngôn ngữ
C sang ngôn ngữ máy), phần mềm CodeVision sẽ tiến hành kiểm tra các lỗi cú pháp, cũng như các thủ tục khác được viết trong file “bai1.c” Nếu không có sai sót, phần mềm sẽ tạo ra file “bai1.hex” lưu trong thư mục “/bai1/exe/” File này sẽ dùng để chạy mô phỏng trên Proteus và nạp cho vi xứ lý khi làm mạch thật
Nếu có lỗi cú pháp hoặc các thủ tục khác trong quá trình lập trình, CodeVision sẽ thông báo có lỗi và có ghi chú lỗi để người lập trình có thể tìm ra và sửa lỗi
Hình 33: Ví dụ về lỗi thiếu dấu “;” ở câu lệnh
Chỉ dẫn báo lỗi tìm thấy sau khi check đến dòng 120, và lỗi thực sự thì nằm ở dòng 119 Quá trình kiểm tra và sửa lỗi cú pháp lặp đi lặp lại tới khi CodeVision thông báo không còn lỗi và tạo file *.hex thành công
Trang 294.1.5 Chạy thử trên mạch mô phỏng
Sau khi lập trình và có được file “bai1.hex”, ta tiến hành chạy thử trên mạch mô phỏng Trở lại mạch mô phỏng bằng phần mềm Proteus:
Hình 34: Mạch nguyên lý xây dựng trên Proteus của ví dụ
Click đúp vào biểu tượng vi xử lý ATmega16 trên mạch mô phỏng, hợp thoại Edit Component của ATmega 16 sẽ mở ra:
Hình 35: Hộp thoại Edit Component
Trong hộp thoại Edit Component, ở ô Program File, click chọn đường dẫn tới file bai1.hex vừa tạo ra bằng phần mềm CodeVision Ở ô CKSEL Fuses, chọn tần số cho thạch anh là 4Mhz
Sau khi thiết lập xong, nhấn nút Start ở góc dưới bên trái màn hình để chạy mạch mô phỏng, nếu các bước trên làm chính xác, thì kết quả trên màn hình sẽ thấy đèn Led sáng nhấp nháy theo chu kỳ 0,5s Nếu muốn dừng mô phỏng, nhấn nút Stop
Trang 30Hình 36: Nút Start và Stop
Quan sát trên màn hình, sẽ thấy màu của chân PB5 nhấp nháy xanh đỏ theo chu kỳ 0,5s Màu đỏ ứng với mức điện áp +5V, màu xanh ứng với mức điện áp 0v Khi chân PB5 màu đỏ thì Led sáng, khi chân PB5 màu xanh thì đèn tắt đúng như nguyên lý điều khiển đã trình bày Như vậy sau bài tập Điều khiển thiết bị ngoài, người đọc có thể tự mở rộng thêm, ví dụ như nháy nhanh rồi nháy chậm theo chu kỳ, điều khiển 2 hay nhiều đèn Led cùng lúc và cho chúng phối hợp sáng/tắt với nhau theo ý muốn, hiển thị trên led 7 thanh, điều khiển bật/tắt động cơ
Tóm tắt 4.1
Điều khiển thiết bị ngoài qua mạch công suất
Các theo tác trên các phần mềm Proteus và CodeVision
Khái niệm delay, lặp…
Các file header, set trạng thái các chân của vi xử lý
Câu hỏi mở rộng:
Điều khiển nhiều led bằng nhiều chân của vi điều khiển
Hiển thị số trên led 7 thanh (cấu tạo và nguyên lý hoạt động của led 7 thanh xem ở phần phụ lục)
Trang 31Ban đầu khi cấp điện, vi xử lý điều khiển sáng/tắt đèn led theo chu kỳ 0,5s
Khi người dùng nhấn nút điều khiển, chu kỳ sáng/tắt đèn led được điều chỉnh thành 2s Khi người dùng nhấn nút điều khiển lần nữa, chu kỳ sáng/tắt đèn led lại được điều chỉnh
về 0,5s
…
Như vậy ta thấy về cơ bản, phần lập trình điều khiển sáng/tắt led tương tự như ví dụ Điều
khiển thiết bị ngoài, chỉ khác ở chỗ chu kỳ sáng/tắt (trong hàm delay_ms()) được thay đổi
theo tác động bấm nút của người dùng nhờ tính năng ngát ngoài
4.2.2 Nguyên lý điều khiển và xây dựng mạch mô phỏng trên Proteus
Nguyên lý điều khiển giống như trong bài ví dụ Điều khiển thiết bị ngoài
Mạch mô phỏng trên Proteus cũng tương tự ví dụ Điều khiển thiết bị ngoài, trừ việc có thêm một nút bấm đưa vào chân PD2/INT0 để điều khiển ngắt INT0
Hình 37: Mạch mô phỏng ví dụ Lập trình sử dụng ngắt
Trang 324.2.3 Lập trình cho vi xử lý
a) Xác định yêu cầu làm việc của vi xử lý
Vi xử lý điều khiển bật/tắt đèn Led theo chu kỳ 0,5s và 2s theo tác động bấm nút của người dùng
b) Xây dựng thuật toán điều khiển
Thuật toán cho ví dụ được thể hiện trên sơ đồ sau:
Hình 38: Sơ đồ thuật toán ví dụ Lập trình sử dụng ngắt ngoài
Ý tưởng của thuật toán này như sau
Chu kỳ nháy được đặt bằng một biến x, trong chương trình, x hoặc có giá trị 500 (0,5s)
hoặc 2000 (2s)
Khi ngắt ngoài được kích hoạt, chương trình ngắt gán giá trị x = 2000 (nếu giá trị hiện thời của x = 500), hoặc gán giá trị x = 500 (nếu giá trị hiện thời của x = 2000) Chương trình chính sẽ thực hiện điều khiển nháy led với chu kỳ x
Như vậy khi người dùng nhấn nút, sẽ kích hoạt ngắt ngoài, đổi giá trị biến x, đèn led sẽ được điều khiển nhấp nháy theo giá trị biến x tương ứng
Trong ô “Mode”, click chọn “Falling Edge” để chọn chế độ kích hoạt ngắt ở cạnh lên
d) Viết chương trình điều khiển
Trong ví dụ này có sử dụng biến x để đặc trưng cho chế độ làm việc của mạch Biến là
một khái niệm trong lập trình, để chỉ các giá trị số, giá trị logic, chuỗi ký tự, matrận… Biến
có thể có giá trị không đổi hoặc thay đổi trong lập trình tùy thuộc vào cách sử dụng
Trang 33Mỗi kiểu biến có đặc trưng khác nhau (để chỉ giá trị số, giá trị logic…), muốn sử dụng biến trong lập trình cần phải có bước “khai báo” Bao gồm khai báo tên biến (x, y, bien1, bien2,…) và kiểu dữ liệu(char, str, …) Các kiểu và thuộc tính của kiểu dữ liệu được cho trong bản phần phụ lục
Trong ví dụ này ta khai báo biến x là biến kiểu int (giá trị số nguyên từ -32768 ~
+32767)
Include thêm file header sau: delay.h
Khai báo biến bằng dòng lệnh: char x=500; Ở đây chúng ta gán cho x giá trị x=500 ngay từ đầu, để khi cấp điện, đèn led nhấp nháy ngay với chu kỳ 0,5s
Hình 40: Khai báo biến và nơi viết chương trình ngắt
Viết chương trình phục vụ ngắt ngoài: Trình phục vụ ngắt ngoài được viết tại vị trí như trong hình trên Cấu trúc chương trình ngắt có thể được hình dung như sau:
interrupt [EXT_INT0] void ext_int0_isr(void)
Ký hiệu hai dấu bằng “==” là ký hiệu của phép so sánh, như dòng lệnh trên, giá trị trả về
sẽ bằng 0, vì giá trị hiện thời của x là 2000 khác 500
x == 500 = 0;
Nếu biểu thức so sánh trả về giá trị 1, các dòng lệnh a sẽ được thực hiện, nếu giá trị biểu thức so sánh trả về bằng không, các dòng lệnh B sẽ được thực hiện