PDA

View Full Version : Hỏi về ngắt nhận INT_RDA trong PIC 16f877a!


dvnccbmacbt
06-08-2008, 09:19 PM
Em có vài chỗ thắc mắc về giao tiếp mong mọi người giúp đỡ:
khi khởi động hay reset pic thì có byte nào trong bọ đệm nhận không? Bởi vì khi em vừa
enable_interrupts(INT_RDA); thì có ngắt xảy ra và lặp lại liên tục?
đây là code của em

#include <16F877A.h>
#device 16F877*=16 ADC=8
//#fuses HS,NOWDT,NOPROTECT,NOLVP,xt
#FUSES HS //High speed Osc (> 4mhz)
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOCPD //No EE protection

#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOWDT

#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bi ts=8) // Giao tiep RS232

#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>

signed int16 so_xung,t1,t2,t3,err,err_temp,err_sum;
int1 chieu_quay,on,a;
int8 i,fini,j,n,cur,dem_chong_nhieu;
char str[10],value[5],data[5],b;
int16 m;
float Kp1,Ki1,Kd1,Kp2,Ki2,Kd2,Kp3,Ki3,Kd3;
float u_t;
float p_r_temp,p_r_temp1,p_r_temp2,p_r;
float p,tb,tf,vmax, amax;



#INT_RDA
void ngat_serial()
{ printf("a\r");
gets(str);
printf("b\r");
if ((str[strlen(str)-2]=='1')&&(str[strlen(str)-1]=='p')) fini = 1;
else if ((str[strlen(str)-2]=='1')&&(str[strlen(str)-1]=='i')) fini = 2;
else if ((str[strlen(str)-2]=='1')&&(str[strlen(str)-1]=='d')) fini = 3;
else if ((str[strlen(str)-2]=='1')&&(str[strlen(str)-1]=='v')) fini = 4;
else if ((str[strlen(str)-2]=='2')&&(str[strlen(str)-1]=='p')) fini = 5;
else if ((str[strlen(str)-2]=='2')&&(str[strlen(str)-1]=='i')) fini = 6;
else if ((str[strlen(str)-2]=='2')&&(str[strlen(str)-1]=='d')) fini = 7;
else if ((str[strlen(str)-2]=='3')&&(str[strlen(str)-1]=='p')) fini = 8;
else if ((str[strlen(str)-2]=='3')&&(str[strlen(str)-1]=='i')) fini = 9;
else if ((str[strlen(str)-2]=='3')&&(str[strlen(str)-1]=='d')) fini = 10;
else if ((str[strlen(str)-2]=='v')&&(str[strlen(str)-1]=='m')) fini = 11;
else if ((str[strlen(str)-2]=='a')&&(str[strlen(str)-1]=='m')) fini = 12;
else if ((str[0]=='o')&&(str[1]=='n')) on = 1;
strncpy(value,str,strlen(str)-2);
for(n=0;n<=9;n++) str[n]=NULL;

if (fini == 1) { Kp1 = (float)atol(value); }
else if (fini == 2) { Ki1 = (float)atol(value); }
else if (fini == 3) { Kd1 = (float)atol(value); }
else if (fini == 4) { p_r = (float)atol(value); }
else if (fini == 5) { Kp2 = (float)atol(value); }
else if (fini == 6) { Ki2 = (float)atol(value); }
else if (fini == 7) { Kd2 = (float)atol(value); }
else if (fini == 8) { Kp3 = (float)atol(value); }
else if (fini == 9) { Ki3 = (float)atol(value); }
else if (fini == 10){ Kd3 = (float)atol(value); }
else if (fini == 11){ vmax = (float)atol(value); }
else if (fini == 12){ amax = (float)atol(value); }

fini=0;
for(n=0;n<=4;n++) value[n]=NULL;
}



void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
set_timer0(5);
setup_timer_1 (T1_INTERNAL|T1_DIV_BY_8);
set_timer1(63035);
enable_interrupts(INT_EXT);
ext_int_edge(H_TO_L);
setup_ccp1(CCP_PWM);


//------gia tri ban dau cua cac bien-----------//
p_r = p_r_temp = err = err_temp = err_sum = so_xung = chieu_quay = i = j = on = cur= dem_chong_nhieu = 0;
fini = u_t = 0; kp1=ki1=kd1=kp2=ki2=kd2=kp3=ki3=kd3=0; vmax=amax=0;
m=t1=t2=t3=0;
//--------------------------------------------//

set_tris_b(0x00);
set_tris_a(0x00);
set_tris_e(0x00);
set_tris_c(0x80);
set_tris_d(0x00);
output_b(0x0);
output_a(0x0);
output_e(0x0);
output_d(0x0);
setup_timer_2 ( T2_DIV_BY_16, 255, 16);
set_pwm1_duty(0);

printf("ready\r");
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
output_a(0xff);
printf("oh\r");
while (on==0) output_d(0xff);
output_e(0xff);
printf("yeah\r");
//delay_ms(10000);

//---------------------------------------------//
}



và đây là kết quả nhận được (em dùng matlab nhận dữ liệu)

data =

ready



data =

oh



data =

a



data là biến để nhận dữ liệu. Theo như chương trình thì sau khi phát ra chuỗi "ready" và "oh" thì đúng ra phải chờ dữ liệu (while (on==0)). nhưng thực tế lại xảy ra ngắt nhận RDA và in ra "a" và dùng luôn ở đây ( không in ra ký tự "b"). Không biêt tại sao ngay khi enable_interrupts(INT_RDA); thì lại xảy ra ngắt mặc dù em chưa truyền dữ liêu.

Còn khi em thay lệnh gets(str) băng lệnh b=getc(); trong ngắt nhận thì chương trình cứ lặp lại liên tục. đây là dữ liệu nhận được:

data =

ready



data =

oh



data =

a



data =

b



data =

ready



data =

oh



data =

a



data =

b



data =

ready



data =

oh



data =

a



data =

b



data =

ready



data =

oh



data =

a



data =

b



Ở đây sau khi thực hiện ngắt nhận xong chương trình lại quay lại in ra "ready" "oh " rồi lại ngắt (in ra "a" "b" ) rồi lại in ra " ready" "oh" ..... Thế là sao ạ? tại sao chương trình lại lặp lại dược ạ?


Mong mọi người giúp đỡ. Em cảm ơn nhiều.

phamminhtuan
07-08-2008, 01:17 AM
...

#INT_RDA
void ngat_serial()
{ printf("a\r");
gets(str);
printf("b\r");
...


và đây là kết quả nhận được (em dùng matlab nhận dữ liệu)

data =

ready



data =

oh



data =

a

...
Còn khi em thay lệnh gets(str) băng lệnh b=getc(); trong ngắt nhận thì chương trình cứ lặp lại liên tục. đây là dữ liệu nhận được:

data =

ready



data =

oh



data =

a



data =

b



data =

ready



data =

oh



data =

a



data =

b



data =

ready



data =

oh



data =

a



data =

b



data =

ready



data =

oh



data =

a



data =

b


Trước tiên về truyền dữ liệu nối tiếp, bạn có biết là hàm gets() nó thực hiện việc lấy 1 chuỗi dữ liệu nhận được, tức là nó nhận từng ký tự, và chờ nhận ký tự tiếp theo cho đến khi nào gặp được ký tự '\0' thì dừng lại. Trong khi mỗi lần bạn nhận được 1 ký tự bất kì thì xảy ra ngắt, và dĩ nhiên chỉ có 1 ký tự mà bạn dùng gets() thì nó đứng đó chờ hoài rồi. getc() thì được.

Thứ hai là việc cho phép ngắt nhận truyền nối tiếp, nếu cờ nhận đã phất lên, có nghĩa là khi cho phép nó sẽ chạy đến ngắt luôn, bạn xem đã post đủ chương trình chưa, chẳng hạn ngắt INT_TBE, khi bạn dùng hàm printf thì khi phát xong mỗi ký tự trong chuỗi cũng đều xảy ra ngắt TBE nếu như bạn cho phép nó...

dvnccbmacbt
07-08-2008, 08:32 PM
Trước tiên về truyền dữ liệu nối tiếp, bạn có biết là hàm gets() nó thực hiện việc lấy 1 chuỗi dữ liệu nhận được, tức là nó nhận từng ký tự, và chờ nhận ký tự tiếp theo cho đến khi nào gặp được ký tự '\0' thì dừng lại. Trong khi mỗi lần bạn nhận được 1 ký tự bất kì thì xảy ra ngắt, và dĩ nhiên chỉ có 1 ký tự mà bạn dùng gets() thì nó đứng đó chờ hoài rồi. getc() thì được.

cảm ơn bạn. Nhưng mình chưa truyền đi bất kỳ ký tự nào cả, mình vừa mới cắm nguồn cho PIc thôi thì sau khi cho phép ngắt chương trình đã nhảy ngay vào ngắt rôi. Vì vậy mình mới thắc mắc khi reset thì có ký tự nào trong bộ đệm nhận không? Và cho mình hỏi thêm là tại sao khi dùng getc() thì chương trình lại cứ tự động lặp lại việc phát các ký tự "ready" "oh" . Nó cứ tự động lặp lại như vậy: phát ready rồi khi mình cho phép ngắt thì chương trình ngắt phát ra "a" "b" rồi lại lặp lại từ đầu , phát ready rồi lại ngắt và cứ như thế....Nghe có vẻ lạ đúng không? Nhưng mình thực sự không hiểu được.



data =

ready



data =

oh



data =

a



data =

b



data =

ready



data =

oh



data =

a



data =

b



data =

ready



data =

oh



data =

a



data =

b



data =

ready



data =

oh



data =

a



data =

b


bạn có thể cho mình một đoạn code mẫu được không?
Mong mọi người giúp đỡ

tranquangtrung
19-03-2009, 09:50 AM
Nhập môn đệ tử Xin chào các bác!
Các bác cho em hỏi làm thế nào mà ta có thể cấu hình thêm một chân giống như RB0 để sử dụng 2 ngắt ngoài trong PIC6F77A được không.em đang làm để tài về vấn đề này nhưng chưa giải quyết được.Mong các bác giúp đỡ cho em với nhé!
cảm ơn các bác nhiều!!!

Nin
19-03-2009, 09:03 PM
Cái này thuộc phần cứng, cấu hình thế nào được...

phandinh
20-03-2009, 02:53 AM
Nhập môn đệ tử Xin chào các bác!
Các bác cho em hỏi làm thế nào mà ta có thể cấu hình thêm một chân giống như RB0 để sử dụng 2 ngắt ngoài trong PIC6F77A được không.em đang làm để tài về vấn đề này nhưng chưa giải quyết được.Mong các bác giúp đỡ cho em với nhé!
cảm ơn các bác nhiều!!!
bạn phải dùng phần mềm để mở rộng ngắt thôi :
. bạn thiết lập counter0 ---> RA4 là ngõ vào counter0.
. giá trị ban đầu cho counter0 là 255.
. khi RA 4 thay đổi trạng thái thì counter đếm lên 1 ---> tràn ---> ngắt
. lặp lại bước 2

khuongbkhn
08-05-2012, 07:39 PM
Chào mọi người. Mình đang làm đề tài xử lú bản tin GPS. Nhưng mà code vẫn chưa chạy không biết sai ở đâu? Mong mọi người chỉ giúp dùm. Thanks nhiều!

#include "C:\Documents and Settings\FangFang\My Documents\code.h"
#define LCD_ENABLE_PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA_PORT D
#define LCD_TYPE 2
#include <lcd.c>
#byte SPBRG =0x99
#byte RCSTA =0x18
#byte PIR1 =0x0C
#byte RCREG =0x1A
#bit RCIF = 0x0c.5
#bit SPEN =0x18.7
#bit CREN =0x18.4
unsigned char GPSbuffer[70];
int8 position[11];
int8 check=0,i;
unsigned char GPRMC[7]="$GPRMC";
void find_comma()
{
int8 couter=0;
for(i=0;i<70;i++)
{
if(GPSbuffer[i]==',')
{
position[couter]=i;
couter++;
}
}
}
#INT_RDA
void receive_GPSbuffer()
{
char c;
c=getc();
if(check==69)
return;
GPSbuffer[check++]=getc();
if(check<7)
if(GPSbuffer[check-1]!=GPRMC[check-1])
check=0;
}
void time()
{
int8 i;
i=position[0];
printf(lcd_putc,"TIME: %c%c:%c%c:%c%c",GPSbuffer[i+1],GPSbuffer[i+2],
GPSbuffer[i+3],GPSbuffer[i+4],GPSbuffer[i+5],GPSbuffer[i+6]);
delay_ms(1000);
}
void latitude()
{
int8 i;
i=position[2];
if ((GPSbuffer[i+11]=='N') || (GPSbuffer[i+11]=='S'))
printf(lcd_putc,"LAT: %c%c.%c%c %c",GPSbuffer[i+1],GPSbuffer[i+2],GPSbuffer[i
+3],GPSbuffer[i+4],GPSbuffer[i+11]);
else
printf(lcd_putc,"LAT: %c.%c%c %c",GPSbuffer[i+1],GPSbuffer[i+2],GPSbuffer[i
+3],GPSbuffer[i+10]);
delay_ms(1000);
}
void longtitude()
{
int8 i;
i=position[4];
if ((GPSbuffer[i+12]=='W') || (GPSbuffer[i+12]=='E'))
printf(lcd_putc,"LONG: %c%c%c.%c%c %c",GPSbuffer[i+1],GPSbuffer[i+2],GPSbuffer[i
+3],GPSbuffer[i+4],GPSbuffer[i+5],GPSbuffer[i+12]);
else
printf(lcd_putc,"LONG:%c%c.%c%c %c",GPSbuffer[i+1],GPSbuffer[i+2],GPSbuffer[i
+3],GPSbuffer[i+4],GPSbuffer[i+11]);
delay_ms(1000);
}
void main()
{
lcd_init();
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
set_tris_b(0x00); // Set Port B as output port
set_tris_a(0x00);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
while (1)
{
//receive_GPSbuffer();
if (check==69)
{
find_comma();
time();
lcd_putc("\f");
longtitude();
lcd_putc("\f");
latitude();
lcd_putc("\f");
check=0;
}
}

SPBRG=spbrg_value; // Fill SPBRG register to set the baud rate
SPEN=1; // To activate serial port (Tx and Rx pins)
CREN=1; // To enable continuous reception

}

ThuNguyenvan
16-05-2012, 02:47 PM
Mình chuyển qua dùng HitechC lâu rồi nên CCS cũng không nhớ rõ. Tuy nhiên bao giờ thì khi trong isr của ngắt nào đó, bạn cũng phải clear cờ ngắt của nó đi. Ví dụng trong ngắt RDA thì phải có lệnh RXIF = 0, nếu không ngắt sẽ xảy ra liên tục.
Bạn kiểm tra xem đã clear cờ chưa nhé

otacon
27-05-2012, 06:08 PM
Mình chuyển qua dùng HitechC lâu rồi nên CCS cũng không nhớ rõ. Tuy nhiên bao giờ thì khi trong isr của ngắt nào đó, bạn cũng phải clear cờ ngắt của nó đi. Ví dụng trong ngắt RDA thì phải có lệnh RXIF = 0, nếu không ngắt sẽ xảy ra liên tục.
Bạn kiểm tra xem đã clear cờ chưa nhé

Theo mình nghĩ sau khi thoát ngắt với CCS thì nó đã tự xóa cờ ngắt rồi,không biết có phải thằng CCS nó "củ chuối củ mài" hay không chứ mình đã làm với động cơ và thấy là nhiều khi phải "chèn thêm" 1 hoặc 2 dòng lệnh vào những "chỗ hiểm" thì nó mới ổn định và chạy đúng.
bản thân mình đã là giao tiếp qua RS232 với CCS và thấy không có vấn đề gì cả,nhưng có nhiều chương trình trên PC thì rất là dở,chủ yếu là tự viết bằng VB hoặc VC với trình độ còn khá hạn chế