Ðăng Nhập

View Full Version : Sử dụng nhiều ngắt, cần chú ý những gì?


kiwi
12-05-2009, 05:41 PM
Trong chương trình điều khiển động cơ bằng PWM của Pic 16F877A, mình muốn dùng các ngắt sau cho chương trình:
- ngắt TIMER0 ở chế độ counter, ngắt TIMER1 ở chế độ timer phục vụ cho việc xác định tốc độ.
- ngắt RB dùng cho bàn phím để nhập tốc độ vào.
Như vậy có ổn không, nếu được thì cần chú ý những gì?
Rất mong sự giúp đỡ.
Mình là chương trình em mới viết (không chạy được, vì sao?)

#include <Doc encoder.h>
#include <def_877a.h>
#include <lcd_lib_4bit.c>
#use delay(clock=4000000)

int8 int_count1;
int16 tddc,count;
int16 tocdodat;
int16 value;

int8 key;
int16 tocdomoi;//tocdomoi: toc do dang nhap, tocdodat: toc do duoc chon

void row_check(int8 row);

#define So_lan_tran_T1 1
//so_lan_tran_t1 = 1 => cu 1*50000*4=200000us=0.2s thi T1 se tran
#define key_port PORTB
#define key_tris TRISB

#int_rtcc // Ngat Timer 0
void Timer0_isr()//ngat timer0
{
count++;
}

#INT_TIMER1 // Chuong trinh ngat Timer 1
void Timer1_isr()
{
if(--int_count1==0)
{
tddc = (count * 256 + get_timer0()) * 3; // cu 0.2s thi dem xung, tddc(v/p)= soxung*(60s/0.2s)/100
int_count1 = So_lan_tran_T1;
count = 0;
set_timer0(0);
}
SET_TIMER1(15535);
}

#INT_RB
void key_scan(int8 count)
{
if((RBIF)&&(RBIE))
{
for(count = 4;count <= 7; count++)
{
key_tris = 0xF0; // hang ngo vao, cot ngo ra
key_port = 0xF0; // hang muc 1, cot muc 0
if(!bit_test(key_port,count)) // hang count xuong 0 chua?
{
delay_ms(10); // sau 10ms
if(!bit_test(key_port,count)) // kiem tra lai hang count co xuong 0 ko?
{
key_tris = 0x0F; // hang ngo ra, cot ngo vao
switch(count)
{
case 4:
{
key_port = 0xEF; // hang 0 xuong 0
row_check(0); // kiem tra cot ung voi hang 0
}
break;
case 5:
{
key_port = 0xDF; // hang 1 xuong 0
row_check(1); // kiem tra cot ung voi hang 1
}
break;
case 6:
{
key_port = 0xBF; // hang 2 xuong 0
row_check(2); // kiem tra cot ung voi hang 2
}
break;
case 7:
{
key_port = 0x7F; // hang 3 xuong 0
row_check(3); // kiem tra cot ung voi hang 3
}
break;
}
}
}
}

if(tocdomoi>9999)
{
tocdomoi = 0;
LCD_PutCmd(0x01);
}
if(key==11)
{
tocdodat=tocdomoi;
LCD_SetPosition(line_1);
printf(lcd_putchar,"Tocdodc: %04lu",tddc);
LCD_SetPosition(line_2);
printf(lcd_putchar,"Tocdodat: %04lu",tocdodat);
}
else
{
LCD_SetPosition(line_1);
printf(lcd_putchar,"Tocdodc: %04lu",tddc);
LCD_SetPosition(line_2);
printf(lcd_putchar,"Nhaptocdo: %04lu",tocdomoi);
}
set_tris_b(0b11110000);
}
RBIF=0; //Xoa co ngat RB
}

void row_check(int8 row)
{
switch(row)
{
//.............................//
case 0: // truong hop hang 0 bang 0
{
if(!bit_test(key_port,0)) // neu cot 0 bang 0
{
while(!bit_test(key_port,0));
key = 7;
tocdomoi = tocdomoi*10 + key;
//printf("%u\n\r",led_port);
}
if(!bit_test(key_port,1)) // neu cot 1 bang 0
{
while(!bit_test(key_port,1));
key = 8;
tocdomoi = tocdomoi*10 + key;
//printf("%u\n\r",led_port);
}
if(!bit_test(key_port,2)) // neu cot 2 bang 0
{
while(!bit_test(key_port,2));
key = 9;
tocdomoi = tocdomoi*10 + key;
//printf("%u\n\r",led_port);
}
if(!bit_test(key_port,3)) // neu cot 3 bang 0
{
while(!bit_test(key_port,3));
key = 0;
tocdomoi = tocdomoi*10 + key;
//printf("%u\n\r",led_port);
}
break;
}
//.............................//
case 1: // truong hop hang 1 bang 0
{
if(!bit_test(key_port,0))
{
while(!bit_test(key_port,0));
key = 4;
tocdomoi = tocdomoi*10 + key;
//printf("%u\n\r",led_port);
}
if(!bit_test(key_port,1))
{
while(!bit_test(key_port,1));
key = 5;
tocdomoi = tocdomoi*10 + key;
//printf("%u\n\r",led_port);
}
if(!bit_test(key_port,2))
{
while(!bit_test(key_port,2));
key = 6;
tocdomoi = tocdomoi*10 + key;
//printf("%u\n\r",led_port);
}
if(!bit_test(key_port,3))
{
while(!bit_test(key_port,3));
// tocdodat = tocdomoi; //===>>> phim OK, dong y toc do
key = 11;
//printf("%u\n\r",led_port);
}
break;
}
//.............................//
case 2:
{
if(!bit_test(key_port,0))
{
while(!bit_test(key_port,0));
key = 1;
tocdomoi = tocdomoi*10 + key;
//printf("%u\n\r",led_port);
}
if(!bit_test(key_port,1))
{
while(!bit_test(key_port,1));
key = 2;
tocdomoi = tocdomoi*10 + key;
//printf("%u\n\r",led_port);
}
if(!bit_test(key_port,2))
{
while(!bit_test(key_port,2));
key = 3;
tocdomoi = tocdomoi*10 + key;
//printf("%u\n\r",led_port);
}
if(!bit_test(key_port,3))
{
while(!bit_test(key_port,3));
bit_clear(tocdomoi,0);
tocdomoi=tocdomoi/10; //===>>> phim back, xoa 1 so


//printf("%u\n\r",led_port);
}
break;
}
//.............................//
case 3:
{
if(!bit_test(key_port,0))
{
while(!bit_test(key_port,0));
// if(lcd_on_off) //===>>> bat tat LCD
// lcd_Putcmd(0x08);
// else
// lcd_Putcmd(0x0C);
// lcd_on_off++;

//printf("%u\n\r",led_port);
}
if(!bit_test(key_port,1))
{
while(!bit_test(key_port,1));
key = 14; //===>>> Dung dong co

//printf("%u\n\r",led_port);
}
if(!bit_test(key_port,2))
{
while(!bit_test(key_port,2));
key = 15; //===>>> quay thuan

//printf("%u\n\r",led_port);
}
if(!bit_test(key_port,3))
{
while(!bit_test(key_port,3));
key = 16; //===>>> quay nguoc

//printf("%u\n\r",led_port);
}
break;
}
}
}

void init()
{
int_count1 = So_lan_tran_T1;//5 lan 1 giay
setup_timer_0 (RTCC_DIV_1|RTCC_EXT_H_TO_L); // Timer0 is Counter
set_timer0(0);
set_timer1(15535);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_4); // Timer1 is Timer
enable_interrupts(INT_RTCC);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);

enable_interrupts(int_RB);
ext_int_edge(H_to_L);
set_tris_b(0b11110000);

tddc=0;
tocdodat=3000;
tocdomoi=0;
value=800;
key=0;

count = 0;
///////////////////////
setup_ccp2(CCP_PWM);
setup_timer_2(T2_DIV_BY_4, 249, 1);//1khz

lcd_init();
delay_ms(200);
RD2 = 1;
trisD = 0;
TRISA = 0xFF;

}

void main()
{
init();
while(1) // doan chuong trinh tinh toan gia tri pwm, hien thi len LCD
{
///////////TINH TOAN ON DINH TOC DO///////////////////
if(value<=1000)
{
if (tddc>tocdodat)
{
if((tddc-tocdodat)>200)
value=value-10;
else
value=value-1;
}
else
{
if((tocdodat-tddc)>200)
value=value+10;
else
value=value+1;
}
set_pwm2_duty(value);
}
else
value=1000;
///////////////////////////////////////////////////////////
LCD_PutCmd (0x01);//clear lcd
}
}

lequocbao
14-05-2009, 12:58 PM
vậy thì làm sao bác xác định chiều quay?
theo mình bạn nên chọn :
-timer1 chế độ couter 16 bit để đếm xung vào từ encoder.
-rb0 kiểm tra chiều quay.
- còn lại timer2 lấy mẩu để bít tốc độ của thằng ku dcdc.
- timer0 làm việc khác khè ...khè...