Sử dụng ATMega328 với bộ dao động nội?


17

Tôi có một dự án mà tôi nghĩ sẽ phù hợp nhất với ATMega328P. Tuy nhiên, trong mọi dự án đơn giản mà tôi đã thấy, mọi người luôn kết nối bộ tạo dao động ngoài 16 MHz. Từ những gì tôi có thể thấy, nó nên có một bộ dao động bên trong 8 MHz. Dự án của tôi không đòi hỏi nhiều sức mạnh xử lý, thời gian cũng không cần phải rất chính xác (ngoài UART và I2C). Tôi cũng có một lập trình viên, vì vậy tôi không cần phải lo lắng về bộ tải khởi động.

Có bất kỳ lý do cho tôi để sử dụng một bộ dao động bên ngoài?

Câu trả lời:


19

Những gì bạn không nói là độ chính xác của bộ dao động nội bộ này là gì. Tôi phải mất một thời gian để tìm thấy nó trong bảng dữ liệu , trên trang 369.

10%. Mười phần trăm! Và đó là cho một dao động hiệu chỉnh? Điều này thật kinh khủng. Không phải là không có lý khi hy vọng lỗi thấp đến 1% cho việc này . Microchip / Atmel cung cấp một tài liệu để tự hiệu chỉnh bộ dao động với độ chính xác 1%.

I2C là một giao thức đồng bộ và độ chính xác về thời gian không liên quan miễn là thời gian xung tối thiểu và tối đa được tuân thủ. Mặt khác,
UARTkhông đồng bộ , và sau đó độ chính xác về thời gian thực sự quan trọng. Hầu hết các UART cho phép xảy ra lỗi một nửa bit ở bit cuối cùng (bit stop), do đó, 5% cho truyền 10 bit.

Các bộ dao động hiệu chuẩn nhà máy sẽ không làm ở đây. Bạn sẽ phải trải qua quy trình hiệu chuẩn để đạt 1%. Trong trường hợp đó bạn có thể sử dụng bộ dao động nội. Khác sẽ bạn phải sử dụng một tinh thể.


1
Hãy để tôi củng cố những gì đang được nói ở đây. Tiết kiệm cho mình thời gian và đau đầu và chỉ cần có được một tinh thể. Nếu nguồn điện là một mối quan tâm, hãy sử dụng tinh thể đồng hồ 32khz (6PF cho 48/88/168 ... không chắc chắn về 328. kiểm tra bảng di chuyển) để điều chỉnh bộ dao động bên trong khi khởi động. Thói quen hiệu chuẩn dao động là rất khó, vì vậy hãy cẩn thận nếu bạn đi theo con đường đó. Tôi đã đăng một số mã ví dụ cho nó bên dưới một câu trả lời khác.
tắmMarm0t

6

Khi bạn đang sử dụng UART, một bộ tạo dao động tinh thể sẽ được khuyến khích. Nếu không, bạn có thể sử dụng bộ tạo dao động nội. Một số MCU có bộ dao động bên trong được cắt tại nhà máy, có thể phù hợp với hoạt động của UART.


2
Xem thêm ghi chú ứng dụng này về thời gian UART: maxim-ic.com/app-notes/index.mvp/id/2141
drxzcl

Chà, UART chỉ dành cho giao tiếp với màn hình nối tiếp siêu đơn giản chạy ở tốc độ 9600bps ... Tôi nghĩ rằng cuối cùng tôi sẽ ra lệnh cho bộ dao động và mọi thứ nhưng xem nó có hoạt động mà không có nó không
Earlz

3

"Không nhạy cảm với thời gian". UART rất nhạy cảm về thời gian. Bạn sẽ nhận được rác hoàn chỉnh nếu nó không được đồng bộ hóa một cách thích hợp.

Cách 1: Sử dụng một tinh thể bình thường. Thay đổi đồng hồ chọn cầu chì thích hợp. Lựa chọn tinh thể phụ thuộc vào những gì bạn muốn sử dụng / tốc độ bạn muốn điều này đi. Có "tinh thể ma thuật" sẽ cung cấp cho bạn 0% lỗi cho tỷ lệ tiêu chuẩn (nếu chúng được sản xuất hoàn hảo). Xem các bảng trong Phần 20 [USART0] để biết thêm thông tin (bạn đã đọc biểu dữ liệu .... đúng ???) :).

nhập mô tả hình ảnh ở đây

Tùy chọn 2: Bạn có thể hiệu chỉnh bộ dao động bên trong bằng tinh thể 32khz nếu công suất là một mối quan tâm. Với 32khz, bạn có thể nhận được dòng uA ở chế độ ngủ (Tôi đã giảm xuống còn ~ 2uA). Bạn phải thiết lập một thói quen hiệu chuẩn mặc dù bao gồm bắt đầu / dừng bộ hẹn giờ và xen kẽ timer2 sang chế độ không đồng bộ.

Mã 328P có thể khác nhau ... chức năng này hiện đang hoạt động trên 48/88 (với các định nghĩa phù hợp với IFCPU / baud. Nó hơi xấu / không được tái cấu trúc hoàn toàn nhưng tôi đã học tốt hơn là xoay quanh những thứ hoạt động khi bạn làm việc trên một thời hạn. Tìm kiếm trên diễn đàn AVRFreaks để "điều chỉnh tinh thể 32khz" tương tự như vậy. Đây chỉ là một hương vị cho những gì bạn sẽ tham gia ... Không nhất thiết là những gì sẽ hoạt động.

char OSCCAL_calibration(char starting_cal, int cal_value){
//Function calibrates the internal oscillator so usart comms go through.
//Works by continually checking two different timers:
//   (0 -> tied to internal, and 2 -> async to crystal).
//  Recommended cal_value = 5900 for the crystals we're using.
//  Must be running 8MHZ with clkdiv8 fuse enabled.
//  TODO: Make sure to check all the math on this later.
unsigned char calibrate = FALSE;
int temp;
unsigned char tempL;
volatile char osccal_temp=starting_cal;
int cal_bandwidth = 50;

//int cal_value = 6250;
//int cal_value = 5900; //Works.  Need to find out why.

//Dont use clock prescalers.  We're already div8ing.
//CLKPR = (1<<CLKPCE);        // set Clock Prescaler Change Enable
// set prescaler = 8, Inter RC 8Mhz / 8 = 1Mhz
//CLKPR = (1<<CLKPS1) | (1<<CLKPS0);

TIMSK2 = 0;             //disable OCIE2A and TOIE2
ASSR = (1<<AS2);        //select asynchronous operation of timer2 (32,768kHz)

OCR2B = 200;            // set timer2 compare value.  We probably only need to compare A
OCR2A = 200;

TIMSK0 = 0;             // delete any interrupt sources

TCCR2A = (1<<WGM21);    //Normal operation.  Reset timer on hitting TOP (ocr2a).
TCCR2B = (1<<CS20);     // start timer2 with no prescaling

TCCR1B = (1<<CS10);     // start timer1 with no prescaling

//wait for everythnig to mellow out.
while((ASSR & (1<<TCN2UB)) | (ASSR & (1<<OCR2BUB)) | (ASSR & (1<<TCR2BUB)) | (ASSR & (1<<OCR2AUB)) | (ASSR & (TCR2AUB)));       //wait for TCN2UB and TCR2UB to be cleared

//This is specifically for the crystal to stabilize.  Check for better times.
_delay_ms(1000);

while(!calibrate){
    cli();  // disable global interrupt

    TIFR1 = 0xFF;   // delete TIFR1 flags
    TIFR2 = 0xFF;   // delete TIFR2 flags

    TCNT1H = 0;     // clear timer1 counter
    TCNT1L = 0;
    TCNT2 = 0;      // clear timer2 counter

    //Stop timer on compare match.
    while ( !(TIFR2 & (1<<OCF2A)) );
    TCCR1B = 0;

    //Check for overflows (useless if it happens).
    sei();
    if ( (TIFR1 & (1<<TOV1)) ){
        temp = 0xFFFF;      // if timer1 overflows, set the temp to 0xFFFF
    }else{   // read out the timer1 counter value
        tempL = TCNT1L;
        temp = TCNT1H;
        temp = (temp << 8);
        temp += tempL;
        }

    //Check timer value against calculated value.           
    if (temp > (cal_value+(cal_bandwidth/2))){
        //Oscillator is too fast.
        osccal_temp--;
        OSCCAL=osccal_temp;
    }else if (temp < (cal_value-(cal_bandwidth/2))){
        //Oscillator is too slow.
        osccal_temp++;
        OSCCAL=osccal_temp;
    }else{
        //Just right.
        calibrate = TRUE;
        }

    TCCR1B = (1<<CS10); // start timer1
    }

//TODO: Stop timers, ya?
//Now setup timer2 to run "normally" aka async+interrupts.
//Disable interrupt source. Set mask.  Wait for registers to clear.
TIFR2 = (1<<TOV2);
TIMSK2 = (1<<TOIE2);
ASSR = (1<<AS2);        //select asynchronous operation of timer2 (32,768kHz)
TIMSK0 = 0;             // delete any interrupt sources

//Normal Op. 256 prescale.
TCCR2A = 0x00;
TCCR2B = (1<<CS22) | (1<<CS21);

TCCR1B = 0x00;     // turn off timer1

//wait for everythnig to mellow out.
while((ASSR & (1<<TCN2UB)) | (ASSR & (1<<OCR2BUB)) | (ASSR & (1<<TCR2BUB)) | (ASSR & (1<<OCR2AUB)) | (ASSR & (TCR2AUB)));       //wait for TCN2UB and TCR2UB to be cleared

//This is specifically for the crystal to stabilize.  Check for better times.
_delay_ms(1000);
return osccal_temp;
}

2

Cũng cần lưu ý rằng một tinh thể mất nhiều thời gian để bắt đầu. Đó thực sự là vì độ chính xác của nó: nó chỉ lấy năng lượng từ một dải tần số rất hẹp. Điều này có thể là một gánh nặng cho các công cụ hoạt động bằng pin, nơi bạn thức dậy mcu trong một thời gian rất ngắn mỗi giờ và sau đó: chờ đợi một giây ở mức năng lượng đầy đủ để tinh thể bắt đầu là một mất mát ròng. Bộ cộng hưởng gốm chính xác hơn bộ tạo dao động RC bên trong nhưng nhỏ hơn một tinh thể và bắt đầu tương ứng.

Tất nhiên, một atmega 16 MHz uống nhiều nước trái cây hơn và cần điện áp cao hơn so với 8 MHz, nhưng có sẵn các tinh thể 8 MHz (hoặc thấp hơn, xuống tới 32kHz); sự lựa chọn này cũng có thể là một trình tiết kiệm năng lượng.


0

Nếu bạn không cần nhiều thời gian hoặc chính xác, thì không cần bộ tạo dao động ngoài. Trong khi tháo rời một số máy in cũ, tôi tình cờ thấy rất nhiều IC nhưng không phải là một bộ dao động duy nhất trên tàu.


0

Tôi đoán bạn đã thấy ứng dụng này lưu ý: AVR053: Hiệu chỉnh bộ dao động RC bên trong .

Tôi đoán từ nó, và ghi chú ứng dụng từ nhận xét của @drxzcl ở trên, bạn sẽ có thể quyết định về mặt lý thuyết điều gì là đúng.


Khi đã có câu trả lời được chấp nhận, bạn nên cố gắng nói thêm điều gì đó, nếu không nó không hữu ích lắm
clabacchio

@clabacchio - câu trả lời này đã được hai ngày tuổi và ngày được chấp nhận từ hôm qua. Nó không thể được chấp nhận khi điều này được đăng.
stevenvh

@stevenvh đúng, tôi không nhận ra đó chỉ là một bản chỉnh sửa; mặc dù, đó là một câu trả lời không đầy đủ
clabacchio

@clabacchio - "câu trả lời không đầy đủ". Đã đồng ý! Tôi không thể thấy "bạn sẽ có thể quyết định" rất hữu ích.
stevenvh

@clabacchio - Này, tôi cũng nói "2 ngày trước" bây giờ. Một phút trước nó nói "đã trả lời ngày hôm qua". Phải chính xác là 48 giờ! :-)
stevenvh
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.