D0E0 POP AC C; Restore the Accumulatorand DPTR 005A 32 RET

Một phần của tài liệu Nghiên cứu về phần mềm Keil Software (Trang 37 - 44)

005A 32 RETI

; FUNCTION com_isr (END)

Các thanh ghi cho phép ngắt (Interrupt Enable Registers)

8051 cung cấp điều kiện ngắt cho nhiều chip ngoại vi. Quá trình ngắt hoàn toàn phụ thuộc vào bit EA của Interrupt Enable (IE) SFR. Khi bit EA lên mức 1 thì quá trình ngắt được thực hiện. Khi bit EA xuống mức 0 thì quá trình ngắt bị vô hiệu.

Mỗi quá trình ngắt thì được kiểm soát bởi than ghi IE SFR. Tên một số chip 8051 có thể có hơn 1 thanh ghi IE. Kiểm tra tài liệu về chip đó để tận dụng các quá trình ngắt.

Các port song song vào/ra (Parallel Port I/O)

Một chip 8051 bình thường có 4 port vào ra song song mà bạn có thể kết nối với các thiết bị ngoại vi. Chúng là Port 0, Port 1, Port 2, Port 3. Một số IC 8051 mở rông có tới 8 Port xuất nhập.

Port Direction Width Alternate use

P0 I/O 8 bits Mux'd. 8-bit bus: A0-A7 & D0-D7 P1 I/O 8 bits P1.0-P1.7: Available for user I/O P2 I/O 8 bits Mux'd. 8-bit bus: A8-A15

P3 I/O 8 bits P3.0: RXD (Serial Port Receive) P3.1: TXD (Serial Port Transmit) P3.2: /INT0 (Interrupt 0 input) P3.3: /INT1 (Interrupt 1 input) P3.4: T0 (Timer/Counter 0 Input) P3.5: T1 (Timer/Counter 1 Input) P3.6: /WR (Write Data Control) P3.7: /RD (Read Data Control)

Các Port trên IC 8051 bình thường thì không có các dữ liệu trên thanh ghi điều khiển. Thay vào đó, các chân của Port 1, Port 2, Port 3 mỗi chân có thể tăng lên mà chúng có thể là đầu nhập hay đầu xuất. Để ghi giá trị vào một Port bạn chỉ đơn giản ghi giá trị tùng chân của Port đó. Để lấy giá trị từ Port trước hết giá trị của chân phải được ghi là 1 ( đây cũng là giá trị ban đầu sau khi RESET ).

Ví dụ sau là chương trình ghi và xuất giá trị các Port I/O:

sfr P1 = 0x90; // SFR definition for Port 1 sfr P3 = 0xB0; // SFR definition for Port 3

sbit DIPswitch = P1^4; // DIP switch input on Port 1 bit 4 sbit greenLED = P1^5; // green LED output on Port 1 bit 5

void main (void) { unsigned char inval;

inval = 0; // initial value for inval while (1) {

if (DIPswitch == 1) { // check if input P1.4 is high inval = P1 & 0x0F; // read bit 0 .. 3 from P1 greenLED = 0; // set output P1.5 to low

}

else { // if input P1.4 is low greenLED = 1; // set output P1.5 to high }

P3 = (P3 & 0xF0) | inval; // output inval to P3.0 .. P3.3 }

}

IC 80C52 có ba bộ Timer/Counter (Timer 0, Timer 1, và Timer 2). Timer 1 và Timer 0 có các chức năng thông thường như nhau trong khi Timer 2 có khả năng ứng dụng cao hơn. Các timer có thể hoạt động độc lập với nhau với các kiểu định thời, kiểu đếm, kiểu phát tốc độ baud (cho các Port tuần tự).

Chương trình sau là một ví dụ dùng Timer 1 tạo một xung vuông có tần số 10KHz.

#include <reg52.h> /*

* Timer 1 Interrupt Service Routine: executes every 100 clock cycles */

static unsigned long overflow_count = 0; void timer1_ISR (void) interrupt 3 {

overflow_count++; // Increment the overflow count }

/*

* MAIN C function: sets Timer1 for 8-bit timer w/reload (mode 2). * The timer counts to 255, overflows, is reloaded with 156, and * generates an interrupt.

*/

void main (void) {

TMOD = (TMOD & 0x0F) | 0x20; // Set Mode (8-bit timer with reload)

TH1 = 256 - 100; // Reload TL1 to count 100 clocks TL1 = TH1;

ET1 = 1; // Enable Timer 1 Interrupts TR1 = 1; // Start Timer 1 Running EA = 1; // Global Interrupt Enable while (1); // Do Nothing (endless-loop): the timer 1 ISR will

// occur every 100 clocks. Since the 80C51 CPU runs

// at 12 MHz, the interrupt happens 10 KHz.

}

Bộ biến đổi tương tự – số

Các bộ biến đổi tương tự số A/D là các linh kiện chỉ có trên một số thành viên của họ 8051 nhưng khá phổ biến. Các bộ biến đổi A/D thường được điều khiển thông qua thanh ghi chủ ADCON, thanh ghi này được gán cho một vị trí còn trống nào đó trong đoạn nhớ dành cho các SFR, thanh chi ADCON cho phép người sử dụng chọn lựa kênh cần được biến đổi A/D, bặ đầu một biến đổi mới và kiểm tra trạng thái của lần biến đổi hiện tại.

Các bộ biến đổi A/D điển hình cần 40 chu kỳ lệnh hoặc ít hơn để hoàn tất việc biến đổi và chúng được cấu hình để tạo ra ngắt vào lúc hoàn tất việc biến đổi, việc này làm cho bộ vi điều khiển định hướng đến một vector ngắt cụ thể dành cho việc biến đổi A/D. thông thường khuyết điểm của bộ biến đổi A/D là bộ này yêu cầu bộ vi điều khiển phải ở mức tính cực thay vì đi vào nghỉ để chờ ngắt do việc biến đổi hoàn tất. Kết quả của việc biến đổi được đọc từ một SFR khác hoặc một cặp SFR, phụ thuộc vào độ phân giãi của bộ biến đổi.

Chương trình sau là ví dụ chuyển đổi tương tự từ tín hiệu ngõ vào sang số:

#include <ADUC812.H> #include <stdio.h> void main (void) {

unsigned char chan_2_convert;

SCON = 0x50; // Configure the serial port. TMOD |= 0x20;

TH1 = 0xA0; TR1 = 1; TI = 1;

// Configure A/D to sequentially convert each input channel.

ADCCON1 = 0x7C; // 0111 1100 while (1) {

unsigned int conv_val; unsigned char channel;

// Start a conversion and wait for it to complete. chan_2_convert = (chan_2_convert + 1) % 8;

ADCCON2 = (ADCCON2 & 0xF0) | chan_2_convert; SCONV = 1;

while (ADCCON3 & 0x80);

// Read A/D data and print it out. channel = ADCDATAH >> 4;

conv_val = ADCDATAL | ((ADCDATAH & 0x0F) << 8);

printf ("ADC Channel %bu = 0x%4.4X\r\n", channel, conv_val); }

}

Bộ biến đổi số sang tương tự ( D/A coverter)

Bộ biến đổi nàychuye63n đổi tían hiệu số đi vào thành tín hiệu dòng điện ở ngõ ra. IC Philips 87LPC769 là một trong các IC có tích hợp bộ chuyển đổi số – tương tự. IC Philips 87LPC769 gồm 2 kênh, và bộ chuyển đổi 8bit D/A dễ dàng

thực hiện với chương trình. Ví dụ sau cho ta thấy cách dùng bộ chuyển đổi sử dụng D/A SFRs.

/*

* This program generates sawtooth waveforms on the DAC * of the Philips 87LPC769.

*/

#include <REG769.H> void main (void) {

// Disable the A/D Converter (this is required for DAC0)

ADCI = 0; // Clear A/D conversion complete flag ADCS = 0; // Clear A/D conversion start flag ENADC = 0; // Disable the A/D Converter

// Set P1.6 and P1.7 to Input Only (Hi Z). P1M2 &= ~0xC0;

P1M1 |= 0xC0;

ENDAC0 = 1; // Enable the D/A Converters ENDAC1 = 1;

while (1) {

unsigned int i;

// Create a sawtooth wave on DAC0 and the // opposite sawtooth wave on DAC1.

for (i = 0; i < 0x100; i++) { DAC0 = i; DAC1 = 0xFF - i; } } }

Điều khiển cấp điện (Power Reduction Modes)

Chế độ nghỉ (Idle mode) được kích hoạt bằng cách thiết lập bit IDLE bằng 1. chế độ nghỉ làm dừng mọi việc thực thi chương trình. Các nội dung trên RAM được bảo toàn và mạch dao động tiếp tục hoạt động nhưng xung clock bị khó không đến được CPU. Các bộ định thời và UART tiếp tục thực hiện bìn thường các chức năng của chúng.

Chế độ nghỉ được kết thúc bằng cách kích hoạt một điểm ngắt bất kỳ. Khi việc thực thile65nh ngắt ISR kết thúc thì hệ thống sẽ làm việc lại từ lênh set bit IDLE lên 1.

Sau đây là chương trình thực hiện chế độ nghỉ:

sfr PCON = 0x87; void main (void) { while (1) { task_a (); task_b (); task_c ();

PCON |= 0x01; /* Enter IDLE Mode - Wait for enabled interrupt */ }

}

Chế độ giảm cấp điện ( power down mode) được thiết lập bằng cách set bit PDWN lên 1. trong chế độ nàyma5ch dao động trong chip bị dừng. Như vậy các bộ định thời và UART cũng như việc thực hiện phần mềm đều tạm ngưng. Miễn là có điện áp tối thiểu 2V đặt vào chip thì các nội dung lưu trên RAM vẫn được bảo toàn.

Cách duy nhất để buộc bộ vi điều khiển ra khỏi chế độ giảm công suất là áp đặt thiết lập lại (RESET) bộ vi điều khiển này khi cấp điện.

Sau đây là chương trình thự hiện quá trình giãm cấp điện:

sfr PCON = 0x87; void main (void) { while (1) { task_a (); task_b (); task_c ();

PCON |= 0x02; /* Enter Power Down Mode */ }

}

Bộ định thời WATCHDOG

Bộ định thời Watchdog có sẵn trên nhóm mở rộng của các thành viên họ 8051. mục đích của bộ định thời Watchdog là thiết lập lại (reset) lại bộ vi điều khiển nếu bộ định thời không được cung cấp một trình tự thao tác cụ thể trong một

khoảng thời gian xác định. Điều này ngăn ngừa việc nạp lại Wachdog mọt cách trùng khớp ngẫu nhiên bởi các phần mềm khác.

Trong họ 8051, watchdog thường được thực hiện dưới dạng một bộ định thời khác trên chip, bộ định thời này lập tỉ lệ giảm tần số mạch dao động hệ thống và kế đến đếm xung clock đã được chia tỉ lệ. Khi bộ định thời quay vòng, hệ thống thiết lập lại từ đầu (reset). Watchdog có thể được cấu hình đối với tốc độ quay vòng và thường có thể được sử dụng làm bộ định thời khác mặc dù đây là bộ định thời có độ phân giải thấp.

Chương trình sau đây cho thấy cách thiết lập giá trị ban đầu và reset watchdog:

#include <reg51f.h>

/* This function adjusts the watchdog timer compare value to the current * PCA timer value + 0xFF00. Note that you must write to CCAP4L first, * then write to CCAP4H. */

void watchdog_reset (void) { unsigned char newval; newval = CH + 0xFF; CCAP4L = 0;

CCAP4H = newval; }

void main (void) { unsigned int i;

/* Configure PCA Module 4 as the watchdog and make sure it doesn't time-out immediately. */

watchdog_reset (); CCAPM4 = 0x48;

/* Configure the PCA for watchdog timer. */ CMOD = (CMOD & 0x01) | 0x40;

/* Start the PCA Timer: From this point on, we must reset the watchdog timer every 0xFF00 clock cycles. If we don't, the watchdog timer will reset the MCU. */

CR = 1;

/* Do something for a while and make sure that we don't get reset by the watchdog. */

for (i = 0; i < 1000; i++) { watchdog_reset ();

}

/* Stop updating the watchdog and we should get reset. */ while (1);

Một phần của tài liệu Nghiên cứu về phần mềm Keil Software (Trang 37 - 44)