Ta thường truyền thông giữa máy tính và vi điều khiển thông qua cổng này để trao đổi dữ liệu đo đạc, điều khiển, việc này chỉ cần sử dụng 3 chân theo sơ đồ sau : Trong đó: Thứ tự chân T
Trang 1GIAO TIẾP MÁY TÍNH TOÀN TẬP
Tài liệu này biên soạn chủ yếu dựa theo giáo trình “Đo lường và điều khiển bằng máy tính” của Thầy Nguyễn Đức Thành ĐH Bách Khoa Tp.HCM cùng với quá trình thực hành của mình qua các đồ án và luận văn Tài liệu vẫn có thể có nhiều sai xót và chưa đầy đủ (Bluetooth, Internet sẽ được bổ sung sau) nhưng chắc chắn sẽ giúp cho các bạn sinh viên mạnh dạng hơn trong việc sử dụng máy tính để điều khiển,
đo đạc thông qua các ví dụ cụ thể.
MỤC LỤC :
1 GIAO TIẾP QUA CỔNG COM RS232
2 GIAO TIẾP QUA CỔNG MÁY IN
3 GIAO TIẾP QUA KHE CẮM PCI
4 GIAO TIẾP QUA CỔNG USB
Trang 2I.Giao tiếp qua cổng nối tiếp RS232:
Ta thường sử dụng truyền thông nối tiếp thông qua cổng COM máy tính có 9
chân hoặc 25 chân, nhưng cổng 9 chân thì phổ biến hơn Ta thường truyền thông giữa
máy tính và vi điều khiển thông qua cổng này để trao đổi dữ liệu đo đạc, điều khiển,
việc này chỉ cần sử dụng 3 chân theo sơ đồ sau :
Trong đó:
Thứ tự chân Tên tín hiệu Chiều Ý nghĩa
Tuy nhiên mức điện áp logic của máy tính lại khác với mức điện áp logic của vi
điều khiển nên ta cần 1 vi mạch chuyển mức logic (MAX232 hoặc DS275) Cụ thể sơ
đồ như sau:
khiển
GND
M I C R O C O N T R O L E R
5 V
1 3 4 5
2 6
1 2 9
1 1
1 0
1 3 8
1 4 7
C 1 +
C 1
-C 2 +
C 2
V +
V
-R 1 O U T
R 2 O U T
T 1 I N
T 2 I N
R 1 I N
R 2 I N
T 1 O U T
T 2 O U T
5 V
C 4
C 1
1 u F
G N D ( 5 )
5 V
C 2
1 u F
G N D ( 5 )
R X D ( 2 )
T X D ( 3 )
R X D ( 2 )
Trang 3Có 1 điều mà ta cần lưu ý đó là cách sử dụng các chân của MAX232 vì rất dễ nhầm nếu trong trường hợp không có datasheet : Max232 thực hiện nhiệm vụ chuyển mức logic từ máy tính qua vi điều khiển và ngược lại Vì vậy ví dụ với chân R1IN thì ta nên hiểu nó nhận dữ liệu xuất từ máy tính hay vi điều khiển? Để khỏi bị nhầm thì bạn
cứ nhớ trong đầu là chỉ có máy tính thôi Như vậy ta chỉ cần nhớ 1 điều là máy tính truyền dữ liệu thông qua chân Rin và nhận dữ liệu thông qua chân Tout Nhớ như vậy
thì ta hiển nhiên hiểu các chân kết nối với vi điều khiển thế nào
Và chỉ với 3 chân của cổng COM ta đã sẵn sàng thực hiện các thí nghiệm truyền dữ liệu hay điều khiển
Cấu trúc dữ liệu truyền đi theo chuẩn RS232:
Start bit 8 bits dữ liệu Parity bit Stop bit Một chuỗi truyền dữ liệu gồm tất cả 11 bit, trong đó 1 bit Start (cho biết là sắp truyền dữ liệu), 8 bit dữ liệu ( dữ liệu trao đổi hai chiều giữa máy tính và vi điều khiển), 1 bit Parity (dùng để kiểm tra lỗi khi truyền, với khoảng cách ngắn thì không cần kiểm tra Parity), 1 bit Stop cho biết kết thúc chuỗi dữ liệu Khi không truyền
đường dây sẽ ở trạng thái Mark (mức 1) Logic trên đường dây theo kiểu Mức 1 (-10V), Mức 0 (+10V).
Tín hiệu truyền nối tiếp dưới dạng các bit, số bit trong 1 giây được gọi là baud, vận tốc truyền thông dụng là 300, 600, 1200, 2400, 4800, 9600, 19200
Một điều cần lưu ý là nơi truyền và nơi nhận phải cùng được thiết lập tốc độ truyền giống nhau để đảm bảo dữ liệu nhận được không bị sai Khi ta truyền dữ liệu
Mức 1
Mức 0
Trang 4điều khiển từ máy tính xuống vi điều khiển mà vi điều khiển “nín thinh” không làm gì
cả thì điều đầu tiên cần xem lại là tốc độ truyền nhận 2 bên đã đúng chưa !
Mạng truyền thông RS232:
Vì ta chỉ thực hiện những thí nghiệm nhỏ thì truyền thông theo chuẩn RS232 đã
tạm đủ Tuy nhiên trong trường hợp ta muốn giao tiếp giữa máy tính với nhiều vi điều
khiển thì mọi chuyện sẽ rắc rối hơn do chuẩn này không có ưu tiên trên đường truyền,
không có địa chỉ nơi nhận Tuy vậy nếu khéo léo 1 chút thì ta vẫn có thể thực hiện
được mạng truyền thông RS232 bằng những giải thuật hợp lý nhằm tránh xung đột
trên đường truyền và sai xót có thể Sau đây là sơ đồ kết nối và giải thuật giám sát của
máy tính với 2 vi điều khiển :
T X D ( 3 )
C 4
1 u F
5 V
M I C R O C O N T R O L E R 1
5 V
+ 1 u FC 3
C 2
1 u F
U 2 A
7 4 0 8
1
2 3
G N D ( 5 )
M A X 2 3 2
1 4
2
1 2 9
1 1
1 3 8
1 4 7
C 1 +
C 1
-C 2 +
C 2
V +
V
-R 1 O U T
T 1 I N
R 1 I N
T 1 O U T
5 V
R X D ( 2 )
G N D ( 5 )
G N D ( 5 )
C 1
1 u F
T X D ( 3 )
R X D ( 2 )
R X D ( 2 )
M I C R O C O N T R O L E R 2
5 V
C O M P U T E R
Chắc các bạn sẽ thắc mắc tại sao mình thêm vào cổng AND 7408 ? Điều gì sẽ
xảy ra khi chúng ta kết nối trực tiếp và chỉ có 1 vi điều khiển truyền dữ liệu?Khi
không truyền thì chân TXD của con thứ 1 sẽ ở trạng thái chờ (mức 1), và khi con thứ
2 truyền thì chắc chắn sẽ có bit 0 nào đó gửi về máy tính nhưng chân TXD của con
Trang 5thứ nhất đột ngột bị hạ xuống mức 0 do phần cứng sẽ gây ra chạm mạch, đôi khi có thể cháy vi điều khiển Chính vì thế theo cách của mình thì nên cách ly bằng cổng AND thì khi 1 con truyền sẽ không ảnh hưởng đến con kia Tương tự với nhiều vi điều khiển hơn thì bạn dùng cổng AND nhiều ngõ vào hơn hoặc kết nối các cổng AND 2 ngõ vào để được số ngõ vào mong muốn Còn chân nhận dữ liệu từ máy tính thì không cần cách ly Tuy nhiên phần cứng này không giải quyết chuyện 2 vi điều khiển cùng truyền 1 lúc mà phải được giải quyết bằng phần mềm Do đó giải thuật
mà mình nghĩ là theo kiểu máy tính là người chủ động, còn 2 vi điều khiển sẽ bị động, tức là theo kiểu đối thoại như sau :
while (1)
{
“ Máy tính: Ê A ! Nhiệt độ lò nướng là bao nhiêu hả mạy?
VĐK A : Dạ em đo được 120 độ, thèng B nó đo vận tốc động cơ đó, anh hỏi nó đi!
Máy tính : Ê B ! Mày đang chạy với vận tốc bao nhiêu vậy?
VĐK B : Dạ em chạy có 2000 vòng/phút hà, anh đừng bắn tốc độ
”
}
Và như vậy sẽ không có chuyện cả hai vi điều khiển cùng truyền 1 lúc Nhưng
có 1 điều cân phải nói là dữ liệu chỉ có 8 bit (256 ) thôi, sao biết máy tính truyền lệnh
và dữ liệu cho thằng nào, A hay B? Mình có ý kiến thế này, nếu như dữ liệu mà máy tính truyền cho vi điều khiển nhỏ hơn hoặc bằng 127 thì bạn quy định rằng bit lớn nhất là bit địa chỉ, ví dụ 0XXXXXXX là gửi cho cho em A, còn 1XXXXXXX là gửi
cho em B, đó chính là bit D0, nhất định hai em A và B sẽ không giành giật nhau “Của anh Computer gửi cho tao mà ! ” Tại sao mình chọn D0 mà không chọn D7? Đó là
do dữ liệu của mình có lúc chẵn, lúc lẻ mà thằng D7 sẽ là bit chẵn lẻ, chịu khó dữ liệu nhỏ 1 chút nhưng chỉ gửi 1 lần Còn nếu dữ liệu dài lằng ngoằng thì nên tách nó ra thành nhiều lần gửi liên tiếp nhau, byte đầu tiên sẽ qui định địa chỉ của vi điều khiển (giao tiếp được với 255 con VĐK lận đó) Cái này dùng cho cả truyền và nhận, nhưng bạn nên thống nhất là số byte truyền và nhận là cố định, ví dụ máy tính luôn luôn truyền 2 byte cho tất cả vi điều khiển, và các vi điều khiển luôn luôn truyền 3 byte cho máy tính, làm như vậy ta sẽ được lợi là code cho từng vi điều khiển sẽ gần giống nhau, thằng nào có số byte ngắn hơn thì số byte còn lại là 0 và ghép vô gửi luôn Dưới
Trang 6đây mình xin Code thử bằng C cho vi điều khiển XXX (ai biết bạn dùng loại nào !) có địa chỉ là 0, nó nhận 2 byte từ máy tính :
//***************Ví dụ 1********************
unsigned char data[2]; //mảng dữ liệu nhận
int i ; //biến đếm số byte
int my_data = 0 ;//xác định dữ liệu có phải dành cho mình hay không
void uart_int() //hàm ngắt ngoài.
{
if (i == 0 ) //nhận byte đầu tiên
{
if (SBUF == 0 ) //Nếu bộ đệm nhận byte dầu đúng là địa chỉ 0
{
my_data = 1;// haha, đúng là quà của anh Computer gửi cho mình rồi! }
else my_data = 0;//quê thiệt, ảnh gửi cho em khác rùi !
}
if (my_data == 1)//Nếu đúng là của ảnh gửi thì phải nhận cả 2 món !
{
data[i] = SBUF;//Đem cất quà nào !
}
i = i ++;//Thêm 1 món nữa
if (i == 2)//Nhận đủ 2 món rùi
{
i = 0; //Tiếp tục xoè tay chờ nhận quà
my_data = 0;
}
}
//************************************************
Bạn thấy không, đoạn code trên có thể dùng cho cả các vi điều khiển có địa chỉ khác Tuy nhiên,viết chung chung bằng C thì nó là như vậy, với mỗi họ VĐK sẽ thêm thắt chút ít vào hàm ngắt truyền thông nối tiếp ví dụ như phải xoá cờ ngắt nhận vv
Trang 7Tiếp theo ta sẽ tìm hiểu module truyền thông nối tiếp của Visual Basic, để có thể viết chương trình máy tính giao tiếp với vi điều khiển Điều trước tiên là các bạn phải download được file : MSCOMM32.OCX sau đó quăng vào C:/windows/system32 Đơn giản, chỉ cần vào google gõ là ra ngay thui ! Sau đó bạn mở Visual Basic lên, chọn kiểu Form thiết kế, xong rùi trên thanh Menu Bar có task Project—Components
Ở task Control bạn nhấn Browse để Add thư viện điều khiển cổng COM, nó ở trong system 32 đó ! Sau khi add và nhấn OK thì bên task General sẽ có biểu tượng hình điện thoại để bàn
Bạn click vào biểu tượng thoại rồi vẽ lên form 1 hình chữ nhật, lập
tức biểu tượng điện thoại xuất hiện trên
form, như vậy là ta đã thêm đối tượng
Com Control vào chương trình điều khiển
Đối tượng đầu tiên mặc định có tên là
Mscomm1 Nếu như máy tính bạn có hơn
2 cổng COM thì vẽ thêm vô 1 cái nữa và
thằng vẽ sau tên là Mscomm2
Sau đây là các hàm chính trong VB liên quan
đến việc truyền thông RS232.
- Object.CommPort = [value]
Đặt cấu hình chọn cổng giao tiếp, mặc
định là cổng số 1, tuy nhiên để cho chắc chắn
Trang 8bạn nên mở Device Manager để xem Object ở đây chính là đối tượng Mscomm mà ta
vẽ trên form Ví dụ:
Mscomm1.CommPort = 1
- Object.Settings = [value]
Value = “Baud rate, Parity bit, Data bit, Stop bit “
Baud rate: là tốc độ truyền nhận giữa máy tính và vi điều khiển (110, 300, 600,
1200, 2400, 9600, 14400, 19200, 28800, 38400 )
Parity bit : bit kiểm tra chẵn lẻ, N : non parity (default), E : Even (kiểm tra chẵn), O : Odd (kiểm tra lẻ) Tuy nhiên nên để giá trị mặc định là N vì không cần
kiểm tra với khoảng cách truyền ngắn và ít bị nhiễu Lưu ý dây cáp truyền tín hiệu bạn nên bố trí xa các thiết bị liên quan đến từ trường như động cơ, relay nhằm tránh bị nhiễu.
Data bit : số bit dữ liệu mà ta muốn truyền đi, có giá trị từ 4, 5, 6, 7, 8(default) Stop bit : số bit dừng, có thể là 1, 1.5, 2
Ví dụ : Mscomm1.Settings = “9600, N, 8, 1” Tốc độ truyền là 9600, không kiểm tra chẵn lẻ, 8 bit dữ liệu và 1 bit stop
- Object.PortOpen = [True/False]
Cho phép chương trình chúng ta đóng hay mở cổng COM, lưu ý là chương trình của chúng ta không thể mở cổng com trong khi 1 chương trình khác đang sử dụng cổng COM
Ví dụ : Mscomm1.PortOpen = True , chiếm lấy cổng COM để truyền thông.
khác có thể sử dụng cổng com để truyền thông.
- Var = Object.Input
Đọc giá trị thu của bộ đệm vào biến Var Sử dụng khi ta nhận dữ liệu.
Ví dụ : Dim nhiet_do As byte
nhiet_do = Mscomm1.Input
- Object.Inputlen = [number]
Qui định số ký tự đọc bởi Input Nên chọn Inputlen = 0 sẽ cho phép đọc toàn bộ vùng đệm Trường hợp ta không biết chuỗi dữ liệu nhận được gồm bao nhiêu ký tự thì nên chọn Inputlen = 0 sẽ cho phép đọc hết, còn nếu chúng ta biết mỗi lần truyền nhận chỉ
Trang 9có 1 ký tự thì nên chọn Inputlen = 1 sẽ chỉ đọc 1 ký tự đó ra thôi Sau khi tìm hiểu lênh phía sau tôi sẽ giải thích kỹ hơn về bộ đệm.
- Object.Inbuffersize = [number]
Qui định kích thước của bộ đệm, number có giá trị mặc định là 1024 nếu ta không thiết lập lệnh này Bạn hình dung thế này, giả sử bạn qui định kích thước của
bộ đệm máy tính bạn là 1 byte thì dữ liệu nhận được sẽ được ghi vào ô nhớ có kích thước 1 byte này, dữ liệu nhận sau sẽ đè lên dữ liệu trước, do đó mỗi lần nhận 1 ký tự thì bạn phải nhanh chóng lưu ký tự này Còn nếu bạn có kích thước 2 byte thì khi nhận được 1 ký tự, máy tính sẽ ghi vào ô nhớ 1, nhận ký tự tiếp theo sẽ ghi vào ô nhớ
2, còn ký tự thứ 3 thì được ghi vào ô nhớ 1 và cứ thế tiếp tục .
Nếu bạn lập trình tốt và có ý sẽ xử lý mỗi ký tự mỗi khi nhận được nó thì nên thiết lập như sau để tối ưu bộ đệm và tối ưu tốc độ thực thi :
Mscomm1.Inputlen = 1
Nghĩa là tạo ra bộ đệm có kích thước 1 ký tự và chỉ đọc ra 1 ký tự thôi.
- Object.InputMode = [value]
Value = ComInputModeText : Bộ đệm sẽ thu và chuyển thành kiểu ký tự chứ
không phải số, lưu ý trên đường truyền chỉ có mã Ascii của ký tự được truyền đi
Ví dụ vi điều khiển gửi số 48 (#30H) cho máy tính mà ta thiết lập InputMode = 0 thì bộ đệm sẽ chứa chữ số 0 kiểu string.
Value = ComInputModeBinary: Bộ đệm sẽ nhận nguyên số được nhận Ví dụ
như trên thì máy tính sẽ nhận được số 48.
- Var = Object.InbufferCount
Lệnh này sẽ trả về số ký đã nhận được trong bộ đệm vào biến Var, xoá bộ đệm nhận bằng cách cho Object.InbufferCount = 0.
- Object.Output = [value]
Value có thể là số hay chữ,hay chuỗi nhưng tất cả đều được truyền đi bằng
mã ascii của ký tự.
Ví dụ: Mscomm1.Output = 5 , thì lúc đó số được máy tính truyền đi là #35H chính
là mã ascii của số 5 Cũng tương tự vậy nếu truyền số 55 thì nó sẽ gửi đi 2 byte
#35H và #35H liên tiếp nhau.
Trang 10- Object.Rthreshold = [number]
Number = 0 – 1024 Lệnh này cho phép ta thiết lập nhận number ký tự thì sẽ gọi chương trình phục vụ ngắt nhận.
Ví dụ : Mscomm1.Rthreshold = 3 , mỗi lần nhận được 3 ký tự thì sẽ gọi chương trình phục vụ ngắt 1 lần Gán bằng 0 đồng nghĩa với việc không gọi chương trình ngắt.
- Object.Sthreshold = [number]
Tương tự như trên, ở đây ta đặt số byte truyền đi để gọi chương trình phục vụ ngắt phát Nói chung lệnh này ít được sử dụng, chỉ trong 1 số trường hợp đặc biệt mới dùng Ví dụ ta muốn truyền 1 chuỗi dữ liệu nhưng muốn rằng cứ truyền 3 ký tự thì sẽ dừng 1 khoảng 200ms Đố bạn làm cách nào? hãy thử suy nghĩ giải thuật thôi ! Chương trình phục vụ ngắt (cả truyền và nhận) được viết trong procedure sau :
Private Sub MSComm1_OnComm()
.
End Sub
Bạn có thể double click vào biểu tượng cái điện thoại trên form để viết code cho chương trình ngắt Vấn đề là làm sao biết là ngắt truyền hay ngắt nhận? Bạn có thể biết điều đó bằng cách kiểm tra thuộc tính sau:
If Mscomm1.CommEvent = ComEvReceive then ‘Ngắt nhận
If Mscomm1.CommEvent = ComEvSend then ‘Ngắt phát
OK vậy là ta đã có kiến thức cơ bản để thao tác với truyền thông RS232 bằng Visual Basic Giờ chúng ta sẽ cùng nhau làm một số ví dụ từ dễ đến khó để hiểu rõ việc truyền nhận dữ liệu bằng máy tính như thế nào !
Ví dụ 1: Viết chương trình Visual Basic truyền 1 ký tự từ vi điều khiển, sau đó
nhận lại 1 ký tự và hiển thị
Trang 11Bạn thiết kế 1 form có dạng sau :
Ô Text 1 chứa ký tự truyền đi mỗi khi nhấn nút Send Ô Text 2 chứa ký
tự nhận được
Sau đây là code và giải thích chương trình :
Ví dụ trên thật là đơn giản phải không bạn? Chỉ là các thiết lập cơ bản để truyền thông RS232 và mình cũng đã giải thích rõ từng lệnh Tiếp theo ta sẽ xét thêm 1 ví dụ nữa
Ví dụ 2: Viết chương trình truyền kích thước cho máy vẽ , là chiều dài và chiều rộng
của hình chữ nhật có kích thước từ 0 – 100 (cm) Máy vẽ sau khi đã nhận được cả hai kích thước thì sẽ gửi lại ký tự ! để confirm Nếu sau 5s sau khi truyền mà không thấy replay thì báo máy vẽ bị lỗi Trong thời gian chờ confirm của vi điều khiển thì máy tính không được phép ra lệnh vẽ cho đến khi nhận ký tự “!”
Bạn thiết kế form có dạng như sau :
Trang 12Ta thiết kế thêm 2 cái đèn báo để báo trạng thái của máy vẽ, 1 đèn báo máy vẽ đã sẵn sang nhận lệnh : xanh là OK, đỏ là đang xử lý, 1 đèn báo lỗi : xanh là OK, đỏ là bị lỗi
Ví dụ 3: Viết chương trình máy tính điều khiền và giám sát 2 vi điều khiển Một vi
điều khiển nhận nhiệt độ (100-200oC) thiết lập từ máy tính để điều khiển điện trở nung và đo nhiệt độ bằng Thermocouple qua kênh ADC Vi điều khiển kia nhận tốc
độ (1000-5000 vòng/phút) thiết lập từ máy tính và đo tốc độ thông qua Encoder và truyền về máy tính.( Đây chính là bài toán máy tính giám sát nhiều vi điều khiển mà tôi đã từng đề cập ở trên)