PDA

View Full Version : Problem with receiving data from com port !! Please help me...


meopic
11-11-2009, 08:38 PM
Chào mọi người !! Chả là mình đang làm 1 đề tài giao tiếp máy tính qua cổng com với PIC16F88 nhưng lại gặp vấn đề ở khâu lấy dữ liệu từ cổng COM để hiển thị lên PC.
Sau khi mình lập trình VB6 để nhận thì trên PC thu được như hình :
http://anh.us/thumbs-1257945521_S566_MI.jpg[/url
[code] #include <16f88.h>
#include <def_88.h>
#device *=16 ADC=10
#fuses NOWDT, HS, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B5,rcv=PIN_B2,bi ts=9)
#include <lcd_lib_4bit.c> // Thu vien ham cho LCD
int16 temp;
int8 nghin,tram,chuc,donvi;
int1 mili_volt;
float volt;

void convert_bcd(int16 x)
{
nghin = x / 1000 +0x30;
temp = x % 1000;
tram = temp / 100 +0x30;
temp = temp % 100;
chuc = temp / 10 +0x30;
donvi = temp % 10 +0x30;
}
void xuat_ra_lcd()
{
temp = read_adc() ;
volt=(float)(temp*5)/1023;
if(volt<1) mili_volt=1;
else mili_volt=0;
volt=volt*1000;

convert_bcd((int16)volt);
lcd_putcmd(0xc0);//con tro o dau hang 2

if(mili_volt==0)
{

lcd_putchar(nghin);
lcd_putchar(".");
}

lcd_putchar(tram);
lcd_putchar(chuc);
lcd_putchar(donvi);

if(mili_volt==1) printf(lcd_putchar," mV");
else printf(lcd_putchar," V");
}
void convert_pc(int16 x)
{
nghin = x / 1000 ;
temp = x % 1000;
tram = temp / 100 ;
temp = temp % 100;
chuc = temp / 10 ;
donvi = temp % 10 ;
}
void xuat_ra_pc() {

temp = read_adc() ;
volt=(float)(temp*5)/1023;
if(volt<1) mili_volt=1;
else mili_volt=0;
volt=volt*1000;

convert_pc((int16)volt);
printf("%u",nghin);
}
void main( ){

trisb=0x00;

LCD_init();
delay_us(100);
LCD_Putcmd(0X80);
printf(LCD_putchar,"DIEN AP U= ");

setup_adc( ADC_CLOCK_INTERNAL );
Setup_ADC_ports (0);
Set_ADC_channel (0) ;
Delay_us (300); // delay 10 us
while(1){
xuat_ra_lcd();
printf("%u\,%u\%u", nghin);

}
}
còn đây là đoạn code VB của mình:
Private Sub EXIT_Click()
End
End Sub

Private Sub Form_Load()
With MSComm1
MSComm1.CommPort = 1 ' Using Com1
MSComm1.Settings = "9600,n,8,1"
MSComm1.RThreshold = 1
End With
End Sub

Private Sub MSComm1_OnComm()
Dim s As String
Dim s1 As String
Dim s2 As String
s = MSComm1.Input
s1 = Left$(s, 4)
Text1.Text = "Va = " & s1 & " v"
s2 = Right$(s, 4)
Text2.Text = "Vb = " & s2 & " v"
End Sub

Private Sub on1_Click()
MSComm1.PortOpen = True
End Sub
************************************************** *******
nhờ các cao thủ chỉ giáo! Mong ACE nhanh nhanh hồi đáp sớm ! Thanks!!!!
************************************************** *******

do mới post bài lân đầu nên chưa biết cách post code! ACE thông cảm !!!
đây là sơ proteus
[url=http://anh.us/3bc9accfce.html]http://anh.us/thumbs-1257946573_P707_hebhe.jpg (http://anh.us/3bc9accfcc.html)

xuannhat115
11-11-2009, 08:51 PM
Đây cũng là đề tài mà mình đang làm học kì này. Vấn đề hiển thị ra LCD mình đã làm ok tuy nhiên việc hiển thị lên PC cung gặp phải vấn đề như trên. Hi vọng các cao thủ giúp đỡ để tụi mình có thể hiển thị được giá trị điện áp lên PC thành công.
Theo mình thì vấn đề ở đây là chương trình VB, việc mình printf một loạt hiển thị lên PC thì ở đây PC sẽ nhận theo cơ chế nào với thuộc tính MSCOMM1.INPUT
Thứ 2, khi gửi data đến cổng com thì pc nhận loại dữ liệu gì ??
Mong có sự hồi đáp kịp thời của các cao thủ để diễn đàn của chúng ta ngày càng phát triển hơn !!!

xuannhat115
12-11-2009, 10:54 AM
hic !!! các BRO ơi giúp em với ! em đag cần gấp lắm !!! gần đến lúc thông đề tài zồi!!!
anh Bắc ơi
anh Fal ơi

Delfy_Coltech
12-11-2009, 04:39 PM
Các bạn thử nhận dữ liệu gửi lên PC bằng công cụ gửi kèm này xem đã OK chưa nhé?
1. Nếu chưa nhận được --> Check lại hàm printf. (Mình nghĩ là đã OK)
2. Nếu nhận được --> Hàm nhận của bạn viết bằng VB có vấn đề.

- Đầu tiên bạn cứ nhận cả chuỗi điện áp gửi lên đã.
Xem có nhận được chưa? Rồi hãy tìm cách tách chúng ra.
Mình không dùng VB nên không rõ cách tách lắm.
Good luck!

meopic
14-11-2009, 03:36 PM
Mình đã thử viết 1 đoạn CCS đơn giản để gửi đén pc 3 kí tự abc như sau :
#include <16f88.h>
#include <def_88.h>
#device *=16 ADC=8
#FUSES NOWDT, HS, NOPUT, MCLR, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
#use delay(clock=4000000)
#use rs232(baud=9600, parity= N,xmit=PIN_B5,rcv=PIN_B2, bits=9)
#include <LCD_4BIT16F88edit.C> // Thu vien ham cho LCD
void main(){
while (1) {trisb=0x00;
lcd_init();
lcd_putcmd(0x80);
printf(lcd_putchar,"meoakul");
printf("abc");
}
}
Tuy nhiên khi dùng cái Terminal của bạn thì nó hiển thị theo kiểu hex là 1 dãy các số 80 và mình tra bảng mã ASCII thì không có số đó.
Còn đây là sơ đồ mô phỏng Proteus của mình :
http://up.anhso.net/upload/20091114/15/o/anhso-34_meowin005.jpg
Phải chăng khi mô phỏng dữ liệu ra PC sẽ không chính xác !!???
Có ai đã mô phỏng được rùi thì chỉ giáo giúp mình nhé !!!

Delfy_Coltech
15-11-2009, 11:54 PM
#use rs232(baud=9600, parity= N,xmit=PIN_B5,rcv=PIN_B2, bits=9)

Ở đây, bạn khai báo số bít truyền-nhận là 9. Trong khi cái Terminal kia chỉ cho phép giao tiếp 8 bit là cao nhất mà.

Bạn sửa lại theo chuẩn 8 bits xem nha'! (Nhìn kỹ cái Terminal chút nhé!)

meopic
19-11-2009, 01:18 PM
Cảm ơn bạn, mình đã làm mạch thật và chạy thử. Kết quả là những gì mình gửi ở pc lên là đúng nhưng bên cạnh đó mình gặp phải vấn đề sau :
Ở ccs mình printf("meoakul") như trên, và khi dùng cái terminal của bạn thì receive lại dc là : <0><0><0>meoakul??.... vẫn còn kèm theo 1 số kí tự lạ như <0>, ?. Đây là trường hợp khi mình dùng đầy đủ 2 chân rx, tx của PIC.
Tuy nhiên khi mình ngắt chân RB2( tức chân rx) của pic nối với max232 thì những gì hiển thị được trên terminal của bạn là hoàn toàn đúng như những j mình gửi lên từ ccs.
Vậy phải chăng khi chỉ làm 1 tác vụ gửi dữ liệu từ pic lên pc thì tác vụ còn lại ( ghi dữ liệu từ pc xuống pic) là không cần thiết !!!
Mong các bác chỉ giáo dùm !! thanks

meopic
24-11-2009, 02:11 PM
sao o có cao nhân nào ra tay chỉ giáo kẻ hậu bối này hết nhỉ !!!!!

Delfy_Coltech
24-11-2009, 07:53 PM
Tất nhiên nếu bạn không dùng đến chức năng truyền từ PC xuống PIC thì chỉ cần nối chân RC6 qua Max232 lên chân 2 của COM.
Tuy nhiên không phải vì việc nối cả TX và RX lên COM mà xảy ra lỗi như bạn nói.

Có thể lỗi đó là do mạch của bạn hoặc do cách lập trình.

Thử dùng hàm printf("abc\n\r"); Xem có lỗi không nào?

meopic
26-11-2009, 03:12 PM
hehe, mình đã test thành công. Dường như đây là vấn đề phần cứng, sau khi mình làm lại mạch 1 cách cẩn thận thì mạch đã ok, truyền lên pc okie ( còn truyền từ pc xuống thì chưa test :D). Thanks bác Delfy.

meopic
26-11-2009, 03:29 PM
hehe, đúng là biển học rộng thật, được cái này thì lại lòi ra cái khác o biết, Bác Delfy cho e hỏi là "\r" có ý nghĩa gì vậy !! Mấy cái \kí tự khác e bit nhưng tự nhiên gặp cái \r e lại o đoán ra dc nó có nghĩa gì !! Các bác chỉ giáo nhé !!!

Delfy_Coltech
27-11-2009, 12:09 AM
hehe, đúng là biển học rộng thật, được cái này thì lại lòi ra cái khác o biết, Bác Delfy cho e hỏi là "\r" có ý nghĩa gì vậy !! Mấy cái \kí tự khác e bit nhưng tự nhiên gặp cái \r e lại o đoán ra dc nó có nghĩa gì !! Các bác chỉ giáo nhé !!!

Có gặp lỗi thì mới biết cách debug đúng không nào!
Qua đây, chắc bạn cũng rèn luyện cho mình tính cẩn thận hơn. :)
Đúng là việc giao tiếp PIC với PC, nếu phần cứng mà không tốt thì dễ nhiễu lắm!

Còn cái "\r" là gì thì bạn test thử biết ngay ấy mà.

Thử truyền lên PC 3 dòng sau:

printf("Xin chao\r");
printf("PIC VIET NAM");
printf(" 2009");


=> Rồi suy ra "\r" có ý nghĩa gì nhé! (Ở đây r=row).
Thân.

namqn
27-11-2009, 07:57 AM
...
=> Rồi suy ra "\r" có ý nghĩa gì nhé! (Ở đây r=row).
Thân.
Theo tài liệu "The C programming Language" của Brian Kernighan và Dennis Ritchie thì "\r" là chuỗi thoát cho ký tự "carriage return".

Thân,

Delfy_Coltech
27-11-2009, 03:25 PM
Theo tài liệu "The C programming Language" của Brian Kernighan và Dennis Ritchie thì "/r" là chuỗi thoát cho ký tự "carriage return".

Thân,

Đúng rùi! Em nhầm. "\r" là Carriage Return.
Chức năng của nó là chuyển xuống dòng mới khi in.

meopic
28-11-2009, 11:38 AM
Sau khi nghiên cứu " THE ANSI C PROGRAMMING LANGUAGE" thì em xin edit lại ý kiến của bác Delfy 1 chút là: " \r= move to begin of newline", chứ o phải là chuyển xuống dòng mới như bác nói ( như bác nói thì \n mới chính xác). Em chỉ mạo muội có ý kiến vậy thôi, có j các bác chỉ giáo thêm nhé !!!
Thân !!

meopic
28-11-2009, 12:06 PM
Sau khi đã truyền lên pc okie, e lại tiếp tục chuyển sang nghiên cứu phần truyền từ pc xuống com. Em định thiết lập 1 form VB như sau :
http://c.uploadanh.com/upload/1/748/0.4342357_1_1.jpg

Em sẽ lập trình để khi mình nhập từ bàn phím vào Text 1 số kí tự, sau đó press Send thì ở LCD4bit của em cũng sẽ nhận được tương ứng.
Em có tham khảo trên 4rum mình và tiến hành lập trình vb tương tự như sau;
Private Sub Form_KeyPress(KeyAscii As Integer)
Dim DataToSend As String
DataToSend = KeyAscii
MSComm1.Output = DataToSend
End Sub
Private Sub Form_Load()
With MSComm1
.Settings = "9600,N,8,1"
.RThreshold = 1
.SThreshold = 0
.InBufferSize = 1024
.OutBufferSize = 1024
.InputMode = comInputModeText
.ParityReplace = ""
.CommPort = 6 ' using com6
End With
End Sub

Và ở CCS thì em viết chương trình cho pic16f88 của mình như sau :
#include <16f88.h>
#include <def_88.h>
#device *=16 ADC=10
#fuses NOWDT, HS, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B5,rcv=PIN_B2,bi ts=9)
#include <LCD_4BIT16F88edit.C> // Thu vien ham cho LCD
void main()
{
trisB=0x00;
lcd_init();
lcd_putcmd(0x80);
getc();
}

Về hardware của e thì đã okie hết, nhưng có điều e chưa chắc về chương trình VB và CCS( vì e nạp và chạy thử rùi nhưng o thấy trăng sao j cả :D). Với lại e cũng chưa thiết lập code cho command send của mình, các bác cho e ý kiến nhá !!
Về phần VB chắc code gửi data của e vẫn chưa được : vẫn còn hoài nghi cái chỗ mscomm1.output=datatosend.
Về phần CCS chắc code nhận data chắc cũng o ổn : e nghi ngờ cách dùng hàm getc() của mình, hehe.
Các tiền bối chỉ giáo cho kẻ hậu bối này với nhá !!!
Thanks nhìu nhìu !!!

meopic
30-11-2009, 10:54 AM
các cao nhân đi đâu hết rùi !! Chỉ giáo dùm e 1 cái...

Delfy_Coltech
01-12-2009, 10:58 AM
Hey boy,

Về phần VB chắc code gửi data của e vẫn chưa được : vẫn còn hoài nghi cái chỗ mscomm1.output=datatosend.

Có một vài chia sẻ với bạn.
Thứ nhất: vấn đề của bạn hỏi không ai có thể bỏ công ra ngồi viết form VB rồi làm mạch test cho bạn được. Điều quan trọng là bạn nên tự tìm hiểu và làm. Khi nào gặp lỗi gì thì post code lên hỏi. Cứ làm rồi sẽ bắt được lỗi thôi! (Không dc thì nhờ!) :)

Thứ hai: Bạn có dùng phần mềm tạo các cặp cổng COM ảo (Virtual Serial Port Driver) không?
Nó rất hữu ích cho việc test các phần mềm lập trình truyền nhận qua cổng COM.
Nếu bạn chưa có thì tải file mình gửi kèm nhé. Rồi cài đặt và lập trình test xem mình lập trình VB đã truyền nhận được chưa. (Có thể dùng form bạn lập trình gắn cho COM ảo 3 truyền dữ liệu lên Terminal gắn cho COM ảo 4 chẳng hạn)

Thứ ba: Sau khi truyền nhận VB đã ổn.
Bạn tiếp tục nghía đến CCS. Làm sao để nhận 1 chuỗi từ VB gửi xuống.
Theo mình, khi gửi bạn nên đánh dấu bằng các kí tự bắt đầu và kết thúc chuỗi gửi.
Ở CCS, viết code sao cho khi gặp kí tự bắt đầu của 1 chuỗi gửi xuống thì getc().
Và cứ getc() cho đến bao giờ gặp kí tự kết thúc thì thôi.
Và put cái chuỗi nhận được đấy lên LCD.

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

meopic
01-12-2009, 12:19 PM
Bác hỉu sai ý em rùi, ko phải là e nhờ các bác viết dùm mà là nhờ các bác tư vấn dùm cái đoạn code vb và ccs e đã post ở trên.
Các bác chỉ dùm e cái điểm dc và chưa đc để e rút kinh nghiệm. Vì e vẫn chưa làm dc việc gửi 1 kí tự từ vb xuống và hiể thị lên lcd. Mong các bác nhiệt tình giúp e
Thân !!

phuocxin
01-12-2009, 04:44 PM
ở vb bạn phải viết là
Private Sub Form_KeyPress(KeyAscii As Integer)
Dim DataToSend As String
datatosend="a"
MSComm1.Output = DataToSend
End Sub

meopic
02-12-2009, 12:32 PM
Mình đã làm theo cách của bạn tuy nhiên vẫn chưa dc. Mình nghĩ vấn đề của mình nằm ở chương trình ccs. Bởi vì mình thấy mún hiển thị lên LCD thì cần có lệnh LCD_PUTCHAR hay PRINTF(LCD_PUTCHAR,"....") nhưng ở ccs của mình thì chỉ có GETC() mà không có các lệnh hiển thị lên LCD >> vậy thì làm sao mà hhiển thị dc các bác nhỉ !!! Theo chủ quan của e là như vậy, các bác cho e hồi âm nhé
Thanks !!!

8051topic
02-12-2009, 09:03 PM
Ý của bạn Delfy_Coltech là bạn nên viết hoàn chỉnh từng phần, chắc chắn VB đúng rồi mới viết tiếp CCS (hay ngược lại cũng được).
Mình thấy trang này chỉ rất cơ bản phần VB, có cả file chạy sẵn nữa, bạn có thể làm theo để biết lỗi sai do chương trình trên VB hay CCS.
http://www.rentron.com/sending_data.htm

khaivinh_plc
10-12-2009, 12:44 AM
Minh gop y chut:

vi du ban tao ra mot o text và dat ten la text1 thi ban phai viet la :
VB:
MSComm1.Output = text1.Text ' noi dung text1 se truyen xuong


O phan vdk thi ban viet code nhan 1 ky tu do, luu vao bien nao do roi tha ho ma xu ly...chu y la pc gui xuong la ky tu.

meopic
16-12-2009, 09:08 PM
Cái mình cần là cái chô chương trình ở C để nhận kí tự mà bạn nói đó, mình đag kẹt chỗ đó nên mới nhờ mọi người tư vấn. Bạn có thể đưa ra 1 ít code cho mình tham khảo dc o ? Mình cũng đã làm bằng cách dùng hàm getc() tuy nhiên vẫn chưa dc !!
Thân !!

Delfy_Coltech
19-12-2009, 01:42 AM
Ủa vấn đề của meopic vẫn chưa giải quyết được hả!
Tại sao bạn không làm theo cách mình đã nói ở trên nhỉ!
Ví dụ đơn giản: Truyền kí tự "A"--> Getc()--> Putchar lên LCD.

Nhưng muốn get được ký tự đó. Không phải là cứ viết hàm getc() trong void main() là được. Mà phải cần sử dụng đến ngắt RDA (Nếu chưa biết bạn có thể đọc thêm trong CCS_Manual_2k9).

- Khi truyền một ký tự hoặc một chuỗi xuống PIC. (Thường mình dùng 2 chân RC6 và RC7 để truyền-nhận), sẽ xảy ra ngắt RDA (ngắt xảy ra khi có sự nhận dữ liệu qua giao thức RS-232).

Lúc này bạn sẽ khai báo hàm ngắt và viết câu lệnh nhận dữ liệu truyền xuống trong hàm ngắt này.
Rồi trong void main(). Enable ngắt là OK.

Code sẽ như sau:

//1. PIC setting
....
//2. Interrupts Program
INT_RDA
VOID GET_CHAR()
{
char c;
c=getc();
putc(c);// Gửi lại ký tự vừa nhận được lên PC
}

VOID main()
{
enable_interrupts(global);
enable_interrupts(int_rda);
while(true)
{

}

}

meopic
19-01-2010, 10:34 AM
Thanks các bác nhìu, special with Delfy mem, hehe ! Nhờ có sự chỉ bảo tận tình của các bác mà em đã hiểu thêm dc nhìu thứ !!
Thân !!

Delfy_Coltech
19-01-2010, 06:43 PM
4-rum là nơi để trao đổi, học hỏi lẫn nhau mà bạn.
Let's share to be share!

hangocminh1989
12-07-2011, 01:16 AM
oh, các bác ơi, em gửi chuỗi kí tự xuống pic từ pc, sau đó xuất ra lcd là sao lcd chỉ xuất có 1 kí tự vậy ạ?
em gửi lại pc kĩ tự vừa nhận thì đầy đủ, mà gửi lên lcd thì chỉ được 1 kí tự thui.
ví dụ em gửi chữ "bc" từ pc xuông pic mà chỉ nhận được mỗi chữ "c" trên lcd thui, trong khi em gửi ;lại liền pc chuỗi kí tự đó lại đủ cả, hic, mong các bác giải thích cho em.

hein_ts
17-07-2011, 02:46 AM
Mình cũng xin post thêm ít kinh nghiệm của mình nhé. Lần đó mượn được cái mạch của anh khóa trên về nạp code chạy thử, giống hệt hiện tượng như trên, tức là lúc được lúc không, <0>... Akay quá, đi làm hẳn một modul Max232 mới ghép vào chạy không sai lấy một bit, tưởng con max on board hỏng thay con khác vẫn bị. Cuối cùng phát hiện ra là thiếu nguồn mã chân 15 của max. Hic!