PDA

View Full Version : dsPIC30F4011 RS232 RS485 nhờ mọi người giúp!!!


hpecom
24-06-2008, 12:23 AM
Kính gửi anh Nam và các bạn,

Em dùng dsPIC30F4011 và dsPIC2010 giao tiếp RS485. dsPIC30F4011 vừa giao tiếp RS485 vừa giao tiếp RS232 với PC.

_ Tình trạng lỗi như sau: + với dsPIC30F4011 nếu dùng kết nối RS485 thì tín hiệu truyền từ PIC lên chập chờn, lúc được lúc không lúc thì nhiễu loạn, nếu sờ tay vào dây nối giữa dsPIC và Max485 thì nhiễu càng nhiều. Toàn nhận được các ký tư <0> và các số ngẫu nhiên đủ thứ.
Với RS232 thì chạy tốt, khi sờ tay vào dây nối giữa dsPIC và RS232 thì không xuất hiện các giá trị trên.
+ Đối với dsPIC30F2010 thì làm việc tốt cả với RS232 và RS485.
Dưới đây là Schematic và code em sửa từ Tutorial của anh Nam.

Mong rằng các bạn đã gặp tình huống này thì chia sẻ kinh nghiệm xử lý cho mình và mọi người cùng biết.

Xin cảm ơn và chào đoàn kết.

namqn
24-06-2008, 09:05 PM
Trước hết, cần nối các chân AVDD và AVSS vào những điện thế thích hợp. Ngay cả khi chúng ta không dùng module ADC, vẫn cần phải nối những chân này đến nguồn. Đơn giản vì chúng ta không biết cấu trúc bên trong của dsPIC như thế nào, nên không thể khẳng định rằng thả nổi hai chân này sẽ không gây ảnh hưởng gì đến các module lân cận nó.

Và các cặp chân nguồn luôn luôn cần tụ bypass (decoupling) để đảm bảo hoạt động ổn định, thường dùng tụ gốm/kẹo (ceramic) 100 nF (104) cho mục đích này.

Thân,

hpecom
25-06-2008, 01:32 AM
Chào anh Nam và các bạn,

Em đã cắm tụ mà vẫn không xử lý được hiện tượng trên, em dùng điện trở 10K treo chân Tx của dsPIC lên nguồn thì thấy không còn tình trạng trên, nhưng lại sinh một tình trạng mới khi viết code truyền. Đoạn code em viết như sau:

#include <p30f4011.h>

_FOSC(CSW_FSCM_OFF & XT_PLL4);//FRC_PLL4
_FWDT(WDT_OFF);
_FBORPOR(PBOR_OFF & MCLR_EN);
_FGS(CODE_PROT_OFF);

//------------------------------------------------------------------------------
//Cac hang so cua chuong trinh (gia tri tuc thoi dung trong chuong trinh)
#define Fcy 4000000 //Tan so thuc thi lenh (Thach anh 4MHz)
#define baud 9600 //Toc do baud cua RS232
#define _ISR_PSV __attribute__((interrupt, auto_psv))

//Cac prototype cho cac chuong trinh con
void Init_PORTS(void);
void Init_ADC10(void);
void Init_TMR1(void);
void Init_UART1(void);
//void Init_UART2(void);
unsigned int CRC_Calc(int* pMes);

//Cac bien toan cuc
unsigned int gFlag_1,gFlag_2;
unsigned char gFwd[]={0x01,0x06,0x01,0x50,0x00,0x01,0x49,0xE7};
unsigned char gRev[]={0x01,0x06,0x01,0x50,0x00,0x02,0x09,0xE6};
unsigned char gStop[]={0x01,0x06,0x01,0x50,0x00,0x00,0x88,0x27};
unsigned char gSpe[]={0x01,0x06,0x00,0x80,0x03,0x89,0x0A};
unsigned char gRec[10]={0,1,2,3,4,5,6,7,8,9};
unsigned char gRPos=0;
unsigned char gTPos=0;
unsigned char gRCount=0;
unsigned char gCmd=0;
int gEE_Return;
//------------------------------------------------------------------------------
//Chuong trinh chinh
int main(void) {
Init_PORTS(); //Khoi tao cac cong I/O
Init_TMR1(); //Khoi tao Timer 1
Init_UART1(); //Khoi tao module UART1
//Init_UART2(); //Khoi tao module UART2
_LATB3=0; //Cho phep nhan Data
while (1)
{ if(gFlag_1)
{ gFlag_1=0;
_LATB0^=1;
_LATB3=1; //Cho phep gui Data
while(gTPos!=gRPos)
{ //U1TXREG = gRec[1]; //Neu bo dong nay
//while (!U1STAbits.TRMT); //va bo dong nay thi lenh truyen ben duoi khong duoc thuc hien
U1TXREG = gRec[gTPos];
while (!U1STAbits.TRMT);
if(++gTPos>9) gTPos=0;
};
_LATB3=0; //Cho phep nhan Data
}
};
}
//================================================== ==========================
//Function tinh CRC
//================================================== ==========================
unsigned int CRC_Calc(int* pMes)
{ unsigned int mCRC_Reg=0xFFFF;
unsigned char mHighByte;
unsigned char mLowByte;
return 1;
}
//Chuong trinh con khoi tao cac cong I/O, de xuat cac tin hieu PWM, va doc tin
//hieu dieu chinh cua bien tro tai AN0
void Init_PORTS(void) {
TRISB = 0x0000; //Chan RB0 la ngo vao analog AN0, cac chan khac
//la ngo ra
LATD = 0; //Xoa thanh ghi chot cong D
TRISD = 0xFFFE;
//LATE=0;
//TRISE=0xFF;
}
//Chuong trinh con khoi tao Timer 1, tran sau moi 1 giay o muc xung 8 Mips
void Init_TMR1(void) {
TMR1 = 0; //Xoa so dem trong TMR1
PR1 = 0x3D09; //Nguong tran la 1 giay ung voi clock = 32 MHz
_T1IF = 0; //Xoa co ngat cua Timer 1
T1CON = 0x8030; //Dung fcy lam clock, prescale = 1:256
_T1IE = 1; //Cho phep ngat khi Timer 1 tran
}
//Chuong trinh con khoi tao module UART1
void Init_UART1(void) {
U1MODE = 0x8000; //Main I/O, 8-bit, no parity, 1 stop bit
//U1MODE = 0x8400; //ALT I/O, 8-bit, no parity, 1 stop bit
U1STA = 0x0400; //bit10=UTXEN
U1BRG = (((Fcy/baud)/16)-1); //38400 bps @ Fcy = 8 MHz
_U1RXIF = 0;
_U1RXIE=1;
}
//Chuong trinh xu ly ngat Timer 1
//void _ISR _T1Interrupt(void)
void _ISR_PSV _T1Interrupt(void)
{ _LATD0^=1;
_T1IF = 0; //Xoa co ngat
}
//Chuong trinh xu ly ngat truyen thong UART
void _ISR_PSV _U1RXInterrupt(void)
{ gFlag_1 = 1;
while(U1STAbits.URXDA)
{ gRec[gRPos]=U1RXREG;
if (++gRPos>9) gRPos=0;
if(++gRCount>9) gRCount=0;
};
_U1RXIF = 0;
}

Nếu bỏ 2 dòng lệnh 71 và 72 thì 2 dòng lệnh 73 và 74 không được thực hiện, mặc dù khi có dữ liệu đến thì dsPIC vẫn xảy ra ngắt UART.
Khi có 2 dòng lệnh này thì cả hai dòng dưới cũng được thực hiện. Dữ liệu truyền không còn bị nhiễu như trước.
Mong anh và mọi người trợ giúp!!!

Chúc mọi người một ngày mới tốt đẹp!

namqn: bạn chú thích thẳng dòng 71 và 72 là những dòng nào trong code.

namqn
25-06-2008, 02:10 AM
Bạn chú thích thẳng vào code đã post vị trí hai dòng đó, vì copy code đã post vào trình soạn thảo cho thấy dòng 71 chỉ có chú thích chứ không chứa lệnh.

Thân,

hpecom
25-06-2008, 03:22 PM
Xin lỗi anh vì em copy thiếu phần title của chương trình!
Dạ, nó nằm trong vòng lặp While() thứ 2 của hàm Main(), đó là 2 dòng lệnh này anh ạ:

//U1TXREG = gRec[1]; //Neu bo dong nay
//while (!U1STAbits.TRMT); //va bo dong nay thi lenh truyen ben duoi khong duoc thuc hien


Nếu em bỏ dấu comment thì cả hai lệnh truyền sẽ được thực hiện. Còn để như hiện tại thì nó sẽ không được truyền.
Em vẫn chưa tìm ra được nguyên nhân.

namqn
25-06-2008, 05:45 PM
Theo sơ đồ phần cứng của bạn, chân PWM1L/RE0 điều khiển chiều truyền/nhận của MAX485. Và trong code hiện tại không có lệnh thao tác trạng thái của chân này. Như vậy trạng thái của các chân DE và /RE (đã nối vào nhau) của MAX485 là không xác định trước, và dễ bị nhiễu nếu chân RE0 là ngõ vào, vì chỉ được treo bởi một điện trở 10 k lên 5 V.

Thân,

hpecom
26-06-2008, 12:33 AM
Dạ em đã sửa lại code.
Em thử nhiều lần thì phát hiện rằng: trong vòng lặp While() thứ 2 của hàm Main() nếu số lần truyền là số chẵn thì không bị mất dữ liệu, còn nếu số lần truyền là số lẻ thì sẽ mất ký tự cuối cùng, không biết điều này có liên quan gì đến việc cấu hình không vậy anh?


#include <p30f4011.h>

_FOSC(CSW_FSCM_OFF & XT_PLL4);//FRC_PLL4
_FWDT(WDT_OFF);
_FBORPOR(PBOR_OFF & MCLR_EN);
_FGS(CODE_PROT_OFF);

//----------------------------------------------------------------------------
//Cac hang so cua chuong trinh (gia tri tuc thoi dung trong chuong trinh)
#define Fcy 4000000 //Tan so thuc thi lenh (Thach anh 4MHz)
#define baud 9600 //Toc do baud cua RS232
#define _ISR_PSV __attribute__((interrupt, auto_psv))
//----------------------------------------------------------------------------
//Cac prototype cho cac chuong trinh con
void Init_PORTS(void);
void Init_ADC10(void);
void Init_TMR1(void);
void Init_UART1(void);
//void Init_UART2(void);
//----------------------------------------------------------------------------
//Khai bao bien toan cuc
unsigned int CRC_Calc(int* pMes);

unsigned int gFlag_1,gFlag_2;
unsigned char gFwd[]={0x01,0x06,0x01,0x50,0x00,0x01,0x49,0xE7};
unsigned char gRev[]={0x01,0x06,0x01,0x50,0x00,0x02,0x09,0xE6};
unsigned char gStop[]={0x01,0x06,0x01,0x50,0x00,0x00,0x88,0x27};
unsigned char gSpe[]={0x01,0x06,0x00,0x80,0x03,0x89,0x0A};
unsigned char gRec[10]={0,1,2,3,4,5,6,7,8,9};
unsigned char gRPos=0;
unsigned char gTPos=0;
unsigned char gRCount=0;
unsigned char gCmd=0;
int gEE_Return;
//================================================== ==========================
//CHUONG TRINH CHINH
//Kiem tra co gFlag (co bao UART1 nhan du lieu)
//Truyen ky tu nhan duoc
//================================================== ==========================
int main(void) {
Init_PORTS(); //Khoi tao cac cong I/O
Init_TMR1(); //Khoi tao Timer 1
Init_UART1(); //Khoi tao module UART1
//Init_UART2(); //Khoi tao module UART2
_LATE0=0; //Cho phep nhan Data
while (1)
{ if(gFlag_1)
{ gFlag_1=0;
_LATB0^=1;
_LATE0=1; //Cho phep gui Data

/* Thuc hien truyen du lieu ra cong UART1
_ Neu truyen 2n ky tu thi khong mat Data
_ Neu truyen (2n+1) ky tu thi mat ky tu cuoi cung
*/
while(gTPos!=gRPos)
{ U1TXREG = gRPos; //
while (!U1STAbits.TRMT);
U1TXREG = gTPos; //
while (!U1STAbits.TRMT);
U1TXREG = gRCount; //
while (!U1STAbits.TRMT);
U1TXREG = gCmd; //
while (!U1STAbits.TRMT);
U1TXREG = gRec[gRPos]; //
while (!U1STAbits.TRMT);
U1TXREG = gRec[gTPos]; //
while (!U1STAbits.TRMT); //
if(++gTPos>9) gTPos=0;
};
_LATE0=0; //Cho phep nhan Data
}
};
}
//================================================== ==========================
//Function tinh CRC
//================================================== ==========================
unsigned int CRC_Calc(int* pMes)
{ unsigned int mCRC_Reg=0xFFFF;
unsigned char mHighByte;
unsigned char mLowByte;
return 1;
}
//================================================== ==========================
//Proc khoi tao cac cong I/O
//================================================== ==========================
void Init_PORTS(void) {
TRISB = 0x0000; //RB0 la ngo ra
LATD = 0; //Xoa thanh ghi chot cong D
TRISD = 0xFFFE;
LATE=0;
TRISE=0x0000; //PortE la Digital Output
}
//================================================== ==========================
//Proc khoi tao va setup Timer1 (Ngat sau 1S)
//================================================== ==========================
void Init_TMR1(void) {
TMR1 = 0; //Xoa so dem trong TMR1
PR1 = 0x3D09; //Nguong tran la 1 giay (=4000000/256)
_T1IF = 0; //Xoa co ngat cua Timer 1
T1CON = 0x8030; //Dung fcy lam clock, prescale = 1:256
_T1IE = 1; //Cho phep ngat khi Timer 1 tran
}
//================================================== ==========================
//Proc khoi tao module UART1
//Baud rate = 9600, 8 bit Data, no Parity, 1 bit stop
//================================================== ==========================
void Init_UART1(void) {
U1MODE = 0x8000; //Main I/O, 8-bit, no parity, 1 stop bit
//U1MODE = 0x8400; //ALT I/O, 8-bit, no parity, 1 stop bit
U1STA = 0x0400; //bit10=UTXEN
U1BRG = (((Fcy/baud)/16)-1); //38400 bps @ Fcy = 8 MHz
_U1RXIF = 0;
_U1RXIE=1;
}
//================================================== ==========================
//Proc Xu ly ngat Timer1
//================================================== ==========================
void _ISR_PSV _T1Interrupt(void)
{ _LATD0^=1;
_T1IF = 0; //Xoa co ngat
}
//================================================== ==========================
//Proc Xu ly ngat khi UART1 nhan Data
//Dung mang 10 ky tu lam bo dem (+4 ky tu bo dem cua dsPIC)
//================================================== ==========================
void _ISR_PSV _U1RXInterrupt(void)
{ gFlag_1 = 1;
_LATB1^=1;
while(U1STAbits.URXDA)
{ gRec[gRPos]=U1RXREG;
if (++gRPos>9) gRPos=0;
if(++gRCount>9) gRCount=0;
};
_U1RXIF = 0;
}

Trong code trên em cho truyền 6 ký tự, kết quả nhận được đầy đủ nhưng giá trị nhận được không như mong muốn: Lệnh truyền thứ 5 và thứ 6 là em truyền 2 ký tự cuối cùng nhận được. Nhưng sao chương trình truyền toàn giá trị 0.
Chương trình xử lý ngắt có sai không anh?

namqn
26-06-2008, 01:20 AM
À, bạn chưa cho biết đang thử nghiệm theo kiểu nào? Bạn đang gửi trả những gì nhận được từ dsPIC về nó hay sao?

Thân,

hpecom
26-06-2008, 08:43 AM
Hiện tại em dùng PC (có RS232-RS485 converter) để thử nghiệm việc truyền nhận.
Em nhận các ký tự truyền từ PC xuống dsPIC và dsPIC truyền trả lại PC những ký tự nó đã nhận được.
Và em đã tìm ra lỗi: Nguyên nhân do em không có khoảng delay sau khi truyền có lẽ MAX485 chưa truyền xong em đã nâng DE/RE lên 1 nên mất ký tự cuối cùng.
Nhưng em không hiểu sao khi mình truyền 2, 4, 6. ký tự thì lại không bị mất và mình nên delay khoảng bao lâu là tốt nhất vậy anh?

namqn
26-06-2008, 11:00 PM
Hiện tại em dùng PC (có RS232-RS485 converter) để thử nghiệm việc truyền nhận.
Em nhận các ký tự truyền từ PC xuống dsPIC và dsPIC truyền trả lại PC những ký tự nó đã nhận được.
Và em đã tìm ra lỗi: Nguyên nhân do em không có khoảng delay sau khi truyền có lẽ MAX485 chưa truyền xong em đã nâng DE/RE lên 1 nên mất ký tự cuối cùng.
Nhưng em không hiểu sao khi mình truyền 2, 4, 6. ký tự thì lại không bị mất và mình nên delay khoảng bao lâu là tốt nhất vậy anh?
Nếu gửi dữ liệu từ PC xuống dsPIC và dsPIC trả lại dữ liệu thì nên thiết kế cơ chế bắt tay.

MAX485 chỉ chuyển mức tín hiệu từ RS-232 (so với 0 V) thành RS485 (vi sai) thôi, nhưng dsPIC cần điều khiển các chân DE và /RE một cách thích hợp.

Về code ở trên, có thể giải thích những gì đang diễn ra như sau:

Vì các bit <7:6> của thanh ghi U1STA bằng '00', mỗi ký tự nhận được tại UART1 của dsPIC sẽ tạo 1 ngắt, do đó vòng lặp while () trong code xử lý ngắt chẳng có tác dụng gì ngoài việc chỉ đọc ký tự đó vào bộ đệm nhận rồi trở về, sau khi bật cờ gFlag_1. Khi đó vòng lặp chính trong main() có thể phát hiện ra đã thu được một ký tự và dsPIC bắt đầu phát một loạt ký tự về PC, việc phát là ổn vì code kiểm tra trạng thái của bộ đệm phát, và chỉ thoát khỏi vòng lặp kiểm tra khi đã phát xong ký tự. Phía PC thu được như thế nào lại là chuyện khác.

Trong quá trình dsPIC đang phát loạt ký tự về PC, nếu PC cũng phát tiếp một ký tự nữa thì không rõ chuyện gì sẽ xảy ra, vì không rõ hành vi của bộ chuyển đổi RS-232/RS-485 bên phía PC.

Câu hỏi của bạn về truyền 2, 4, 6 ký tự lại không bị mất là không rõ ràng, vì không rõ dsPIC phát hay PC phát? Ở đây thực chất có 2 kênh truyền nhưng chỉ có một đường truyền, do đó cần xác định rõ ràng.

Khi dsPIC phát và PC thu, dsPIC có thể đặt trạng thái cho MAX485 nối vào nó để làm việc đó. Khi PC phát và dsPIC thu, thông thường dsPIC không biết lúc nào sẽ xảy ra việc truyền thông, nên nó thường phải đặt trạng thái cho MAX485 nối vào nó ở chế độ thu. Tuy nhiên, như đã nêu ở trên, vẫn có khả năng PC thử phát 1 ký tự vào đường truyền đang được dùng để phát từ dsPIC về PC.

Hành vi của phía chủ động phát là PC đến lúc này vẫn chưa rõ.

Thân,

hpecom
27-06-2008, 12:26 AM
Dạ, vì em đang thử nghiệm xem UART hoạt động thế nào nên em cho PC chỉ truyền 1 ký tự để dsPIC xảy ra ngắt trên UART1. Khi dsPIC nhận được ký tự thì dsPIC truyền ngược lại nhiều ký tự cho PC (trong code em truyền 6 ký tự), số kỵ tự này là lẻ thì PC không nhận được ký tự cuối cùng anh ạ.


Em cảm ơn anh!

namqn
27-06-2008, 01:28 AM
Phía PC bạn dùng công cụ gì để theo dõi việc truyền nhận? Dựa vào đâu bạn khẳng định khi phát loạt 6 ký tự từ dsPIC thì 2 ký tự sau cùng đều là 0 (lý do của câu hỏi này là các ký tự có mã ASCII < 0x20 đều thuộc loại không thể hiển thị được, vì chúng là các mã điều khiển)?

Nếu bạn dùng dsPIC phát liền một mạch các loạt ký tự với độ dài của loạt ký tự khác nhau thì sao (cứ thử phát 3, 4, 5, 6, ... ký tự liên tiếp thì kết quả thế nào)?

Thân,

hpecom
27-06-2008, 11:18 AM
Dạ, em sử dụng Terminal V1.9b. Em nhận dữ liệu dạng Hex nên chắc chắn là giá trị 0 anh ạ. Trong 6 giá trị em truyền thì 2 giá trị cuối là các giá trị nhận được từ PC.

Nếu em không nhận dữ liệu từ PC mà tự cho dsPIC phát thì không vấn đề gì anh ạ, vì lúc đó nối thẳng DE/RE lên 5V.

em đợi tin Anh!

namqn
27-06-2008, 06:11 PM
Dạ, em sử dụng Terminal V1.9b. Em nhận dữ liệu dạng Hex nên chắc chắn là giá trị 0 anh ạ. Trong 6 giá trị em truyền thì 2 giá trị cuối là các giá trị nhận được từ PC.

Nếu em không nhận dữ liệu từ PC mà tự cho dsPIC phát thì không vấn đề gì anh ạ, vì lúc đó nối thẳng DE/RE lên 5V.

em đợi tin Anh!
Nếu như vậy thì phải đặt vấn đề dữ liệu phát từ PC có gì bất thường. Bạn có thể dùng 8 LED nối với 1 port nào đó của dsPIC hay không? Nếu được thì thử phát từ PC từng ký tự, hiển thị toàn bộ 8-bit thu được ra LED, mỗi ký tự được phát cách nhau vài giây để bạn có thời gian kiểm tra dữ liệu mà dsPIC đã thu được.

Thân,

hpecom
27-06-2008, 08:36 PM
Vâng em sẽ báo cáo kết quả với anh.
Còn một việc nữa mà em vẫn băn khoăn là chân Tx. Hôm trước nó có hiện tượng nhiễu giống như bị bỏ lửng, em treo một điện trở 10K lên 5V thì nó không bị nhiễu nữa nhưng em thấy làm thế không đúng vì bình thường chân Tx đâu có ai treo lên như vậy. Mong anh và mọi người chỉ bảo

Em cảm ơn anh!

namqn
27-06-2008, 11:17 PM
Vâng em sẽ báo cáo kết quả với anh.
Còn một việc nữa mà em vẫn băn khoăn là chân Tx. Hôm trước nó có hiện tượng nhiễu giống như bị bỏ lửng, em treo một điện trở 10K lên 5V thì nó không bị nhiễu nữa nhưng em thấy làm thế không đúng vì bình thường chân Tx đâu có ai treo lên như vậy. Mong anh và mọi người chỉ bảo

Em cảm ơn anh!
Đúng vậy, tôi có bao giờ cần treo chân TX lên đâu.

Thân,

hpecom
29-06-2008, 11:12 AM
Kính gửi anh Nam và các bạn,

Em đã làm theo hướng dẫn của anh, kết quả hiển thị trên LED đúng bằng giá trị PC truyền anh ạ.
Em đã xử lý được hiện tượng mất ký tự cuối bằng cách Delay một khoảng thời gian ngay sau khi truyền ký tự cuối cùng trước khi hạ chân DE/RE.
Đây là đoạn code:

#include <p30f4011.h>

_FOSC(CSW_FSCM_OFF & XT_PLL4);//FRC_PLL4
_FWDT(WDT_OFF);
_FBORPOR(PBOR_OFF & MCLR_EN);
_FGS(CODE_PROT_OFF);

//----------------------------------------------------------------------------
//Cac hang so cua chuong trinh (gia tri tuc thoi dung trong chuong trinh)
#define Fcy 4000000 //Tan so thuc thi lenh (Thach anh 4MHz)
#define baud 9600 //Toc do baud cua RS232
#define _ISR_PSV __attribute__((interrupt, auto_psv))
//----------------------------------------------------------------------------
//Cac prototype cho cac chuong trinh con
void Init_PORTS(void);
void Init_ADC10(void);
void Init_TMR1(void);
void Init_UART1(void);
void Init_UART2(void);
unsigned short CRC16(unsigned char* puchMsg, unsigned char usDataLen);
//----------------------------------------------------------------------------
//Khai bao bien toan cuc
/* Table of CRC values for high-order byte */
unsigned char auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
/* Table of CRC values for low-order byte */
unsigned char auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;

unsigned char gFwd[]={0x01,0x06,0x01,0x50,0x00,0x01,0x49,0xE7};
unsigned char gRev[]={0x01,0x06,0x01,0x50,0x00,0x02,0x09,0xE6};
unsigned char gStop[]={0x01,0x06,0x01,0x50,0x00,0x00,0x88,0x27};
unsigned char gSpe[]={0x01,0x06,0x00,0x80,0x03,0x89,0x0A};
unsigned char gRec[20]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,1 9};
unsigned char gRPos=0;
unsigned char gTPos=0;
unsigned char gRCount=0;
unsigned char gCmd=0;
int gEE_Return;
unsigned int gFlag_2;
unsigned char gReceiving=0; //Co bao dang nhan du lieu
unsigned int gRecDelay=30; //Thoi gian Delay de nhan het chuoi du lieu
unsigned int gcRecDelay=30; //Dem thoi gian Delay de nhan het chuoi du lieu
unsigned char gSending=0; //Co bao dang gui du lieu
unsigned int gSendDelay=20; //Thoi gian delay sau moi lan gui du lieu
unsigned int gcSendDelay=20; //Dem thoi gian delay sau moi lan gui du lieu

unsigned int gFlag_1;
unsigned char gRec_1; //Ky tu lenh nhan tu UART1
unsigned char gReceiving_2=0; //Co bao dang nhan du lieu
unsigned int gRecDelay_2=30; //Thoi gian Delay de nhan het chuoi du lieu
unsigned int gcRecDelay_2=30; //Dem thoi gian Delay de nhan het chuoi du lieu
unsigned char gSending_2=0; //Co bao dang gui du lieu
unsigned int gSendDelay_2=30; //Thoi gian delay sau moi lan gui du lieu
unsigned int gcSendDelay_2=30; //Dem thoi gian delay sau moi lan gui du lieu

unsigned int gDelay=200;


//================================================== ==========================
//CHUONG TRINH CHINH
//Kiem tra co gFlag (co bao UART1 nhan du lieu)
//Truyen ky tu nhan duoc
//================================================== ==========================
int main(void) {
int mDelay=0;
Init_PORTS(); //Khoi tao cac cong I/O
Init_TMR1(); //Khoi tao Timer 1
Init_UART1(); //Khoi tao module UART1
Init_UART2(); //Khoi tao module UART2
_LATE0=0; //Cho phep nhan Data
while (1)
{ if(gFlag_2)
{ gFlag_2=0;
//_LATB0^=1;
_LATE0=1; //Cho phep gui Data
while(gTPos!=gRPos)
{ U2TXREG = gRec[gTPos]; //
while (!U2STAbits.TRMT); //
if(++gTPos>19) gTPos=0;
gcSendDelay=gSendDelay;
gSending=1;
};
}
if(gFlag_1)
{ gFlag_1=0;
U1TXREG = gRec_1; //
while (!U1STAbits.TRMT); //
}
};
}
//================================================== ==========================
//Function tinh CRC
//================================================== ==========================
unsigned short CRC16(unsigned char * puchMsg, unsigned char usDataLen)
{ unsigned char uchCRCHi = 0xFF ; /* high CRC byte initialized */
unsigned char uchCRCLo = 0xFF ; /* low CRC byte initialized */
unsigned uIndex ; /* will index into CRC lookup*/
/* table*/
while (usDataLen--) /* pass through message buffer*/
{ uIndex = uchCRCHi ^ *puchMsg++ ; /* calculate the CRC*/
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
uchCRCLo = auchCRCLo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}
/*
unsigned int CRC_Calc(int* pMes)
{ unsigned int mCRC_Reg=0xFFFF;
unsigned char mHighByte;
unsigned char mLowByte;
return 1;
}
*/
//================================================== ==========================
//Proc khoi tao cac cong I/O
//================================================== ==========================
void Init_PORTS(void)
{ /*PortB: Output
RB0-RB7: Du lieu cho LCD
DB8: Dieu khien den nen LCD
*/
LATB=0; //Xoa thanh ghi chot port B
TRISB = 0x0000; //RB0 la ngo ra
/*PortD: Output dieu khien SPI
RD0-RD2: Lua chon Slave
RD3: Tao xung clock
*/
LATD = 0; //Xoa thanh ghi chot cong D
TRISD &= 0xFFF0;
/*PortC: Du lieu SPI
RC13: SDI
RC14: SDO
*/
LATC=0;
TRISC |=0x2000;
TRISC &=0xBFFF;
/*PordE: In/Out
RE0: Ngo ra dieu khien MAX485
RE1-RE5,RE8: Doc trang thai cac nut nhan
*/
LATE=0; //Xoa thanh ghi chot Port E
TRISE=0x00FE;
/*PortF: In/Output
RF0, RF1, RF6: Dieu khien LCD
Cac pinc con lai dung cho UARTx
*/
LATF=0;
TRISF &=0xFFBC;
}
//================================================== ==========================
//Proc khoi tao va setup Timer1 (Ngat sau 1S)
//================================================== ==========================
void Init_TMR1(void) {
TMR1 = 0; //Xoa so dem trong TMR1
//PR1 = 0x3D09; //Nguong tran la 1 giay (=4000000/256)
PR1 = 100; //Nguong tran la 650uS
_T1IF = 0; //Xoa co ngat cua Timer 1
T1CON = 0x8030; //Dung fcy lam clock, prescale = 1:256
_T1IE = 1; //Cho phep ngat khi Timer 1 tran
}
//================================================== ==========================
//Proc khoi tao module UART1
//Baud rate = 9600, 8 bit Data, no Parity, 1 bit stop
//================================================== ==========================
void Init_UART1(void) {
U1MODE = 0x8000; //Main I/O, 8-bit, no parity, 1 stop bit
//U1MODE = 0x8400; //ALT I/O, 8-bit, no parity, 1 stop bit
U1STA = 0x0400; //bit10=UTXEN
U1BRG = (((Fcy/baud)/16)-1); //38400 bps @ Fcy = 8 MHz
_U1RXIF = 0;
_U1RXIE=1;
}
//================================================== ==========================
//Proc khoi tao module UART2
//Baud rate = 9600, 8 bit Data, no Parity, 1 bit stop
//================================================== ==========================
void Init_UART2(void) {
U2MODE = 0x8000; //Main I/O, 8-bit, no parity, 1 stop bit
//U2MODE = 0x8400; //ALT I/O, 8-bit, no parity, 1 stop bit
U2STA = 0x0400; //bit10=UTXEN
U2BRG = (((Fcy/baud)/16)-1); //38400 bps @ Fcy = 8 MHz
_U2RXIF = 0;
_U2RXIE=1;
}
//================================================== ==========================
//Proc Xu ly ngat Timer1
//================================================== ==========================
void _ISR_PSV _T1Interrupt(void)
{ _LATD0^=1;
if(gReceiving)
{ if(--gcRecDelay<1)
{ gReceiving=0;
gFlag_2= 1;
}
}
if(gSending)
{ if(--gcSendDelay<1)
{ gSending=0;
_LATE0=0; //Cho phep nhan Data
}
}
_T1IF = 0; //Xoa co ngat Timer1
}
//================================================== ==========================
//Proc Xu ly ngat khi UART1 nhan Data tu PC
//Dung mang 20 ky tu lam bo dem (+4 ky tu bo dem cua dsPIC)
//================================================== ==========================
void _ISR_PSV _U1RXInterrupt(void)
{ gFlag_1=1; //Co bao nhan duoc ky tu tu UART2
gRec_1=U1RXREG; //Nhan du lieu tu bo dem thu
_U1RXIF = 0; //Xoa co ngat UART2
}
//================================================== ==========================
//Proc Xu ly ngat khi UART2 nhan Data tu Inverter
//Dung mang 20 ky tu lam bo dem (+4 ky tu bo dem cua dsPIC)
//================================================== ==========================
void _ISR_PSV _U2RXInterrupt(void)
{ gcRecDelay=gRecDelay; //Reset biet dem thoi gian Delay
gReceiving=1; //Bat co bao dang doi ky tu tiep theo
gRec[gRPos]=U2RXREG; //Nhan du lieu tu bo dem thu
if (++gRPos>19) gRPos=0; //
_LATD1^=1; //Doi trang thai LED de bao hieu co xay ra ngat UART1
_U2RXIF = 0; //Xoa co ngat UART1
}


Mong anh và mọi người góp ý!

thienstar
05-11-2009, 11:34 PM
Minh đang làm mạng RS485 dùng con 16f688 làm chạy được ngon lành. Nhưng khi mô phỏng thử mạng RS485 dùng 16f688 và 16f877a thì bắt đầu gặp vấn đề không đồng bộ tín hiệu chập chờn. Xin hỏi có phải tại tốc độ của 2 con Pic này không tương thích dẫn đến sai số này không? hay là lỗ do chương trình mô phỏng?(Protues). Anh em ai đã trải nghiệm qua rùi xin cho mình lãnh giáo
Cám ơn.