PIC24HJ头文件中包含了delay函数,定义如下:
/**************************
延时函数头文件
**************************/
#include "Generic.h"
#if defined(__PIC24H__)
#ifndef Fcy
#define Fcy 10000000 //10 000 000 10M
#endif
#endif
#define Delay_60nS_Cnt (Fcy * 0.00000006)
#define Delay_150nS_Cnt (Fcy * 0.00000015)
#define Delay_360nS_Cnt (Fcy * 0.00000036)
#define Delay_450nS_Cnt (Fcy * 0.00000045)
#define Delay_600nS_Cnt (Fcy * 0.0000006)
#define Delay200uS_count (Fcy * 0.0002)
#define Delay_1mS_Cnt (Fcy * 0.001)
#define Delay_2mS_Cnt (Fcy * 0.002)
#define Delay_5mS_Cnt (Fcy * 0.005)
#define Delay_15mS_Cnt (Fcy * 0.015)
#define Delay_1S_Cnt (Fcy * 1)
/* delays specific to each LCD type */
/* delay btw RS/RW signal to E signal */
#define DelayRSSetupTime_Cnt Delay_60nS_Cnt
/* delay btw E rise and Data available */
#define DelayDBOutput_Cnt Delay_360nS_Cnt
/* min E pulse width low */
#define DelayEPulseWidthLow_Cnt Delay_150nS_Cnt
/* min E pulse width high */
#define DelayEPulseWidthHigh_Cnt Delay_450nS_Cnt
/* E pulse cycle time */
#define DelayEPulseWidth_Cnt Delay_600nS_Cnt
/* min Power On Reset time */
#define DelayPORXLCD_Cnt Delay_15mS_Cnt
/* generic delay for LCD */
#define DelayXLCD_Cnt Delay_5mS_Cnt
//void delaynus(uint);
就是进行了一些简单的宏定义,没有看到实际的延时函数,然后找了一下PIC24FJ中的函数函数,是用于XLCD的,而里面的函数在src中已经定义了,进行移植怕出现问题。
然后在PIC24HJ的目录下找delay的函数,果然找到了一个,但是放在XLCD目录下,也就是说,这个是编译器一定定义好的,发现这个延时函数也是用于液晶的延时,定义的形式如下:
void DelayDBOutput(void) /* provides delay for Data Output */
{
int i;
for(i=0;i
asm("clrwdt");
}
这里有一个CLRWDT,如何通过这样的形式实现延时?另外还有一个参数TCY_CNT_PER_LOOP这个是怎么用的?
这里的一条汇编语句,clrwdt应该是在函数函数中避免看门狗复位。
这样的话,延时函数还是需要自己来编写的,但是时钟的问题又出现了。
下面先引用一段关于XT,LP和
XT是使用1M到4M的石英晶体振荡器。
LP是使用低于1M的陶瓷振荡器,不是什么感抗震荡
上述都是用外部晶振,只是所用晶振的材质和频率不同。
RC是不使用外部晶振,直接用内部的RC时钟电路。
其中HS和XT因为用石英晶体振荡器,所得时钟比较准确,适用于各种串口、can、TCPIP通信的场合。但缺点是频率大所以功耗也大。
用LP和RC的特点是功耗小,但LP频率低,陶瓷振荡器输出的时钟精度不够高,RC的误差更大。适用于不用通信的普通控制场合。
一共有四个时钟源,包括外部晶振,内部快速RC和慢速RC,以及一个辅助时钟源。
其中,外部晶振可以选择是否倍频,以及XT,HS,EC三种模式,就有6种时钟。
FRC包括不分频,固定为16和N分频,和PLL,一共有四种。
另外包括一个辅助晶振和一个低频的振荡器,一个有12种。
其中POSCMD选择外部时钟还是高速,低速的时钟模式:
其中HS模式为高增益模式,在高频时应用。
按照分频和倍频,可以将外部时钟设置到高达40M的Fcy,如下图:
这里,如果选用外部晶振为10M,然后通过PLLPRE分频到0.8M~8M,默认为/2,这样,为5M,然后,经过锁相环倍频,
这里默认为50,这样,得到的频率为250M,然后再经过PLLPOST,默认为/4,这样得到的是62.5M,超过了40M的限制。
应该设置PLLPOST为/8,则时钟为31.25M
下面是头文件对CLKDIV的申明,如下:
__extension__ typedef struct tagCLKDIVBITS {
union {
struct {
unsigned PLLPRE:5;
unsigned :1;
unsigned PLLPOST:2;
unsigned FRCDIV:3;
unsigned DOZEN:1;
unsigned DOZE:3;
unsigned ROI:1;
};
struct {
unsigned PLLPRE0:1;
unsigned PLLPRE1:1;
unsigned PLLPRE2:1;
unsigned PLLPRE3:1;
unsigned PLLPRE4:1;
unsigned :1;
unsigned PLLPOST0:1;
unsigned PLLPOST1:1;
unsigned FRCDIV0:1;
unsigned FRCDIV1:1;
unsigned FRCDIV2:1;
unsigned :1;
unsigned DOZE0:1;
unsigned DOZE1:1;
unsigned DOZE2:1;
};
};
} CLKDIVBITS;
寄存器的结构如下:
OK,根据上面的设置,可以进行如下的编程:
采用10M的时钟,通过如下的时钟的初始化得到:
void osc_init()
{
//_CLKLOCK=0;
_PLLPRE=0;
_PLLDIV=0X1E;
_PLLPOST=0;
}
得到一个40M的FCY,然后主程序中执行如下程序:
int main(void)
{
osc_init();
// uchar i;
mPORTBOutputConfig(IOPORT_BIT_9);
while(1)
{
mPORTBClearBits(IOPORT_BIT_9);
delayn(255);
mPORTBSetBits(IOPORT_BIT_9);
delayn(255);
}
return 0;
}
查看汇编语言窗口,执行一条设置端口电平的指令的时间为:4个周期,这样,按照上面的设置,B9拉低电平,然后延时25*4+(25*6*255)=38.35us
25: mPORTBOutputConfig(IOPORT_BIT_9);
004F2 801630 mov.w 0x02c6,0x0000
004F4 2FDFF1 mov.w #0xfdff,0x0002
004F6 600001 and.w 0x0000,0x0002,0x0000
004F8 881630 mov.w 0x0000,0x02c6
如果设置PLLPRE为6,则一开始8分频,得到指令周期是10M,则一条设置端口的指令时间为4*100ns=400ns。
通过仿真验证程序OK.
而DOZE模式的设置,对端口是没有影响的,以为端口是外设,不会影响外设的时间,而只会影响到CPU.
;i+=tcy_cnt_per_loop)<>
文章评论(0条评论)
登录后参与讨论