Giáo trình Đo lường và điều khiển bằng máy tính - Chương 4: Lập trình cho máy tính điều khiển

Khi dùng máy tính để đo lường, điều khiển ta phải giải quyết vấn đề

là xuất một dữ liệu 8 bit ra một thanh ghi hay đọc dữ liệu 8 bit từ thanh ghi

vào một biến.

Vấn đề này được giải quyết dễ dàng bởi các ngôn ngữ lập trình trong

môi trường DOS như hợp ngữ, Qbasic, Pascal, C. Với hệ điều hành

Windows 98, 2000XP thì công việc trở nên phức tạp hơn.

pdf25 trang | Chuyên mục: Công Nghệ Tri Thức & Máy Học | Chia sẻ: dkS00TYs | Lượt xem: 1764 | Lượt tải: 2download
Tóm tắt nội dung Giáo trình Đo lường và điều khiển bằng máy tính - Chương 4: Lập trình cho máy tính điều khiển, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
ám dứt lệnh đang thực hiện, 
cất một số thông tin vào ngăn xếp và thực hiện thường trình phục vụ ngắt 
ISR (Interrupt Service Rovtine) đã định sẵn. Khi đã thực hiện xong ISR, 
VXL quay trở lại nơi đã rời khỏi. 
Có tất cả 256 ngắt cho họ VXL 8086, một số ngắt (đa số) không liên 
quan gì đến ngoại vi, số ít còn lại là ngắt cứng phục vụ cho việc giao tiếp 
VXL với ngoại vi như ngắt thời gian, bàn phím, con chuột, cổng song song, 
cổng nối tiếp, đĩa cứng, đĩa mềm, card âm thanh… 
VXL quản lý ngắt qua vector ngắt, vector ngắt cho biết địa chỉ chứa 
ISR cho mỗi loại ngắt. Bảng các địa chỉ gọi là bảng vector ngắt (bảng 4.1). 
Mỗi địa chỉ chiếm bốn byte 
Các ngắt ký hiệu INT N có địa chỉ ISR ở trong 
các ô nhớ: gồm địa chỉ đoạn CS và địa chỉ tương đối 
IP, địa chỉ vật lý CS x 16 + IP 
Các ngắt được xếp ưu tiên từ cao đến thấp như 
sau: 
INT0; INTn; NMI; IRQ0; IRQ1; IRQ8 ÷ IRQ15; 
IRQ3; IRQ4, IRQ5; IRQ6; IRQ7; INT1 
INTn là các ngắt mềm và ngắt ngoại lệ. 
Vi xử lý xử lý ngắt ngoài thông qua vi mạch điều khiển ưu tiên ngắt 
PIC (Priority Interrupt Controller), các mainboard đời cũ dùng hai PIC 
8259A còn các mainboard đời mới tích hợp trong một chip đa năng theo 
công nghệ ASIC (chip set) 
PIC có các thanh ghi phục vụ xử lý ngắt 
PIC 1: ngắt IRQ7, 6, 5, 4, 3, 2, 1, 0 có địa chỉ 20H và 21H 
IP 
CS 
N x 4 
N x 4 + 1 
N x 4 + 2 
N x 4 + 3
Tác giả: TS Nguyễn Đức Thành Trang 105 
Thành phố Hồ Chí Minh, tháng 4 năm 2006 
Bảng 4.1: Bảng vector ngắt 
INT (Hex) IRQ Sử dụng 
00 - 01 Exception Handlers Chia cho zero 
02 IRQ không che (NMI) Sai parity 
03 - 07 Exception Handlers Xử lý các ngoại lệ 
08 Ngắt cứng IRQ0 Timer Hệ thống 
09 Ngắt cứng IRQ1 Bàn phím 
0A Ngắt cứng IRQ2 Chuyển hướng sang IRQ9 
0B Ngắt cứng IRQ3 Cổng nối tiếp 2, 4 
0C Ngắt cứng IRQ4 Cổng nối tiếp 1, 3 
0D Ngắt cứng IRQ5 Card âm thanh 
0E Ngắt cứng IRQ6 Đĩa mềm 
0F Ngắt cứng IRQ7 Cổng song song 
10 ÷ 6F Ngắt mềm Ngắt do phần mềm 
70 Ngắt cứng IRQ8 Đồng hồ thời gian thực 
71 Ngắt cứng IRQ9 Chuyển hướng từ IRQ2 
72 Ngắt cứng IRQ10 Dự trữ 
73 Ngắt cứng IRQ11 Dự trữ 
74 Ngắt cứng IRQ12 Con chuột PS/2 
75 Ngắt cứng IRQ13 Đồng xử lý 
76 Ngắt cứng IRQ14 Đĩa cứng 
77 Ngắt cứng IRQ15 Dự trữ 
78 - FF Ngắt mềm Ngắt do phần mềm 
Bảng 4.2 Các thanh ghi của PIC 
Địa chỉ Đọc/Viết Chức năng 
Viết Từ điều khiển khởi động 1 ICW1 
Viết Từ điều khiển hoạt động 2 OCW2 
Viết Từ điều khiển hoạt động 3 OCW3 
Đọc Yêu cầu ngắt IRR 
20H 
Đọc Phục vụ ngắt ISR 
Viết Từ điều khiển khởi động 2 ICW2 
Viết Từ điều khiển khởi động 3 ICW3 
Viết Từ điều khiển khởi động 4 ICW4 
21H 
Đọc/Viết Mặt ra ngắt IMR 
Từ điều khiển hoạt động 1 OCW1 
 CHƯƠNG 4: LẬP TRÌNH CHO MÁY TÍNH ĐIỀU KHIỂN Trang 106 
PIC2: ngắt IRQ15, 14, 13, 12, 11, 10, 9, 8 có địa chỉ tương ứng là A0H 
và A1H 
 Muốn che một ngắt nào đó ta cho bit tương ứng của nó trong OCW1 
bằng 1. Ví dụ, muốn cho phép IRQ3 ta gởi byte F7 đến địa chỉ 21H lúc này 
các IRQ 0 ÷ 7 trừ IRQ3 sẽ bị cấm. 
 Muốn không ảnh hưởng đến các IRQ khác ta dùng lệnh: 
Outportb (OX21, (inportb (0X21) & OXF7)); (trong C) 
 Muốn che IRQ3 ta gởi lệnh: 
Outportb (OX21, (inportb (OX21) ⏐ OX08)); 
 Muốn sử dụng ngắt ta phải viết chương trình phục vụ ngắt ISR, đặt 
địa chỉ của chương trình này vào vị trí phù hợp trên bảng vector ngắt, trước 
đó cần phải cất địa chỉ đã có sẵn để sau đó phục hồi trở lại. Khi có ngắt 
xảy ra và ISR thực hiện xong phải báo trở lại cho PIC bằng cách gởi EOI 
(end of interrupt) đến OCW2, thông thường là byte 20H (cho ngắt thường). 
Việc khởi động PIC do ROM BIOS đảm nhiệm ta không cần quan tâm đến. 
 Ví du : Lập trình ngắt dùng C 
#include 
#include 
#include 
#include 
#include 
void main(void) 
{ 
 No_irq = 5; 
 init_isr(No_irq); 
 { /*Thêm mã*/ 
 } 
 close_isr(No_irq); 
} 
/* INIT INTERRUPT SERVICE ROUTINE */ 
void init_isr (int irq_num) 
{ 
 disable(); 
 if ( irq_num < 8 ) 
 old_handler1 = getvect(irq_num+8); 
Tác giả: TS Nguyễn Đức Thành Trang 107 
Thành phố Hồ Chí Minh, tháng 4 năm 2006 
 else 
 old_handler1 = getvect(irq_num-8+0x70); 
 if ( irq_num < 8 ) 
 setvect(irq_num+8, isr); 
 else 
 setvect(irq_num-8+0x70, isr); 
 if ( irq_num < 8 ) 
 { 
 int_mask = inportb(0x21) & ~(0x01<<irq_num); 
 outportb(0x21, int_mask); 
 } 
 else 
 { 
 int_mask = inportb(0xa1) & ~(0x01<<(irq_num-8)); 
 outportb(0xa1, int_mask); 
 } 
 enable( ); 
} 
/* CLOSE INTERRUPT SERVICE ROUTINE */ 
void close_isr(int irq_num) 
{ 
 int int_mask; 
 disable(); 
 if ( irq_num < 8 ) 
 { 
 int_mask = inportb(0x21) | (0x01<<irq_num); 
 outportb(0x21,int_mask); 
 setvect(irq_num+8,old_handler1); 
 } 
 else 
 { 
 int_mask = inportb(0xa0) | (0x01<<(irq_num-8)); 
 outportb(0xa1,int_mask); 
 setvect(irq_num-8+0x70,old_handler1); 
 } 
 enable(); 
} 
/* INTERRUPT SERVICE ROUTINE */ 
void interrupt isr(void) 
 CHƯƠNG 4: LẬP TRÌNH CHO MÁY TÍNH ĐIỀU KHIỂN Trang 108 
 { 
 disable(); 
 {/* thêm mã*/ 
 } 
 outportb(0x20,0x20); 
 if ( DDA_irq > 7 ) 
 { outportb(0xa0,0x20); } 
 enable(); 
} 
 Ví dụ: đếm số lần nút nhấn tác động dùng ngắt IRQ3 
 #include 
#include 
#include 
#include 
void interrupt (*oldIrq3)(void); 
void interrupt countToggle(void); 
int i = 0; 
long j = 0; 
#define IRQ3 0x0B /* IRQ3 address */ 
int main(void) 
{ 
 window(5,5,50,75); 
 clrscr(); 
 gotoxy(1,3); 
 cprintf("Do-while loop iteration # "); 
 oldIrq3 = getvect(IRQ3); /* lưu vectơ ngắt cũ */ 
 setvect(IRQ3, countToggle); /* cài vectơ ngắt mới */ 
 outportb(0x21, ( inportb(0x21) & 0xF7 ) ); /* cho phép IRQ3 */ 
Tác giả: TS Nguyễn Đức Thành Trang 109 
Thành phố Hồ Chí Minh, tháng 4 năm 2006 
 /*Vòng lặp, khi bấm phím thì thoát khỏi chương trình, khi nhấn nút thì vào ISR*/ 
 do { 
 j++; 
 gotoxy(27,3); cprintf("%ld\n", j); 
 } while(!kbhit()); 
 /* Có phím bấm, thoát khỏi chương trình chính */ 
 setvect(IRQ3, oldIrq3); 
 outportb(0x21, (inportb(0x21) | 0x08) ); /* cấm IRQ3 */ 
 /* Số lần bấm phím*/ 
 printf("\nswitch presses i = %d\n", i); 
 printf("j = %ld\n", j); 
 return 0; 
} /* end of main */ 
/* Chương trình phục vụ khi IRQ3 lên mức cao */ 
void interrupt countToggle(void) 
{ 
 disable(); 
 i++; 
 outportb(0x20, 0x20); /* send EOI signal */ 
 enable(); 
} 
Ví dụ: Chương trình đọc kết quả chuyển đổi cùa card ADC 8 bit, mỗi 
khi đổi xong vi mạch cho tín hiệu EOC tác động lên IRQ3, kết quả chuyển 
đổi lưu vào file văn bản 
#include 
#include 
#include 
#include 
#define IRQ3 0x0b /* IRQ3 */ 
#define BASEADDRESS 608 /*Địa chỉ gốc */ 
#define TRUE 1 
#define FALSE 0 
#define MAXSIZE 5000 /* Lấy 5000 mẫu */ 
/* globals */ 
int EOC; /* Đổi xong */ 
int readData; /* Kết quả đổi thập phân */ 
float i; /* Số lần lặp */ 
float data[MAXSIZE][2]; /* Mảng chứa các kết quả chuyển đổi */ 
FILE* fp; /*Con trỏ đến file ASCII */ 
int j; /* Biến đếm */ 
/* prototypes */ 
void interrupt (*oldIrq3)(void); 
void interrupt eocTrue(void); /* 
int main(void) 
{ 
 clrscr(); 
 fp = fopen("data.txt", "wt"); /* file chứa kết quả */ 
 /* khởi động mảng về 0.0 */ 
 CHƯƠNG 4: LẬP TRÌNH CHO MÁY TÍNH ĐIỀU KHIỂN Trang 110 
 for(j= 0; j < MAXSIZE; j++) { 
 data[j][0] = 0.0; 
 data[j][1] = 0.0; 
 }; 
 printf("data array initialized\n"); 
 i = 0.0; 
 oldIrq3 = getvect(IRQ3); 
 setvect(IRQ3, eocTrue); 
 outportb(0x21, ( inportb(0x21) & 0xF7 ) ); 
 EOC = FALSE; 
 do { 
 readData = inportb(BASEADDRESS); /*Kích đồi */ 
 while(EOC == FALSE) { /* Chờ EOC ON */ }; 
 readData = inportb(BASEADDRESS); /* Đọc kết quả*/ 
 EOC = FALSE; /* Xóa EOC */ 
 data[i][0] = i; 
 data[i][1] = (float)(readData * 5.0/255.0); /* Dổi ra volt */ 
 i++; 
 } while(i < MAXSIZE); 
 printf("Writing to file...\n"); 
 for(j=0; j < MAXSIZE; j++) { 
 fprintf(fp, "%f\t%f\n", data[j][0], data[j][1]); 
 }; 
 printf("done\n"); 
 fclose(fp); 
 setvect(IRQ3, oldIrq3); 
 outportb(0x21, (inportb(0x21) | 0x08) ); 
 printf("Bye!\n"); 
 return 0; 
} /* end of main */ 
/* Gọi ISR cho EOC ON mỗi khi IRQ3 múc cao*/ 
void interrupt eocTrue(void) 
{ 
 #pragma asm pushf; 
 #pragma asm cli; 
 EOC = TRUE; 
 outportb(0x20, 0x20); 
 #pragma asm popf; 
 return; 
 } /* end of eofTrue */ 
Ví dụ: lập trình ngắt trong Turbo Pascal 
unit ngat; 
 interface 
 uses dos,crt; 
 {$I+} 
 var 
 Interrupt9 : procedure ; 
Tác giả: TS Nguyễn Đức Thành Trang 111 
Thành phố Hồ Chí Minh, tháng 4 năm 2006 
 Procedure Int9; interrupt; 
 Procedure SetInt9; 
 Procedure ResetInt9; 
 IMPLEMENTATION 
 { Interrupt subroutine } 
Procedure Int9; 
begin 
 { call original interrupt } 
 Interrupt9; 
 {insert code here} 
end; 
Procedure SetInt9; 
 var R : registers; 
 begin 
 { save current IRQ9 } 
 getintvec($71,@Interrupt9); {$71: interrupt of IRQ9} 
 { load new IRQ9 } 
 setintvec($71,@ nt9); 
 end; 
Procedure ResetInt9; 
 var R : registers; 
 begin 
 { restore IRQ9 } 
 setintvec($71,@Interrupt9); 
 end; 
Begin 
End. 
Viết chương trình ngắt trong Windows tương đối khó, đòi hỏi 
trình độ lập trình cao, các bạn có thể đọc thêm trên mạng ở địa 
chỉ www.jungo.com 
Bài tập gợi ý 
1/Download chương trình windriver và nghiên cứu cách viết driver và 
ngắt cho card ISA, PCI 
2/ Viết chương trình Visual Basic đo và điều khiển nhiệt độ dùng card 
ISA có ADC0908 và 8255 
3/ Lặp lại câu 2 dùng Visual C và Delphi 

File đính kèm:

  • pdfGiáo trình Đo lường và điều khiển bằng máy tính - Chương 4 Lập trình cho máy tính điều khiển.pdf
Tài liệu liên quan