вот код из книги Шпака "Прграммирование на язеке С для микр. AVR и PIC"
чип ATmega169, частота Taimer1 8Mгц
Код
void Calibration(void)
{
unsigned char calibrate = 0;
int temp;
unsigned char tempL;
CLKPR = _BV(CLKPCE); /* Устанавливаем разряд разрешения
изменения кооэффициента масштабирования
частоты генератора в регистре CLKPR
микроконтр. Это специальные регистры ATmega169 */
CLKPR = _BV(CLKPS1) | _BV(CLKPS0); // Коэффициент деления 8
// Внутрений RC 8Mгц / 8 = 1Мгц
TIMSK2 = 0; //сбрасываем разряды OCIE2A и TOIE2
ASSR = _BV(AS2); // Использование внешнегом кварца 32768 кГц для T/C2
OCR2A = 200; //Использование регистра сравнения А T/C2
TIMSK0 = 0; // Удаляем все источники прерывания
TCCR1B = _BV(CS10); // Запускаем T/C1 без предделителя
TCCR2A = _BV(CS20); // Запускаем T/C2 без предделителя
while((ASSR & 0x01) | (ASSR & 0x04)); // Ожидание сброса рязрядов TCN2UB и TCR2UB
for(int i = 0; i < 10; i++)
_delay_loop_2(30000); // Ожидание стабилизации внешнего генератора
while(!calibrate)
{
//////////////////////// этот блок написан как рекомндует ATMEL///////////
cli(); //
TIFR1 = 0xFF; // Удаление флагов //
TIFR2 = 0xFF; //
TCNT1H = 0; // Обнуляем счетный регистр
TCNT1L = 0;
TCNT2 = 0; // Обнуляем счетный регистр
while ( !(TIFR2 && (1<<OCF2A)) ); //
TCCR1B = 0; //
sei(); //
////////////////////////////////////////////////////////////////////////////
if ( (TIFR1 && (1<<TOV1)) ) // Если переполнение счетчика
{
temp = 0xFFFF;
}
else // Если переполнения нет то считываем
{
tempL = TCNT1L;
temp = TCNT1H;
temp = (temp << 8);
temp += tempL;
}
if (temp > 6250) //если внутренний генератор "спешит" ...
{
OSCCAL--; //уменьшаем значение регистра калибровки
}
else if (temp < 6120) // если отстает
{
OSCCAL++; //увеличиваем
}
else
calibrate = 1; // частота коректна
TCCR1B = _BV(CS10);
}
}
{
unsigned char calibrate = 0;
int temp;
unsigned char tempL;
CLKPR = _BV(CLKPCE); /* Устанавливаем разряд разрешения
изменения кооэффициента масштабирования
частоты генератора в регистре CLKPR
микроконтр. Это специальные регистры ATmega169 */
CLKPR = _BV(CLKPS1) | _BV(CLKPS0); // Коэффициент деления 8
// Внутрений RC 8Mгц / 8 = 1Мгц
TIMSK2 = 0; //сбрасываем разряды OCIE2A и TOIE2
ASSR = _BV(AS2); // Использование внешнегом кварца 32768 кГц для T/C2
OCR2A = 200; //Использование регистра сравнения А T/C2
TIMSK0 = 0; // Удаляем все источники прерывания
TCCR1B = _BV(CS10); // Запускаем T/C1 без предделителя
TCCR2A = _BV(CS20); // Запускаем T/C2 без предделителя
while((ASSR & 0x01) | (ASSR & 0x04)); // Ожидание сброса рязрядов TCN2UB и TCR2UB
for(int i = 0; i < 10; i++)
_delay_loop_2(30000); // Ожидание стабилизации внешнего генератора
while(!calibrate)
{
//////////////////////// этот блок написан как рекомндует ATMEL///////////
cli(); //
TIFR1 = 0xFF; // Удаление флагов //
TIFR2 = 0xFF; //
TCNT1H = 0; // Обнуляем счетный регистр
TCNT1L = 0;
TCNT2 = 0; // Обнуляем счетный регистр
while ( !(TIFR2 && (1<<OCF2A)) ); //
TCCR1B = 0; //
sei(); //
////////////////////////////////////////////////////////////////////////////
if ( (TIFR1 && (1<<TOV1)) ) // Если переполнение счетчика
{
temp = 0xFFFF;
}
else // Если переполнения нет то считываем
{
tempL = TCNT1L;
temp = TCNT1H;
temp = (temp << 8);
temp += tempL;
}
if (temp > 6250) //если внутренний генератор "спешит" ...
{
OSCCAL--; //уменьшаем значение регистра калибровки
}
else if (temp < 6120) // если отстает
{
OSCCAL++; //увеличиваем
}
else
calibrate = 1; // частота коректна
TCCR1B = _BV(CS10);
}
}
обьясните пожалуйста почему такая большая пауза для стабилизации внешнего кварца, нигде не нашел ответа,
и почему значение выбранное для коректировки генератора лежит в пределах 6120 - 6250 какак я понял 32768/200= 163,84 тогда получается 8000000/8/163,84 = 6103,5
и еще как синхронизировать внутрений генератор с помощью часового кварца если нет специальных регистров для коректировки