2009-08-01 16 views
6

Tôi đang thực hiện một vi điều khiển 8051 giao tiếp không dây với máy tính. Bộ vi điều khiển sẽ gửi một chuỗi đến cổng nối tiếp của nó (DB9) và máy tính sẽ nhận được chuỗi này và thao tác nó.Tôi làm cách nào để gửi chuỗi từ seri 8051 chỉ ONCE?

Vấn đề của tôi là tôi không biết cách làm cho 8051 truyền chuỗi chỉ một lần. Vì tôi cần thao tác chuỗi ở đầu PC nên nó chỉ được nhận một lần. Hiện tại, mặc dù trong mã C tôi đang gửi chuỗi một lần, trên máy tính của tôi, tôi nhận được cùng một chuỗi liên tục. Tôi cho rằng điều này là bởi vì bất cứ điều gì trong SBUF được truyền liên tục. Có cách nào để tôi chỉ có thể gửi chuỗi của mình một lần không? Có cách nào để làm trống SBUF không?

Tôi đã cố gắng sử dụng chân RTS (Yêu cầu gửi) (pin thứ 7) trên DB9 vì tôi đọc ở đâu đó nếu tôi phủ nhận điện áp trên chốt đó, nó sẽ dừng luồng dữ liệu vào cổng nối tiếp. Vì vậy, những gì tôi đã làm được lập trình vi điều khiển của tôi để gửi chuỗi và sau đó gửi logic cấp 0 đến một pin đầu ra đã được kết nối với pin RTS DB9 của tôi. Tuy nhiên, điều đó không hiệu quả.

Có ai có bất kỳ đề xuất nào không? Tôi thực sự đánh giá cao họ.

EDIT

Phần mềm tôi đang sử dụng trên PC là X-CTU cho mô-đun Xbee. Đây là mã trên vi điều khiển của tôi:

include reg51.h 
void SerTx(unsigned char); 
void main(void) 
{ 
    TMOD = 0x20; 
    TH1 = 0xFD; 
    SCON = 0x50; 
    TR1 = 1; 

    SerTx('O'); 
    SerTx('N'); 
    SerTx('L'); 
    SerTx('Y'); 

} 

void SerTx(unsigned char x) 
{ 
    SBUF = x; 
    while(TI==0); 
    TI = 0; 
} 

Ai đó có thể vui lòng xác minh rằng trên thực tế, chỉ gửi chuỗi một lần?

EDIT

Hình như Steve, brookesmoses và Neil nhấn đinh trên đầu khi họ nói rằng đó là những gì đã xảy ra sau khi chức năng chính của tôi đã gây ra vấn đề. Tôi vừa thử đoạn mã gợi ý mà Steve đưa lên (cụ thể hơn là (;;) và xác định serTX bên ngoài chính) và nó hoạt động hoàn hảo. Bộ điều khiển có thể được khởi động lại và do đó cùng một mã giữ lặp lại chính nó.

Cảm ơn bạn rất nhiều vì đã trợ giúp! :)

+0

Phần mềm tôi đang sử dụng trên PC là X-CTU cho mô-đun Xbee. Đây là mã trên vi điều khiển của tôi: #include void SerTx (unsigned char); void main (void) { \t TMOD = 0x20; \t TH1 = 0xFD; \t SCON = 0x50; \t TR1 = 1; \t \t \t SerTx ('O'); \t SerTx ('N'); \t SerTx ('L'); \t SerTx ('Y'); \t void SerTx (unsigned char x) { \t SBUF = x; \t khi (TI == 0); \t TI = 0; } } Ai đó có thể vui lòng xác minh rằng trên thực tế, chỉ gửi chuỗi một lần? – CodeConfused

+0

Vui lòng chỉnh sửa câu hỏi của bạn và chèn mã, được định dạng dưới dạng mã để dễ đọc hơn. –

+0

@CodeConfused: Tôi rất vui vì tất cả chúng tôi đã tìm được giải pháp! Tôi có thêm hai yêu cầu cho bạn. (1) Đối với câu hỏi này và tất cả các câu hỏi khác của bạn về Stack Overflow, vui lòng đánh dấu câu trả lời là "được chấp nhận" bằng cách nhấp vào dấu tích lớn bằng câu hỏi bạn cung cấp câu trả lời hay nhất cho câu hỏi của bạn. Điều này rất hữu ích cho những người khác có thể có cùng câu hỏi trong tương lai, vì họ có thể thấy ngay câu trả lời tốt nhất. (2) Trong câu hỏi này, hãy định dạng mã như mã. Để thực hiện việc này, hãy chỉnh sửa câu hỏi, chọn mã và nhấn nút mã (đó là nút có số 1 và số 0 trên đó). Cảm ơn. –

Trả lời

6

Bạn có thể xác nhận rằng 8051 thực sự đang gửi dữ liệu chỉ một lần? Một cách để kiểm tra sẽ là sử dụng phạm vi để xem điều gì đang xảy ra trên chốt TX của UART.

Bạn đang sử dụng phần mềm nào trên PC? Tôi khuyên bạn nên sử dụng phần mềm giao tiếp đơn giản như HyperTerminal hoặc PuTTY. Nếu họ đang hiển thị chuỗi được gửi đến máy tính nhiều lần, thì rất có thể là lỗi trong phần mềm chạy trên 8.051.

EDIT: Thành thật mà nói, điều này nghe giống như loại gỡ lỗi mà các kỹ sư phải đối mặt thường xuyên, và vì vậy đây là cơ hội tốt để bạn thực hành giải quyết vấn đề theo kiểu cũ.

Nếu tôi có thể rất cùn, tôi đề nghị bạn làm như sau:

  1. Debug. Hãy thử mọi thứ, nhưng đừng đoán là. Thí nghiệm. Thực hiện các thay đổi nhỏ trong mã của bạn và xem điều gì sẽ xảy ra. Hãy thử mọi thứ bạn có thể nghĩ đến. Tìm kiếm trên web để biết thêm thông tin.
  2. Nếu điều đó không tạo ra giải pháp, hãy quay lại đây và cung cấp cho chúng tôi tất cả thông tin chúng tôi cần. Điều đó bao gồm phần liên quan của mã, đầy đủ chi tiết của phần cứng bạn đang sử dụng, và các thông tin về những gì bạn đã cố gắng trong bước 1.

EDIT: Tôi không có đại diện để chỉnh sửa các câu hỏi, vì vậy đây là mã đăng bởi OP trong các bình luận cho câu hỏi của mình:

#include<reg51.h> 

void SerTx(unsigned char); 

void main(void) 
{ 
    TMOD = 0x20; TH1 = 0xFD; SCON = 0x50; TR1 = 1; 
    SerTx('O'); SerTx('N'); SerTx('L'); SerTx('Y'); 

    void SerTx(unsigned char x) 
     { SBUF = x; while(TI==0); TI = 0; } 
} 

Như Neil và Brooksmoses đề cập đến trong câu trả lời của họ, trong một hệ thống nhúng, các chức năng chính là không bao giờ được phép chấm dứt. Vì vậy, bạn hoặc cần phải đặt mã của bạn trong một vòng lặp vô hạn (có thể là những gì vô tình xảy ra), hoặc thêm một vòng lặp vô hạn ở cuối, do đó, chương trình có hiệu quả tạm dừng.

Ngoài ra, hàm SerTx phải được xác định bên ngoài chính. Điều này có thể đúng về mặt cú pháp, nhưng nó giữ mọi thứ đơn giản không khai báo hàm trong các hàm khác.

Vì vậy, cố gắng này (tôi tôi cũng đã thêm một số ý kiến ​​trong một nỗ lực để làm cho mã dễ hiểu):

#include<reg51.h> 

void SerTx(unsigned char); 

void main(void) 
{ 
    /* Initialise (need to add more explanation as to what 
     each line means, perhaps by replacing these "magic 
     numbers" with some #defines) */ 
    TMOD = 0x20; 
    TH1 = 0xFD; 
    SCON = 0x50; 
    TR1 = 1; 

    /* Transmit data */ 
    SerTx('O'); SerTx('N'); SerTx('L'); SerTx('Y'); 

    /* Stay here forever */ 
    for(;;) {} 

} 

void SerTx(unsigned char x) 
{ 
    /* Transmit byte */ 
    SBUF = x; 

    /* Wait for byte to be transmitted */ 
    while(TI==0) {} 

    /* Clear transmit interrupt flag */ 
    TI = 0; 
} 
+0

Tôi đang sử dụng các mô-đun Xbee, Steve, vì vậy phần mềm trên PC là X-CTU. Tuy nhiên, tôi đã cố gắng khắc phục sự cố bằng cách sử dụng Hyperterminal. Điều tương tự xảy ra trên đó, tức là chuỗi được nhận liên tục. – CodeConfused

+0

Tuyệt đối bạn có thể rất thẳng thừng, Steve! :) Bất cứ điều gì giúp! Mã của bạn đã lừa, cảm ơn rất nhiều. P.S. TI = 0 không chính xác để vô hiệu hóa bộ phát. TI đã bị buộc phải bằng không vì sau khi truyền một nhân vật, 8051 tăng cờ TI để báo hiệu rằng nó đã sẵn sàng để truyền tải nhiều hơn. – CodeConfused

2

Thật khó để nói những gì vấn đề là không nhìn thấy bất kỳ mã 8051. Ví dụ: lỗi logic ở phía đó có thể dẫn đến dữ liệu được gửi nhiều lần hoặc phần mềm 8051 có thể đang đợi ACK không bao giờ nhận được, v.v.

Thông thường mã 8051 phải gửi rõ ràng từng mã nhân vật, nhưng tôi cho rằng điều này được chăm sóc cho bạn bởi thời gian chạy C.

Việc sử dụng RTS/CTS (Yêu cầu gửi/xóa để gửi) là để kiểm soát luồng (tức là để tránh tràn bộ đệm - bộ đệm thường nhỏ trên các bộ vi điều khiển này) và không dừng truyền hoàn toàn.

6

Mã bạn được đăng không có vòng lặp trong main(), vì vậy bạn cần phải xác định thời gian chạy của trình biên dịch C của bạn khi hàm main() trả về sau khi gửi 'Y'. Cho vấn đề của bạn, tôi tưởng tượng trình biên dịch tạo ra một số mã để làm một số dọn dẹp sau đó khởi động lại vi (có thể là thiết lập lại phần cứng, có thể chỉ cần khởi động lại thời gian chạy C). Có vẻ như chương trình của bạn hoạt động chính xác như bạn đã viết, nhưng bạn đã bỏ qua những gì xảy ra trước và sau khi hàm main() được gọi.

Nếu bạn muốn chuỗi của mình được gửi một lần và chỉ một lần, hãy làm như sau: while(1) {} được thêm sau khi ký tự cuối cùng được gửi. Nhưng, sau đó chương trình của bạn không làm gì cả - nó sẽ chỉ thực hiện một vòng lặp trống mãi mãi. Một thiết lập lại (chẳng hạn như đi xe điện) là cần thiết để bắt đầu lại, và gửi chuỗi.

Lưu ý rằng nếu vi của bạn có bộ đếm thời gian giám sát, nó có thể can thiệp và buộc đặt lại không mong muốn. Nếu điều này xảy ra, chuỗi của bạn sẽ được gửi một lần cho mỗi lần đặt lại cơ quan giám sát (có thể giống như một lần mỗi giây, với tỷ lệ tùy thuộc vào phần cứng của bạn).

Ngoài ra, có serTx() được xác định lồng bên trong chính() có lẽ không phải là những gì bạn muốn.

+0

Cảm ơn Neil, bạn đã hoàn toàn đúng. Nhưng có cách nào để tôi thoát khỏi vòng lặp trống mà không có phần cứng không? – CodeConfused

+0

P.S. Tôi không nghĩ rằng vi của tôi có một bộ đếm thời gian watchdog. – CodeConfused

+0

Tôi đoán câu trả lời đơn giản là: làm cho vòng lặp làm điều gì đó. Phần vững nhúng thường có vòng lặp chính chạy mãi mãi. Vòng lặp này sẽ thăm dò phần cứng để xem nếu có một số công việc cần làm, chẳng hạn như dữ liệu mới từ cổng nối tiếp hoặc đầu vào kỹ thuật số đã thay đổi, sau đó gọi một hàm thích hợp để xử lý sự kiện đó. – Neil

2

Phản hồi câu trả lời của Neil (trong câu trả lời, vì tôi chưa có đại diện để nhận xét): Trong trường hợp vi điều khiển điển hình không có hệ điều hành, không rõ ngay chức năng exit() được gọi ngầm ở kết thúc của chính() nên làm - hoặc, chính xác hơn, nó không thể làm như bình thường "kết thúc chương trình và trở về hệ điều hành", bởi vì không có hệ điều hành để trở về.

Hơn nữa, trong một ứng dụng thực sự, bạn hầu như không bao giờ muốn chương trình dừng lại, trừ khi bạn tắt hệ thống. Vì vậy, một điều mà việc thực hiện exit() nên chắc chắn không làm là chiếm nhiều không gian mã.

Trong một số hệ thống tôi đã làm việc, exit() không thực sự được thực hiện ở tất cả - nếu bạn không sử dụng nó, thậm chí không lãng phí một byte trên đó! Kết quả là khi đường dẫn thực hiện đến cuối main(), chip chỉ lang thang vào một vùng đất lala để thực hiện bất cứ điều gì xảy ra trong bit tiếp theo của bộ nhớ, và thường nhanh chóng kết thúc hoặc bị mắc kẹt trong một vòng lặp hoặc bị lỗi với một opcode bất hợp pháp. Và kết quả thông thường của một lỗi với một opcode bất hợp pháp là ... khởi động lại chip.

Điều đó có vẻ giống như một lý thuyết hợp lý cho những gì đang xảy ra ở đây.

+0

Cảm ơn brooksmoses. Bạn giải thích rằng thực sự tốt!Và tôi nghĩ đó là chính xác những gì đang diễn ra ở đây. – CodeConfused

Các vấn đề liên quan