当前位置:首页 > 单片机 > 单片机
[导读]在PIC的单片机中有多种型号有内部RC振荡器的功能,从而省去了晶振,不但节省了成本,并且我们还多了两个IO端口可以使用。但是,由于RC振荡器中电阻、电容的离散性很大,因此,在有内部RC振荡器的单片机中,它的内部R

在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罢了,这在产品开发的一开始就要注意的。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

磁场等对电流互感器的运行误差有较大影响 , 需进行定量检测和评估才能满足精准电能计量和安全稳定运行的要求。鉴于此 ,研究面向电流互感器幅值校正的非线性参数化函数 ,揭示磁场变化对电流互感器二次侧电流幅值测量的实际影响 ,...

关键字: 电流互感器 幅值特性 误差 校准

ConsT680智能温度自动检定系统是集计算机技术、电子技术、自动测试技术于一体的自动化温度检定装置 , 可以实现超高效率并行多任务管理 , 布线简便 , 可以快速实现被检传感器接线;配备专业智能多通道精密测温仪 , 兼...

关键字: 工作原理 步骤 校准

在下述的内容中,小编将会对网络分析仪的相关消息予以报道,如果网络分析仪是您想要了解的焦点之一,不妨和小编共同阅读这篇文章哦。

关键字: 网络分析仪 分析仪 校准

以下内容中,小编将对照度计的相关内容进行着重介绍和阐述,希望本文能帮您增进对照度计这个测试测量仪器的了解,和小编一起来看看吧。

关键字: 照度计 校准 测试测量

摘要:传统的罗氏线圈校准工作大多在实验室里完成,没有考虑到测量用的附属设施设备,而将罗氏线圈独立地进行校准,且72套罗氏线圈校准工作量比较大,效率比较低,测量不同步。鉴于此,设计了一种新型的72套罗氏线圈同时校准的方法,...

关键字: 罗氏线圈 校准 同步

红外测温仪校准-完整指南

关键字: 测试 校准

校准:校准的目的是对照计量标准,评定测量装置的示值误差,确保量值准确,属于自下而上量值溯源的一组操作。 检定:检定的目的则是对测量装置进行强制性全面评定。这种全面评定属于量值统一的范畴,是自上而下的量值传递过程。

关键字: 校准 检定

AD7124-4是一款适合高精度测量应用的低功耗、低噪声、完整模拟前端。 该器件内置一个低噪声24位Σ-Δ型模数转换器(ADC),可配置为提供4个差分输入或7个单端或伪差分输入。 片内低增益级确保ADC中可直接输入小信号...

关键字: ad7124 校准

为增进大家对压力变送器的认识,本文将基于两点介绍压力变送器:1、压力变送器的日常维护,2、压力变送器如何校准。

关键字: 压力变送器 指数 校准
关闭