You can use any polarity, but if you can, please use a negative center connector 10-15V DC.
Background from STK500 Manual:
An external 10 - 15V DC power supply is required. The input circuit is a full bridge rectifier, and the STK500 automatically handles both positive or negative center connectors. If a positive center connector is used, it can be impossible to turn the STK500 off since the power switch disconnects the GND terminal. In this case, GND can be supplied through the RS-232 cable shield if connected or through alternative GND connections.
$ dmesg
pl2303 converter now attached to ttyUSB0
List supported MCUs:
avrdude -c stk500v2 -p ?
Read lfuse:
avrdude -c stk500v2 -p m16 -P /dev/ttyUSB0 -U lfuse:r:lfuse.hex:b
Read hfuse:
avrdude -c stk500v2 -p m16 -P /dev/ttyUSB0 -U hfuse:r:hfuse.hex:b
Set lfuse:
avrdude -c stk500v2 -p m16 -P /dev/ttyUSB0 -U lfuse:w:0b11110000:m
Read the datasheet, and search for "Fuse Low Byte" and "Fuse High Byte". For
my configuration, for an external clock, 0000
needs to be written to
CKSEL3...CKSEL0
STK500 is having a resonator on it's own, so AVR has to be configured to use an external clock source. For this, the external clock options needs to be selected, and that is the same as in the case of ATMEGA16L.
This is using an ATTINY2313 chip. First I want to see if I can get the lfuse to read.
Read lfuse:
$ avrdude -c stk500v2 -p t2313 -P /dev/ttyUSB0 -U lfuse:r:lfuse.hex:b
$ cat lfuse.hex
0b1100100
Read hfuse:
avrdude -c stk500v2 -p t2313 -P /dev/ttyUSB0 -U hfuse:r:hfuse.hex:b
$ cat hfuse.hex
0b11011111
This more or less matches the datasheet. I say more or less, as one section
suggests that the default value for CKSEL3..1 is 001
whereas the document
also mentions:
The device is shipped with CKSEL =
0100
, SUT =10
, and CKDIV8 programmed.
For an xtal configuration, I need CKSEL3..1 to be 111 for crystal above 8 Mhz.
CKSEL0
fuse together with SUT1..0
determines startup.
Also looking at examples with V-USB:
$(AVRDUDE) -U hfuse:w:0xdb:m -U lfuse:w:0xef:m
Meaning hfuse to be on 0b11011011
and lfuse to be on 0b11101111
1
1
1
1
0
0
1
1
1
1
1
0
1
1
1
1
What changes in VUSB configuration is that Brown-Out detection voltage is put to 2.7V
0
1
1
1
1
1
0
0
0
1
1
1
0
1
0
1
This means that we will not use a prescaler and CKSEL3..1
will be 111
meaning external Xtal above 8 MHz. CKSEL0
becomes 1
which togther with
SUT0
being 0
and SUT1
being 1
means Crystal Oscillator, fast
rising power configuration.
Let's program those bytes:
avrdude -c stk500v2 -p t2313 -P /dev/ttyUSB0 -U hfuse:w:0xdb:m -U lfuse:w:0xef:m
And now let's try to blink it. This is blink.c
#define F_CPU 12000000
#define LED_DELAY 200
#include <avr/io.h>
#include <util/delay.h>
int main(void) {
DDRB = 0xff;
for(;;) {
_delay_ms(LED_DELAY);
PORTB = 0b00001000;
_delay_ms(LED_DELAY);
PORTB = 0b00000100;
_delay_ms(LED_DELAY);
PORTB = 0b00000010;
_delay_ms(LED_DELAY);
PORTB = 0b00000001;
_delay_ms(LED_DELAY);
PORTB = 0b00000010;
_delay_ms(LED_DELAY);
PORTB = 0b00000100;
}
}
And this is my Makefile
:
:::make
MMCU=attiny2313
AVRDUDE_DEVICE=t2313
CC=avr-gcc
OBJCOPY=avr-objcopy
CMPNAME=blink
STKPORT=/dev/ttyUSB0
CFLAGS=-g -mmcu=$(MMCU) -v
$(CMPNAME).hex : $(CMPNAME).out
$(OBJCOPY) -j .text -O ihex $(CMPNAME).out $@
$(CMPNAME).out : $(CMPNAME).o
$(CC) $(CFLAGS) -o $@ -Wl,-Map,$(CMPNAME).map $<
$(CMPNAME).o : $(CMPNAME).c
$(CC) $(CFLAGS) -Os -c $<
$(CMPNAME).s: $(CMPNAME).c
$(CC) -S $(CFLAGS) -o $<
program: $(CMPNAME).hex
avrdude -p $(AVRDUDE_DEVICE) -c stk500v2 -P $(STKPORT) -U flash:w:$(CMPNAME).hex:i
fuses:
avrdude -p $(AVRDUDE_DEVICE) -c stk500v2 -P $(STKPORT) -U hfuse:w:0xdb:m -U lfuse:w:0xef:m
clean:
rm -f *.o *.out *.map *.hex
.PHONY: clean program fuses
Goal is to creata timer that measures 10 minutes using the internal oscillator and nothing more.
uucp
group to be able to access serial
devices.SPROG2
from ISP6PIN
VTARGET
- connectedAREF
- connectedRESET
- connectedXTAL1
- disconnected (we do not provide clock from STK500)OSCSEL
- does not matterBSEL2
- disconnected (related to high voltage programming)PJUMP
- disconnected (related to high voltage programming)Read lfuse and hfuse (I had to re-connect xtal for these)
avrdude -c stk500v2 -P /dev/ttyUSB0 -p m8 -U lfuse:r:lfuse-origin.hex:b
avrdude -c stk500v2 -P /dev/ttyUSB0 -p m8 -U hfuse:r:hfuse-origin.hex:b
Fuses were:
- lfuse: 0b11100000
- hfuse: 0b11011001
Write fuses so chip will use internal oscillator. From datasheet, in order
to have internal RC oscillator used I need CKSEL3..0
set as: 0100 - 0001
For the 1MHz option CKSEL3..0
needs to be 0001
HFUSE explanation (highest bit first)
- RSTDISBL
- 1
- PC6 is reset pin
- WDTON
- 1
- WDT enabled by WDTCR
- SPIEN
- 0
- Serial programming enabled
- CKOPT
- 1
- Oscillator options
- EESAVE
- 1
- EEPROM not preserved through chip erase
- BOOTSZ1
- 0
- Boot size related
- BOOTSZ0
- 0
- Boot size related
- BOOTRST
- 1
- Boot reset vector
HFUSE can stay as it is
LFUSE explanation (highest bit first)
- BODLEVEL
- 1
- Brown out related
- BODEN
- 1
- Brown out related
- SUT1
- 1
- start-up time related
- SUT0
- 0
- start-up time related
- CKSEL3
- 0
- OK
- CKSEL2
- 0
- OK
- CKSEL1
- 0
- OK
- CKSEL0
- 0
- Shall be changed to 1
New values then:
- lfuse 0b11100001
- 0xe1
- hfuse 0b11011001
- 0xd9
avrdude -c stk500v2 -p m8 -P /dev/ttyUSB0 -U hfuse:w:0xd9:m -U lfuse:w:0xe1:m
Now xtal jumper removed from STK500, and I can read fuses again.
And now let's try to blink it via PORTC. This is blink.c
#define F_CPU 1000000
#define LED_DELAY 200
#include <avr/io.h>
#include <util/delay.h>
int main(void) {
DDRC = 0xff;
for(;;) {
_delay_ms(LED_DELAY);
PORTC = 0b00001000;
_delay_ms(LED_DELAY);
PORTC = 0b00000100;
_delay_ms(LED_DELAY);
PORTC = 0b00000010;
_delay_ms(LED_DELAY);
PORTC = 0b00000001;
_delay_ms(LED_DELAY);
PORTC = 0b00000010;
_delay_ms(LED_DELAY);
PORTC = 0b00000100;
}
}
And this is my Makefile
:
:::make
MMCU=atmega8
AVRDUDE_DEVICE=m8
CC=avr-gcc
OBJCOPY=avr-objcopy
CMPNAME=blink
PROGRAMMER=stk500v2
STKPORT=/dev/ttyUSB0
CFLAGS=-g -mmcu=$(MMCU) -v
$(CMPNAME).hex : $(CMPNAME).out
$(OBJCOPY) -j .text -O ihex $(CMPNAME).out $@
$(CMPNAME).out : $(CMPNAME).o
$(CC) $(CFLAGS) -o $@ -Wl,-Map,$(CMPNAME).map $<
$(CMPNAME).o : $(CMPNAME).c
$(CC) $(CFLAGS) -Os -c $<
$(CMPNAME).s: $(CMPNAME).c
$(CC) -S $(CFLAGS) -o $<
program: $(CMPNAME).hex
avrdude -p $(AVRDUDE_DEVICE) -c $(PROGRAMMER) -P $(STKPORT) -U flash:w:$(CMPNAME).hex:i
fuses:
avrdude -p $(AVRDUDE_DEVICE) -c $(PROGRAMMER) -P $(STKPORT) -U hfuse:w:0xd9:m -U lfuse:w:0xe1:m
clean:
rm -f *.o *.out *.map *.hex
.PHONY: clean program fuses
#define F_CPU 1000000
#include <avr/io.h>
#include <avr/interrupt.h>
volatile int port_value;
ISR(TIMER0_OVF_vect)
{
if(port_value==0) {
port_value=1;
} else {
port_value=0;
}
}
int main(void) {
// SETTING PORTC DIRECTION AS OUTPUT
DDRC = 0xff;
// INITIALIZING DISPLAY VALUE
port_value = 0;
// SETTING TIMER0 SOURCE TO CLKIO/1024
TCCR0|=(1<<CS02)|(1<<CS00);
TCCR0&=~(1<<CS01);
// ENABLE TIMER0 INTERRUPT
TIMSK|=(1<<TOIE0);
// ENABLE GLOBAL INTERRUPT
sei();
for(;;) {
PORTC=port_value;
}
}
When XTAL1 jumper is not mounted, the internal clock system is disconnected. This allows external clock signals or crystals to be used as tar- get clock source for the AVR.
When the XTAL1 jumper is not mounted, an external clock source or crystal can be con- nected to the PORTE header.
Fuses shall remain the same - still using an internal 1MHz clock, see above
TCCR2
:WGM21
has to be 1
WGM20
has to be 0
This way the max value shall be in OCR2
registerCS2
has to be 1
CS1
has to be 1
CS0
has to be 1
ASSR
Asynchronous Status RegisterAS2
has to be 1
This code fragment will display the counter's
value on the STK500 LEDs.
Note: I was looking at /usr/avr/include/avr/iom8.h
for finding
register names.
:::c
#define F_CPU 1000000
#include <avr/io.h>
volatile int port_value;
int main(void) {
// SETTING PORTC DIRECTION AS OUTPUT
DDRC = 0xff;
// SHOW WHERE WE ARE
PORTC = 0x01;
// TIMER2 SETTINGS
// 1.) DISABLE INTERRUPTS
// - DISABLE OUTPUT COMPARE MATCH INTERRUPT
TIMSK &= ~(1<<OCIE2);
// - DISABLE OVERFLOW INTERRUPT
TIMSK &= ~(1<<TOIE2);
// 2.) SELECT ASYNC OPERATION
ASSR|=(1<<AS2);
// 3.) INITIALIZE VALUES
// - COUNTER VALUE
TCNT2 = 0;
// - COMPARE MATCH VALUE
OCR2 = 0xff;
// - CONFIGURE TIMER2 FOR 1024 PRESCALE
TCCR2 |= (1<<WGM21)|(1<<CS22)|(1<<CS21)|(1<<CS20);
// 4.) WAIT FOR ASYNC OPERATION TO FINISH
// - Wait for TCN2UB, OCR2UB, and TCR2UB
PORTC = 0x02;
while((ASSR & (1<<TCN2UB))) {;};
PORTC = 0x03;
while((ASSR & (1<<OCR2UB))) {;};
PORTC = 0x04;
while((ASSR & (1<<TCR2UB))) {;};
// 5.) CLEAR INTERRUPT FLAGS
TIFR &= ~((1<<OCF2)|(1<<TOV2));
// ENABLE INTERRUPTS
for(;;) {
PORTC=TCNT2;
}
}
:::c
#define F_CPU 1000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
volatile int one_sec_flag;
#define LED_DELAY 50
ISR(TIMER2_COMP_vect)
{
one_sec_flag = 1;
}
int main(void) {
// SETTING GLOBAL VALUE
one_sec_flag = 0;
// SETTING PORTC DIRECTION AS OUTPUT
DDRC = 0xff;
// DURING INIT SETTING PORT TO ALL 0 TO LIGHT ALL THE LEDS
PORTC = 0x0;
// TIMER2 SETTINGS
// 1.) DISABLE INTERRUPTS
// - DISABLE OUTPUT COMPARE MATCH INTERRUPT
TIMSK &= ~(1<<OCIE2);
// - DISABLE OVERFLOW INTERRUPT
TIMSK &= ~(1<<TOIE2);
// 2.) SELECT ASYNC OPERATION
ASSR|=(1<<AS2);
// 3.) INITIALIZE VALUES
// - COUNTER VALUE
TCNT2 = 0;
// - COMPARE MATCH VALUE
OCR2 = 31;
// - CONFIGURE TIMER2 FOR 1024 PRESCALE
TCCR2 |= (1<<WGM21)|(1<<CS22)|(1<<CS21)|(1<<CS20);
// 4.) WAIT FOR ASYNC OPERATION TO FINISH
// - Wait for TCN2UB, OCR2UB, and TCR2UB
while((ASSR & (1<<TCN2UB))) {;};
while((ASSR & (1<<OCR2UB))) {;};
while((ASSR & (1<<TCR2UB))) {;};
// 5.) CLEAR INTERRUPT FLAGS
TIFR &= ~((1<<OCF2)|(1<<TOV2));
// 6.) ENABLE INTERRUPTS
// - Output compare match interrupt enable
TIMSK |= (1<<OCIE2);
sei();
for(;;) {
if(one_sec_flag == 1) {
PORTC = ~(1<<0);
_delay_ms(LED_DELAY);
PORTC = ~(0);
one_sec_flag = 0;
}
}
}