ATMega8 and an External Clock

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have an Atmega8 and an external oscillator. The oscillator is a rectangular, 4-pin component that I picked up in a local surplus store (no data sheets, loose parts, no regular stock); however, I did some research on the internet, and I think that this is likely the data sheet. Based on some research on avrFreaks, I believe that this is an "external clock."

I would like to experiment with this clock source - in particular I am working thru Deans USART tutorial (I know that 16Mhz is not one of the "magic numbers," but it seems to be within the 2% error tolerance that Dean references). I want to use it with my ATMega8. I am programming the mcu with an AVRISP MKII.

Can someone offer some advice as to whether I am think in the following thru correctly?

First: To use this clock source, it seems that I need to select "External Clock" in the fuse drop down menu in AVR Studio. Table 12 on page 32 of the data sheet suggests that the only 3 options for the ATMega8 and an external clock are:

Quote:
6 CK "“ BOD enabled
6 CK 4.1 ms - Fast rising power
6 CK 65 ms - Slowly rising power

In the drop down menu "6 CK 65 ms" isn't a choice, but "6 CK 64 ms" is a choice - I assume that they are the same? Not sure if I understand which "start-up" time I should use, but since the "default" setting that the chip ships with is "Slowly rising power," I am inclined to select that option - does that sound right?

Second: Also, with respect to the CKOPT Fuse, the data sheet says

Quote:
By programming the CKOPT Fuse, the user can enable an internal 36 pF capacitor between
XTAL1 and GND, and XTAL2 and GND.

So, I assume that I should check that box on the fuse dialogue menu?

Third: Per Figure 13 on page 32 of the mcu data sheet and the clock's data sheet, I hook pin #7 of the clock to GND, #8 to XTAL1 of the mcu, #14 to Vcc (5V, same as the mcu) and leave #1 unconnected.

Fourth: When I am done experimenting, I want to re-set internal clock. If I program mcu with my AVRISP MKII while it is still connected to the external clock, will I be able to re-set the internal clock (i.e., the factory setting)? Is it as simple as going into the fuse menu and selecting the "default" fuse setting?

Thanks for any help and patience.

Russ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1) crystals and oscillators may take some time from the application of power before they resonate so picking slow start time is the "safe" option

2) CKOPT is to do with directly connected cystals - no need to worry when an oscillator is used - it'll be full swing anyway.

3) Yup you just apply power to the module and run it's output to the AVR's XTAL1 pin - that's all you need.

4) Yup, switching back (as long as the external is still oscillating) is no problem. (I'm not sure why you would though - wouldn't you always prefer to use the more accurate clock once it's working?)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for your quick reply.

clawson wrote:
4) Yup, switching back (as long as the external is still oscillating) is no problem. (I'm not sure why you would though - wouldn't you always prefer to use the more accurate clock once it's working?)

Yes, I guess...but reading the various posts about folks locking up their chips by messing with fuses kind of make me nervous :oops: I sort of thought that when I was done with the USART experiment, it would be a good idea to re-set the clock back to something safe, that I knew should work, in the event the oscillator went bad or the dog ate it...

BTW - Would I need the same clock source (16Mhz oscillator) to re-set fuse, or would any external clock due the trick?

Russ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As you have an oscillator you need have no worries about any setting of CKSEL as you can always get back from the brink. The one "dangerous" fuse in the mega8 is the RSTDISBL one - but that's in the other fuse byte - so just steer clear of ever setting that fuse byte.

To do ISP assuming the CKSEL are set to either crystal or oscillator all you need is a square wave at >(fISP *4) applied to the XTAL1 pin.

If you have a second AVR load it with a program to toggle all the pins. If you set it to 8MHz int RC then you can probably get about 1MHz out of all the IO pins. Use that to provide a square wave for fixing CKSEL accidents in future if the dog eats your canned oscillator.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you. I appreciate your help.

clawson wrote:
To do ISP assuming the CKSEL are set to either crystal or oscillator all you need is a square wave at >(fISP *4) applied to the XTAL1 pin.

So, if my external clock is 16MHZ, then in the AVR Studio settings for the AVRISP MKII, I need to make sure that the fISP is less than 4Mhz.

clawson wrote:
If you have a second AVR load it with a program to toggle all the pins. If you set it to 8MHz int RC then you can probably get about 1MHz out of all the IO pins. Use that to provide a square wave for fixing CKSEL accidents in future if the dog eats your canned oscillator.
Would I toggle with the same type of code that I would use to blink an LED? And set the frequency of the on/off toggle ("blinking") to fISP*4? If that was the case, then I guess I could use PWM with a 50% duyt cycle? Do I really connect all of the pins of the second AVR to XTAL1 of the target? So, for example, if I was using an extra ATMega8, that would be approximately 23 IO pins? I am not sure that I understand how the technique of using a second AVR as clock source works...I will search google and this forum and see what I can find to help me understand better. The concept is interesting, and after I finish experimenting with USART, I may try and play around with that.

In the meantime, I have another canned oscillator (~7.128Mhz that I purchased from the same place) that I can use in a pinch (fISP will need to be less than 7.128Mhz/4). I will need to look around for a data sheet for that one.

And I will keep my dog away well fed and from the oscillator.

I really do appreciate you time, help and patience.

Russ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

So, for example, if I was using an extra ATMega8, that would be approximately 23 IO pins? I am not sure that I understand how the technique of using a second AVR as clock source works...

#include 

int main(void) {
  DDRB = 0xFF;
  DDRC = 0xFF;
  DDRD = 0xFF;
  while(1) {
    PORTB ^= 0xFF
    PORTC ^= 0xFF
    PORTD ^= 0xFF
  }
}

Toggles all the IO pins. It's overkill really - you only need to wiggle one pin but this gives you tons of pins to choose from (PORTC only has 7, not 8 bits by the way)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To which pin of the second AVR do I attach XTAL1 of the target?

Thanks.

Russ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Any IO

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you.

Russ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well the good news is that I successfully loaded the USART code I was experimenting with (essentially Dean's with some modifications to experiment) - using the external clock.

Everything seemed to work like a charm...now I am going to see if I can figure out how I can use "printf()" (working thru this thread and the example and explanation in the avr-libc manual) and maybe tie the USART with the code I wrote to debounce a momentary switch and/or rotate my servos.

Thank you for your help, clawson. I do appreciate it.

Russ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's some simple (output only) printf() stuff I use on a mega16:

#include 
#include 

int uart_putc(char c, FILE *unused) {
	while (!(UCSRA & (1<<UDRE)));
	UDR = c;
	return 0;
}

FILE uart_str = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);

int main(void) {
	UBRRL = 51; // 9600 @ 8MHz
	UCSRB = (1<<TXEN); // only using it as output debug channel

	stdout = &uart_str; // printf to UART

	printf("Hello world\n"); // UART

That's about the minimum you can get away with to use printf() in GCC.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Here's some simple (output only) printf() stuff I use on a mega16:

#include 
#include 

int uart_putc(char c, FILE *unused) {
	while (!(UCSRA & (1<<UDRE)));
	UDR = c;
	return 0;
}

FILE uart_str = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);

int main(void) {
	UBRRL = 51; // 9600 @ 8MHz
	UCSRB = (1<<TXEN); // only using it as output debug channel

	stdout = &uart_str; // printf to UART

	printf("Hello world\n"); // UART

That's about the minimum you can get away with to use printf() in GCC.

Excellent - thank you. Can I ask you a question or 2?

In reading thru the avr-libc manual example on io and googling, most example code uses this format:

int uart_putc(char c, FILE *stream)

But you use:

int uart_putc(char c, FILE *unused)

Can you help me understand the distinction (if any)? I had assumed (before seeing your code) that the reference to "FILE *stream" in the argument list of the put function was to indicate that that function needed a steam when it called; and in the context of printf (where uart_str is set to stdout as you have done), the stream is the one opened by the following snippet of your code:

FILE uart_str = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);

Also, a basic question about printf(). I think that the way that printf() works - "behind the scenes" so to speak - is that print() sends one character at a time to the stream that equates to stdout (ignoring for a minute the formatting characters). So that in an operating system environment (where stdout is pre-determined) there is a put function already associated with, or part of printf() as a sub-function so to speak. In the case of your code and the code in the avr-libc manual example, the put function is provided by the code you write - and that is why the following code (which send one character at a time to UDR works with printf() and the AVT USART:

while (!(UCSRA & (1<<UDRE)));
	UDR = c;

I know that my terminology is imprecise and that my understanding of the mechanics of stdio, streams and C in general is on the shallow side - But am I on the right track on the concept here?

I appreciate your help and patience.

Russ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Can you help me understand the distinction (if any)? I had assumed (before seeing your code) that the reference to "FILE *stream" in the argument list of the put function was to indicate that that function needed a steam when it called; and in the context of printf (where uart_str is set to stdout as you have done), the stream is the one opened by the following snippet of your code:

The second parameter to the function you provide allows the file-stream system "behind" printf to pass a pointer to the FILE structure for the open stream to which the routine has been attached so that you may access fields within it if you want to. For the simple case of UART or LCD output routine I wouldn't see much point in it.
Quote:

In the case of your code and the code in the avr-libc manual example, the put function is provided by the code you write

As the manual explains:
Quote:
The standard streams stdin, stdout, and stderr are provided, but contrary to the C standard, since avr-libc has no knowledge about applicable devices, these streams are not already pre-initialized at application startup. Also, since there is no notion of "file" whatsoever to avr-libc, there is no function fopen() that could be used to associate a stream to some device. (See note 1.) Instead, the function fdevopen() is provided to associate a stream to a device, where the device needs to provide a function to send a character, to receive a character, or both. There is no differentiation between "text" and "binary" streams inside avr-libc. Character \n is sent literally down to the device's put() function. If the device requires a carriage return (\r) character to be sent before the linefeed, its put() routine must implement this

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay...this is helpful. Thank you.

In your code, then "unused" is a keyword. Doing a quick google, it looks to be used here to avoid errors or warnings that the second argument of you put function is not being used - is that correct?

Russ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Nope 'unused' is the name of the variable just as in:

int add(int apples, int oranges){

where 'apples' and 'oranges' are the names of the variable parameters to the function.

I use 'unused' for two reasons. One it just makes the code more readable for a human who hopefully realises that although the parameter is being defined to meet the documented API it's not actually used and secondly some code verification systems (lint etc) may actually recognise the use of 'unused' and not bother to warn "function has parameter specified that is never used" (or whatever)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am using an stk500 now. I know it has an on-board external clock, but if I want to use a 16Mhz crystal oscillator (i.e., a canned oscillator) as the external clock, then I would need to do the following:

  • Put the canned oscillator on some external board (like a bread board);
  • Use a jumper wire to connect the appropriate output pin of the canned oscillator to XTAL1; and
  • Disconnect the XTAL1 and OSCSEL jumpers on the stk500
Correct?

Russ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sound right or thereabouts, Russ.

But why not simply use a 16 MHz crystal instead of the oscillator? The STK500 has a socket for a crystal, and by just moving a jumper the clock signal from this gets distributed to the target section instead of the software generated STK500 clock.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
But why not simply use a 16 MHz crystal instead of the oscillator?

I don't have a 16Mhz crystal....:)

I had a 16Mhz canned oscillator lying around and had used it to experiment with on a bread board (before I got my stk500 - which recently came in the mail). I was getting to know the stk500, and want to tryout some code I had written based on a 16Mhz clock.

Before I decided to purchase the stk500, I had purchased a few canned oscillators of varying frequencies - thought that on a bread board they would be easier to use than wiring up a crystal circuit.

Now I need to pick up some crystals :)

Russ