📄 timer.c
字号:
/******************************************************************************/
//
// File Name : Timer.c
// Description : S3C2443 PWM Timer test
// Version : 0.3
// Date : July 3, 2003
// 0.0 : Programming start (February 27,2002 in 2410) -> SOP
// 0.1 : Modified by Y. H. Lee
// 0.2 : edited by junon
// 0.3: Modified by Jcs (2006.05.20)
// 0.4 : modified by Dongjin Kim (20 Dec. 2006)
// (add comments, corelate with test plan)
/*******************************************************************************/
/* Include Files */
#include "system.h"
#include "timer.h"
/* Structure Define for DMA Special Registers */
typedef struct tagDMA
{
volatile U32 DISRC; //0x0
volatile U32 DISRCC; //0x4
volatile U32 DIDST; //0x8
volatile U32 DIDSTC; //0xc
volatile U32 DCON; //0x10
volatile U32 DSTAT; //0x14
volatile U32 DCSRC; //0x18
volatile U32 DCDST; //0x1c
volatile U32 DMASKTRIG; //0x20
volatile U32 DMAREQSEL; //0x24
}DMA;
static volatile int dmaDone;
int TestMode;
volatile int isWdtInt1;
//=========================================================================
//
// Timer input clock frequency = PCLK/{prescaler value+1}/{divider value}
// {prescaler value} = 0 ~ 255, {divider value} = 2,4,8,16
//
//=========================================================================
/******************** Selection Routine for Timer Test ********************/
void * func_timer_test[][2]=
{
(void *)Test_TimerNormal, "Timer Normal ",
(void *)Test_TimerInt, "Timer Interrupt ",
(void *)Test_TimerDma, "Timer DMA ",
0,0
};
void Test_Timer(void)
{
int i;
while(1)
{
printf("\n\n============== Timer Function Test ==============\n");
i=0;
printf("\n");
while(1)
{ //display menu
printf("%2d:%s",i,func_timer_test[i][1]);
i++;
if((int)(func_timer_test[i][0])==0)
{
printf("\n");
break;
}
if((i%2)==0)
printf("\n");
}
printf("\n=================================================\n");
printf("\nPress Enter key to exit : ");
i = GetIntNum();
if(i==-1) break; // return.
if(i>=0 && (i<((sizeof(func_timer_test)-1)/8)) ) // select and execute...
( (void (*)(void)) (func_timer_test[i][0]) )();
}
}
/******************** PWM Timer Normal Operation Test ********************/
void Test_TimerNormal(void)
{
int save_B,save_H,save_PB,save_PH,save_MI;
char key;
/* Save Current Register related to PWM Port */
//Save Current GPB, G, H Configure Registers
save_B = rGPBCON;
save_H = rGPHCON;
//Save Pull-Up Disable Register
save_PB = rGPBUDP;
save_PH = rGPHUDP;
//Save Miscellaneous Control Register
save_MI = rMISCCR;
/* Setting Port related to PWM */
// PortB
rGPBUDP = rGPBUDP & ~(0x3ff)|0x2aa; //GPB[4:0] Pull Up/Down disable
rGPBCON = rGPBCON & ~(0x3ff) |0x2aa; //TCKL, TOUT[3:0]
// PortH
rGPHUDP = rGPHUDP & ~(0x3<<26)|(0x2<<26); //GPH[13] Pull Up/Down disable
rGPHCON = rGPHCON & ~(0x3<<26) |(0x2<<26); //GPH13=>CLKOUT0
// Miscellaneous Control Register
rMISCCR = rMISCCR & ~(0x7<<4) |(0x4<<4); //Select PCLK with CLKOUT0 to monitor PCLK
printf("[Select Timer Test Setting]\n");
printf("a. Prescaler 1, 0: 0, Dead zone Disable, MUX 4~0: 1/2, (H/L)duty 50 \n");
printf("b. Prescaler 1, 0: 7, Dead zone Enable, MUX 4~0: 1/16, (H/L)duty 50 \n");
printf("c. (H/L)duty 0(All low), TCNT =< TCMP, Inverter On\n");
printf("d. TCLK Input Divider Test\n");
printf("Select [a ~ d]: \n");
key = getchar();
printf("\n");
/* Timer Configuration Register.0, 1(TCFG0, TCFG1) Setting */
switch(key)
{
case 'a':
rTCFG0 = rTCFG0 & ~(0xffffff) | 0x00000; //Dead zone=0, Prescaler1=0, Prescaler0=0
rTCFG1 = 0x0; //All Interrupt, MUX 4 ~ 0: 1/2
printf("Prescaler1=0, Prescaler0=0, Dead Zone Disable, MUX 4 ~ 0: 1/2, Duty 50 percent \n");
break;
case 'b':
rTCFG0 = rTCFG0 & ~(0xffffff) | (0x0)<<16 | (0x7)<<8 | (0x7); //Dead zone=0, Prescaler1=7, Prescaler0=7
rTCFG1 = rTCFG1 & ~(0xffffff) | (0x3)<<16 | (0x3)<<12 | (0x3)<<8 | (0x3)<<4 | (0x3); //All Interrupt, MUX 4 ~ 0: 1/16
printf("Prescaler1=8, Prescaler0=8, Dead zone=200 Enable, MUX 4 ~ 0: 1/16, duty = 50 percent, Consider Dead zone effect\n");
break;
case 'c':
rTCFG0 = rTCFG0 & ~(0xffffff) | 0x0; //Dead zone=0, Prescaler1=0, Prescaler0=0
rTCFG1 = rTCFG1 & ~(0xffffff) | 0x0; //All Interrupt, MUX 4 ~ 0: 1/2
printf("Prescaler1=0, Prescaler0=0, Dead Zone Disable, Invert On, MUX 4 ~ 0: 1/2\n");
printf("(H/L)Duty 0(All low), when TCNT =< TCMP, Invertered(All high)\n");
break;
case 'd':
rTCFG0 = rTCFG0 & ~(0xffffff) | 0x0; //Dead zone=0, Prescaler1=0, Prescaler0=0
rTCFG1 = rTCFG1 & ~(0xffffff) | 0x4 | 0x4 << 4 | 0x4 << 8 | 0x4 << 12 | 0x4 << 16; //All Interrupt, MUX 4 ~ 0: 1/2
printf("TCLK Input Divider Test\n");
break;
default:
rGPBCON = save_B;
rGPHCON = save_H;
rGPBUDP = save_PB;
rGPHUDP = save_PH;
rMISCCR = save_MI;
return;
}
//(1/(PCLK/(Prescaler+1) /divider) * (count+1) (count Max 65535) = Timer clock (Frequency)
//(1/(50MHz/1 /2)) * 2001 = 0.0800 msec ( 12.49 KHz)
//(1/(50MHz/1 /2)) * 4001 = 0.1600 msec ( 6.25 KHz)
//(1/(50MHz/1 /2)) * 5001 = 0.2000 msec ( 4.99 KHz)
//(1/(50MHz/1 /2)) * 10001 = 0.4000 msec ( 2.49 KHz)
//(1/(50MHz/8 /16)) * 2001 = 5.1225 msec ( 195.217 Hz)
//(1/(50MHz/8 /16)) * 4001 = 10.242 msec ( 97.631 KHz)
//(1/(50MHz/8 /16)) * 5001 = 12.802 msec ( 78.109 Hz)
//(1/(50MHz/8 /16)) * 10001 = 25.602 msec ( 39.058 Hz)
rTCNTB0 = 2000;
rTCNTB1 = 4000;
rTCNTB2 = 5000;
rTCNTB3 = 10000;
rTCMPB0 = 2000 - 1000; //(H/L)duty 50%
rTCMPB1 = 4000 - 2000;
rTCMPB2 = 5000 - 2500;
rTCMPB3 = 10000 - 5000;
rTCON = rTCON & ~(0xffffff) | 0x1<<1 | 0x1<<9 | 0x1<<13 | 0x1<<17 | 0x1<<21 ; //Manual update
switch(key)
{
case 'a':
rTCON = rTCON & ~(0xffffff) | 0x599909; //Auto reload, Inverter off, No operation, Start, Dead zone Disable
break;
case 'b':
rTCNTB0 = rTCNTB0 & ~(0xffff) | 5; //(1/(50.8MHz/8/16)) * (5+1) = 0.01536 msec ( 65.104kHz)
rTCMPB0 = 5 - 2; // L width : 4(10.54us), H width : 2(5.12us)
rTCON = rTCON & ~(0xffffff) | 0x6aaa0a; //Auto reload, Inverter off, Manual update, Stop, Dead zone Disable
rTCON = rTCON & ~(0xffffff) | 0x599909| (0x1) << 4; //Auto reload, Inverter off, No operation, Start, Dead zone Enable
break;
case 'c':
rTCNTB0 = rTCNTB0 & ~(0xffff) | 1000;
rTCMPB0 = 300;
rTCNTB1 = rTCNTB1 & ~(0xffff) | 1000;
rTCMPB1 = 999;//1 Timer operating clock cycle is low, and 1000 clock cycle is high
rTCNTB2 = rTCNTB2 & ~(0xffff) | 1000;
rTCMPB2 = 1000;//Tout keep low, inverted signal is high
rTCNTB3 = rTCNTB3 & ~(0xffff) | 1000;
rTCMPB3 = 1001;//Tout keep low, inverted signal is high
rTCON = rTCON & ~(0xffffff) | 0x1 << 1 | 0x1 << 9 | 0x1 << 13 | 0x1 << 17 | 0x1 << 21; //Auto reload disable, Inverter off, Manual update, Stop, Dead zone Disable
rTCON = rTCON & ~(0xffffff) | 0x1 | 0x1 << 2 | 0x1 <<8 | 0x1 << 10| 0x1 << 12 | 0x1 << 14 | 0x1 << 16 | 0x1 << 18| 0x1 << 20; //Auto reload enable, Inverter On, No Operation, Start, Dead zone Disable
//printf("rTCNTB0 = Dec:%d, rTCNTO0 = Dec:%d, rTCMPB0 = Dec:%d\n",rTCNTB0, rTCNTO0, rTCMPB0);
break;
case 'd':
rTCON = rTCON & ~(0xffffff) | 0x599909; //Auto reload, Inverter off, No operation, Start, Dead zone Disable
break;
default:
break;
}
if(key=='a' && (PCLK==(200000000/4)))
{
printf("PCLK 50MHz\n");
printf("Timer0: count 2000, 0.0800 msec ( 12.49 KHz) L: 40us, H: 40.04us\n");
printf("Timer1: count 4000, 0.1600 msec ( 6.25 KHz) L: 80us, H: 80.04us\n");
printf("Timer2: count 5000, 0.2000 msec ( 4.99 KHz) L:100us, H: 100us\n");
printf("Timer3: count 10000,0.4000 msec ( 2.49 KHz) L:200us, H: 200us\n");
}
else if(key=='b' && (PCLK==(200000000/4)))
{
printf("PCLK 50MHz\n");
printf("* Timer0 = TOUT0_DZ, Timer1 = NTOUT0_DZ, deadzone length 1\n");
printf("Timer0: count 5, 0.01536 msec(65.104 KHz) L: 10.54us, H: 5.12us\n");
printf("Timer1: L: All low\n");
printf("Timer2: count 5000, 12.802 msec ( 73.109 Hz) L: 6.40ms, H: 6.402ms\n");
printf("Timer3: count 10000,25.602 msec ( 39.058 Hz) L: 12.800ms,H:12.802ms\n");
}
else if(key=='c' && (PCLK==(200000000/4)))
{
printf("PCLK 50MHz\n");
printf("Timer0: count 300, 0.0400 msec ( 24.97 KHz) H: 28us, L: 12.04us\n");
printf("Timer1: count 999, 0.0400 msec ( 24.97 KHz) H: 0.04us, L: 40us\n");
printf("Timer2: count 1000 H: All High\n");
printf("Timer3: count 1001 H: All High\n");
}
else if(key=='d')
{
printf("Applying the clock signal of (390.625Khz, 3V, duty 50 percent) \n");
printf("to TCLK(TP20) input, then\n");
printf("Timer0: count 2000, 5.12 msec ( 195 Hz)\n");
printf("Timer1: count 4000, 10.24 msec ( 97.63 Hz)\n");
printf("Timer2: count 5000, 12.80 msec ( 78.107 Hz)\n");
printf("Timer3: count 10000, 25.61 msec ( 39.056 Hz)\n");
}
printf("\nProbe PCLK(TP18).\n");
printf("Probe TOUT0(TP21) for Timer0.\n");
printf("Probe TOUT1(TP22) for Timer1.\n");
printf("Probe TOUT2(TP23) for Timer2.\n");
printf("Probe TOUT3(TP24) for Timer3.\n");
printf("\nCheck PWM (Pulse Width Modulation) Output\n");
printf("Press any key.\n");
getchar();
/* Stop Timer0, 1, 2, 3, 4 */
rTCON = 0x0; //One-shot, Inverter off, No operation, Dead zone disable, Stop Timer
rGPBCON = save_B;
rGPHCON = save_H;
rGPBUDP = save_PB;
rGPHUDP = save_PH;
rMISCCR = save_MI;
}
/******************** Timer Interrupt 0/1/2/3/4 test ********************/
volatile int variable0,variable1,variable2,variable3,variable4;
int j;
void Test_TimerInt(void)
{
variable0 = 0;variable1 = 0;variable2 = 0;variable3 = 0;variable4 = 0;
/* Timer0,1,2,3,4 Interrupt service is available */
rINTMSK = ~(BIT_TIMER4 | BIT_TIMER3 | BIT_TIMER2 | BIT_TIMER1 | BIT_TIMER0);
// printf("rINTMSK (After) = 0x%8x <= Timer4,3,2,1 Bit[14:10]\n",rINTMSK);
/* Timer0,1,2,3,4 Interrupt Service Routine Entry Point Determine */
pISR_TIMER0 = (int)Timer0Done;
pISR_TIMER1 = (int)Timer1Done;
pISR_TIMER2 = (int)Timer2Done;
pISR_TIMER3 = (int)Timer3Done;
pISR_TIMER4 = (int)Timer4Done;
printf("\n[Timer 0,1,2,3,4 Interrupt Test]\n\n");
rTCFG0 = rTCFG0 & ~(0xffffff) | 0xff | 0xff<<8; //Dead zone=0,Prescaler1=255(0x0f),Prescaler0=255(0x0f)
rTCFG1 =rTCFG1 & ~(0xffffff) | 0x001233; //All interrupt,Mux4=1/2,Mux3=1/4,Mux2=1/8,Mux1=1/16,Mux0=1/16
rTCNTB0 = 30000;
rTCNTB1 = 30000;
rTCNTB2 = 30000;
rTCNTB3 = 30000;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -