PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   Giao tiếp cổng COM và LPT (http://www.picvietnam.com/forum/forumdisplay.php?f=44)
-   -   cần giúp giao tiếp pc và 18f4680 qua cổng com (http://www.picvietnam.com/forum/showthread.php?t=2666)

tungtot_vl 01-08-2008 08:03 AM

cần giúp giao tiếp pc và 18f4680 qua cổng com
 
mình đã làm giao tiếp qua pc và pic qua cổng com cho các pic 184580 và 18f4550 thì nhận và truyền dữ liệu bình thường nhưng khi dùng pic 18f4680 thì chỉ nhận được data từ pic lên pc còn truyền từ pc xuống thì pic ko nhận được. mình không hiểu vì sao nữa. không biết 18f4680 có cần khai báo gì thêm hay sai xót gì không đạn nào biế chỉ giúp với.
mình đã thử giữa các pic cho cùng 1 chương trình và mạch text nhưng chỉ có 18f4680 là không nhận data từ pc gởi xuống. chỉ giúp mình nhé.

namqn 01-08-2008 06:08 PM

Trích:

Nguyên văn bởi tungtot_vl (Post 17887)
mình đã làm giao tiếp qua pc và pic qua cổng com cho các pic 184580 và 18f4550 thì nhận và truyền dữ liệu bình thường nhưng khi dùng pic 18f4680 thì chỉ nhận được data từ pic lên pc còn truyền từ pc xuống thì pic ko nhận được. mình không hiểu vì sao nữa. không biết 18f4680 có cần khai báo gì thêm hay sai xót gì không đạn nào biế chỉ giúp với.
mình đã thử giữa các pic cho cùng 1 chương trình và mạch text nhưng chỉ có 18f4680 là không nhận data từ pc gởi xuống. chỉ giúp mình nhé.

Code của bạn ra sao (ít nhất là phần cấu hình cho PIC và các đoạn code liên quan đến giao tiếp RS-232)?

Thân,

tungtot_vl 23-08-2008 05:21 PM

max232
 
Trích:

Nguyên văn bởi namqn (Post 17896)
Code của bạn ra sao (ít nhất là phần cấu hình cho PIC và các đoạn code liên quan đến giao tiếp RS-232)?

Thân,

lâu rồi không lên mạng nên em không phản hồi lại anh nam được, thành thật xin lỗi. em đã khắc phục được lỗi trên rồi. nguyên nhân là có 1 số vdk em khai báo "set_tris_c(0x00);" nhưng vẫn giao tiếp nhận và truyền với pc bình thường. nhưng có một số khai báo "set_tris_c(0x80);" thì mới truyền được.
em có ý này muốn nhờ anh nam chỉ giáo thêm.
từ trước đến nay khi giao tiếp pic với pc. khi pc gởi xuống 1 chuỗi data, thì em lập trì cho pic mỗi lần ngắt chỉ nhận 1 byte sau đó nhảy về vị trí cũ, rồi lại nhảy vào ngắt nhận byte khác cho đến khi hết chuỗi data từ pc gởi xuống thì thôi. chuỗi từ pc gởi xuống có bao nhiêu byte thì ngắt bấy nhiêu lần.
không biết có cách nào để khi pc gởi xuống 1 chuổi có nhiều byte mà pic chỉ ngắt có 1 lần nhảy vào nhận toàn bộ data rồi mới nhảy ra không hả anh nam. nếu bác nào biết hoặc có ý kiến gì xin chỉ giúp luôn.

ngohaibac 23-08-2008 05:25 PM

Trích:

Nguyên văn bởi tungtot_vl (Post 18348)
lâu rồi không lên mạng nên em không phản hồi lại anh nam được, thành thật xin lỗi. em đã khắc phục được lỗi trên rồi. nguyên nhân là có 1 số vdk em khai báo "set_tris_c(0x00);" nhưng vẫn giao tiếp nhận và truyền với pc bình thường. nhưng có một số khai báo "set_tris_c(0x80);" thì mới truyền được.
em có ý này muốn nhờ anh nam chỉ giáo thêm.
từ trước đến nay khi giao tiếp pic với pc. khi pc gởi xuống 1 chuỗi data, thì em lập trì cho pic mỗi lần ngắt chỉ nhận 1 byte sau đó nhảy về vị trí cũ, rồi lại nhảy vào ngắt nhận byte khác cho đến khi hết chuỗi data từ pc gởi xuống thì thôi. chuỗi từ pc gởi xuống có bao nhiêu byte thì ngắt bấy nhiêu lần.
không biết có cách nào để khi pc gởi xuống 1 chuổi có nhiều byte mà pic chỉ ngắt có 1 lần nhảy vào nhận toàn bộ data rồi mới nhảy ra không hả anh nam. nếu bác nào biết hoặc có ý kiến gì xin chỉ giúp luôn.

Cái này không thể được với PIC18F4680. Bạn xem lại datasheet phần UART thì bộ đệm chỉ là 1 byte thôi, nên mỗi lần chỉ nhận được 1 byte. Có thể các dòng đời cao hơn sẽ hỗ trợ UART có bộ đệm cao hơn.

Chúc bạn thành công.

phamminhtuan 23-08-2008 08:54 PM

Trích:

Nguyên văn bởi tungtot_vl (Post 18348)
lâu rồi không lên mạng nên em không phản hồi lại anh nam được, thành thật xin lỗi. em đã khắc phục được lỗi trên rồi. nguyên nhân là có 1 số vdk em khai báo "set_tris_c(0x00);" nhưng vẫn giao tiếp nhận và truyền với pc bình thường. nhưng có một số khai báo "set_tris_c(0x80);" thì mới truyền được.
em có ý này muốn nhờ anh nam chỉ giáo thêm.
từ trước đến nay khi giao tiếp pic với pc. khi pc gởi xuống 1 chuỗi data, thì em lập trì cho pic mỗi lần ngắt chỉ nhận 1 byte sau đó nhảy về vị trí cũ, rồi lại nhảy vào ngắt nhận byte khác cho đến khi hết chuỗi data từ pc gởi xuống thì thôi. chuỗi từ pc gởi xuống có bao nhiêu byte thì ngắt bấy nhiêu lần.
không biết có cách nào để khi pc gởi xuống 1 chuổi có nhiều byte mà pic chỉ ngắt có 1 lần nhảy vào nhận toàn bộ data rồi mới nhảy ra không hả anh nam. nếu bác nào biết hoặc có ý kiến gì xin chỉ giúp luôn.

Có 1 giải thuật nhận dữ liệu từ UART thế này, bạn dùng bộ đệm 16 byte nhé
PHP Code:

unsigned char RxR=0RxW=0buffer[16];
#INT_RDA
void rda_isr() {
   
buffer[RxW] = getc();
   
RxW++;
   
RxW&=0x0F;
}

void main() {
   
//init UART, interrupt...
  
while(1) {
  if(
RxR != RxW) {
     
//xử lý byte nhận được ở đây
    
RxR++;
    
RxR&=0x0F;
  }
 }


Làm theo cách trên thì bạn sẽ không bỏ sót byte nào từ PC gởi xuống cả

tungtot_vl 28-08-2008 04:31 PM

cảm ơn 2 bạn nhiều. code của bạn minh tuan liệu có ổn không. nếu trong vòng lặp while(1) thời gian làm việc cho vòng này từ 5 đến 10 phút thì khi pc gởi xuống liên tục nhiều byte mà trong khi vòng if(RxR != RxW) {
//xử lý byte nhận được ở đây
RxR++;
chưa kịp xử lý thì sẽ bị tràn bộ đệm buffer[16]; thì sao. nếu bị tràn thì sẽ bị mất byte thôi. cò nếu tăng buffer[16]; lên thì không biết tăng bao nhiêu cho thích hợp nữa vì nó phụ thuộc vào số byte pc gởi xuống và thời gian xử lý hết vòng while(1) phải không. mong bạn góp ý kiến.
bạn haibac có thể nói rỏ hơn pic nào có nhiều bộ đệm trong uart không.
cảm ơn hai bạn nhiều!

namqn 28-08-2008 09:52 PM

Trích:

Nguyên văn bởi tungtot_vl (Post 18440)
cảm ơn 2 bạn nhiều. code của bạn minh tuan liệu có ổn không. nếu trong vòng lặp while(1) thời gian làm việc cho vòng này từ 5 đến 10 phút thì khi pc gởi xuống liên tục nhiều byte mà trong khi vòng if(RxR != RxW) {
//xử lý byte nhận được ở đây
RxR++;
chưa kịp xử lý thì sẽ bị tràn bộ đệm buffer[16]; thì sao. nếu bị tràn thì sẽ bị mất byte thôi. cò nếu tăng buffer[16]; lên thì không biết tăng bao nhiêu cho thích hợp nữa vì nó phụ thuộc vào số byte pc gởi xuống và thời gian xử lý hết vòng while(1) phải không. mong bạn góp ý kiến.
bạn haibac có thể nói rỏ hơn pic nào có nhiều bộ đệm trong uart không.
cảm ơn hai bạn nhiều!

Nếu vòng lặp while (1) của bạn lâu như vậy thì bạn nên viết lại để thường xuyên kiểm tra bộ đệm hơn.

Bộ đệm có thể tăng lên theo yêu cầu của khối dữ liệu, nếu xử lý không kịp trong vòng while (1). PIC18F4680 có khá nhiều RAM.

PIC24/dsPIC hay PIC32 có bộ đệm 4 mức cho module UART. Như thế là đủ cho việc giao tiếp bằng RS-232 rồi.

Cho đến giờ, bạn vẫn chưa đưa ra vấn đề cụ thể của bạn, mà chỉ hỏi cách thực hiện những gì mà bạn cho là giải pháp. Tôi cho rằng thời gian hoàn tất một vòng while (1) từ 5 đến 10 phút là không hợp lý, nên viết lại.

Thân,

cskiller 28-08-2008 10:46 PM

Sử dụng bộ đệm dạng queue vòng trong ngắt #INT_RDA, vừa tận dụng tối đa kích thước buffer mà ko cần reset các buffer counter vừa tiện lợi nhận dạng và xử lý dữ liệu(có thể đọc chuỗi byte hay string từ queue này).

namqn 28-08-2008 11:49 PM

Trích:

Nguyên văn bởi cskiller (Post 18448)
Sử dụng bộ đệm dạng queue vòng trong ngắt #INT_RDA, vừa tận dụng tối đa kích thước buffer mà ko cần reset các buffer counter vừa tiện lợi nhận dạng và xử lý dữ liệu(có thể đọc chuỗi byte hay string từ queue này).

Chẳng phải code của phamminhtuan đã hiện thực đúng những gì bạn vừa nêu sao?

Thân,

cskiller 29-08-2008 08:58 AM

Trích:

Nguyên văn bởi namqn (Post 18449)
Chẳng phải code của phamminhtuan đã hiện thực đúng những gì bạn vừa nêu sao?

Thân,

Không, code của bạn phamminhtuan chỉ xử lý được khi vòng while kịp xử lý dữ liệu trong buffer. Còn khi PC gởi data hàng loạt mà vòng while chưa kịp xử lý thì dẫn đến dữ liệu có thể bị chồng lấn lẫn nhau vì RxR và RxR không có quan hệ gì với nhau.
Giả sử RxR = 5, RxW = 10 sau đó nếu PC gởi 11 ký tự thì RxR=RxW=5 nghĩa là ko có nhận được dữ liệu gì ah? Còn nếu PC gởi lớn hơn 11 ký tự thì ...
Nên phải sử dụng 2 điều kiện: if(RxW ==(16 + RxR -1)%16) để báo trạng thái buffer tràn. Nếu muốn cho phép ghi đè dữ liệu khi tràn(xóa byte cũ nhất chưa được xử lý) hay không(byte mới nhận bị bỏ qua) thì thêm dòng xử lý sau đó.

Good luck.

ngohaibac 30-08-2008 09:18 PM

Em đã làm rồi, để không bị đè dữ liệu không kịp xử lý và để nhận hàng loạt dữ liệu thì có giải pháp sau:

1.Khi setting cho RS232 trên PC thì chọn Flow Control là XON/XOFF. Và phần mềm bên dưới cũng xử lý dùng các kí tự XON/XOFF để điều khiển dòng dữ liệu từ PC truyền xuống. Khi bên PC nhận dc tín hiệu XOFF nó sẽ tự k gửi xuống nữa, khi nhận kí tự XON nó sẽ tiếp tục gửi xuống.

2. Quá trình xử lý thực hiện trong hàm ngắt, chứ không phải trong vòng lặp While trong main. Tất nhiên là biết chính xác độ dài của khối dữ liệu ví dụ là n = 20; Khai báo một mảng dữ liệu ở một bank nào đó.

Code:

static bank1 unsigned char data[n]; // Khai báo ở bank 1
static bank1 unsigned char index = 0; // biến đếm

Còn trong hàm ngắt xử lý nhận như sau:
Code:

//Send XOFF character
if (index == n){
      index = 0;
      // Do something with data
}
else {
    data[index] = UART_Data;
    index++; // increase index
};
//Send XON character

Chúc bạn thành công.

tungtot_vl 04-09-2008 09:01 PM

cách của bạn haibac cung hay. nhưng khó quá, thông thường mình chỉ gởi từ pc xuống pic để xử lý thôi còn ngược lại từ pic lên pc để pc xử lý thì chưa biết cách làm.
mình cũng đang gặp vấn đề về địa chỉ eeprom của 18f4680. con này có eeprom 1k nhưng mình tìm datasheet của nó để xem địa chỉ eeprom của nó nhưng không tìm được. bạn nào biết địa chỉ eeprom của nó nằm trong khoảng nào chỉ giúp mình với. vì mình cũng cần lưu data vào eeprom. nhưng khi lưu ở địa chỉ 0xc9 đến 0x160 thì không lưu được ở các địa chỉ này mong các bạn chỉ giúp

namqn 04-09-2008 10:11 PM

Trích:

Nguyên văn bởi tungtot_vl (Post 18637)
cách của bạn haibac cung hay. nhưng khó quá, thông thường mình chỉ gởi từ pc xuống pic để xử lý thôi còn ngược lại từ pic lên pc để pc xử lý thì chưa biết cách làm.
mình cũng đang gặp vấn đề về địa chỉ eeprom của 18f4680. con này có eeprom 1k nhưng mình tìm datasheet của nó để xem địa chỉ eeprom của nó nhưng không tìm được. bạn nào biết địa chỉ eeprom của nó nằm trong khoảng nào chỉ giúp mình với. vì mình cũng cần lưu data vào eeprom. nhưng khi lưu ở địa chỉ 0xc9 đến 0x160 thì không lưu được ở các địa chỉ này mong các bạn chỉ giúp

Thông tin trong tập tin "18f4680.lkr" (trong thư mục con "lkr" của thư mục cài đặt MPLAB C18):
Code:

CODEPAGE  NAME=eedata    START=0xF00000      END=0xF003FF      PROTECTED
Vùng EEPROM của PIC18F4680 có địa chỉ bắt đầu là 0xF00000, kết thúc tại 0xF003FF. Bạn tham khảo các ví dụ về EEPROM của CCS C xem có hàm nào dùng để ghi vào EEPROM hay không (Theo tài liệu hướng dẫn của CCS C thì có hàm write_eeprom(address, value)).

Nếu tự viết hàm thì bạn chú ý mục 7 trong datasheet (Data EEPROM Memory), xem kỹ các ví dụ 7-1 và 7-2. Bạn sẽ thấy là truy xuất vùng nhớ EEPROM bằng cách bật bit EPGD của thanh ghi EECON1, còn địa chỉ thì chỉ có 10 bit, bắt đầu từ 0x0000 và kết thúc tại 0x03FF.

Thân,

tungtot_vl 05-09-2008 09:05 AM

cảm ơn anh nam đã giúp đỡ.

tungtot_vl 10-09-2008 09:46 PM

các anh giúp eeprom với.
bài này em gởi từ pc xuống nhiều chuỗi dũa liệu khác nhau.
khi gởi chuổi đầu tiên thì data viết vào và đọc ra cho chuôi đầu là đúng.
khi gởi tiếp chuổi thứ 2 thì chuổi data của chuổi thứ 2 đọc ra cũng đúng nhưng chuỗi 1 đọc ra lại sai
khi gởi chuỗi 3 thì chuối 3 đọc ra đúng còn chuỗi 1 và 2 đọc ra sai.
cứ tiếp tục như vậy. chuỗi vừa gởi xuống thì đọc đúng còn các chuỗi khác thì bị sai. trong khi khoảng cách địa chỉ giữa các chuỗi lớn hơn data gởi xuống
tôi không rỏ vì sao nữa. ai biết chỉ giúp với.


Code:

#include<18F4580.h>
#fuses NOLVP,NOWDT,PUT,hs,NOPROTECT,NOBROWNOUT
#device 18f4680*=16 ADC=10 high_ints=true
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use fast_io(a)
#byte porta=0x05
#use fast_io(b)
#byte portb=0x06
#use fast_io(c)
#byte portc=0x07
#use fast_io(d)
#byte portd=0x08
#use fast_io(e)
#byte porte=0x09
#define ch1    0x0005    //
#define ch2    0x00a5    // khoang cach 160 byte
#define ch3    0x0145
#define ch4    0x01e5
#define ch5    0x0285

//======================================================
int8 ram[150];
int8 count = 0;
int8 tam,l;
//==============================================================================
          void giao_tiep();
          void viet_eeprom();


#INT_EEPROM FAST
void viet_eeprom()
  {  int8 ma,j;
      ma = ram[0]; // mã xác định chuỗi
      printf(" %u",ma);
          switch(ma)
              {  case 1: for(j=0;j<139;j++) { write_eeprom(ch1+j,ram[j]); printf(" %u",ram[j]);  } break;
                case 2: for(j=0;j<139;j++) { write_eeprom(ch2+j,ram[j]); printf(" %u",ram[j]);  } break;
                case 3: for(j=0;j<139;j++) { write_eeprom(ch3+j,ram[j]); printf(" %u",ram[j]); } break;
                case 4: for(j=0;j<139;j++) { write_eeprom(ch4+j,ram[j]); printf(" %u",ram[j]); } break;
                case 5: for(j=0;j<139;j++) { write_eeprom(ch5+j,ram[j]); printf(" %u",ram[j]); } break;  /// printf(" %u",read_eeprom(ch5+j)); dùng vẫn sai
              }

  }

#INT_RDA
void giao_tiep() // doc pc xuong ram roi do vao eeprom
  {  int8 c,i;
      c = getc();
  //--------------------------------
      if(c!=250)  //1 byte dau tien dung de chon ma chuoi
        {
          ram[count] = count; count++;  }
      else
        { count=0; viet_eeprom();  printf("ok");  }

  }

 ////////////////////////////////////////////////
 void main()
  {
      set_tris_b(0);
      set_tris_a(0);
      set_tris_c(0x80);
      set_tris_e(0);
      set_tris_d(0);
      enable_interrupts(INT_eeprom);
      enable_interrupts(INT_RDA);
      enable_interrupts(global);
    while(true)
        {
          printf("ch1 ");
          for(l=0;l<139;l++)
            {
                tam = read_eeprom(ch1+l);
                delay_ms(5);
                printf("/%u",tam);
            }
          delay_ms(3000);
          printf("ch2 ");
          for(l=0;l<139;l++)
            {
                tam = read_eeprom(ch2+l);
            printf("/%u",tam);
            }
          delay_ms(1000);
          printf("ch3 ");
          for(l=0;l<139;l++)
            {
                tam = read_eeprom(ch3+l);
            printf("/%u",tam);
            }
          delay_ms(1000);
          printf("ch4 ");
          for(l=0;l<139;l++)
            {
                tam = read_eeprom(ch4+l);
                printf("/%u",tam);
            }
          delay_ms(1000);
          printf("ch5 ");
          for(l=0;l<139;l++)
            {
                tam = read_eeprom(ch5+l);
                printf("/%u",tam);
            }
          delay_ms(1000);
        }
  }



Múi giờ GMT. Hiện tại là 09:04 PM.

Tên diễn đàn: vBulletin Version 3.7.2
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam