您好,今天是: ·加入收藏·设为首页·联系站长·
网站首页 | 公司介绍 | 维修项目 | 收费标准 | 维修联盟 | 联系方式 | 在线报修 | 电器导购 | 本站地图  Rss2.0 Wap1.2

网站首页 | 行业新闻 | 家电维修 | 电脑维修 | 工控维修 | 制冷维修 | 网站制作 | 网络工程 | 休闲娱乐 | 英文欣赏 | 维修论坛

维修品牌 索尼 松下 日立 东芝 爱华 夏普 三星 三洋 先锋 健伍 胜利 飞利浦 日电 JVC NEC LG 长虹 海尔 康佳 王牌 海信 创维 牡丹 苹果 IBM 优派 狮龙 厦新 厦华 康力 宏基 三菱 JBL 湖山 熊猫 金正 万利达 安桥 高士达 明基 戴尔 BenQ DELL 长城 台达 现代 美格 EMC HPC SUN 联想 上广电 SVA TCL 北京牌 大宇 山水 彩星 冠捷 美的 格力 奇声 新科 狄克威尔 EIZO 金星 Sony Sharp Sanyo Haier Apple
当前位置:北京燕旭电子公司 >> 工控维修 >> 工控单片机开发 >> 浏览文章 立即入驻本站 | 免费发布供应信息
关于PIC单片机的内部RC振荡器的校准
作者:佚名 来源:互联网 文章点击数:

  在PIC的单片机中有多种型号有内部RC振荡器的功能,从而省去了晶振,不但节省了成本,并且我们还多了两个IO端口可以使用。
  但是,由于RC振荡器中电阻、电容的离散很大,因此,在有内部RC振荡器的单片机中,它的内部RAM中都会有一个名为OSCCAL的校准寄存器,通过置入不同的数值来微调RC振荡器的振荡频率。并且,单片机的程序存储器中,也会有一个特殊的字来储存工厂生产时测得的校准值。下面我以常用的12C508A和12F629为例加以说明。
  12C508A的复位矢量是程序的最高字0x1FF,这个字节生产商已经固定的烧写为MOVLW 0xXX,指令执行后,W寄存器中即为校准值XX,当我们需要校准时,那么,在紧接着的地址0x0应该是一条这样的指令:MOVWF OSCCAL。接下去RC振荡器就会以标准的振荡频率运行了。
  12F629的校准值也存放在最高字--0x3FF中,内容是RETLW 0xXX,但它的复位矢量却是0x0。这样,在我们需要校准RC振荡器时,在初始化过程中要加上下面两句:
    CALL  0x3ff
    MOVWF OSCCAL
  当然,你还要注意寄存器的块选择位。
  以前,我在做项目时,没太注意这个问题,这是因为在使用12C508A时,HI-TECH在进行编译时已经偷偷地替我们做了这项工作。它会在程序的0x0处自动加一条MOVWF OSCCAL。用12F629做接收解码代替2272时也没发生什么问题,但是在用被它作滚动码解码器时却发现接收距离的离散很大。经多次试验终于找出是没对振荡器的振荡频率进行校正所至。
  因此,需要另外编写用于校正的语句,我用了两种方法来实现这个目的:
  1、用内嵌汇编的形式
  #asm   //此段汇编程序用于将位于程序段3FFH的
   call 3ffh  //内部RC振荡器的校准值放入校准寄存器,
   bsf _STATUS,5  //在进行C语言调试时应屏蔽这段程序
   movwf _OSCCAL
  #endasm
  2、用C语言标准形式
  const unsigned char cs @ 0x3ff; //在函数体外
  ...
  OSCCAL=cs;   //仿真时屏蔽此句
  用这两种方法都有一个小缺陷--仿真时,程序无法运行,这是由于C编译器并没有为我们在0x3FF放置一条RETLW 0xXX的语句。因此,程序运行到这里之后,并没有把一个常数(校准值)放入W寄存器然后返回,而是继续执行这条语句的下一句--0x0及其之后的程序,也就是说程序到此就乱了。因此如程序后面注释所示,在仿真时,应先屏蔽这几句程序。在程序调试完成后,需要烧写时,把注释符去掉,再编译一次就可以了。
  我还有一种想法,不用屏蔽语句,那就是用函数来实现,就是在0x3FF起建立一个函数,函数体内只有一条语句,如下:
  char jz()
  {
    return 0;
  }
  当然,还要考虑C函数返回时,一定会选择寄存器0,实际上这个函数的起始地址应小于0x3FF。但是我找了我所能找到的参考资料,并上网找了多次,也没找到为函数绝对定位的方法,希望有知道的朋友指点一下。
  还有,12C508A是一次编程的,并且0x1FF处的内容,我们是无法改变的,也就是说你在此处编写任何指令,编程器都不会为你烧写,或者说即使烧写了也不会改变其中的内容。
  可12F629是FLASH器件,可多次编程,如果你没有故意选择,正品的编程器(如Microchip的PICSTART  PLUS)是不会对存有校准值的程序空间进行编程的。即使你无意中对这个程序空间进行了编程,你也可以用一条RETLW 0xXX放在0x3FF处再编程一次就可以了,但这个XX值可能是不正确的,需经实验确定(请参考后面说明)。
  为了检验OSCCAL的值对振荡器频率的影响,特编写了下面一个小程序进行验证:
#include
//*********************************************************
__CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & BOREN & PROTECT & CPD);
//内部RC振荡器普通IO口;无效看门狗;上电延时;内部复位;掉电复位;代码保护;数据保护
//*********************************************************
#define out GPIO0  //定义输出端
#define jc GPIO3  //定义检测端
//*********************************************************
void interrupt zd();  //声明中断函数
//主函数***************************************************
void main()
{
 CMCON=7;
 OPTION=0B00000011; //分频比为1:16,
 TRISIO=0B11111110;
 GPIO=0B00000000;
 WPU=0;
 T0IF=0;
 GIE=1;
 T0IE=1;
 while(1){
   if(jc)OSCCAL=0xFF;
   else OSCCAL=0;
 }
}
//中断函数*************************************************
void interrupt zd()
{
 T0IF=0;
 out=!out;
}
  程序其实很简单,就是在中断中让out脚的电平翻转,翻转的时间为4096个指令周期,电平周期为8192个指令周期。而指令的周期又决定于RC时钟频率。在主程序中,不断的检测JC端口的电平,然后根据此端口电平的值修改OSCCAL寄存器的值。当然,最后从OUT脚的波形周期上反映出了OSCCAL寄存器的值改变。
  经用示波器测量(抱歉,手边没有频率计),JC端接地时,OUT端的电平周期为9.5毫秒左右;而JC端接正电源时,OUT端的电平周期为6毫秒左右。也就是说OSCCAL的值越大,单片机的时钟频率越高。并且,这个变化范围是很大的,因此,如果使用PIC单片机的内部RC振荡器时,对其振荡频率进行校正是十分必要的。这也是我在做滚动码接收解码器时,产品离散很大的原因。望大家以后使用内部RC振荡器时能够注意到此点。
  但还有一点要注意,即使你对RC振荡器进行了校正,你也别指望这个4MHz的RC振荡器肯定会很标准,实际上它还是一个RC振荡器,它的振荡频率是电压、温度的函数,也就是说这个振荡频率会随着电压和温度的变化而变化,只是经校正后的值更接近4MHz罢了,这在产品开发的一开始就要注意的。




人支持

发表评论】【告诉好友】【打印此文】【收藏此文】【关闭窗口
  最新文章
  热门文章
  推荐信息

| 设为首页 | 加入收藏 | 关于本站 | 联系站长 | 友情链接 | 版权申明 | 雁过留声 | 网站地图

Copyright 2000-2008 Powered by Bjlxjw.COM,北京龙旭电子技术服务中心 All Rights Reserved.
全天24小时服务电话:010-60118386、85451495.传真:010-64621509 技术支持:13146594250. E-Mail:bjlxjw@126.com
报修咨询服务QQ:879851559 技术支持QQ: 275960024 网站制作服务QQ: 377152508 维修讨论群:27584257(非技术人员请勿加入,加入本群请注明来意!)
送修联系地址:北京市朝阳区三元桥顺源里2号(坐车到三元桥下车南行60米三元东桥下向西200米左右路南建设银行后边即到)
免责声明:我站部分文章信息来自网络,如果侵犯了原作者的著作权,请直接联系我站,我站必将第一时间删除,谢谢支持! 京ICP备06024783号