Phản ứng bất ngờ của Atmega16 trên UART


8

Phản ứng bất ngờ của Atmega16 trên UART

Tóm tắt vấn đề

Tôi đã flash một Atmega16 với mã sẽ dẫn đến Atmega16 gửi lại bất kỳ ký tự nào tôi gửi cho nó thông qua một thiết bị đầu cuối. Tôi nhận được phản hồi, nhưng hiếm khi nhân vật tôi gửi. Tôi có thể thấy đầu ra chính xác bằng cách thay đổi tốc độ baud nhưng tôi không hiểu tại sao tốc độ baud chính xác hoạt động.

Thêm chi tiết

Tôi đang cố gắng tìm hiểu thêm về lập trình phần mềm trong thời gian riêng của mình vì tôi khá thích nó. Cho đến nay trong chương trình phần sụn tôi đã thực hiện tại uni, chúng tôi đã được cung cấp các tệp mã bộ xương thực hiện nhiều giao diện ngoại vi và thiết lập cho chúng tôi, nhưng tôi muốn tự mình tìm hiểu điều này. Tôi đã có một vài câu hỏi về những gì tôi đang làm ở đây rắc khắp bài viết nhưng cuối cùng tôi sẽ phân loại chúng. Nếu bạn nhận ra bất kỳ sự hiểu lầm hoặc lỗ hổng tiềm năng nào trong kiến ​​thức của tôi, tôi sẽ đánh giá rất cao bất kỳ đầu vào nào bạn có thể có.

Mật mã

Mã tôi đã flash vào Atmega16 của tôi được lấy gần như dòng cho hướng dẫn 'Sử dụng USART trong AVR-GCC' được tìm thấy trên trang này . Tất cả những gì tôi đã thêm là #define cho F_CPU. Mã ban đầu không có #define cho F_CPU vì vậy mã của tôi sẽ không được biên dịch trong AtmelStudio 7. Có ai có thể giải thích lý do tại sao tác giả sẽ không xác định F_CPU trong tệp gốc của họ không? Tôi đoán họ có thể đã sử dụng một số công cụ hoặc trình biên dịch khác ngoài Atmel Studio 7 nhưng tôi không thể nói chắc chắn được.

#include <avr/io.h>
#define F_CPU 7372800 //this was chosen because the tutorial states this is the frequency we want to operate at
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((( F_CPU / 16) + ( USART_BAUDRATE / 2)) / ( USART_BAUDRATE )) - 1)

int main ( void )
{
    char ReceivedByte ;
    UCSRB = (1 << RXEN ) | (1 << TXEN ); // Turn on the transmission and reception circuitry
    UCSRC = (1 << URSEL ) | (1 << UCSZ0 ) | (1 << UCSZ1 ); // Use 8- bit character sizes
    UBRRH = ( BAUD_PRESCALE >> 8); // Load upper 8- bits of the baud rate value into the high byte of the UBRR register
    UBRRL = BAUD_PRESCALE ; // Load lower 8- bits of the baud rate value into the low byte of theUBRR register
    for (;;) // Loop forever
    {
        while (( UCSRA & (1 << RXC )) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
        ReceivedByte = UDR ; // Fetch the received byte value into the variable " ByteReceived "
        while (( UCSRA & (1 << UDRE )) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
        UDR = ReceivedByte ; // Echo back the received byte back to the computer
    }
}

Thiết lập phần cứng

Ảnh cài đặt phần cứng

  • MCU: Atmega16;
  • Toolchain: Atmel Studio 7, nhấp nháy với rồng AVR;
  • Nguồn cung cấp: Đường ray 5V được lấy từ một trường phát triển do trường đại học cung cấp (được lấy từ USB máy tính). Tụ điện đĩa gốm 100nF được sử dụng để bỏ qua trên đường dây điện bánh mì
  • Bộ chuyển đổi USB sang nối tiếp: Cái này . TXD trên bộ chuyển đổi USB sang nối tiếp được kết nối với RXD Atmega (Chân 15). RXD trên bộ chuyển đổi được kết nối với RXD trên Atmega (Chân 14).
  • Phần mềm đầu cuối: PuTTY (với tốc độ baudrate là 9600).

    Bằng chứng của các phản ứng không chính xác

    Để nhắc lại, Atmega nên trả lại những gì đã được gửi tới nó, tức là OUTPUT phải chính xác như INPUT.

    Đầu ra PuTTY

    ĐẦU VÀOĐẦU RAf&f6z>d0không gian0xsố 8

    Chụp dao động

    Tôi đã sử dụng Máy chụp ảnh của mình với giải mã nối tiếp để kiểm tra xem Atmega có nhận được đầu vào chính xác hay không. Chẳng hạn, khi tôi nhấn phím 'f', nó được nhận chính xác. Đầu ra vẫn là '6' (hoặc ký hiệu '&' đôi khi).

Chụp phạm vi trên chân RX của Atmega16 cho thấy rằng ký tự chính xác đang được gửi qua phần mềm đầu cuối ('f')

Chụp phạm vi trên chân TX của Atmega16 cho thấy phản hồi không mong muốn đang được gửi lại ('6')

Một sửa chữa tôi vấp phải mà tôi không hiểu

Nếu tôi thay đổi baudrate thành 2500in PuTTY, mọi thứ sẽ được hiển thị chính xác. Tôi đã chọn giá trị này một cách ngẫu nhiên và tôi không biết tại sao nó hoạt động (điều đó khiến tôi tin rằng tôi đã mắc lỗi ở đâu đó với baudrate nhưng tôi không thấy nơi nào tôi đã sao chép hướng dẫn gần như chính xác ... Tôi nghĩ).

Câu hỏi

  1. Tôi đã làm gì sai / chuyện gì đang xảy ra ở đây?
  2. Tại sao hướng dẫn ban đầu không #define F_CPU?
  3. Tại sao cài đặt tốc độ baud thành 2500 khắc phục sự cố? (Tôi nghi ngờ điều này sẽ được trả lời nếu câu hỏi 1 được trả lời)

2
Chỉ cần xác định F_CPU với một số giá trị sẽ không khiến micro chạy ở tần số đó. F_CPU phải được định nghĩa là tần suất bạn định cấu hình micro để chạy - nhưng tôi không thấy bất kỳ bằng chứng nào cho thấy bạn đã định cấu hình này ở bất cứ đâu ...
brhans

Câu hỏi được viết tốt. Điều duy nhất sẽ cải thiện nó sẽ là một sơ đồ.
Blair Fonville

LMộtTEX

Tôi nhận thấy rằng bạn không có tinh thể bên ngoài trên bảng của bạn. Bạn đang sử dụng đồng hồ RC nội bộ? Tần số nào bạn mong đợi bộ xử lý sẽ chạy ở?
scotty3785

Nhờ thảo luận của bạn về F_CPU, tôi đã điều tra và chơi xung quanh và đăng giải pháp. Tôi tưởng tượng nó rõ ràng với bạn (như với tôi bây giờ ) nhưng nó có thể giúp đỡ người khác.
daviegravee

Câu trả lời:


0

Tôi đã tìm ra rồi! Nhờ những bình luận về F_CPU khi trả lời OP tôi đã thực hiện một số điều tra (điều này có thể rõ ràng với tất cả các bạn).

Tóm tắt giải pháp

Atmega16 không chạy ở tần số mà tôi nghĩ là do tôi không hiểu cách thay đổi tần số hệ thống. Bằng cách kiểm tra các cầu chì trong Atmel Studio, tôi có thể thấy tôi đang chạy ở mức 2 MHz (đây không phải là tần số xung nhịp tiêu chuẩn theo như tôi biết nhưng tôi sẽ không tham gia vào đó), và không phải là 7.3728 MHz như hướng dẫn.

F_CPU không thay đổi tần số xung nhịp của MCU (Atmega16). Tần số của Atmega16 không được thay đổi thành 7.3728 MHz vì cần thiết để lấy ví dụ mã hoạt động. Nó vẫn chạy ở tần số được xác định bởi các cầu chì (trong trường hợp này là 2 MHz, nhiều hơn về điều này dưới đây) vì vậy cách tính giấy của baudrate mong muốn khác với những gì thực sự được sử dụng.

Mã làm việc

#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 2000000 //THIS LINE IS **NOT** CHANGING THE FREQUENCY OF THE MCU: CHANGE MCU FREQUENCY IN FUSES
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((( F_CPU / 16) + ( USART_BAUDRATE / 2)) / ( USART_BAUDRATE )) - 1)

int main ( void ){
    char ReceivedByte ;
    UCSRB = (1 << RXEN ) | (1 << TXEN ); // Turn on the transmission and reception circuitry
    UCSRC = (1 << URSEL ) | (1 << UCSZ0 ) | (1 << UCSZ1 ); // Use 8- bit character sizes
    UBRRH = ( BAUD_PRESCALE >> 8); // Load upper 8- bits of the baud rate value into the high byte of the UBRR register
    UBRRL = BAUD_PRESCALE ; // Load lower 8- bits of the baud rate value into the low byte of theUBRR register
    for (;;){ // Loop forever
        while (( UCSRA & (1 << RXC )) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
        ReceivedByte = UDR ; // Fetch the received byte value into the variable " ByteReceived "
        while (( UCSRA & (1 << UDRE )) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
        UDR = ReceivedByte ; // Echo back the received byte back to the computer
    }
}

Thêm chi tiết

Baudrate mong muốn vs những gì Atmega đã thực sự làm

Baudrate mong muốn (từ hướng dẫn) là 9600, đây là baudrate tôi đã sử dụng trong PuTTY. Tốc độ baudrate thực tế có thể được tính bằng phương trình được tô sáng trong Bảng 60 (trang 147) của biểu dữ liệu Atmega16.

Bảng phương trình để tính baudrate và UBRR từ trang 147 Bảng dữ liệu Atmega16

Trong ví dụ mã BAUD_PRESCALEUBRR trong tính toán. BAUD_PRESCALEđược đánh giá là 47 với các giá trị được xác định cho F_CPUUSART_BAUDRATE.

BAUD= =foSc16(UBRR+1)
BAUD= =2,000,00016(47+1)
BAUD2,604

Và đây là gốc rễ của vấn đề. Atmega16 hoạt động ở mức 2 MHz, điều đó có nghĩa là giá trị của f_ {osc} khác với ví dụ hướng dẫn, dẫn đến tốc độ baudrate là 2.604 so với 9.600.

Lưu ý rằng f_osc là tần số hệ thống thực tế của MCU, không được xác định bởi F_CPU.

Vì vậy, điều đó cũng trả lời câu hỏi thứ 3 của tôi: thay đổi baudrate thành 2.500 may mắn đủ gần với baudrate hoạt động của MCU để thiết bị đầu cuối có thể diễn giải chính xác kết quả.

Thay đổi tần số của MCU

Để thay đổi tần số của MCU trong AtmelStudio 7, hãy đi:

Tools > Device programming > Fuses > Change SUT_CKSEL (or LOW.SUT_CKSEL in my case) to desired frequency (make sure you have read up on the side effects of this). 

Tần số được sử dụng trong ví dụ này không phải là tần số xung nhịp bên trong tiêu chuẩn, vì vậy tôi sẽ sử dụng 2 MHz.

Tóm tắt câu trả lời cho câu hỏi của riêng tôi

  1. Tôi đã làm gì sai / chuyện gì đang xảy ra ở đây? Trả lời : Không thực sự thay đổi tần số xung nhịp thành tần số xung nhịp trong hướng dẫn dẫn đến tốc độ truyền khác với dự kiến ​​sẽ khiến phần mềm đầu cuối (PuTTY) không đồng bộ với MCU
  2. Tại sao hướng dẫn ban đầu không #define F_CPU? Trả lời : Vẫn không hoàn toàn chắc chắn nhưng tôi đoán nó sẽ được định nghĩa trong một tệp thực hiện không được đưa ra trong hướng dẫn và tác giả đã không sử dụng IDE như Atmel Studio
  3. Tại sao cài đặt tốc độ baud thành 2500 khắc phục sự cố? (Tôi nghi ngờ điều này sẽ được trả lời nếu câu hỏi 1 được trả lời) Trả lời : May mắn đoán được một số gần với tốc độ baud của Atmega16
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.