热度 26
2013-12-20 10:24
3760 次阅读|
0 个评论
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和 HS是使用超过4M的 石英晶体振荡器 。 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)