Running Attiny45 on xtal
Posted: Tue Dec 13, 2011 10:59 pm
Hi, Trying to understand the code better. I'm using the tiny45 for the caps locker circuit (very similar to the easy logger).
Got it running ok using the internal osc at 16500000 so now want to try using an xtal instead.
Changed the fuses low 0xff & high 0xdf, and used a 12000000 crystal, the circuit works fine still...
a quick explanation of this line would be helpful:
What I would now like to know now is with the crystal fiited and running ok, what parts of this c code is now redundant?
the more i delete, the more errors im getting! Thought that most of this code was for the PLL which I thought guess shouldn't be needed now...
Appreciate any guidance...
Got it running ok using the internal osc at 16500000 so now want to try using an xtal instead.
Changed the fuses low 0xff & high 0xdf, and used a 12000000 crystal, the circuit works fine still...
a quick explanation of this line would be helpful:
Code: Select all
TCCR1 = 0x0b; /* select clock: 16.5M/1k -> overflow rate = 16.5M/256k = 62.94 Hz */
What I would now like to know now is with the crystal fiited and running ok, what parts of this c code is now redundant?
the more i delete, the more errors im getting! Thought that most of this code was for the PLL which I thought guess shouldn't be needed now...
Code: Select all
static void timerInit(void)
{
TCCR1 = 0x0b; /* select clock: 16.5M/1k -> overflow rate = 16.5M/256k = 62.94 Hz */
}
/* ------------------------ interface to USB driver ------------------------ */
uchar usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (void *)data;
usbMsgPtr = reportBuffer;
if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */
if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */
/* we only have one report type, so don't look at wValue */
buildReport();
return sizeof(reportBuffer);
}else if(rq->bRequest == USBRQ_HID_GET_IDLE){
usbMsgPtr = &idleRate;
return 1;
}else if(rq->bRequest == USBRQ_HID_SET_IDLE){
idleRate = rq->wValue.bytes[1];
}
}else{
/* no vendor specific requests implemented */
}
return 0;
}
/* ------------------------ Oscillator Calibration ------------------------- */
/* Calibrate the RC oscillator to 8.25 MHz. The core clock of 16.5 MHz is
* derived from the 66 MHz peripheral clock by dividing. Our timing reference
* is the Start Of Frame signal (a single SE0 bit) available immediately after
* a USB RESET. We first do a binary search for the OSCCAL value and then
* optimize this value with a neighboorhod search.
* This algorithm may also be used to calibrate the RC oscillator directly to
* 12 MHz (no PLL involved, can therefore be used on almost ALL AVRs), but this
* is wide outside the spec for the OSCCAL value and the required precision for
* the 12 MHz clock! Use the RC oscillator calibrated to 12 MHz for
* experimental purposes only!
*/
static void calibrateOscillator(void)
{
uchar step = 128;
uchar trialValue = 0, optimumValue;
int x, optimumDev, targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
/* do a binary search: */
do{
OSCCAL = trialValue + step;
x = usbMeasureFrameLength(); /* proportional to current real frequency */
if(x < targetValue) /* frequency still too low */
trialValue += step;
step >>= 1;
}while(step > 0);
/* We have a precision of +/- 1 for optimum OSCCAL here */
/* now do a neighborhood search for optimum value */
optimumValue = trialValue;
optimumDev = x; /* this is certainly far away from optimum */
for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){
x = usbMeasureFrameLength() - targetValue;
if(x < 0)
x = -x;
if(x < optimumDev){
optimumDev = x;
optimumValue = OSCCAL;
}
}
OSCCAL = optimumValue;
}
/*
Note: This calibration algorithm may try OSCCAL values of up to 192 even if
the optimum value is far below 192. It may therefore exceed the allowed clock
frequency of the CPU in low voltage designs!
You may replace this search algorithm with any other algorithm you like if
you have additional constraints such as a maximum CPU clock.
For version 5.x RC oscillators (those with a split range of 2x128 steps, e.g.
ATTiny25, ATTiny45, ATTiny85), it may be useful to search for the optimum in
both regions.
*/
void usbEventResetReady(void)
{
calibrateOscillator();
eeprom_write_byte(0, OSCCAL); /* store the calibrated value in EEPROM */
}
/* ------------------------------------------------------------------------- */
/* --------------------------------- main ---------------------------------- */
/* ------------------------------------------------------------------------- */
int main(void)
{
uchar i;
uchar calibrationValue;
calibrationValue = eeprom_read_byte(0); /* calibration value from last time */
if(calibrationValue != 0xff){
OSCCAL = calibrationValue;
}
odDebugInit();
usbDeviceDisconnect();
for(i=0;i<20;i++){ /* 300 ms disconnect */
_delay_ms(15);
}
usbDeviceConnect();
wdt_enable(WDTO_1S);
timerInit();
TimerDelay = 630; /* initial 10 second delay */
usbInit();
sei();
for(;;){ /* main event loop */
wdt_reset();
usbPoll();
/* A USB keypress cycle is defined as a scancode being present in a report, and
then absent from a later report. To press and release the Caps Lock key, instead of
holding it down, we need to send the report with the Caps Lock scancode and
then an empty report. */
if(usbInterruptIsReady() && reportCount < 2){ /* we can send another key */
buildReport();
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
}
timerPoll();
}
return 0;
}
Appreciate any guidance...