Ðăng Nhập

View Full Version : nhờ xe, giúp e


robotpic
05-11-2010, 12:27 AM
e viêt chương trình sau có 2 lổi e chưa hiểu nguyên nhân:

đặt câu hỏi trước gởi code sau:

chương trình e dùng ngắt ngoài chân rc3 rc4 rc5 của pic 4331 để đọc encoder

câi 1: nếu encoder quay thì xung tang theo theo tốc đọ của encoder , nhưng mà e không quay encoder thì nó cũng tăng lên?
câu 2: còng if nếu e viết :
while(TRUE)
{
IF(XUNG>1000||xung1>1000||xung2>1000) RA0=0;
else IF(XUNG>1200||xung1>1200||xung2>1200) RA1=0;
else IF(XUNG>1300||xung1>1300||xung2>1300) RA2=0;
else IF(XUNG>1400||xung1>1400||xung2>1400) RA3=0;
else IF(XUNG>1500||xung1>1500||xung2>1500) RA4=0;
else IF(XUNG>1600||xung1>1600||xung2>1600) RA5=0;
else IF(XUNG>2000||xung1>2000||xung2>2000) CT_PWM_POWER();
else IF(XUNG>3000||xung1>3000||xung2>3000) CT_PWM_CCP ();
else IF(XUNG>3000||xung1>3000||xung2>3000)
{
RD0=0;
DELAY_MS(500);
RD1=0;
DELAY_MS(500);
RD2=0;
DELAY_MS(500);
RD3=0;
DELAY_MS(500);
RD4=0;
DELAY_MS(500);
}
}
thì nó khi encoder quay mấy vòng đi chăng nữa nó cũng chỉ dừng lệnh if đầu tiên tức chỉ có ra0 sáng.

còn khí e viết như thế nầy thì nhận hết ok:
while(TRUE)
{
IF(XUNG>1000||xung1>1000||xung2>1000) RA0=0;
IF(XUNG>1200||xung1>1200||xung2>1200) RA1=0;
IF(XUNG>1300||xung1>1300||xung2>1300) RA2=0;
IF(XUNG>1400||xung1>1400||xung2>1400) RA3=0;
IF(XUNG>1500||xung1>1500||xung2>1500) RA4=0;
IF(XUNG>1600||xung1>1600||xung2>1600) RA5=0;
IF(XUNG>2000||xung1>2000||xung2>2000) CT_PWM_POWER();
IF(XUNG>3000||xung1>3000||xung2>3000) CT_PWM_CCP ();
IF(XUNG>3000||xung1>3000||xung2>3000)
{
RD0=0;
DELAY_MS(500);
RD1=0;
DELAY_MS(500);
RD2=0;
DELAY_MS(500);
RD3=0;
DELAY_MS(500);
RD4=0;
DELAY_MS(500);
}
}


đây là toàn bộ code của e:


#include <18f4331.h>
#INCLUDE <def_4331.h>

#FUSES HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT,NOPUT,NOCPD,NO DEBUG,NOFCMEN,NOCPB,STVREN,NOPWMPIN,HPOL_LOW
#FUSES MCLR,NOWINEN,NOIESO,NOWRTC,NOWRTB,NOWRTD,NOEBTR,NO WRT,NOEBTRB,EXCLKD0,T1STANDARD

#use delay(clock=20000000)

#use fast_io(a)
#use fast_io(d)
#use fast_io(c)
#use fast_io(e)

long XUNG,XUNG1,XUNG2;

#INT_EXT //RC3
VOID DEM_NGAT()
{
XUNG++;
return ;
}

#INT_EXT1 //RC4
VOID DEM_NGAT_1()
{
XUNG1++;
return ;
}

#INT_EXT2 //RC5

VOID DEM_NGAT_2()
{

XUNG2++;
return;
}

VOID CT_PWM_POWER()
{
SET_POWER_PWM0_DUTY(100);

SET_POWER_PWM2_DUTY(500);

SET_POWER_PWM4_DUTY(200);

SET_POWER_PWM6_DUTY(500);

}
VOID CT_PWM_CCP ()
{

SET_PWM2_DUTY(250);
SET_PWM1_DUTY(500);
}


void main()
{
trisa=0x00;
porta=0xff;

trisb=0x00;
portb=0x00;

trisc=0b00111000;
portC=0x0f;

trisd=0x00;
portd=0xff;

trise=0x00;
porte=0xff;

setup_power_pwm_pins( PWM_ODD_ON,PWM_ODD_ON,PWM_ODD_ON,PWM_ODD_ON);
setup_power_pwm(PWM_CLOCK_DIV_4|PWM_FREE_RUN,1,0,1 24,0,1,0);
set_power_pwm_override(1, false, 0);
set_power_pwm_override(3, false, 0);
set_power_pwm_override(5, false, 0);
set_power_pwm_override(7, false, 0);

SETUP_CCP1(CCP_PWM);
SETUP_CCP2(CCP_PWM);
setup_timer_2(T2_DIV_BY_4,124,1);

enable_interrupts(GLOBAL);
enable_interrupts(INT_EXT);
enable_interrupts(INT_EXT1);
enable_interrupts( INT_EXT2);
ext_int_edge(0, L_TO_H );
ext_int_edge(1, L_TO_H );
ext_int_edge(2, L_TO_H );


xung=0;
xung1=0;
xung2=0;

while(TRUE)
{
IF(XUNG>1000||xung1>1000||xung2>1000) RA0=0;
IF(XUNG>1200||xung1>1200||xung2>1200) RA1=0;
IF(XUNG>1300||xung1>1300||xung2>1300) RA2=0;
IF(XUNG>1400||xung1>1400||xung2>1400) RA3=0;
IF(XUNG>1500||xung1>1500||xung2>1500) RA4=0;
IF(XUNG>1600||xung1>1600||xung2>1600) RA5=0;
IF(XUNG>2000||xung1>2000||xung2>2000) CT_PWM_POWER();
IF(XUNG>3000||xung1>3000||xung2>3000) CT_PWM_CCP ();
IF(XUNG>3000||xung1>3000||xung2>3000)
{
RD0=0;
DELAY_MS(500);
RD1=0;
DELAY_MS(500);
RD2=0;
DELAY_MS(500);
RD3=0;
DELAY_MS(500);
RD4=0;
DELAY_MS(500);
}
}

}

falleaf
05-11-2010, 09:19 AM
Viết code như vậy nó chạy vậy thì chả có gì lạ. Nhưng không có thời gian sửa lỗi cho bạn, chỉ nói sơ bạn biết lỗi ngay.

Trường hợp 1, nếu bạn viết dạng if XUNG > và ELSE IF thì tất nhiên nếu XUNG lớn hơn 1000, thì lúc nào nó cũng đã lớn hơn 1000 rồi, nên nó chỉ chạy cái IF đầu tiên.

Trường hợp 2, khi bạn viết một loạt IF, thì nó kiểm đúng XUNG > 1000, sau đó nó kiểm tiếp xem XUNG có lớn hơn 1200 không, nếu lớn hơn 1200 thì nó thực thi RA1 = 0. Vậy nên bạn nhận được kết quả đúng như mong đợi.

Code của bạn viết bản thân không hiểu rõ về code nên dẫn tới sai lung tung.

Nếu chưa quen viết code, viết ra thành lời những gì mình muốn, sau đó hãy viết code.

Còn nữa, trong C thì XUNG1 và xung1 phân biệt nhau, chứ không phải như ASM, viết như vậy thì làm sao nó chạy đúng được.

Sẽ chẳng ai trả lời chi tiết cho bạn cái này được với cách viết code như thế này.

Chúc vui.

dinhminh09
05-11-2010, 12:03 PM
while(TRUE)
{
IF(XUNG>1000||xung1>1000||xung2>1000) RA0=0;
IF(XUNG>1200||xung1>1200||xung2>1200) RA1=0;
IF(XUNG>1300||xung1>1300||xung2>1300) RA2=0;
IF(XUNG>1400||xung1>1400||xung2>1400) RA3=0;
IF(XUNG>1500||xung1>1500||xung2>1500) RA4=0;
IF(XUNG>1600||xung1>1600||xung2>1600) RA5=0;
IF(XUNG>2000||xung1>2000||xung2>2000) CT_PWM_POWER();
IF(XUNG>3000||xung1>3000||xung2>3000) CT_PWM_CCP ();
IF(XUNG>3000||xung1>3000||xung2>3000)
{


khúc này chỉ cần thêm vài cái {}
là ok rôi



while(TRUE)
{
IF(XUNG>1000||xung1>1000||xung2>1000)
{ RA0=0;

{
IF(XUNG>1200||xung1>1200||xung2>1200) RA1=0;

{
IF(XUNG>1300||xung1>1300||xung2>1300) RA2=0;

{
IF(XUNG>1400||xung1>1400||xung2>1400) RA3=0;

{
IF(XUNG>1500||xung1>1500||xung2>1500) RA4=0;

{
IF(XUNG>1600||xung1>1600||xung2>1600) RA5=0;

{
IF(XUNG>2000||xung1>2000||xung2>2000) CT_PWM_POWER();

{
IF(XUNG>3000||xung1>3000||xung2>3000) CT_PWM_CCP ();

{
IF(XUNG>3000||xung1>3000||xung2>3000)
}}}}}}}}

chưa thử nó mô phỏng thế nào nhừng mình nghĩ chắt cái này dúng ý bạn
http://www.picvietnam.com/forum/showthread.php?t=3266

falleaf
05-11-2010, 12:07 PM
Toi !!!

Chúc vui

robotpic
05-11-2010, 10:40 PM
while(TRUE)
{
IF(XUNG==1000||xung1==1000||xung2==1000) RA0=0;
else IF(XUNG==1200||xung1==1200||xung2==1200) RA1=0;
else IF(XUNG==1300||xung1==1300||xung2==1300) RA2=0;
else IF(XUNG==1400||xung1==1400||xung2==1400) RA3=0;
else IF(XUNG==1500||xung1==1500||xung2==1500) RA4=0;
else IF(XUNG==1600||xung1==1600||xung2==1600) RA5=0;
else IF(XUNG==2000||xung1==2000||xung2==2000) CT_PWM_POWER();
else IF(XUNG==3000||xung1==3000||xung2==3000) CT_PWM_CCP ();
else IF(XUNG>4000||xung1>4000||xung2>4000)
{
RD0=0;
DELAY_MS(500);
RD1=0;
DELAY_MS(500);
RD2=0;
DELAY_MS(500);
RD3=0;
DELAY_MS(500);
RD4=0;
DELAY_MS(500);
}
}

mình đã sửa được câu 1. chạy ok,

nhưng còn câu 2 chưa giả được.

mình không quay encorder vong nao ma nó vẫn thăng giá trị xung,

nếu mình ko quay để thời gian cũng thấy chương trình chạy từ đầu đến cuối.

bác falleaf nói cũng sai ah.

mình viết thế cũng dc, nhưng do định nghĩa sai thôi.

dinhminh09
06-11-2010, 12:46 PM
ngửi cái sơ đồ nguyên lý hay cái mô phỏng lên mình xem với. thật ra mình không biết bạn so sanh encorder như thế nào

robotpic
07-11-2010, 08:41 AM
mình thực hành trên boad test nên không vẻ.

chân rc3 vào encoder tương ứng chương trình ngăt ext
chân rc4 vào encoder1 tương ứng ngắt ext1
chân rc5 vào encoder2 tương ứng ngắt ext2


mình viết như thế đó bạn dinhminh09

dinhminh09
07-11-2010, 09:38 AM
thật sự mình không nắm rõ về hoạt động của encorder. nhưng encoder gửi dữ liệu theo cách nào. nhưng nếu bạn dùng ngắt thì khi có ngắt xảy ra thì hàm ngắt hoạt động

#INT_EXT
VOID DEM_NGAT()
{
XUNG++;
return ;
}

vậy encorder đưa về nó hoạt động như thế nào?
nếu encorder không quay mà xung vẫn tăng lên thì chứng tỏ hàm ngắt vẫn đang thực hiện.
theo ý của mình thì như zậy có sai sót j mong bỏ qua cho.

robotpic
07-11-2010, 11:52 AM
mình cung không rỏ vì sao ngắt nó lại tự chạy.
dùng encoder này mình khai báo như trền trang đầu tiên thì các chân rc3-rc5 mỗi khi có thay đổi từ o lên 1 thì nhảy đến ngắt. encoder của mình dùng 100 xung. tức mỗi vòng quay thì chương trình sẽ ngắt 100 lần. nhưng đàn này không quay nó vẫn ngắt xảy ra.

dinhminh09
07-11-2010, 01:34 PM
If the GIE and INTE bits
are also set, the processor will redirect program
execution to the interrupt vector.

chắt là bạn chưa xoá cờ ngắt thì phải
#bit INTEDG = 0x81.6
#bit GIE = 0x0b.7
#bit INTE = 0x0b.4
INTEDG = 1;// cho phép ngắt cạnh lên
#INT_EXT
VOID DEM_NGAT()
{
XUNG++;
GIE = 0; //xoá cờ ngắt
INTE =0; //xoá cờ ngắt
return ;
}

thử lại xem sao mình cũng không biết có đúng không nữa.
thử lại rồi thông báo cho mình với

robotpic
08-11-2010, 09:29 PM
Uh mÌnh chƯa xÓa cỜ ngẮt.
NhƯng viẾt nhƯ bẠn ĐÂu phẢi xÓa cỜ ngẮt nhỈ.

dinhminh09
09-11-2010, 12:06 AM
vậy à. mình cũng đâu có biết. mình chỉ đọc trong datasheet rồi viết ra vậy thôi.
ủa viết lệnh xóa cờ ngắt là lệnh j nhỉ

robotpic
10-11-2010, 11:29 PM
bạn set dung bit chứ bạn, nếu không chương trình hiểu nhầm

dinhminh09
11-11-2010, 08:49 AM
nói thật là mình không hiểu ý bạn cho lắm. trước giờ để gán cho một bit bằng 0 mình vẫn làm như vậy cái sai ở đây là gì. và như thế nào là đúng

bit_set(var,bit); dùng hàm này à. bit_set(var,bit) Hàm này tương đương: var |= (1<<bit); dùng nó được à. mình nghĩ là không

mà cai code của banjchay chưa zậy. chạy rồi cho mình bản hoang chỉnh luôn đi :D

robotpic
11-11-2010, 10:42 PM
uh nó chạy rồi. nhưng vẫn không tốt. mình đang tìm hiểu, cái chính là mình xóa cờ ngắt sau mõi lần gọi chương trình ngắt. nhưng 3 ngắt mình thấy chu kỳ khác nhau.

vì sao ngăt ext2 lại số vong quay nhiều hơn.
#include <18f4331.h>
#INCLUDE <def_4331.h>

#FUSES HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT,NOPUT,NOCPD,NO DEBUG,NOFCMEN,NOCPB,STVREN,NOPWMPIN,HPOL_LOW
#FUSES MCLR,NOIESO,NOWRTC,NOWRTB,NOWRTD,NOEBTR,NOWRT,NOEB TRB,EXCLKD0,T1STANDARD,NOWINEN

#use delay(clock=20000000)

#use fast_io(a)
#use fast_io(d)
#use fast_io(c)
#use fast_io(e)


#DEFINE GIAI_MA1 RE0
#DEFINE GIAI_MA2 RE1
#DEFINE GIAI_MA3 RE2

#DEFINE NUT_AN RA0
#DEFINE CT_HT RA4

long XUNG,XUNG1,XUNG2;
int1 nut1,nut2,nut3,nut4,nut5,nut6,nut7,nut8;
int1 CT_HT1,CT_HT2,CT_HT3,CT_HT4,CT_HT5,CT_HT6,CT_HT7,C T_HT8;
#INT_EXT //RC3
VOID DEM_NGAT()
{
XUNG++;
INT0IF=0;
return ;
}

#INT_EXT1 //RC4
VOID DEM_NGAT_1()
{

XUNG1++;
INT1IF=0;
return ;
}

#INT_EXT2 //RC5

VOID DEM_NGAT_2()
{
XUNG2++;
INT2IF=0;
return;
}

VOID CT_PWM_POWER()
{
SET_POWER_PWM0_DUTY(100);

SET_POWER_PWM2_DUTY(500);

SET_POWER_PWM4_DUTY(200);

SET_POWER_PWM6_DUTY(500);

}
VOID CT_PWM_CCP ()
{

SET_PWM2_DUTY(250);
SET_PWM1_DUTY(500);
}
void main()
{
trisa=0x00;
porta=0xff;

trisb=0x00;
portb=0x00;

trisc=0b00111000;
//portC=0b00111000;

trisd=0x00;
portd=0xff;

trise=0x00;
porte=0xff;



setup_power_pwm_pins( PWM_ODD_ON,PWM_ODD_ON,PWM_ODD_ON,PWM_ODD_ON);
setup_power_pwm(PWM_CLOCK_DIV_4|PWM_FREE_RUN,1,0,1 24,0,1,0);
set_power_pwm_override(1, false, 0);
set_power_pwm_override(3, false, 0);
set_power_pwm_override(5, false, 0);
set_power_pwm_override(7, false, 0);

SETUP_CCP1(CCP_PWM);
SETUP_CCP2(CCP_PWM);
setup_timer_2(T2_DIV_BY_4,124,1);

enable_interrupts(GLOBAL);
enable_interrupts(INT_EXT);
enable_interrupts(INT_EXT1);
enable_interrupts(INT_EXT2);
ext_int_edge(0, L_TO_H );
ext_int_edge(1, L_TO_H );
ext_int_edge(2, L_TO_H );


xung=0;
xung1=0;
xung2=0;


while(TRUE)
{
IF(xung2==100) RA0=0;
else IF(XUNG2==1200) RA1=0;
else IF(XUNG2==1300) RA2=0;
else IF(xung2==1400) RA3=0;
else IF(xung2==1500) RA4=0;
else IF(xung2==1600) RA5=0;
else IF(xung2==2000) CT_PWM_POWER();
else IF(xung2==3000) CT_PWM_CCP ();
else IF(xung2>4000)
{
RD0=0;
DELAY_MS(500);
RD1=0;
DELAY_MS(500);
RD2=0;
DELAY_MS(500);
RD3=0;
DELAY_MS(500);
RD4=0;
DELAY_MS(500);
RD5=0;
DELAY_MS(500);
RD6=0;
DELAY_MS(500);

}
}

}