如图,单片机和晶振的位置,不知道对外部晶振起振的影响大不大
我手头上有3个切换外部晶振的程序,都试过,晶振貌似都不工作,测量晶振两个电容(30PF)的电压都是4.95V和VCC一样的。
程序一:
void change_ocInit(void) //切换外部晶振{
IFMT = 0x06; // AUXRA
IFD = 0x6f ; // AUXRA = 0x6f,enable XTALE & BORSET
ISPCR|= 0x80; // enable ISP
SCMD = 0x46;
SCMD = 0xb9;
_nop_();
_nop_();
_nop_();
IFMT = 0x06; // AUXRA
IFD = 0x2b ; // disable INOSC
ISPCR|= 0x80; // enable ISP
SCMD = 0x46;
SCMD = 0xb9;
}
程序二:
void Register_Initialization()
{
//CKCON0 = 0x00; //CKCON0为时钟控制寄存器0,
//Bit7 = 0禁止USB时钟和USB功能,
//Bit6 = 0禁止时钟倍频(×8),
//Bit5~4倍频时钟输入选择6MHz,Bit3 = 0保留位,
//Bit2~0系统时钟分频器选择位为000即系统时钟SYS=MCK=22.1184MHz
//在设置外部晶振时需要注意:
//先使能外部晶振(XTAL)标志位XTALE,
//然后再打开并选择外部晶振MCK时钟源、OSCin时钟源XTAL,
//最后再关闭内部IHRCOE即内部快频RC震荡使能位,
//根据颜工技术支持的说法,此内部快频RC振荡使能位可以不关闭,
//外部时钟也会很精确,只是会让费一些额外的能耗,最好是关掉内部快频RC振荡使能位
EA = 0 ;
IFD = 0x70; //(ISP/IAP Flash 数据寄存器)开外部晶振,置位CKCON2.Bit5位,使能XTAL振荡电路
IFADRH = 0x00; //注意这里的配置
IFADRL = 0x40;
IFMT = 0x04;
ISPCR |= 0x80;
SCMD = 0x46;
SCMD = 0xB9;
_nop_();
ISPCR &= ~0x80;
IFMT = 0x00;
IFD = 0xFF;
EA = 1;
DelayMs(5); //延时,以待外挂晶振稳定
EA = 0;
IFD = 0x71; //选择XTAL,置位CKCON2.Bit0位,OSCin时钟源选择XTAL
IFADRH = 0x00; //注意这里的配置
IFADRL = 0x40;
IFMT = 0x04;
ISPCR |= 0x80;
SCMD = 0x46;
SCMD = 0xB9;
_nop_();
ISPCR &= ~0x80;
IFMT = 0x00;
IFD = 0xFF;
EA = 1; //下面执行写CKCON2 = 0x61的配置,即设置外部晶振时钟作为本产品的系统时钟,
//外部晶振时钟频率22.1184MHz等于本产品的系统时钟SYSCLK
EA = 0; //关总中断
IFD = 0x61; //清零CKCON2.Bit4位,禁止内部快频RC震荡电路IHRCOE
//配置CKCON2 = 0x61;即将CKCON2的值0x61赋值给IFD,
//等待下面将IFD中的值0x61写入到IFADRL寄存器CKCON2所对应的地址0x40中,
//CKCON2为时钟控制寄存器2,
//Bit7~6 =01 XTAL振荡器增益控制寄存器,
//软件必须写01,Bit5 = 1使能XTAL振荡电路,Bit4 = 0禁止内部快频RC振荡电路,
//Bit3~2 = 00 MCK时钟源选择OSCin,
//Bit1~0 = 01 OSCin时钟源选择XTAL即外部晶振时钟
IFADRH = 0x00; //在P页访问时,IFADRH必须设置为”00”
IFADRL = 0x40; //IFADRL索引P页内特殊功能寄存器地址
IFMT = 0x04; //IFMT=04H则执行写P页操作,在SCMD激活之后IFD的数据会被载入到IFADRL索引的特殊功能寄存器,
//这些特殊功能寄存器在P页模式下不支持读功能
ISPCR |= 0x80; //ISPCR为ISP控制寄存器,Bit7 ISP/IAP/P页操作使能位,=1 使能 ISP/IAP/P页编程/擦除/读功能
SCMD = 0x46; //SCMD为连续命令数据寄存器,SCMD是激活ISP/IAP/P页的命令口,
//如果SCMD连续填入0x46h,0xB9h并且ISPCR.7 = 1,ISP/IAP/P页被激活
SCMD = 0xB9;
_nop_(); //延时一个_nop_()语句的时间
ISPCR &= ~0x80;//ISPCR为ISP控制寄存器,Bit7 ISP/IAP/P页操作使能位,
//=0 所有的ISP/IAP/P页编程/擦除/读都是被禁止的
IFMT = 0x00; //IFMT为ISP/IAP闪存模式表,IFMT的作用是用来选择闪存是被用来执行众多的ISP/IAP功能
//还是选择P页寄存器的访问,Bit 7~4: 保留,当IFMT改写时这些位必须写入”0”,
//Bit3~0: ISP/IAP/Page-P操作模式选择,=0x00 备用,=0x01 AP/IAP-存储器读,
//=0x02 AP/IAP-存储器编程,=0x03 AP/IAP-存储器页擦除, =0x04 P页SFR写
IFD = 0xFF;
//IFD为ISP/IAP闪存数据寄存器,IFD是ISP/IAP操作的数据端口寄存器,
//在ISP/IAP写操作时IFD的数据将被写入到期望的地址,
//在ISP/IAP读操作时IFD的值是读到期望地址的数据
EA = 1; //打开总中断
/////////////////////
//AUXR2 = 0x00;
//Bit3:T1X12,当C/T=0时,定时器1时钟源选择,=0 清零选择SYSCLK/12作为时钟源;
//Bit2:T0X12,当C/T=0时,定时器0时钟源选择,=0 清零选择SYSCLK/12作为时钟源
//T2MOD = 0x00;
//Bit4:T2X12,定时器2时钟源选择,=0 当T2CON.C/T2 = 0选择SYSCLK/12作为捕获和自动重载模式定时器2的时钟源
//T3MOD = 0x00;
//Bit4:T3X12,定时器3时钟源选择,=0 当T3CON.C/T3 = 0选择SYSCLK/12作为定时器3时钟源
}
程序三:
/*先用内部,再调用外部XTAL*/
/*实际上,先从外部调到内部,再从内部调到外部*/
#include<REG_MA805.H>
#include"intrins.h"
typedef unsigned int uint16;
uint16 k = 10;
uint16 num;
void DelayMs(uint16 ms)
{
uint16 i, j;
for(i = 0; i < ms; i++)
{
for(j = 0; j < 1320; j++);
}
}
void T0_int(void)
{
TMOD = 0X01;
TH0 = 0XFC;
TL0 = 0X66;
ET0 = 1;
TF0 = 0;
}
void main(void)
{
T0_int();
T0_int();
/////注意/////////
/////注意/////////
IFMT = 0X07;
ISPCR |= 0X80;
SCMD = 0X46;
SCMD = 0XB9;
ISPCR &= 0X7F;
SCMD = 0X00;
P0 = IFD; //把AUXR的上电复位值调出来,供我们写程序用
//特别是在原因的寄存器上改写的程序,会很有用的
//如果没有这段程序的话,我们在操作IFD的话,就不是在AUXR的基础上动作的,而是在IFD(FF)上操作的
///////////////
///////////////想想,如果没有以上的这段程序的话,结果会怎么样的?
while(k--) //检测外挂的晶振
{
P2 = ~P2;
DelayMs(1000);
}
k = 10;
/*调用内置高频*/
IFMT = 0X06;
IFD &= 0XFB;
IFD |= 0X04; //操作IFD就是操作AUXRA
//选择内置高频,使内置高频起振
ISPCR |= 0X80;
SCMD = 0X46;
SCMD = 0XB9;
ISPCR &= 0X7F;
SCMD = 0X00;
EA = 1;
TR0 = 1;
while(!(num == 5)); //延时以待稳定
num = 0;
TR0 = 0;
EA = 0;
IFMT = 0X06;
IFD &= ~0X03; //操作IFD就是操作AUXRA
//选择内置高频
IFD |= 0X00;
ISPCR |= 0X80;
SCMD = 0X46;
SCMD = 0XB9;
ISPCR &= 0X7F;
SCMD = 0X00;
/*完毕*/
IFMT = 0X06;
IFD &= ~0X08; //操作IFD就是操作AUXRA
//关闭外部晶振
ISPCR |= 0X80;
SCMD = 0X46;
SCMD = 0XB9;
ISPCR &= 0X7F;
SCMD = 0X00;
/*完毕*/
IFMT = 0X07;
ISPCR |= 0X80;
SCMD = 0X46;
SCMD = 0XB9;
ISPCR &= 0X7F;
SCMD = 0X00;
P1 = IFD; //检验AURXA设置后的情况
while(k--)
{
P2 = ~P2;
DelayMs(1000);
}
/*调用外部晶振*/
IFMT = 0X06;
IFD |= 0X08; //操作IFD就是操作AUXRA
//选择外部晶振
ISPCR |= 0X80;
SCMD = 0X46;
SCMD = 0XB9;
ISPCR &= 0X7F;
SCMD = 0X00;
EA = 1;
TR0 = 1; //延时以待晶振稳定
while(!(num == 5));
num = 0;
TR0 = 0;
EA = 0;
IFMT = 0X06;
IFD |= 0X03; //操作IFD就是操作AUXRA
//选择外部晶振
ISPCR |= 0X80;
SCMD = 0X46;
SCMD = 0XB9;
ISPCR &= 0X7F;
SCMD = 0X00;
IFMT = 0X06;
IFD &= ~0X04; //操作IFD就是操作AUXRA
//关闭内置高频
ISPCR |= 0X80;
SCMD = 0X46;
SCMD = 0XB9;
ISPCR &= 0X7F;
SCMD = 0X00;
/*完毕*/
IFMT = 0X07;
ISPCR |= 0X80;
SCMD = 0X46;
SCMD = 0XB9;
ISPCR &= 0X7F;
SCMD = 0X00;
P1 = IFD;
while(1)
{
P2 = ~P2;
DelayMs(1000);
}
}
void T0_inter() interrupt 1
{
TH0 = 0XFC;
TL0 = 0X66;
num++;
}
|