Thông báo

Collapse
No announcement yet.

USART:Sao PC nhận được toàn là 0x00, điên cái đầu

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • USART:Sao PC nhận được toàn là 0x00, điên cái đầu

    Em làm mạch giao tiếp mega8 với PC (laptop):
    +Dùng IC chuyển mức áp RS232
    +do laptop ko có COM nên phải xài USB to RS232 cable
    +không có thạch anh 7.3728 nên dùng tạm 8Mhz nội của mega8

    Em thử truyền nhận giữa hai con mega8 hoặc mega8 với mega16 thì bình thường, tự mỗi con truyền nhận cũng bình thường, đang hứng thú đem cắm vô PC là oooc eei....e dùng COMport monitor nó toàn nhận 0x00, gửi xuống VDK cũng ko nhận được. code của e bên dưới mấy huynh có kinh nghiệm sửa lỗi giùm e phát:

    CHO EM HỎI THÊM : trong mạch chuyển mức áp của con MAX232 trong giao tiếp USART với PC em thấy thường dùng tụ 10uF, một số thiết kế lại chỉ dùng tụ 0.1uF là sao vậy,có phải để thay đổi độ lớn áp ra trên bus RS232.

    Code:
    #include <avr/io.h>
    #include <avr/iom8.h>
    #include <avr/interrupt.h>
    #include <avr/delay.h>

    #define FOSC 8000000//clock speed
    #define BAUD 9600
    #define MYUBRR ((FOSC/(16*BAUD))-1)

    unsigned char data_in;
    unsigned char data_out;

    void main(void)

    {
    DDRB=0xff
    USART_init(MYUBRR);
    sei();

    while(1)
    {
    data_out=0X0F;
    _delay_ms(1000);
    USART_transmit(data_out);
    data_out=0Xf0;
    _delay_ms(1000);
    USART_transmit(data_out);
    };

    while(1)
    {};

    };

    //*******************************************
    void USART_init(unsigned int ubrr)
    {
    /*Tao toc do BAUD*/
    UBRRH=(unsigned char) (ubrr>>8);
    UBRRL=(unsigned char) ubrr;
    /*Kich hoat module thu va phat*/
    UCSRB|=(1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
    /*Chon khung du lieu: 8bit, no parity, 2 stop bit*/
    UCSRC|=(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);
    };

    //*******************************************
    void USART_transmit(unsigned char data)
    {
    /*cho cho thanh ghi dem phat rong*/
    while(!(UCSRA&(1<<UDRE)))
    {};
    UDR=data;
    };

    //*******************************************


    //*******************************************
    ISR(USART_RXC_vect)
    {
    data_in=UDR;
    PORTB=data_in;
    };

    //*******************************************
    Last edited by apple; 19-09-2008, 12:28.
    Mấy ai định nghĩa được tình yêu.
    Có gì đâu một buổi chiều.
    Kề dao lên cổ yêu hay chết .
    Gật đầu cái rụp thế là yêu.

    --------
    Apple

  • #2
    thạch anh nội chỉ dùng cho ứng dụng ko cần độ chính xác về thời gian thì xài được. muốn tạo tốc độ baud chính xác phải dùng thạch anh lẻ (vd: 7.3728,11.0592) như trong datasheet thì mới giao tiếp được với các thiết bị ngoại vi khác cu tèo ạ !

    Comment


    • #3
      thạch anh nội chỉ dùng cho ứng dụng ko cần độ chính xác về thời gian thì xài được. muốn tạo tốc độ baud chính xác phải dùng thạch anh lẻ (vd: 7.3728,11.0592) như trong datasheet thì mới giao tiếp được với các thiết bị ngoại vi khác cu tèo ạ !
      Ai bảo thế? datasheet chỉ khuyên dùng XTAL lẻ thôi, còn thạch anh 2x vẫn tạo baurate tốt với sai số 2% trở lại, thu phát tốt, mình thu phát toàn dùng thạch anh nội mà có sao đâu.

      Với chương trình trên, mình không tìm thấy chỗ nào có vấn đề, không hiểu sao bỏ vào AVRStudio chạy đến câu UBRRH và UBRRL đều cho bằng 0, vậy không ổn rồi. Bạn cài thủ công UBRRH=0, UBRRL=0x33 thử xem sao.
      Last edited by Kilodeth; 21-09-2008, 22:36.
      Đẹp từng kilomét

      Comment


      • #4
        Mình đã tìm ra chỗ sai là đây:
        ((FOSC/(16*BAUD))-1)
        Phải đổi lại thành:
        ((FOSC/16/BAUD)-1)
        Các bạn có thấy lạ ko, hai phép toán trên hoàn toàn như nhau nhưng lại ko cho kết quả giống nhau. Mình hiểu như vậy ko biết có đúng ko:
        trong phép tính tìm ra MYUBRR có một phép tính nhỏ:
        16*BAUD=16*9600=153600
        trong khi biến ubrr trong thủ tục
        void USART_init(unsigned int ubrr)
        lại chỉ định nghĩa là kiểu biến 2byte ko dấu, do vậy khi tính bị tràn dữ liệu và dẫn đến các phép tính sau bị sai.

        Thật là tai hại khi chỉ sơ xuất một chút mà mò muốn điên cái đầu, xém tính thay con mega8 khác
        Last edited by apple; 21-09-2008, 23:29.
        Mấy ai định nghĩa được tình yêu.
        Có gì đâu một buổi chiều.
        Kề dao lên cổ yêu hay chết .
        Gật đầu cái rụp thế là yêu.

        --------
        Apple

        Comment


        • #5
          Nguyên văn bởi Kilodeth Xem bài viết
          Ai bảo thế? datasheet chỉ khuyên dùng XTAL lẻ thôi, còn thạch anh 2x vẫn tạo baurate tốt với sai số 2% trở lại, thu phát tốt, mình thu phát toàn dùng thạch anh nội mà có sao đâu.

          Với chương trình trên, mình không tìm thấy chỗ nào có vấn đề, không hiểu sao bỏ vào AVRStudio chạy đến câu UBRRH và UBRRL đều cho bằng 0, vậy không ổn rồi. Bạn cài thủ công UBRRH=0, UBRRL=0x33 thử xem sao.
          tại sao ko dùng thạch anh lẻ với sai số 0% mà đi dùng thạch anh 2x làm gì cho nó cực vậy!

          Comment


          • #6
            tại sao ko dùng thạch anh lẻ với sai số 0% mà đi dùng thạch anh 2x làm gì cho nó cực vậy!
            Bởi vì có gì xài đó , với lại thạch anh chẵn dễ tính nhẩm chu kỳ, trì hoãn, pwm.. hơn
            Đẹp từng kilomét

            Comment


            • #7
              Với thạch anh nội 8MHZ, muốn đôn BAUD lên 57600 hoặc 115200 thì chịu vì lúc này sai số lên 2.1% và -3.5%. Chẳng lẽ cứ dùng mãi 9600? Nhiều lúc cũng cực lắm.

              Comment


              • #8
                ((FOSC/(16*BAUD))-1)
                ((FOSC/16/BAUD)-1)
                hoàn toàn khác nhau chứ nhẩy?. Trong FOSC/16/BAUD thì phép chia nào được thực hiện trước? AVR có hiểu được không?

                Comment


                • #9
                  Nguyên văn bởi apple Xem bài viết
                  Mình đã tìm ra chỗ sai là đây:


                  Phải đổi lại thành:


                  Các bạn có thấy lạ ko, hai phép toán trên hoàn toàn như nhau nhưng lại ko cho kết quả giống nhau. Mình hiểu như vậy ko biết có đúng ko:
                  trong phép tính tìm ra MYUBRR có một phép tính nhỏ:
                  trong khi biến ubrr trong thủ tục lại chỉ định nghĩa là kiểu biến 2byte ko dấu, do vậy khi tính bị tràn dữ liệu và dẫn đến các phép tính sau bị sai.

                  Thật là tai hại khi chỉ sơ xuất một chút mà mò muốn điên cái đầu, xém tính thay con mega8 khác
                  Đúng vậy. Khi làm với codevision phải chú ý casting các biến. Đặc biệt là với phép nhân và chia. Nếu ko sẽ dẫn đến việc sai ko biết do đâu.
                  AVR đã quay trở lại: ATMEGA32: 66k, ATMEGA8A: 30k, ATMEGA48: 30k.
                  Xem thêm tại Online Store ---> Click here
                  Mob: 0982.083.106

                  Comment


                  • #10
                    Mình đã tìm ra chỗ sai là đây:
                    Trích:
                    ((FOSC/(16*BAUD))-1)
                    Phải đổi lại thành:
                    Trích:
                    ((FOSC/16/BAUD)-1)
                    Các bạn có thấy lạ ko, hai phép toán trên hoàn toàn như nhau nhưng lại ko cho kết quả giống nhau. Mình hiểu như vậy ko biết có đúng ko:
                    trong phép tính tìm ra MYUBRR có một phép tính nhỏ:
                    Trích:
                    16*BAUD=16*9600=153600
                    trong khi biến ubrr trong thủ tục
                    Trích:
                    void USART_init(unsigned int ubrr)
                    lại chỉ định nghĩa là kiểu biến 2byte ko dấu, do vậy khi tính bị tràn dữ liệu và dẫn đến các phép tính sau bị sai.

                    Thật là tai hại khi chỉ sơ xuất một chút mà mò muốn điên cái đầu, xém tính thay con mega8 khác
                    Bạn xác định được lỗi như vậy cũng rất tốt, thế nhưng gốc rễ vấn đề là do AVRstudio không được tối ưu (optimized) phù hợp. Thế nên cả dòng ((FOSC/(16*BAUD))-1) đưa cho AVR xử lý và xảy ra tình trạng như bạn thấy. Nó còn báo conflicting type ở đoạn mã đó nữa, nói chung AVRStudio mình chưa rành.

                    Cùng đoạn mã trên, mình copy qua CodeVision xuất ra ngay UBRRL=0x33. Đó là do Codevision mình đã set tối ưu nên toàn bộ câu lệnh đều do trình dịch tính toán và xuất ra. Bạn thử xem
                    Đẹp từng kilomét

                    Comment


                    • #11
                      Đúng vậy. Khi làm với codevision phải chú ý casting các biến. Đặc biệt là với phép nhân và chia. Nếu ko sẽ dẫn đến việc sai ko biết do đâu.
                      AVRstudio chứ bác, Codevision lại không mắc bệnh này, thế mới hay!
                      Đẹp từng kilomét

                      Comment


                      • #12
                        Nguyên văn bởi Kilodeth Xem bài viết
                        AVRstudio chứ bác, Codevision lại không mắc bệnh này, thế mới hay!
                        Code vision vẫn bị. Mình đã bị dính mấy phát.
                        AVR đã quay trở lại: ATMEGA32: 66k, ATMEGA8A: 30k, ATMEGA48: 30k.
                        Xem thêm tại Online Store ---> Click here
                        Mob: 0982.083.106

                        Comment


                        • #13
                          Mấy bữa nay bận quá chưa test bằng codevison được. Nếu bác Kilodeth thử bằng codevision mà ko bị thì mình nghĩ có lẽ trong Codevision, sau khi mình khai báo các phần tử,các phép toán để tìm ra MYUBRR là nó sẽ thi hành theo kiểu một chương trình con riêng biệt do nó tự sinh ra bên trong (các biến do nó tự định nghĩa) để tính ko phụ thuộc vào kiểu của ubrr còn thằng AVRstudio việc khai báo các phép toán và thông số tìm ra MYUBRR chỉ được dùng như một công thức để tính sau đó trong thủ tục void USART_init(unsigned int ubrr) nó mới đem cái công thức đó ra tính nên mới có chuyện bị tràn như vậy.

                          Theo mình tốt nhất nên cảnh giác với cái kiểu lỗi loại này dù ta có dùng trình biên dịch nào đi nữa cũng nên cẩn thận có như thế "làm nông mới bớt sợ trời hành"
                          Last edited by apple; 23-09-2008, 21:33.
                          Mấy ai định nghĩa được tình yêu.
                          Có gì đâu một buổi chiều.
                          Kề dao lên cổ yêu hay chết .
                          Gật đầu cái rụp thế là yêu.

                          --------
                          Apple

                          Comment


                          • #14
                            Kinh nghiệm của tôi khi lập trình C với chíp không nên làm các phép tính gộp qua dài vì giới hạn của RAM trong chíp. Có thể lệnh đó trên máy tính thì không sai nhưng trên chíp sẽ gặp vấn đề như bạn đó.
                            ((FOSC/(16*BAUD))-1)
                            sẽ được thực hiện như sau:
                            a = FOSC;
                            a /= (16*BAUD);
                            a -= 1;

                            và một nguyên tắc nữa là nên thực hiện ép kiểu khi tính toán để có kết quả đúng, không bị báo lỗi warning
                            Last edited by sidesignvn; 02-10-2008, 11:03.
                            Dùng hàng VN - Giữ lại USD cho đất nước.

                            Comment

                            Về tác giả

                            Collapse

                            apple Tìm hiểu thêm về apple

                            Bài viết mới nhất

                            Collapse

                            Đang tải...
                            X