title
收藏本站
联系站长
关于本站
首页 信息发布 产品宣传 论坛交流 学习文章 技术人生 项目源码 技术资料 人才收录
 今天是: 2010年9月7日 星期 二
欢迎光临!单片机群号:25930265 71062262 21829895 64584393 26583231(只限加一群)  
 当前位置: 欢迎话题互动专区 --> 技术交流版 --> AVR专区
 AVRmega88内部RC校正  
1111
昵称:tamson
级别:
贡献值:33832
经验值:13390
给他留言
来自:广东-深圳
校准的原理我先说一下:
  使用两个定时器,timer1和timer2,使用timer1的原因是因为他是16位的定时器,可以计数很大,不至于很快就溢出,timer2是用来对外部32K晶体周期计数的,timer1是对内部RC谐振进行计数,等timer2溢出的时候,比较timer1的值和理论值的差别,对校准寄存器进行修改。可以多校准几次,寻找最小的那个差。代码如下:
  有几个宏先给出值
  
  #define MAX_CAL_LOOP_CNT (100)
  
  #define TARGETVAL_CALIBRATION (62500)
  
  至于为什么TARGETVAL_CALIBRATION值为62500,给出说明,timer2计周期的个数为255个,那当32.768计数到255时,理论上使用内部RC计数的值应该为 8000000 * 256 / 32768 = 62500
  
  
  bool pal_calibrate_rc_osc(void)
  {
   /*
   * Use the 32.768 kHz external crystal oscillator as reference clock source.
   */
   /*
   * This is the actual value of the timer to be calibrated
   * after each calibration run.
   */
   uint16_t curr_value_cal_timer = 0;
  
   /* This is the best OSCCAL value. */
   uint8_t best_value_osccal = 0;
   /*
   * This is the smallest difference between the target value and the actual value
   * of the timer the timer to be calibrated.
   */
  
   uint16_t best_dif_timers = ~(0);
   /*
   * This is the difference between between the target value and the actual value
   * of the timer the timer to be calibrated of the current calibration attempt.
   */
   uint16_t curr_dif_timers = 0;
  
   uint16_t counter;
   uint8_t tccr2b;
   uint8_t tccr1b;
   uint8_t tccr1a;
   uint16_t seed = 0;
   bool cal_result = true;
  
   ENTER_CRITICAL_REGION();
  
   /*
   * Save current values of timer status.
   */
   tccr2b = TCCR2B;
   tccr1b = TCCR1B;
   tccr1a = TCCR1A;
  
   /*
   * Stop timers 1 and 2.
   * Set timer 1 to normal mode (no CTC, no PWM, just count).
   */
   TCCR2B = 0;
   TCCR1B = 0;
   TCCR1A = 0;
  
   for (counter = 0; counter < MAX_CAL_LOOP_CNT; counter++)
   {
   /*
   * Delete pending timer 1 and 2 interrupts, and clear the
   * counters.
   */
   TIFR1 = 0xFF;
   TIFR2 = 0xFF;
   TCNT2 = 0;
   TCNT1 = 0;
  
   /* Kick timer1 with internal clock source and no prescaler */
   TCCR1B = (1 << CS10);
  
   /*
   * Kick timer2 with external 32.768 Hz asynchronous clock
   * and no prescaler
   */
   TCCR2B = (1 << CS20);
   ASSR = (1 << AS2);
  
   /*
   * Wait for timer 2 to overflow.
   */
   while (!(TIFR2 & (1 << TOV2)))
   {
   /* Wait */
   }
  
  
   /*
   * Stop timer 1. Now, TCNT1 contains the number of CPU cycles
   * counted during F_CPU / (32 * 256) cycles.
   */
   TCCR1B = 0;
   TCCR2B = 0;
  
   curr_value_cal_timer = TCNT1;
   seed += curr_value_cal_timer;
  
   /*
   * Check if reference timer is running at all,
   * i.e. the reference clock is available.
   */
   if (0 == curr_value_cal_timer)
   {
   /* Reference timer is not running, return error. */
   cal_result = false;
   break;
   }
  
   if (curr_value_cal_timer <= (uint16_t)(TARGETVAL_CALIBRATION))
   {
   curr_dif_timers = (uint16_t)(TARGETVAL_CALIBRATION) - curr_value_cal_timer;
   }
   else
   {
   curr_dif_timers = curr_value_cal_timer - (uint16_t)(TARGETVAL_CALIBRATION);
   }
  
   if (curr_dif_timers < best_dif_timers)
   {
   best_dif_timers = curr_dif_timers;
   best_value_osccal = OSCCAL;
   }
  
   if (curr_value_cal_timer <= (uint16_t)(TARGETVAL_CALIBRATION))
   {
   /* Too slow, increase speed */
   OSCCAL++;
   }
   else
   {
   /* Too fast, lower speed */
   OSCCAL--;
   }
   }
  
   /*
   * Set the seed for the random number generator based on the
   * calibration results.
   */
   srand(seed);
  
   TCCR2B = tccr2b;
   TCCR1B = tccr1b;
   TCCR1A = tccr1a;
   LEAVE_CRITICAL_REGION();
  
   OSCCAL = best_value_osccal;
  
   return (cal_result);
  }
  由于随着时间的推移,内部RC又会不准了,所以要定时去校准,才能保证内部定时器准确。这样32.768K的晶体就可以作为在省电模式下定时器2的外部时钟。定时器2的设置给出:
   TIFR2 = _BV(OCF2A);
   TIFR2 = _BV(OCF2B);
   TIFR2 = _BV(TOV2);
   /* Enable the timer overflow interrupt */
   TIMSK2 |= _BV(TOIE2);
   ASSR = _BV(AS2); //set async mode
   TCCR2B = 0x00;
   TCNT2 = 0x61; //set count
   OCR2A = 0x9F;
   TCCR2B = 0x07; //启动定时器,定时器的时间定为5s,这个时间根据自己的情况在修改
2010-04-20 11:08:31
资料 邮箱
登录之后才能发表新的讨论或者回复
本网站部分资料转自网上,如有侵权请来信告明,我们会尽快删除  | 网站地图
Copyright @ 2007-2010 深圳单片机交流网.版权所有
网站创办者:詹长亮,周发辉,李林盛
网站支持:zcl843@163.com QQ:380476830 13723787271詹长亮