Você está na página 1de 9

Bài 5.

1 - Giao tiếp UART chế độ Multi-Processor


Nội dung Các bài cần tham khảo trước

Cấu trúc AVR.


1. Chế độ Multi-Processor trong AVR UART. WinAVR.
2. Sử dụng Multi-Processor. C cho AVR.
Download ví dụ Mô phỏng với Proteus.
Giao tiếp UART

I. Chế độ Multi-Processor trong AVR UART.


       AVR hỗ trợ một khả năng giao tiếp UART ở chế độ “đa xử lí” (Multi-
processor) hay Master-Slaves. Điều đầu tiên bạn cần biết là chế độ này không phải
là chuẩn của UART mà chỉ đặc biệt trên các chip AVR (và có thể trên một số chip
khác của Atmel). Bit MPCM (bit 0) trong thanh ghi UCSRA là nhân tố quan trọng
nhất để quyết định chế độ hoạt động này. Cấu hình mạng Master-Slave dùng
UART được tóm tắt như sau: 
      - Trên mạng này chỉ có 1 Master và có thể có nhiều Slaves, các đường TxD và
RxD của các Slaves được nối chung với nhau (nối song song). Các Slaves và
Master được nối với nhau theo kiểu “bắt chéo”, TxD chung của Slaves nối với
RxD của Master và ngược lại. Mỗi Slave mang 1 địa chỉ riêng do người dùng gán,
đặc biệt có thể có nhiều Slave trùng địa chỉ vẫn không ảnh hưởng đến hoạt động
của mạng.
      - Các Slaves và Master phải được cài đặt khung truyền và baudrate như nhau
(cũng như truyền thông UART thông thường). Khung truyền trong chế độ Master-
Slaves có thể 5, 6, 7,8 hay 9 bit nhưng thông thường khung 9 bit được chọn. Bài
này cũng hướng dẫn dựa trên khung 9 bit. Trong khung truyền 9 bit, 8 bit đầu tiên
được chứa trong thanh ghi dữ liệu UDR như thông thường và bit thứ cao nhất là bit
TXB8 trong thanh ghi USCRB (trường hợp phát) hay bit RXB8 trong thanh ghi
UCSRB (trường hợp thu).
      - Bit MPCM (bit 0) trong thanh ghi UCSRA cho phép một chip làm việc ở chế
độ Master-Slave. Tuy nhiên bit này chỉ  có tác dụng ở chip Slaves, để một chip làm
việc như một Slave (chờ lệnh từ Master) thì bit MPCM của chip này phải được set
lên 1. Bit MPCM của Master không cần set.
     Cơ chế làm việc của chế độ Master-Slaves được giải thích như sau: lúc đầu, các
bit MPCM trên tất cả các Slaves đều được set lên 1, ngắt nhận dữ liệu RXCIE của
các  Slaves được kích hoạt và chúng đang ở chế độ chờ “lệnh” từ Master. Khi chip
Master muốn thực hiện một “cuộc gọi” với một Slave nào đó, nó sẽ phát ra một
“gói địa chỉ” bao gồm 8 bits chứa địa chỉ của Slave cần gọi và bit cao nhất (TXB8)
luôn bằng 1 (xem hình 1).

Hình 1. Gói địa chỉ.


     Khi tất cả 9 bit được các Slaves nhận, bit cao nhất sẽ được Slaves chứa trong bit
RXB8. Nếu bit này bằng 1 các Slaves biết rằng đây là gói địa chỉ, ngắt RXCIE sẽ
xảy ra trên tất cả các Slaves. Quá trình này được chip thực hiện một cách hoàn toàn
tự động. Trong trình phục vụ ngắt RXCIE (SIG_UART_RECV) người lập trình sẽ
thực hiện so sánh giá trị 8 bits địa chỉ nhận về với địa chỉ của từng Slave. Nếu một
Slave nhận thấy địa chỉ mà Master gởi khớp với địa chỉ của nó, người lập trình cần
reset bit MPCM về 0 để tách Slave này ra khỏi chế độ chờ (chờ địa chỉ). Tiếp theo
Master sẽ gởi liên tiếp các “gói dữ liệu” trên đường truyền. Khác với gói địa chỉ,
bit cao nhất (TXB8) trong gói dữ liệu bằng 0 chứ không bằng 1. Trên chip Master,
người lập trình cần viết 2 đoạn chương trình phát gói địa chỉ và gói dữ liệu riêng
biệt. Đối với các Slaves, do bit cao nhất nhận về RXB8=0, ngắt RXCIE chỉ duy
nhất xảy ra trên Slave có bit MPCM=0. Như thế, tất cả các Slaves khác sẽ bỏ qua
gói này (ngắt RXCIE không xảy ra, không ảnh hưởng đến các việc khác) chỉ duy
nhất Slave có địa chỉ trùng trước đó nhận dữ liệu. Một chú ý rất quan trọng là sau
khi byte dữ liệu cuối cùng được nhận, Slave (chip được chọn) phải set lại bit
MPCM lên 1 (do người lập trình thực hiện) để đưa Slave trở lại trạng thái chờ các
cuộc gọi tiếp theo.
     Như vậy, bằng cách nào đó Slave phải biết trước được số lượng bytes dữ liệu
mà Master muốn gởi để kịp thời set bit MPCM lên 1 sau byte cuối. Có một số
cách để biết trước số lượng bytes mà Master sẽ gởi như “thỏa thuận” trước số bytes
cố định cho mỗi cuộc gọi; hoặc đơn giản Master dùng byte dữ liệu đầu tiên (sau
byte địa chỉ) để báo số lượng bytes sẽ gởi tiếp theo; hoặc hay hơn có thể ghép
thông số chỉ lượng bytes cần truyền vào gói địa chỉ nếu như không có quá nhiều
Slaves trên mạng và số lượng bytes truyền cũng không quá lớn. Nhưng dù cách
nào đi nữa, cần có sự “thỏa thuận” khi lập trình cho Master và Slave. Có một “dấu
hiệu” khác có thể được dùng để phân biệt giữa gói dữ liệu và gói địa chỉ đó là trạng
thái bit RXB8, bằng việc kiểm tra trạng thái bit này chúng ta sẽ biết được gói nào
là dữ liệu (RXB8=0) và gói nào là địa chỉ (RXB8=1). Tuy nhiên cách này không
nhận biết được byte dữ liệu cuối cùng được gởi vì vậy không được sử dụng để set
bit MPCM lên 1.
II. Sử dụng Multi-Processor. 
     Trong ví dụ bài này tôi dùng phương pháp đơn giản là “thỏa thuận” trước giữa
Master và Slave số lương bytes trong một lần truyền, cụ thể chúng ta sẽ thiết lập
một mạng Master-Slaves với 1 Master và 2 Slaves. Các Slave có địa chỉ lần lượt là
1 và 2, chúng ta dùng 2 chân PC0 và PC1 để set địa chỉ cho Slaves (việc này giúp
chúng ta có thể sử dụng 1 chương trình chung cho 2 Slaves). Master chỉ đơn giản
gởi đến mỗi Slave 1 gói địa chỉ và 2 bytes dữ liệu. Các Slaves sẽ hiển thị 2 bytes
dữ liệu lên 2 dòng của LCD. Mạch điện mô phỏng ví dụ trình bày trong hình 2. 
Hình 2. Ví dụ mạng Master-Slaves dùng UART.
Chúng ta cần viết 2 đoạn chương trình riêng cho Master và Slaves. Đoạn chương
trình cho Master được trình bày trong List1.
List 1. Chương trình cho Master.
     Với chip Master, như đã trình bày chúng ta cần viết riêng 2 đoạn chương trình
con phục vụ phát gói dữ liệu và gói địa chỉ. Trong list 1, hai đoạn chương trình này
có tên uart_char_tx và uart_address_tx nằm từ dòng 38 đến 48. Đây chỉ đoạn
code phát uart thông thường (xem bài AVR5 – Giao tiếp UART) cộng thêm với
việc set và reset bit TXB8. Trong đoạn chương trình phát gói dữ liệu, bit TXB8
được reset về 0 bằng câu lệnh UCSRB &= ~(1<<TXB8); trong khi ở đoạn chương
trình phát gói địa chỉ bit này được set lên 1, UCSRB |= (1<<TXB8); (chú ý bit
TXB8 nằm trong thanh ghi USCRB).
     Phần cài đặt cho UART (từ dòng 14 đến dòng 20) bạn đọc hãy xem lại bài
AVR5. Chú ý đến các dòng từ 24 đến 30. Đây là phần gởi địa chỉ và dữ liệu đến
các Slave. Trước khi muốn gởi dữ liệu đến Slave1, chúng ta cần gọi chương trình
con phát địa chỉ uart_address_tx(1) như trong dòng 24, tiếp theo là phát 2 bytes dữ
liệu theo cách thông thường (ví dụ byte1=200, byte2=123). Tương tự chúng ta có
thể phát2 bytes dữ liệu đến Slave2 theo cách này (dòng 28, 29 và 30).
List 2. Chương trình cho Slaves.
     Do chúng ta sử dụng TextLCD để hiển thị kết quả nhận về từ Master, cần
include thư viện myLCD.h (dòng 6). Thư viện stdio.h chứa các hàm xử lí chuỗi ký
tự giúp ích cho việc hiển thị LCD (chúng ta sẽ dùng hàm sprintf) nên cũng cần
được include vào (dòng 5). Biến my_address chứa địa chỉ của Slave, u_data chứa
giá trị nhận về từ UART, biến ind là chỉ số chỉ số bytes nhận về. Gói dữ liệu nhận
về chứa trong mảng alldata[3], mảng dis[5] là mảng ký tự tạm thời hiển thị lên
LCD (xem các khai báo biến trong 2 dòng 14. 15). Địa chỉ Slave do 2 chân PC0 và
PC1 quyết định, việc đọc đỉa chỉ này được thực hiện với dòng lệnh
my_address=PINC & 0x03. Bằng cách chọn địa chỉ “động” như thế chúng ta
không cần viết riêng chương trình cho mỗi Slave.
     Các dòng lệnh từ 24 đến 30 cài đặt thông số cho UART, chú ý cần cho phép
ngắt RXCIE xảy ra dòng 29 và 30). Phần nội dung quan trọng nhất được viết trong
trình phục vụ ngắt ISR(SIG_UART_RECV) (từ dòng 44 đến 60). Khi một ngắt
RXCIE việc đầu tiên cần làm là đọc giá trị nhận về vào biến u_data (dòng 45), nếu
đây là byte đầu tiên nhận về (tức ind=0, byte địa chỉ) thì chúng ta cần so sánh xem
địa chỉ có khớp không (dòng 47). Nếu đúng là địa chỉ của Slave này thì cần reset
bit MPCM về 0 để sẵn sàng nhận dữ liệu (dòng 48), tăng biến ind lên 1. Nếu byte
nhận về không phải là byte đầu tiên mà là byte dữ liệu (biến ind khác 0) chúng ta
sẽ gán byte nhận về vào mảng alldata và tăng biến chỉ số ind (các dòng từ 52 đến
54). Vì trong ví dụ này chúng ta thỏa thuận trước Master chỉ gởi 2 bytes dữ liệu
đến mỗi Slave nên khi biến ind bằng 3, tức là đã nhận đủ 2 bytes dữ liệu chúng ta
cần set lại bit MPCM để kết thúc quá trình nhận, đưa Slave về lại trạng thái chờ,
đồng thời trả biến chỉ số ind về 0 (làm lại từ đầu) (xem các dòng 55 đến 57).
     Khi mô phỏng, bạn hãy nạp chương trình trong List 1 cho chip Master và list2
cho 2 Slaves. Cần set xung clock 8MHz. Nếu bạn thực hiện đúng kết quả sẽ hiển
thị như trong hình 1. 

Você também pode gostar