Chatbox

Các bạn vui lòng dùng từ ngữ lịch sự và có văn hóa,sử dụng Tiếng Việt có dấu chuẩn. Chúc các bạn vui vẻ!
06/10/2011 23:10 # 1
nghien_rbc
Cấp độ: 6 - Kỹ năng: 5

Kinh nghiệm: 4/60 (7%)
Kĩ năng: 0/50 (0%)
Ngày gia nhập: 16/03/2010
Bài gởi: 154
Được cảm ơn: 100
Phản hồi: [Lập trình robocon] Căn bản


Trích:
 Anh nghien_rbc oi có thể nói rõ hơn cho em phần lập trình ngắt không ạ . 
thank anh .

Tài liệu về lập trình ngắt nhiều lắm, bạn có thể nói rõ bạn đang khúc mắc phần nào ở trong mắc và trong một bài toán cụ thể nào thì mới dễ giải quyết vấn đề hơn!
Dưới đây mình sưu tầm được một tài liệu hay về ngắt nếu bạn chưa đọc qua thì có thể tham khảo
1.         Mở đầu 
Ngắt (interrupt) là sự xảy ra của một điều kiện – một sự kiện – làm cho chương trình hiện hành bị tạm ngưng trong khi điều kiện được phục vụ bởi một chương trình khác. Các ngắt đóng vai trò quan trọng trong việc thiết kế và hiện  thực các ứng dụng của bộ vi điều khiển. Các ngắt cho phép hệ thống đáp ứng một sự kiện theo cách không đồng bộ và xử lý sự kiện trong khi một chương trình khác đang thực thi. Một hệ thống được điền khiển bởi ngắt cho ta ảo tưởng đang làm nhiều công việc đồng thời.
CPU dĩ nhiên không thể thực thi nhiều hơn một lệnh ở một thởi điểm nhưng CPU có thể ngưng tạm thời việc thực thi một chương trình để thực thi một chương trình khác rồi sau đó quay trở về thực thi tiếp chương trình đang bị tạm ngưng, đièu này giống như CPU rời khỏi chương trình gọi để thực thi chương trình con bị gọi để rồi sau đó quay trở về chương trình gọi. Sự khác nhau của hai vấn đề vừa nêu là trong một hệ thống được điều khiển bởi ngắt, việc ngắt nhằm đáp ứng một sự kiện này xuất hiện không đồng bộ với chương trình chính đang được thực thi và chương trình chính (hay nói cách khác là CPU) không biết trước là sẽ bị ngắt khi nào.
Chương trình xử lý một ngắt được gọi là trình phục vụ ngắt ISR (interrupt service routine) hay quản lý ngắt (interrupt handler). ISR được thực thi nhằm đáp ứng một ngắt và trong trường hợp tổng quát thực hiện việc xuất nhập đối với một thiết bị. Khi một ngắt xuất hiện, việc thực thi chương trình chính tạm thời bị dừng vì CPU thực hiện việc rẽ nhánh đến trình phục vụ ngắt ISR. CPU thực thi ISR để thực hiện một công việc và kết thúc việc thực thi này khi gặp lệnh “quay về từ một trình phục vụ ngắt”; chương trình chính được tiếp tục tại nơi bị tạm dừng. Ta có thể nói chương trình chính được thực thi ở mức nền (base level) còn ISR được thực thi ở mức ngắt (interrupt level).

 

Hai hình minh họa đơn giản cho interrupt:

 

a)      Chương trình thực thi khi không có ngắt

b)            Chương trình thực thi khi có ngắt

 

Một thí dụ về ngắt điển hình là nhập bằng tay sử dụng bàn phím. Ta thử khảo sát một ứng dụng của lò viba. Chương trình chính có thể điều khiển thành phần công suất của lò để thực hiện việc nấu nướng; tuy nhiên trong khi đang nấu, hệ thống phải đáp ứng việc nhập bằng tay trên cửa lò chẳng hạn như một yêu cầu rút ngắn bớt hay kéo dài thời gian nấu. Khi người sử dụng buông phím nhấn, một ngắt được tạo ra (chẳng hạn một tín hiệu từ mức cao chuyển xuống mức thấp) và chương trình chính bị ngắt. ISR được thực thi để đọc mã phím và thay đổi các điều kiện nấu nướng tương ứng, sau đó kết thúc bằng cách chuyển điền khiển trở về chương trình chính.

Chương trình chính được thực thi tiếp từ nơi tạm dừng. Điều quan trọng trong thí dụ trên là việc nhập bằng tay xuất hiện không đồng bộ nghĩa là xuất hiện ở các khoảng thời gian không báo trước hoặc được điều khiển bởi phần mềm đang được thực thi trong hệ thống. Đấy là một ngắt.

HOẠT ĐỘNG NGẮT. 2. Tổ Chức Ngắt Của 8051. 

2.  . Tổ chức ngắt của 8051

 

Có 5 nguyên nhân tạo ra ngắt (gọi tắt là nguyên nhân ngắt) đối với 8051: hai ngắt do bên ngoài, hai ngắt do bộ định thời và một ngắt do port nối tiếp. Song cũng có nhiều tài liệu kỹ thuật nói rằng có 6 ngắt, nguyên nhân là do họ tính cả lệnh RESET, khi ta thiết lập trạng thái ban đầu cho hệ thống (gọi tắt là reset hệ thống), tất cả các ngắt đều bị vô hiệu hóa (cấm) và sau đó chúng được cho phép riêng rẽ bằng phần mềm.

 

Khi xảy ra hai hay nhiều ngắt đồng thời hoặc xảy ra một ngắt trong khi một ngắt khác đang được phục vụ, ta có 2 sơ đồ xử lý các ngắt: sơ đồ chỗi vòng và sơ đồ hai mức ưu tiên. Sơ đồ chuổi vòng là sơ đồ cố định, còn sơ đồ ưu tiên ngắt được lập trình bởi người sử dụng.

 

 

 

Ta sẽ khảo sát cách thức cho phép và không cho phép ngắt sau đây.

 

2.1      Cho phép và không cho phép ngắt

Khi Reset thì tất cả mọi ngắt đều bị cấm (bị che), có nghĩa là không có ngắt nào được bộ vi điều khiển đáp ứng nếu chúng được kích hoạt. Các ngắt phải được cho phép bằng phần mềm để bộ vi điều khiển có thể đáp ứng được. Có một thanh ghi được gọi là cho phép ngắt (Interrupt Enable) chịu trách nhiệm về việc cho phép (không che) và cấm (che) các ngắt.

 

 

 

IE Register (Interrupt Enable)

 

EA – bit enable hoặc disable tất cả các interrupt.

                  EA=0 thì không ngắt nào được nhận.

                  EA=1 thì từng nguồn ngắt sẽ được mở hoặc cấm bằng cách bật hoặc xóa bit cho phép tương ứng.

ES – bit enable hoặc disable ngắt cổng nối tiếp.

                  ES=0 thì không cho phép ngắt nối tiếp.

                  ES=1 cho phép ngắt nối tiếp.

ET1 – bit enable hoặc disable ngắt tràn của của Timer1.

                  ET1=0 Timer1 không ảnh hưởng đến ngắt.

                  ET1=1 Timer1 kích hoạt ngắt.

EXT1 – cho phép hoặc cấm ngắt ngoài của Timer1.

                  EXT1=0 thì sự thay đổi trạng thái của cổng INT0 không ảnh hưởng đến việc ngắt.

                  EXT1=1 enable ngắt ngoại ngay tại thời điểm INT0 thay đổi trạng thái.

ET0 – bit enable hoặc disable ngắt tràn của Timer0.

                  ET0=0 Timer0 không ảnh hưởng đến ngắt.

                  ET0=1 Timer0 kích hoạt ngắt.

EX0 – bit enable hoặc disable ngắt ngòai của Timer0.

                  EX0=0 thì sự thay đổi trạng thái của INT1 không ảnh hưởng đến việc ngắt.

                                EX0=1 enable ngắt ngoại ngay tại thời điểm INT1 thay đổi trạng thái.

 

 

2.2      Các bước thực hiện khi cho phép một ngắt

Để cho phép một ngắt, trình tự thực hiện các bước sau:

1.  Bit7 của thanh ghi IE là EA phải bật lên cao cho phép các bit còn lại của thanh ghi có hiệu lực

2.      Nếu EA=1 thì tất cả mọi ngắt đều được phép và sẽ được đáp ứng nếu các bit tương ứng của ngắt này trong IE có mức cao. Nếu IE=0 thì không có ngắt nào được đáp ứng, cho dù bit tương ứng trong IE có giá trị cao.

Ví dụ:

a.      Lệnh cho phép ngắt nối tiếp, ngắt Timer0 và ngắt phần cứng ngòai 1 (EXT1)

MOV IE,#100101110B ;

 Vì IE là thanh ghi định đỉa chỉ bit, nên có thể sử dụng các lệnh sau đây để truy cập đến các bit riêng rẽ của thanh ghi:

 SETB   IE.7                ;EA=7 cho phep moi ngat

 SETB   IE.4                ; cho phep ngat noi tiep

SETB   IE.1                ; cho phep ngat timer 1

SETB   IE.2                ; cho phep ngat phan cung ngoai

Tất cả các lệnh này tương đượng với lệnh “MOV IE,#10010110B” trên.

 b.      Lệnh cấm (che) ngắt Timer0:        CLR        IE.1

 

2.3      Ưu tiên ngắt

 

Mỗi một nguyên nhân ngắt được lập trình riêng để có một trong hai mức ưu tiên thông qua thanh ghi chức năng đặc biệt được định địa chỉ bit, thanh ghi ưu tiên ngắt IP (interrupt priority), thanh ghi này có địa chỉ byte là 0B8H như mô tả dưới đây.

 

IP Register (Interrupt Priority) – 0: mức thấp, 1: mức cao.

 

 

 

PS   – ưu tiên cho ngắt port nối tiếp.

PT1 – ưu tiên cho ngắt bộ định thời 1. 

PX1 – ưu tiên cho ngắt ngòai 1. 

PT0 – ưu tiên cho ngắt do bộ định thời 0.

PX0 – ưu tiên cho ngắt ngoài  0.

 Khi hệ thống được thiết lập lại trạng thái ban đầu, thanh ghi IP sẽ mặc định đặt tất cả các ngắt ở mức ưu tiên thấp. Ý tưởng “các mức ưu tiên” cho phép một trình phục vụ ngắt được tạm thời dừng bỏi một ngắt khác nếu ngắt mới này có mức ưu tiên cao hơn mức ưu tiên của ngắt hiện đang được phục vụ. Điều này hoàn toàn hợp lý đối với 8051 vì ta chỉ có 2 mức ưu tiên. Nếu có ngắt với mức ưu tiên cao xuất hiện,  trình phục vụ ngắt cho ngắt có mức ưu tiên thấp phải tạm dừng (nghĩa là bị ngắt). Ta không thể tạm dừng một chương trình phục vụ ngắt có mức ưu tiên  cao.

 Chương trình chính do được thực thi ở mức nền và không được kết hợp với một ngắt nào nên luôn luôn bị ngắt cho dù các ngắt này có mức ưu tiên thấp hay cao. Nếu có 2 ngắt với mức ưu tiên ngắt khác nhau xuất hiện đồng thời, ngắt có ưu tiên cao sẽ được phục vụ trước.

Nếu có 2 ngắt có cùng mức ưu tiên xuất hiện đồng thời, chuỗi vòng cố định sẽ xác định ngắt nào được phục vụ trước. Chuỗi vòng này sẽ là: ngắt ngoài 0, ngắt do bộ định thời 0, ngắt ngoài 1, ngắt do bộ định thời 1, ngắt do port nối tiếp, ngắt do bộ định thời 2.

  

2.4      Xử lý ngắt

Khi có một ngắt chương trình xuất hiện và được CPU chấp nhận, chương trình chính bị ngắt. Các thao tác sau đây xảy ra:

-         Hoàn tất việc thực thi lệnh hiện hành.

-         Bộ đếm chươn trình PC được cất vào stack.

-         Trạng thái của ngắt hiện hành được lưu giữ lại.

-         Các ngắt được chận lại ở mức ngắt.

-         Bộ đếm chương trình PC được nạp địa chỉ vector của trình phục vụ ngắt ISR.

-         ISR được thực thi.

ISR được thực thi để đáp ứng công việc của ngắt. Việc thực thi ISR kết thúc khi gặp lệnh RET1 (trở về từ một trình phục vụ ngắt). Lệnh này lấy lại giá trị cũ của bộ đếm chương trình PC từ stack và phục hồi trạng thái của ngắt cũ. Việc thực thi chương trình chính được tiếp tục ở nơi bị tạm ngưng.

 

 

2.5      Vecto ngắt

 

 

 

Khi một ngắt được chấp nhận, giá trị được nạp cho bộ đếm chương trình được gọi là vector ngắt. Vector ngắt là địa chỉ bắt đầu của trình phục vụ ngắt của nguyên nhân ngắt tương ứng. Các vector ngắt được cho ở bảng  sau.

 

Ngắt do

 

 

 

 

 

Cờ

 

 

 

 

 

Địa chỉ vector

 

 

 

 

 

Reset hệ thống

 

 

 

 

 

RST

 

 

 

 

 

0000H

 

 

 

 

 

Ngắt ngoài 0

 

 

 

 

 

IE0

 

 

 

 

 

0003H

 

 

 

 

 

Bộ định thời 0

 

 

 

 

 

TF0

 

 

 

 

 

000BH

 

 

 

 

 

Ngắt ngoài 1

 

 

 

 

 

IE1

 

 

 

 

 

0013H

 

 

 

 

 

Bộ định thời 1

 

 

 

 

 

TF1

 

 

 

 

 

001BH

 

 

 

 

 

Port nối tiếp

 

 

 

 

 

RI hoặc T1

 

 

 

 

 

0023H

 

 

 

 

 

Bộ định thời 2

 

 

 

 

 

TF2 hoặc EXF2

 

 

 

 

 

002BH

 

 

 

 

 

 

Vecto reset hệ thống (RST ở địa chỉ 0000H) được chứa trong bảng này vì vậy cũng được xem như là 1 ngắt: chương trình chính bị ngắt và bộ đếm chương trình PC được nạp giá trị mới.

 Khi một trình phục vụ ngắt được trỏ tới, cờ gây ra ngắt sẽ tự động bị xóa về 0 bởi phần cứng. Các ngoại lệ bao gồm các cờ RI và TI đối với các ngắt do port nối tiếp; TF2 và EXF2 đối với các ngắt do bộ định thời 2. Các nguyên nhân ngắt thuộc 2 ngoại lệ vừa nêu trên do có 2 khả năng tạo ra ngắt nên trong thực tế CPU không xóa cờ ngắt.

 

Còn một số phần nửa xem thêm ở nguồn trích dẫn: http://bkit4u.com/?topic=page&id=37
Mình giới thiệu thêm bạn một trang tuyệt vời để học về lập trình ngắt với họ 8051 và tất cả các vấn đề liên quan.
http://www.dientuvietnam.net/forums/vi-dieu-khien-ho-8051-53/huong-dan-lap-trinh-keil-c-cho-8051-chi-danh-post-bai-huong-dan-1163/index2.html


 

 


Được chỉnh sửa bởi nghien_rbc vì:lỗi nặng
Các thành viên đã Thank nghien_rbc vì Bài viết có ích:
07/10/2011 09:10 # 2
phamquyenanh.qb
Cấp độ: 2 - Kỹ năng: 1

Kinh nghiệm: 4/20 (20%)
Kĩ năng: 2/10 (20%)
Ngày gia nhập: 20/09/2010
Bài gởi: 14
Được cảm ơn: 2
Phản hồi: [Lập trình robocon] Căn bản


Anh có thể nói rõ cho em phần "Chương trình sử dụng ngắt ngoài để đếm số lổ encoder"  không ạ .
Dạ em cảm ơn 

   



 
07/10/2011 23:10 # 3
nghien_rbc
Cấp độ: 6 - Kỹ năng: 5

Kinh nghiệm: 4/60 (7%)
Kĩ năng: 0/50 (0%)
Ngày gia nhập: 16/03/2010
Bài gởi: 154
Được cảm ơn: 100
Phản hồi: [Lập trình robocon] Căn bản


Trích:
Anh có thể nói rõ cho em phần "Chương trình sử dụng ngắt ngoài để đếm số lổ encoder"  không ạ .
Dạ em cảm ơn 

   
Phần lập trình cho encoder mình có đề cập ở topic này http://forum.duytan.edu.vn/sites/index.aspx?p=forum_thread&forum=517&thread=15147#p0 

Mình post lại ở đây và edit lại code cho đơn giản hơn. Nếu còn khúc mắc về cách giải thích thì hãy để lại comment :d

THUẬT TOÁN ĐO QUẢNG ĐƯỜNG BẰNG ENCODER.

Encoder là gì:

Encoder là thiết bị thường được sử dụng để đo và tính các khoảng cách dựa trên việc đếm số lổ trên encoder.

Có nhiều loại encoder nhưng chúng chỉ khác nhau về số lỗ. Có loại chỉ có 50 lỗ, 100 lỗ nhưng có loại lên đến vài ngàn lỗ.

Cấu tạo:

Encoder thường gồm một tấm tròn được khoét các lỗ cách đều nhau. Encoder 100 lỗ tức là trên tấm đĩa tròn có 100 lỗ. tấm đĩa đó được giử ở trong thân encoder và được nối với trục quay của encoder. Một bên tấm đĩa gắn một con LED phát sáng, bên còn lại gắn một con cảm biến ánh sáng (tương tự như là cảm biến dò đường vậy). Con led phát sáng và con cảm biến ánh sáng nằm cố định khi encoder quay.

Nguyên lý hoạt động của encoder dùng để đếm số lỗ có thể hiểu đơn giản như sau:

-         Khi trục encoder quay, tấm đĩa gắn với trục quay nên cùng quay với trục quay.

-         Con led phát sáng liên tục khi cấp nguồn và chiếu vào tấm đĩa, phía bên kia cứ mỗi lần ánh sáng từ con led chiếu qua 1 lỗ của tấm đĩa thì con cảm biến ánh sáng thu nhận được và xác định tương ứng 1 lỗ. Như vậy nếu trục encoder quay đúng 1 vòng thì tương ứng con cảm biến ánh sáng cũng phát hiện ra đúng số lỗ của encoder đó.

Ví dụ:

Muốn đo quảng đường 1 mét bằng cách sử dụng encoder 100 lỗ và trục của encoder được gắn vào trục quay của bánh xe ta thực hiện như sau:

-         Xác định chu vi của bánh xe (chẳng hạn là 25 cm)

-         Cứ 1 vòng quay của encoder thì bánh xe quay được một vòng, tức là:

Cứ 100 lỗ robot-> chạy được 25 cm

? lỗ                   -> chạy được 100 cm

Vậy ta có số lỗ cần thiết của encoder để robot chạy được 1m bằng 100*100/25=400(lỗ)

Thuật toán sử dụng encoder.

 

 

Chương trình sử dụng ngắt ngoài để đếm số lổ encoder:

 

void EX0_int0(void) interrupt 0  // EX0_int0 là tên hàm ngắt, interrupt 0 tức là hàm thực hiện ngắt ngoài 0 tương ứng với bảng                                                            // vector ngắt.

{

if(encoder==0) //encoder là biến lưu số lỗ encoder nạp vào trước khi cho phép ngắt này hoạt động

            EX0=0;      // nếu đã đếm hết số lỗ thì dừng hoạt động của ngắt     

      else

         encoder=encoder-1; // ngược lại nếu số lỗ cần đếm vẫn còn thì giảm xuống một đơn vị.

}

Như vậy ngắt ngoài 0 sẽ disable khi số lỗ encoder được nạp ban đầu đếm giảm về giá trị 0.

Lưu ý là hàm ngắt trên chỉ được cho phép tại thời điểm ta enable biến cho phép ngắt toàn cục EA = 1; và cho phép ngắt ngoài 0: EX0 = 1;(Xem thêm phía trên) 



 

 


 
08/10/2011 20:10 # 4
phamquyenanh.qb
Cấp độ: 2 - Kỹ năng: 1

Kinh nghiệm: 4/20 (20%)
Kĩ năng: 2/10 (20%)
Ngày gia nhập: 20/09/2010
Bài gởi: 14
Được cảm ơn: 2
Phản hồi: [Lập trình robocon] Căn bản


 // khai bao Header 
#include<reg52.h>
#include<stdio.h>

#define m 2 
sbit start = P1^4; 
sbit Led1 = P1^0; 
sbit Led2 = P1^1;
sbit Led3 = P1^2;
sbit Led4 = P1^3;
sbit note = P3^6;

unsigned char M[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x9 0}; 
unsigned long int result;
unsigned char thousand,hundred,tens,unit; 


void delay_ms(unsigned int time)
{
unsigned int i;
unsigned int j;
for(i = time;i>0;i--)
for(j=0;j<300;j++);
}

void clear_led(void)
{
P1=0xff;
P2=0xff;
}

void Display(void)
{

thousand = result/1000;

if (thousand == 0) 
clear_led();
else 
{ Led4 = 0; Led3 = 1; Led2=1; Led1 = 1;
P2=M[thousand];
delay_ms(m);
clear_led();
}

hundred =(result%1000)/100;

if ((thousand == 0)&&(hundred == 0)) 
clear_led();
else 
{ Led4 = 1; Led3 = 0; Led2=1; Led1 = 1;
P2=M[hundred];
delay_ms(m);
clear_led();
}

tens = ((result%1000)%100)/10;

if ((thousand == 0)&&(hundred == 0)&&(tens == 0)) 
clear_led();
else
{ Led4 = 1; Led3 = 1; Led2=0; Led1 = 1;
P2=M[tens];
delay_ms(m);
clear_led();
}

unit = ((result%1000)%100)%10;
Led4 = 1; Led3 = 1; Led2=1; Led1 = 0;
P2=M[unit]; 
delay_ms(m);
clear_led();
}


void init(void) 
{
TMOD=0x01; 
IE=0x86; 
IP=0x04;
TH0=-5000/256; // Tre 1s
TL0=-5000%256;
result = 0; 
clear_led(); // Xoa LED 
IT1=1; 
TF0=1; 
TR0=1; 
}

void Outdata(void) interrupt 1
{
TR0=0;
Display();
TH0=-5000/256;
TL0=-5000%256;
TR0=1;
}

void Count(void) interrupt 2 
{

EA=0; 
result++;
if(result >= 9999)
{note=1; 
result=0;}
delay_ms(10);
EA=1;
}

void main(void)
{
EA = 0; 
init();
delay_ms(100);
while(start); 
EA = 1; 
result = 0; 
while(1)
{
}
}


ANH CÓ THỂ CHỈ CHO EM TỪNG CÂU LỆNH TRONG PHẦN CHỮ ĐỎ LÀM GÌ KHÔNG Ạ . 



///////////////////////////////////////////////////////



 
08/10/2011 23:10 # 5
nghien_rbc
Cấp độ: 6 - Kỹ năng: 5

Kinh nghiệm: 4/60 (7%)
Kĩ năng: 0/50 (0%)
Ngày gia nhập: 16/03/2010
Bài gởi: 154
Được cảm ơn: 100
[Lập trình robocon] Căn bản


 Có vẻ như bạn đang làm bài hiển thị đèn chạy từ 0 – 9999?

Chử màu xanh là các dòng lệnh của bạn, chử màu đen là tài liệu tham khảo, còn chử màu đỏ là giải thích nông cạn của minh :d 

void init(void) 
{
TMOD=0x01;
IE=0x86; 
IP=0x04;
TH0=-5000/256; // Tre 1s
TL0=-5000%256;
result = 0;           
clear_led(); // Xoa LED 
IT1=1; 
TF0=1; 
TR0=1; 
}

 

TMOD = 0x01;

<img src='http://nd9.upanh.com/b5.s7.d3/045b249df6786a1d70805dc2a266f92e_36268069.anh1.bmp' border='0' alt='%name' />

TMOD = 0x01; // TMOD = 0000.0001

So sánh với sơ đồ bit của thanh ghi TMOD ở trên ta thấy giá trị nạp vào 0x01 ngiã là chọn Timer 0 hoạt động ở chế độ Timer/Counter 16bit

Ở đây THx = TH0 và TLx = TL0

IE=0x86;

Thanh ghi IE (Interrupt Enable Register)

Thanh ghi IE dùng để cho phép hay cấm các ngắt hoạt động. Mặc định khi

khởi động chương trình thì tất cả các ngắt đều bị cấm. Chức năng các bit trong

thanh ghi IE cho trong bảng sau:

 

EA  = 0: cấm tất cả các ngắt

  = 1: cho phép ngắt tuỳ theo trạng thái các bit điều khiển tương ứng

ES  = 0: cấm ngắt tại port nối tiếp

  = 1: cho phép ngắt tại port nối tiếp

ET1  = 0: cấm ngắt tại Timer 1

  = 1: cho phép ngắt tại Timer 1

EX1  = 0: cấm ngắt tại ngắt ngoài 1 ( INT1: chân P3.3)

  = 1: cho phép ngắt tại ngắt ngoài 1

ET0  = 0: cấm ngắt tại Timer 0

  = 1: cho phép ngắt tại Timer 0

EX0  = 0: cấm ngắt tại ngắt ngoài 1 ( INT0 : chân P3.2)

  = 1: cho phép ngắt tại ngắt ngoài 1

IE=0x86; Tức là IE = 1000.0110

Tương ứng với các vị trí thiết lập trên ta có:

EA = 1; // Bạn đã cho phép ngắt toàn cục

EX1 = 1; // Cho phép ngắt ngoài 1

ET0 = 1; // Cho phép ngắt Timer 0

Ngay tại thời điểm này chương trình thực hiện các hàm ngắt mà bạn đã khai báo là:

void Outdata(void) interrupt 1 // Ngắt Timer 0: Tác dụng của hàm ngắt này là hiển thị các led 7 đoạn

void Count(void) interrupt 2  // Ngắt ngoài 1, có lẻ bạn đang sử dụng ngắt này để đếm số lỗ encoder :d ?

 

IP=0x04;

PS   – ưu tiên cho ngắt port nối tiếp.

PT1 – ưu tiên cho ngắt bộ định thời 1. 

PX1 – ưu tiên cho ngắt ngòai 1. 

PT0 – ưu tiên cho ngắt do bộ định thời 0.

PX0 – ưu tiên cho ngắt ngoài  0.

IP = 0x04; // Tức là IP = 0000.0100

Đối chiếu với hình trên, ta thấy PX1 = 1. Như vậy bạn chọn ưu tiên cho ngắt ngoài 1, điều này là dễ hiểu vì việc đọc giá trị cho encoder là quan trọng và cần ưu tiên hơn việc hiển thị giá trị đó ra led 7 đoạn.

 

TH0=-5000/256; // Tre 1s
TL0=-5000%256;

 

TH0 và TL0 là hai thanh ghi chứa giá trị đếm cho timer 0 ở chế độ 16 bit ở trên, còn giá trị được nạp vào cho TH0 và TL0 như trên là để tính toán khoảng thời gian đêm cho đến khi cờ TF0.

 

result = 0;          // Biến lưư giá trị đếm của bạn      
clear_led(); // Xoa LED 
IT1=1; // ngắt ngoài 1 được tác động bằng cạnh âm, tức là mỗi lần thực hiện ngắt bắt đầu khi có sự chuyển trạng thái tín hiệu từ mức cao xuống thấp…..

TF0=1; // có thể không cần thiết
TR0=1; // cho phép timer 0 hoạt động (bắt đầu đếm)



 

 


Được chỉnh sửa bởi nghien_rbc vì:ảnh to quá
09/10/2011 00:10 # 6
nghien_rbc
Cấp độ: 6 - Kỹ năng: 5

Kinh nghiệm: 4/60 (7%)
Kĩ năng: 0/50 (0%)
Ngày gia nhập: 16/03/2010
Bài gởi: 154
Được cảm ơn: 100
[Lập trình robocon] Căn bản


void Count(void) interrupt 2 // Hàm thực hiện ngắt ngoài 1 để đếm số lỗ encoder
{

EA=0;  // Không cho phép bất kỳ ngắt nào hoạt động(xóa bít cho phép ngắt toàn cục). theo mình nghĩ thì không cần bật tắt biến này
result++; // Tăng giá trị lưu số lỗ encoder lên để đếm
if(result >= 9999) 
{
     note=1; // note này bạn định nghĩa cho chân vi điều khiển P3.6, không biết làm gì?
     result=0;   // Reset số lỗ encoder về 0 để thực hiện đếm lại từ đầu nếu số lỗ đã đếm là 10000
}
delay_ms(10); //trể 10ms
EA=1;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void main(void)
{
EA = 0; 
init();                       // Thực hiện khởi tạo: Như đã nói ở trên: cho phép các ngắt hoạt động, nếu encoder quay nó sẻ đếm và hiển thị ra led 7 đọan
delay_ms(100);
while(start); //nếu bạn định nghĩa start này là một nút nhấn thì trong khi chưa nhấn start thì thực hiện khối lệnh ở trong căp dấu {}
EA = 1; // cho phép ngắt toàn cục
result = 0;  // thiết lập giá trị chứa số lỗ encoder = 0 (lưu ý: bạn đã thiết lập nó trong hàm init())
while(1)  // Vòng lặp mãi mãi, như vậy là việc kiểm tra nút nhấn ở trên xem như không thực hiện được
{
} // Đọan này có vẻ hơi khó hiểu

}


 

 


Được chỉnh sửa bởi nghien_rbc vì:lý do lý trấu
09/10/2011 10:10 # 7
phamquyenanh.qb
Cấp độ: 2 - Kỹ năng: 1

Kinh nghiệm: 4/20 (20%)
Kĩ năng: 2/10 (20%)
Ngày gia nhập: 20/09/2010
Bài gởi: 14
Được cảm ơn: 2
Phản hồi: [Lập trình robocon] Căn bản


 Em đang làm cái chương trình đếm số xung nhận được trong một giây rồi xuất ra led 7 đoạn , nhưng tìm hiểu bữa giờ mà chưa hiểu được , cái này có cần dùng timer không anh . anh có thể hướng dẫn  giúp em phần này được không ạ . em cảm ơn .
 



 
10/10/2011 22:10 # 8
nghien_rbc
Cấp độ: 6 - Kỹ năng: 5

Kinh nghiệm: 4/60 (7%)
Kĩ năng: 0/50 (0%)
Ngày gia nhập: 16/03/2010
Bài gởi: 154
Được cảm ơn: 100
Phản hồi: [Lập trình robocon] Căn bản


 uhm, chương trình này đúng là đếm số xung ở chân P3.3 của vi điều khiển. Giống bài toán đo tốc độ động cơ bằng encoder. Chắc là phải dùng timer để tạo độ trể 1 giây. Mà mình thấy bạn đã dùng ngắt timer 0 để tạo độ trể rồi mà. Bạn chạy thử chương trình này trên mô phỏng hay trên mạch thực tế chưa. Mình nghỉ nếu có vấn đề thì chỉ ở phần tạo độ trể thôi, cái tạo độ trể bằng timer này có nhiều cách tính toán để đưa giá trị vào TH, TL.


 

 


 
Các thành viên đã Thank nghien_rbc vì Bài viết có ích:
15/10/2011 11:10 # 9
phamquyenanh.qb
Cấp độ: 2 - Kỹ năng: 1

Kinh nghiệm: 4/20 (20%)
Kĩ năng: 2/10 (20%)
Ngày gia nhập: 20/09/2010
Bài gởi: 14
Được cảm ơn: 2
Phản hồi: [Lập trình robocon] Căn bản


 Anh nghien_rbc anh xem lai gium em cái này với , sao mà mấy cái số ở hàng nghìn , trăm , chục cứ nháy nháy vậy .
thank anh nhiều

File đính kèm Bạn phải đăng nhập mới thấy link download



 
16/10/2011 00:10 # 10
nghien_rbc
Cấp độ: 6 - Kỹ năng: 5

Kinh nghiệm: 4/60 (7%)
Kĩ năng: 0/50 (0%)
Ngày gia nhập: 16/03/2010
Bài gởi: 154
Được cảm ơn: 100
Phản hồi: [Lập trình robocon] Căn bản


Trích:
 Anh nghien_rbc anh xem lai gium em cái này với , sao mà mấy cái số ở hàng nghìn , trăm , chục cứ nháy nháy vậy .
thank anh nhiều
 Theo mình đoán thì thế này, bạn hiển thị bằng cách quét lần lượt từng led 7 đoạn trong ham hienthi(). Tuy nhiên nếu muốn led hiển thị không nhấp nháy thì bạn phải gọi liên tục hàm hienthi() đó. Chứ mình thấy trong hàm main mỗi lần bạn đo tần số xung trong một giây xong bạn mới gọi hàm hiển thị thì chắc chắn là phải nhấp nháy. Nếu hàm đo tần số của bạn ok rồi thì mình nghĩ bạn phải thực hiện hàm hiển thị nhiều hơn bằng cách đặt nó vào trong một ngắt timer chẳng hạn.
void Timer1_int(void) interrupt 3 
{
TH1=0xEC;
TL1=0x78;
TR1=1; // KHOI DONG BO DINH THOI
hienthi(dem);
}
Nếu bạn làm theo cách này thì tạm thời bạn thay đổi hàm void delay_01s(int a) một tí vì lúc này timer được dùng cho việc ngắt. Bạn có thể dùng vòng lặp để tạo thời gian trể như thế này
void delay_01s(unsigned int x){  // nếu muốn trể một giây thì x=1000
unsigned int TGIAN_TRE1;      
      while(x!=0)
 {     
  TGIAN_TRE1=121;
    while(TGIAN_TRE1!=0)
  {    
  TGIAN_TRE1=TGIAN_TRE1-1;
  }
  x=x-1;
      }
}
 Đó chỉ là một cách và mình cũng không có điều kiện để test thử. Có gì bạn thử rồi commnet lại nha. Có mạch mô phỏng không gửi qua mình test thử.
Sao không thấy các bro vào comment hè. Không lẻ để tui ôm bom mà cưa cả đời sao.


 

 


 
16/10/2011 10:10 # 11
phamquyenanh.qb
Cấp độ: 2 - Kỹ năng: 1

Kinh nghiệm: 4/20 (20%)
Kĩ năng: 2/10 (20%)
Ngày gia nhập: 20/09/2010
Bài gởi: 14
Được cảm ơn: 2
Phản hồi: [Lập trình robocon] Căn bản


Dạ em có đưa lên đó anh , file baitapnhom.dsn ah . em dung proteus để mô phỏng .




 
01/11/2011 10:11 # 12
RBC_rbc
Cấp độ: 4 - Kỹ năng: 4

Kinh nghiệm: 24/40 (60%)
Kĩ năng: 9/40 (22%)
Ngày gia nhập: 25/10/2010
Bài gởi: 84
Được cảm ơn: 69
Phản hồi: [Lập trình robocon] Căn bản


 void ngat_timer0(void) interrupt 1
{
TR0=0;
EX0=0;
TH0=-25000/256; //DEM 25000 CHU KY
TL0=-25000%256;
gt_ecoder=0;
EX0=1;
TR0=1;
void ngat_ngoai0(void) interrupt 0
{
gt_ecoder++;
}
 chương trình trên đếm số lỗ encoder trong 25ms.bạn thao khảo nhé.
void main()
 
 
////////////////ngt ngoai 0
  EA=1;
IT0=1;
/// thiet lap ----------------------------------
TMOD=0x01; //   T1 MODE 1 phải nạp lại giá trị
TH0=-25000/256; //DEM 25000 CHU KY
TL0=-25000%256;
///////////// bật Timer 0--------------
IE=0x8A;
TR0=1;
 
     
 while(1) ;
 
 
}

 


 Đặng Ngọc Sỹ - TT CEE 


 
01/11/2011 10:11 # 13
RBC_rbc
Cấp độ: 4 - Kỹ năng: 4

Kinh nghiệm: 24/40 (60%)
Kĩ năng: 9/40 (22%)
Ngày gia nhập: 25/10/2010
Bài gởi: 84
Được cảm ơn: 69
Phản hồi: [Lập trình robocon] Căn bản


 chương trình hiển thị LCD
sbit RS=P0^5;
sbit RW=P0^6;
sbit EN=P0^7;
sbit  LCD_LED=P2^7;
void kt_co_ban(void)   //-------------KIEM TRA CO BAN [CO THE DUNG DELAY 50UM]-------------------
{
LCD_LED = 1;
RS=0;
RW=1;
while(LCD_LED)
{
EN=0;
EN=1;
}
}
void ghi_lenh(unsigned char lenh_LCD)
{
kt_co_ban();
P2=lenh_LCD;
RS=0;
RW=0;
EN=1;
EN=0;
}
void ghi_data(unsigned char data_LCD)
{
kt_co_ban();
P2=data_LCD;
RS=1;
RW=0;
EN=1;
EN=0;
}
//----------------GHI CHUOI KY TU RA LCD--------------------------
void viet_chuoi(char *s)
{
while(*s)
{
ghi_data(*s);
s++;
}
}
void khoi_tao(void)
{
ghi_lenh(0x01);
ghi_lenh(0x38);
ghi_lenh(0x06);
ghi_lenh(0x0e);
}
//---------------XOA MANG HINH LCD----------------------------
void xoa_lcd(void)
{
ghi_lenh(0x01);
}
//-------------------VI TRI CON TRO--------------------------
void vi_tri_con_tro(unsigned char row, unsigned char col)
{
ghi_lenh( (1<<7)|(row<<6)|col );
}

Nếu đếm encoder 2 chiều nên dùng lcd để hiển thị.


 Đặng Ngọc Sỹ - TT CEE 


 
Các thành viên đã Thank RBC_rbc vì Bài viết có ích:
01/11/2011 10:11 # 14
RBC_rbc
Cấp độ: 4 - Kỹ năng: 4

Kinh nghiệm: 24/40 (60%)
Kĩ năng: 9/40 (22%)
Ngày gia nhập: 25/10/2010
Bài gởi: 84
Được cảm ơn: 69
Phản hồi: [Lập trình robocon] Căn bản


 Bài của bạn có phải là thế này:
VD: Đo tần số của xung ngoài đưa đến chân T0 hoặc T1 của vi điều khiển.
Hướng dẫn:
Để đo tần số ta cần phải đếm được số xung trong một khoảng thời gian chính xác.Muốn vậy ta phải sử dụng 2 bộ timer của VDK.
Bộ Timer thứ nhất hoạt động ở chế độ đếm dùng để đếm xung của tính hiệu cần đo tần số trong 1 khoảng thời gian xác định(do timer thứ 2 tạo ra).
Bộ timer thứ 2 có nhiệm vụ tạo khoảng thời gian chính xác cho timer thứ nhất làm việc.
Bạn đọc bài này nhé:
#include<stdio.h>
#include<reg51.h>
#include<math.h>
unsigned long int dem,n;
double f;
void main(void)
{
      TMOD=0x25;
      // timer 0 làm bộ đếm,chế độ 1 đếm xung ở chân T0;
      timer 1 là định thời chế độ 2;
     IE=0x88;
     IP=0x08;
     TH0=TL0=0; // xoá timer 0
     TH1=TL1=-100; /// nap giá trị đầu cho timer 1
     dem=0;
     while(1)
              {
                  TR1=1;
                  TR0=1;
                    while (dem<1000);/// cho hết khoảng thời gian 0.1s
                    n=TH0*256 + TL0 ;/////////đổi giá trị đếm được thành số thập phân
                    f=n*10;
                }

}
chiều rồi mình tiếp tục,giờ hết giơ rồi 


 Đặng Ngọc Sỹ - TT CEE 


 
01/11/2011 14:11 # 15
RBC_rbc
Cấp độ: 4 - Kỹ năng: 4

Kinh nghiệm: 24/40 (60%)
Kĩ năng: 9/40 (22%)
Ngày gia nhập: 25/10/2010
Bài gởi: 84
Được cảm ơn: 69
Phản hồi: [Lập trình robocon] Căn bản


 void ngatT1(void) interrrupt 3
{
      dem++;
      TF1=0;
      TR1=1;
}


 Đặng Ngọc Sỹ - TT CEE 


 
01/11/2011 14:11 # 16
RBC_rbc
Cấp độ: 4 - Kỹ năng: 4

Kinh nghiệm: 24/40 (60%)
Kĩ năng: 9/40 (22%)
Ngày gia nhập: 25/10/2010
Bài gởi: 84
Được cảm ơn: 69
Phản hồi: [Lập trình robocon] Căn bản


 Các bạn hỏi về vấn đề gì thì lập 1 chủ để riêng để tiện trả lời.


 Đặng Ngọc Sỹ - TT CEE 


 
24/04/2012 15:04 # 17
lenhoc91
Cấp độ: 1 - Kỹ năng: 1

Kinh nghiệm: 3/10 (30%)
Kĩ năng: 0/10 (0%)
Ngày gia nhập: 24/04/2012
Bài gởi: 3
Được cảm ơn: 0
Phản hồi: [Lập trình robocon] Căn bản


  mấy a pro c ơi chỉ giúp e với.
  e cần lấy xung của ic 555 để đưa vào 89c51 thay đổi nhịp nháy của mấy con led đơn e nghĩ là dùng ngắt để làm e đọc tài liệu rồi mà vẫn ko hiễu ngắt chỗ nào hết mấy a giúp e với đây là code của e

#include <regx51.h>
#define led P0
void delay(unsigned int ms)
{
unsigned int i;
unsigned char j;
for(i=0;i<ms;i++)
{
for(j=0;j<125;j++)
{
}
}
}
main()
{
while(1)
{
P0=0x00;delay(1000);
P0=0x00;delay(1000);
P0=0x04;delay(1000);
P0=0x08;delay(1000);
P0=0x10;delay(1000);
P0=0x20;delay(1000);
P0=0x40;delay(1000);
P0=0x80;delay(1000);
}
}



 
24/04/2012 15:04 # 18
lenhoc91
Cấp độ: 1 - Kỹ năng: 1

Kinh nghiệm: 3/10 (30%)
Kĩ năng: 0/10 (0%)
Ngày gia nhập: 24/04/2012
Bài gởi: 3
Được cảm ơn: 0
Phản hồi: [Lập trình robocon] Căn bản


 mấy a giúp e với



 
24/04/2012 16:04 # 19
lenhoc91
Cấp độ: 1 - Kỹ năng: 1

Kinh nghiệm: 3/10 (30%)
Kĩ năng: 0/10 (0%)
Ngày gia nhập: 24/04/2012
Bài gởi: 3
Được cảm ơn: 0
Phản hồi: [Lập trình robocon] Căn bản


 ko ai giup e hết vậy



 
Copyright© Đại học Duy Tân 2010 - 2024