用看门狗定时器做计时器,计算程序耗时,超声波测距,FL2440
开发板:FL2440
核心芯片:S3C2440(ARM9)
超声波模块:HC-SR04
超声波模块工作原理:共四个脚,VCC接5V,GND接地,Trig脚接芯片通过IO传出的高电平(持续时间不低于10微秒),之后Echo脚输出一段时间高电平,高电平持续时间即为超声波发出到接收到回波的间隔时间。
主要是为了使用看门狗定时器来作计时器,来计算Echo脚返回的高电平持续时间,要将复位使能与中断使能关闭,然后给“狗”最大数值,持续一段时间后,用最大数值减去当前数值,就可得到消耗的数值,再乘以“狗”每次减数的时间间隔(通过设定预分频与分频因子来确定),就是消耗的时间。
试验期间出现的重要错误:程序自动run后,消耗时间总是0,而采用AXD单步执行则可以得出正确数值——解决方法:将“狗”的每次递减的时间间隔加大。
下面来程序:
2440init.s
1 ;========================================= 2 ; NAME: 2440INIT.S 3 ; DESC: C start up codes 4 ; Configure memory, ISR ,stacks 5 ; Initialize C-variables 6 ; HISTORY: 7 ; 2002.02.25:kwtark: ver 0.0 8 ; 2002.03.20:purnnamu: Add some functions for testing STOP,Sleep mode 9 ; 2003.03.14:DonGo: Modified for 2440. 10 ;========================================= 11 12 GET option.inc 13 GET memcfg.inc 14 GET 2440addr.inc 15 16 BIT_SELFREFRESH EQU (1<<22) 17 18 ;Pre-defined constants 19 USERMODE EQU 0x10 20 FIQMODE EQU 0x11 21 IRQMODE EQU 0x12 22 SVCMODE EQU 0x13 23 ABORTMODE EQU 0x17 24 UNDEFMODE EQU 0x1b 25 MODEMASK EQU 0x1f 26 NOINT EQU 0xc0 27 28 ;The location of stacks 29 UserStack EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~ 30 SVCStack EQU (_STACK_BASEADDRESS-0x2800) ;0x33ff5800 ~ 31 UndefStack EQU (_STACK_BASEADDRESS-0x2400) ;0x33ff5c00 ~ 32 AbortStack EQU (_STACK_BASEADDRESS-0x2000) ;0x33ff6000 ~ 33 IRQStack EQU (_STACK_BASEADDRESS-0x1000) ;0x33ff7000 ~ 34 FIQStack EQU (_STACK_BASEADDRESS-0x0) ;0x33ff8000 ~ 35 36 ;Check if tasm.exe(armasm -16 ...@ADS 1.0) is used. 37 GBLL THUMBCODE 38 [ {CONFIG} = 16 39 THUMBCODE SETL {TRUE} 40 CODE32 41 | 42 THUMBCODE SETL {FALSE} 43 ] 44 45 MACRO 46 MOV_PC_LR 47 [ THUMBCODE 48 bx lr 49 | 50 mov pc,lr 51 ] 52 MEND 53 54 MACRO 55 MOVEQ_PC_LR 56 [ THUMBCODE 57 bxeq lr 58 | 59 moveq pc,lr 60 ] 61 MEND 62 63 64 MACRO 65 $HandlerLabel HANDLER $HandleLabel 66 67 $HandlerLabel 68 sub sp,sp,#4 ;decrement sp(to store jump address) 69 stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original address) 70 ldr r0,=$HandleLabel;load the address of HandleXXX to r0 71 ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX 72 str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack 73 ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR) 74 MEND 75 76 77 78 79 IMPORT Main ; The main entry of mon program 80 81 AREA Init,CODE,READONLY 82 83 ENTRY 84 85 EXPORT __ENTRY 86 __ENTRY 87 ResetEntry 88 ;1)The code, which converts to Big-endian, should be in little endian code. 89 ;2)The following little endian code will be compiled in Big-Endian mode. 90 ; The code byte order should be changed as the memory bus width. 91 ;3)The pseudo instruction,DCD can not be used here because the linker generates error. 92 ASSERT :DEF:ENDIAN_CHANGE 93 [ ENDIAN_CHANGE 94 ASSERT :DEF:ENTRY_BUS_WIDTH 95 96 97 [ ENTRY_BUS_WIDTH=16 98 andeq r14,r7,r0,lsl #20 ;DCD 0x0007ea00 99 ] 100 101 [ ENTRY_BUS_WIDTH=8 102 streq r0,[r0,-r10,ror #1] ;DCD 0x070000ea 103 ] 104 | 105 b ResetHandler 106 ] 107 b HandlerUndef ;handler for Undefined mode 108 b HandlerSWI ;handler for SWI interrupt 109 b HandlerPabort ;handler for PAbort 110 b HandlerDabort ;handler for DAbort 111 b . ;reserved 112 b HandlerIRQ ;handler for IRQ interrupt 113 b HandlerFIQ ;handler for FIQ interrupt 114 115 ;@0x20 116 ; b EnterPWDN ; Must be @0x20. 117 118 119 HandlerFIQ HANDLER HandleFIQ 120 HandlerIRQ HANDLER HandleIRQ 121 HandlerUndef HANDLER HandleUndef 122 HandlerSWI HANDLER HandleSWI 123 HandlerDabort HANDLER HandleDabort 124 HandlerPabort HANDLER HandlePabort 125 126 IsrIRQ 127 sub sp,sp,#4 ;reserved for PC 128 stmfd sp!,{r8-r9} 129 130 ldr r9,=INTOFFSET 131 ldr r9,[r9] 132 ldr r8,=HandleEINT0 133 add r8,r8,r9,lsl #2 134 ldr r8,[r8] 135 str r8,[sp,#8] 136 ldmfd sp!,{r8-r9,pc} 137 138 139 LTORG 140 141 ;======= 142 ; ENTRY 143 ;======= 144 ResetHandler 145 ldr r0,=WTCON ;watch dog disable 146 ldr r1,=0x0 147 str r1,[r0] 148 149 ldr r0,=INTMSK 150 ldr r1,=0xffffffff ;all interrupt disable 151 str r1,[r0] 152 153 ldr r0,=INTSUBMSK 154 ldr r1,=0x7fff ;all sub interrupt disable 155 str r1,[r0] 156 157 158 159 ;To reduce PLL lock time, adjust the LOCKTIME register. 160 ldr r0,=LOCKTIME 161 ldr r1,=0xffffff 162 str r1,[r0] 163 164 [ PLL_ON_START 165 ; Added for confirm clock divide. for 2440. 166 ; Setting value Fclk:Hclk:Pclk 167 ldr r0,=CLKDIVN 168 ldr r1,=CLKDIV_VAL ; 0=1:1:1, 1=1:1:2, 2=1:2:2, 3=1:2:4, 4=1:4:4, 5=1:4:8, 6=1:3:3, 7=1:3:6. 169 str r1,[r0] 170 171 ;program has not been copied, so use these directly, 172 [ CLKDIV_VAL>1 ; means Fclk:Hclk is not 1:1. 173 mrc p15,0,r0,c1,c0,0 174 orr r0,r0,#0xc0000000;R1_nF:OR:R1_iA 175 mcr p15,0,r0,c1,c0,0 176 | 177 mrc p15,0,r0,c1,c0,0 178 bic r0,r0,#0xc0000000;R1_iA:OR:R1_nF 179 mcr p15,0,r0,c1,c0,0 180 ] 181 182 ;Configure UPLL 183 ldr r0,=UPLLCON 184 ldr r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV) 185 str r1,[r0] 186 nop ; Caution: After UPLL setting, at least 7-clocks delay must be inserted for setting hardware be completed. 187 nop 188 nop 189 nop 190 nop 191 nop 192 nop 193 ;Configure MPLL 194 ldr r0,=MPLLCON 195 ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) ;Fin=16.9344MHz 196 str r1,[r0] 197 ] 198 199 ;Check if the boot is caused by the wake-up from SLEEP mode. 200 201 202 203 204 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 205 ;;;;;;;;;;;;; When EINT0 is pressed, Clear SDRAM 206 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 207 ; check if EIN0 button is pressed 208 209 210 1 bl InitStacks 211 212 213 214 215 ;=========================================================== 216 ; Setup IRQ handler 217 ldr r0,=HandleIRQ ;This routine is needed 218 ldr r1,=IsrIRQ ;if there is not 'subs pc,lr,#4' at 0x18, 0x1c 219 str r1,[r0] 220 221 222 223 224 [ :LNOT:THUMBCODE 225 bl Main ;Do not use main() because ...... 226 b . 227 ] 228 229 [ THUMBCODE ;for start-up code for Thumb mode 230 orr lr,pc,#1 231 bx lr 232 CODE16 233 bl Main ;Do not use main() because ...... 234 b . 235 CODE32 236 ] 237 238 239 ;function initializing stacks 240 InitStacks 241 ;Do not use DRAM,such as stmfd,ldmfd...... 242 ;SVCstack is initialized before 243 ;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1' 244 mrs r0,cpsr 245 bic r0,r0,#MODEMASK 246 orr r1,r0,#UNDEFMODE|NOINT 247 msr cpsr_cxsf,r1 ;UndefMode 248 ldr sp,=UndefStack ; UndefStack=0x33FF_5C00 249 250 orr r1,r0,#ABORTMODE|NOINT 251 msr cpsr_cxsf,r1 ;AbortMode 252 ldr sp,=AbortStack ; AbortStack=0x33FF_6000 253 254 orr r1,r0,#IRQMODE|NOINT 255 msr cpsr_cxsf,r1 ;IRQMode 256 ldr sp,=IRQStack ; IRQStack=0x33FF_7000 257 258 orr r1,r0,#FIQMODE|NOINT 259 msr cpsr_cxsf,r1 ;FIQMode 260 ldr sp,=FIQStack ; FIQStack=0x33FF_8000 261 262 bic r0,r0,#MODEMASK|NOINT 263 orr r1,r0,#SVCMODE 264 msr cpsr_cxsf,r1 ;SVCMode 265 ldr sp,=SVCStack ; SVCStack=0x33FF_5800 266 267 ;USER mode has not be initialized. 268 269 mov pc,lr 270 ;The LR register will not be valid if the current mode is not SVC mode. 271 272 ;=========================================================== 273 274 275 276 277 278 279 280 281 ;===================================================================== 282 ; Clock division test 283 ; Assemble code, because VSYNC time is very short 284 ;===================================================================== 285 286 287 288 ALIGN 289 290 AREA RamData, DATA, READWRITE 291 292 ^ _ISR_STARTADDRESS ; _ISR_STARTADDRESS=0x33FF_FF00 293 HandleReset # 4 294 HandleUndef # 4 295 HandleSWI # 4 296 HandlePabort # 4 297 HandleDabort # 4 298 HandleReserved # 4 299 HandleIRQ # 4 300 HandleFIQ # 4 301 302 ;Do not use the label 'IntVectorTable', 303 ;The value of IntVectorTable is different with the address you think it may be. 304 ;IntVectorTable 305 ;@0x33FF_FF20 306 HandleEINT0 # 4 307 HandleEINT1 # 4 308 HandleEINT2 # 4 309 HandleEINT3 # 4 310 HandleEINT4_7 # 4 311 HandleEINT8_23 # 4 312 HandleCAM # 4 ; Added for 2440. 313 HandleBATFLT # 4 314 HandleTICK # 4 315 HandleWDT # 4 316 HandleTIMER0 # 4 317 HandleTIMER1 # 4 318 HandleTIMER2 # 4 319 HandleTIMER3 # 4 320 HandleTIMER4 # 4 321 HandleUART2 # 4 322 ;@0x33FF_FF60 323 HandleLCD # 4 324 HandleDMA0 # 4 325 HandleDMA1 # 4 326 HandleDMA2 # 4 327 HandleDMA3 # 4 328 HandleMMC # 4 329 HandleSPI0 # 4 330 HandleUART1 # 4 331 HandleNFCON # 4 ; Added for 2440. 332 HandleUSBD # 4 333 HandleUSBH # 4 334 HandleIIC # 4 335 HandleUART0 # 4 336 HandleSPI1 # 4 337 HandleRTC # 4 338 HandleADC # 4 339 ;@0x33FF_FFA0 340 END
2440addr.h
1 //ISR 2 3 //_ISR_STARTADDRESS EQU 0x33ffff00 4 #define _IRQ_BASEADDRESS 0x33ffff00 5 /*#define pISR_RESET (*(unsigned *)(_IRQ_BASEADDRESS+0x0)) 6 #define pISR_UNDEF (*(unsigned *)(_IRQ_BASEADDRESS+0x4)) 7 #define pISR_SWI (*(unsigned *)(_IRQ_BASEADDRESS+0x8)) 8 #define pISR_PABORT (*(unsigned *)(_IRQ_BASEADDRESS+0xc)) 9 #define pISR_DABORT (*(unsigned *)(_IRQ_BASEADDRESS+0x10)) 10 #define pISR_RESERVED (*(unsigned *)(_IRQ_BASEADDRESS+0x14)) 11 #define pISR_IRQ (*(unsigned *)(_IRQ_BASEADDRESS+0x18)) 12 #define pISR_FIQ (*(unsigned *)(_IRQ_BASEADDRESS+0x1c))*/ 13 #define pISR_WDT (*(unsigned *)(_IRQ_BASEADDRESS+0x44)) 14 15 16 //UART0 17 #define rUTRSTAT0 (*(volatile unsigned *)0x50000010) //UART 0 Tx/Rx status 18 #define rULCON0 (*(volatile unsigned *)0x50000000) //UART 0 Line control 19 #define rUCON0 (*(volatile unsigned *)0x50000004) //UART 0 Control 20 #define rUFCON0 (*(volatile unsigned *)0x50000008) //UART 0 FIFO control 21 #define rUBRDIV0 (*(volatile unsigned *)0x50000028) //UART 0 Baud rate divisor 22 #define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch) 23 24 25 //WDT 26 #define rWTCON (*(volatile unsigned *)0x53000000) 27 #define rWTDAT (*(volatile unsigned *)0x53000004) 28 #define rWTCNT (*(volatile unsigned *)0x53000008) 29 30 31 32 //INTRRUPT 33 #define rSRCPND (*(volatile unsigned *)0x4A000000) 34 #define rINTMOD (*(volatile unsigned *)0x4A000004) 35 #define rINTMSK (*(volatile unsigned *)0x4A000008) 36 #define rPRIORITY (*(volatile unsigned *)0x4A00000c) 37 #define rINTPND (*(volatile unsigned *)0x4A000010) 38 #define rINTOFFSET (*(volatile unsigned *)0x4A000014) 39 #define rSUBSRCPND (*(volatile unsigned *)0x4A000018) 40 #define rINTSUBMSK (*(volatile unsigned *)0x4A00001C) 41 42 //gpio 43 #define GPBCON (*(volatile unsigned *)0x56000010) 44 #define GPBDAT (*(volatile unsigned *)0x56000014) 45 #define GPBUP (*(volatile unsigned *)0x56000018) 46 47 #define GPECON (*(volatile unsigned *)0x56000040) 48 #define GPEDAT (*(volatile unsigned *)0x56000044) 49 #define GPEUP (*(volatile unsigned *)0x56000048) 50 51 #define GPGCON (*(volatile unsigned *)0x56000060) 52 #define GPGDAT (*(volatile unsigned *)0x56000064) 53 #define GPGUP (*(volatile unsigned *)0x56000068) 54 55 #define uchar unsigned char 56 #define uint unsigned int 57 58 #define prescaler_value 0 59 #define clock_select 2 60 #define BIT_WDT_AC97 (1<<9) 61 #define BIT_WDT (1<<13) 62 63 64 #define EnableIrq(bit) rINTMSK &= ~(bit) 65 #define DisableIrq(bit) rINTMSK |= (bit) 66 #define EnableSubIrq(bit) rINTSUBMSK &= ~(bit) 67 #define DisableSubIrq(bit) rINTSUBMSK |= (bit)
uart.c
1 #include <stdarg.h> 2 #include "2440addr.h" 3 4 void Uart_Init(int baud) 5 { 6 int i; 7 rUFCON0 = 0x0; //UART channel 0 FIFO control register, FIFO disable 8 9 10 //UART0 11 rULCON0 = 0x3; //Line control register : Normal,No parity,1 stop,8 bits 12 // [10] [9] [8] [7] [6] [5] [4] [3:2] [1:0] 13 // Clock Sel, Tx Int, Rx Int, Rx Time Out, Rx err, Loop-back, Send break, Transmit Mode, Receive Mode 14 // 0 1 0 , 0 1 0 0 , 01 01 15 // PCLK Level Pulse Disable Generate Normal Normal Interrupt or Polling 16 rUCON0 = 0x805; // Control register 17 rUBRDIV0=( (int)(50000000/16./baud+0.5) -1 ); //Baud rate divisior register 0 18 //UART1 19 20 for(i=0;i<100;i++); 21 } 22 23 24 25 //===================================================================== 26 void Uart_SendByte(int data) 27 { 28 29 if(data=='\n') 30 { 31 while(!(rUTRSTAT0 & 0x2)); 32 // Delay(1); //because the slow response of hyper_terminal 33 WrUTXH0('\r'); 34 } 35 while(!(rUTRSTAT0 & 0x2)); //Wait until THR is empty. 36 // Delay(1); 37 WrUTXH0(data); 38 39 40 } 41 42 //==================================================================== 43 void Uart_SendString(char *pt) 44 { 45 while(*pt) 46 Uart_SendByte(*pt++); 47 } 48 49 //===================================================================== 50 //If you don't use vsprintf(), the code size is reduced very much. 51 void Uart_Printf(char *fmt,...) 52 { 53 va_list ap; 54 char str[255]; 55 56 va_start(ap,fmt); 57 vsprintf(str,fmt,ap); 58 Uart_SendString(str); 59 va_end(ap); 60 }
main.c
1 #include "2440addr.h" 2 3 void watchdog_test(void) ; 4 extern void Uart_Printf(char *fmt,...); 5 extern void Uart_Init(int baud); 6 void ClearPending(int bit); 7 void ClearSubPending(int bit); 8 __irq void watchdog_isr(void); 9 10 /*-----------------------全局变量定义------------------------*/ 11 unsigned f_ucSencondNo; //看门运行计数器 12 13 void Delay(int x) 14 { 15 int k,j; 16 while(x--) 17 { 18 for (k=0;k<=100;k++) 19 for(j=0;j<=100;j++); 20 21 } 22 } 23 24 void init(void) 25 { 26 GPBCON = 0x1dd7fc; // GPB5,GPB6,GPB8,GPB10设置为输出 27 GPBDAT = ((1<<5)|(1<<6)|(1<<8)|(1<<10)); //使LED全灭 28 GPBDAT&=0xffe; //关闭蜂鸣器 29 GPBUP = 1; 30 31 32 GPECON &= ~((1<<25)|(1<<27)|(1<<26)); 33 GPECON |= (1<<24); 34 GPEUP &= ~(1<<12); 35 36 GPGCON &= ~(3<<4); 37 38 rWTCON &= ~(1<<2);//关闭中断 39 40 } 41 42 int control_on(void) 43 { 44 GPEDAT |= (1<<12); 45 GPBDAT &= ~(1<<8); 46 return 0; 47 } 48 49 50 51 int control_off(void) 52 { 53 GPEDAT &= ~(1<<12); 54 GPBDAT |= (1<<8); 55 return 0; 56 } 57 58 void count_start(void) 59 { 60 //看门狗时间间隔1.28微秒 61 rWTDAT=0xffff; 62 rWTCNT=0xffff; 63 rWTCON |= (1<<5); //打开WDT定时器 64 } 65 66 67 long count_stop(void) 68 { 69 long i=0; 70 rWTCON &= ~(1<<5); //关闭定时器,计时结束 71 i=0xffff-rWTCNT; 72 return i*259; 73 74 75 } 76 77 void Main(void) 78 { 79 Uart_Init(115200); 80 init(); 81 Uart_Printf("\nwatchdog test is beginning\n"); 82 watchdog_test(); 83 } 84 85 void watchdog_test(void) 86 { 87 long time,distance; 88 while(1) 89 { 90 time=0; 91 distance=0; 92 93 rWTCON=((prescaler_value<<8)|(clock_select<<3)); //设置预分频数和除数因数 94 95 control_on(); 96 Delay(2); 97 control_off(); 98 99 while(!(GPGDAT & (0x0004))); 100 count_start(); 101 while(GPGDAT & (0x0004)); 102 time=count_stop(); 103 distance=time/58;//得到厘米 104 105 Delay(50); 106 107 Uart_Printf("time is %d\n",time); 108 Uart_Printf("distance is %d\n",distance); 109 } 110 } 111