Trích:
Nguyên văn bởi bazooka2006
Code:
#include <16F877A.h>
...
#priority rb,rda
...
#int_RB
void rb_isr() // ham phuc vu ngat RB
{
int current;
int last;
set_tris_b(0xff);
current=input_b();
last=current;
delay_ms(50);
set_tris_b(0xff);
current=input_b();
if (current==last)
{
clear_interrupt(int_RDA);
if (!bit_test(current,4)) // ctac tren mam xoay bao ngat
{
if (home) // chi thuc hien khi o che do home:
{ // quay mam ben phai 60 do
en_step1=0;
count1=70;
dir1=1;
en_step1=1;
while (count1>0)
{
count1--;
if ((count1>30)&&(count1<(70-30)))
{
rotate_high1();
}
else
{
rotate_low1();
}
}
count1=0;
}
}
if (!bit_test(current,5)) // ctac trong bao ngat
{
en_step3=0;
delay_ms(500);
count3=2000;
dir3=0;
in_out();
}
if (!bit_test(current,6)) //ctac tren bao ngat
{
en_step2=0;
delay_ms(500);
count2=500;
dir2=1;
go_up_down();
count2=0;
}
if (!bit_test(current,7)) // cam bien phat hien co vat den
{
putc('y');
delay_ms(10);
}
}
clear_interrupt(int_RB);
}
//****************************************************************
#int_RDA // ham phuc vu ngat noi tiep
void RDA_isr()
{
delay_us(50);
ss=getc();
if (ss=='u') // di len
{
count2=2000;
dir2=0;
go_up_down();
printf("done");
}
if (ss=='d') // di xuong
{
count2=2000;
dir2=1;
go_up_down();
printf("done");
}
if (ss=='l') // quay trai
{
count1=70; //1 lan quay 60 do
dir1=0;
left_right();
printf("done");
}
if (ss=='r') // quay phai
{
count1=70;
dir1=1;
left_right();
printf("done");
}
if (ss=='i') //di vao
{
count3=4000; //1 lan di chuyen 30mm
dir3=1;
in_out();
printf("done");
}
if (ss=='o') // di ra
{
count3=4000;
dir3=0;
in_out();
printf("done");
}
if (ss=='#') // test comm
{
putc('!');
delay_us(100);
}
if (ss=='O') // go home: dieu khien tay may
{ // ve vi tri home
home=1;
count1=100;
dir1=0;
left_right();
count2=2000;
dir2=0;
go_up_down();
count3=2666;
dir3=1;
in_out();
home=0;
}
if (ss=='1') // chuong trinh di chuyen cho vat 1
{
count2=10000; // chay xuong
dir2=1;
go_up_down();
catch=1; // gap vat
count2=10000; // di len
dir2=0;
go_up_down();
count1=102; // xoay 90 do
dir1=1;
left_right();
count3=13333; // di ra
dir3=0;
in_out();
count2=10000; // ha xuong
dir2=1;
go_up_down();
catch=0; // nha vat
count2=10000; // di len
dir2=0;
go_up_down();
count1=102; // xoay 90 do
dir1=0;
left_right();
count3=13333; // di vao
dir3=1;
in_out();
}
clear_interrupt(int_rda);
}
void main()
{
enable_interrupts(INT_RB|H_TO_L);
enable_interrupts(GLOBAL);
ext_int_edge(H_TO_L);
enable_interrupts(INT_RDA);
set_tris_d(0x00);
set_tris_b(0xff);
set_tris_a(0x00);
printf("reset");
while (1)
{
}
}
|
Mình có quote cho bạn những đoạn code trên, bạn cần lưu ý những điều sau để tự sửa lại chương trình:
- Trong PIC16F877A không có ưu tiên ngắt, do đó chỉ dẫn #priority không có tác dụng
- Khi xảy ra bất kì 1 ngắt nào, thì GIE = 0 để tránh xảy ra các ngắt chồng nhau, nó chỉ được set = 1 khi có lệnh RETFIE, có nghĩa là khi xảy ra 1 ngắt bất kì thì chỉ khi thực hiện xong ngắt đó mới có thể giải quyết ngắt tiếp theo
- Khi xử lý 1 ngắt, trước khi kết thúc trình phục vụ ngắt, bạn phải xóa cờ ngắt đó bằng lệnh clear_interrupt();, nếu không sau khi thoát ra khỏi ngắt đó, nó sẽ quay trở lại
- enable_interrupts(INT_RB|H_TO_L); không có OR với H_TO_L, tuy nhiên do giá trị H_TO_L = 0, nên chương trình bạn không bị ảnh hưởng
- Dưới đây là file list C/ASM đơn giản để bạn thấy rõ điều đó
PHP Code:
#include<16f877a.h>
#use delay(clock=4Mhz)
#use rs232(baud=9600, UART1)
#INT_RDA
void rda(){
unsigned char c;
c = getc(); //Lệnh này sau khi đọc xong kí tự, thì cờ ngắt tự động bị xóa
output_b(0xAA);
}
#INT_RB
void rb(){
output_b(0x55);
clear_interrupt(INT_RB);
}
void main(){
enable_interrupts(INT_RDA);
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
while(1);
}
đây là file list, lược bớt đoạn đầu, là đoạn chỉ lưu các thanh ghi và lựa chọn nhảy đến vị trí các chương trình phục vụ ngắt, không hề có lệnh nào xóa cờ ngắt
PHP Code:
.................... #INT_RDA
.................... void rda(){
.................... unsigned char c;
.................... c = getc();
003C: BTFSS 0C.5
003D: GOTO 03C
003E: MOVF 1A,W
003F: MOVWF 28
.................... output_b(0xAA);
0040: BSF 03.5
0041: CLRF 06
0042: MOVLW AA
0043: BCF 03.5
0044: MOVWF 06
.................... }
....................
0045: BCF 0C.5
0046: BCF 0A.3
0047: BCF 0A.4
0048: GOTO 023
.................... #INT_RB
.................... void rb(){
.................... output_b(0x55);
0049: BSF 03.5
004A: CLRF 06
004B: MOVLW 55
004C: BCF 03.5
004D: MOVWF 06
.................... clear_interrupt(INT_RB);
004E: BCF 0B.0 //Chỉ khi có lệnh này, thì cờ ngắt của INT_RB mới được xóa
.................... }