用看门狗定时器做计时器,计算程序耗时,超声波测距,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   
原文地址:https://www.cnblogs.com/wuqi1003/p/2745744.html