我正在校准AVR Butterfly内部振荡器,以便能够使用USART,基于AVR提供的示例代码(参见下面的代码)。由于我还想使用两个定时器控制的伺服电机,我想知道在校准过程之后是否可以重复使用16位定时器1 - 我尝试重置TCCR1A / B但是它没有用完(代码也在下面) 。我希望你能帮助我解决这个问题。
void OSCCAL_Calibrate(void){
unsigned char calibrate = 0;
int temp;
unsigned char tempL;
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)
OCR2A = 200; // set timer2 compare value
TIMSK0 = 0; // delete any interrupt sources
TCCR1B = (1<<CS10); // start timer1 with no prescaling
TCCR2A = (1<<CS20); // start timer2 with no prescaling
while((ASSR & 0x01) | (ASSR & 0x04)); //wait for TCN2UB and TCR2UB to be cleared
delayMs(1000); // wait for external crystal to stabilise
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
while ( !(TIFR2 & (1<<OCF2A)) ); // wait for timer2 compareflag
TCCR1B = 0; // stop timer1
sei(); // enable global interrupt
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;
}
if (temp > 6250)
OSCCAL--; // the internRC oscillator runs to fast, decrease the OSCCAL
else if (temp < 6120)
OSCCAL++; // the internRC oscillator runs to slow, increase the OSCCAL
else
calibrate = 1; // the interRC is correct
TCCR1B = (1<<CS10); // start timer1
}
}
void motorInit(){
// reset timer 1
TCCR1A = 0;
TCCR1B = 0;
// initialize Servo Pins
DDRB |= (1<<PB5) | (1<<PB6);
ICR1H = ICR_VALUE >> 8;
ICR1L = ICR_VALUE & (TOP_VALUE);
// reset OCRs
setServoSpeed(0, 0);
setServoSpeed(1, 0);
// Set Timer mode (PWM Phase & Freq. correct, clear on compare match)
// and prescaler (8)
TCCR1A = ((1<<COM1A1) | (1<<COM1B1));
TCCR1B = ((1<<WGM13) | (0<<CS12) | (1<<CS11) | (0<<CS10));
}
答案 0 :(得分:1)
也许您可以检查我之前用于项目的代码,但是您应该注意我将系统频率降低到7.3768 MHz(56700波特率),这可能需要调整。
void OSCCAL_Calibrate(void)
{
uint8_t LoopCount = (0x7F / 2);
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
// Make sure all clock division is turned off (8MHz RC clock)
CLKPR = (1 << CLKPCE);
CLKPR = 0x00;
// Inital OSCCAL of half its maximum
OSCCAL = (0x7F / 2);
// Disable timer interrupts
TIMSK1 = 0;
TIMSK2 = 0;
// Set timer 2 to asyncronous mode (32.768KHz crystal)
ASSR = (1 << AS2);
// Ensure timer 1 control register A is cleared
TCCR1A = 0;
// Start both counters with no prescaling
TCCR1B = (1 << CS10);
TCCR2A = (1 << CS20);
// Wait until timer 2's external 32.768KHz crystal is stable
while (ASSR & ((1 << TCN2UB) | (1 << TCR2UB) | (1 << OCR2UB)));
// Clear the timer values
TCNT1 = 0;
TCNT2 = 0;
while (LoopCount--)
{
// Wait until timer 2 overflows
while (!(TIFR2 & (1 << TOV2)));
// Stop timer 1 so it can be read
TCCR1B = 0x00;
// Check timer value against ideal constant
if (TCNT1 > OSCCAL_TARGETCOUNT) // Clock is running too fast
OSCCAL--;
else if (TCNT1 < OSCCAL_TARGETCOUNT) // Clock is running too slow
OSCCAL++;
// Clear timer 2 overflow flag
TIFR2 |= (1 << TOV2);
看看这个!