Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

[PIC] Timer1 used as a 1.024ms delay me thinks... (code sample attached)

Status
Not open for further replies.
I'd like comments on this simple delay routine. Instead of loops I've used Timer1 with an 8MHz crystal and a 1:8 prescaler. It should increment the LSB every 4us and the TMR1H register every 1.024ms. My math could be off (and my thinking too :confused:) Comments?

Code:
TMRDLY   ;*** using TMR1 as a delay for LCD setup call with W
         ;*** 1.024ms per TMR1H, Delay in ms = 255 - (W * 1.024)
         bcf      STATUS, RP0                ;B0
         clrf     TMR1L                      ;B0 added as per eblc1388 suggestion.
         movwf    TMR1H                      ;B0 TMR1H = W (976us)
         bcf      PIR1, TMR1IF               ;B0 clear the interrupt flag
         btfss    PIR1, TMR1IF               ;B0 test TMR1IF for overflow
         goto     $-1                        ; wait for TMR1IF (overflow)
         return
 
Last edited:
I haven't checked your math and I assume you've intialized Timer1 first, but I've used this method before. It allows for accurate timing when you have an ISR running in the background.
 
Timer1 trips its flag when the whole 16-bit word overflows pass 0xFFFF, not just the high side byte TMR1H. You have to load TMR1L and TMR1H with the correct values which intales performing subtraction for the CALL, RETURN, loading TMR1L TMR1H and general code delays. When you finally find the correct values to plug into the timers, you will have to do it all over again if you want a delay other than this fixed time. To load them with any value other than 1 to indicate 1 millisecond goes against logic.

TMR1H= 1, TMR1L= 2 : so the delay = 257 milliseconds is logical.

TMR1H= 153, TMR1L= 231: so the delay = desired time not representative of the variables is illogical .

The LCD does not have to be precise down to a few microseconds. Using a general millisecond delay routine will work for this and all your other code. Now though the timer is used here, this is still a looping routine. Detecting if a register hits zero or if a flag bit gets set never the less is still a loop once you use Goto $ - 1. Using a timer as a true interrupt is what will qualify the delay as non looping.

Timers are too precious for grunt work like general delays.
 
Just add a "CLRF TMR1L" instruction before loading the W value into TMR1H and the code would be fine.
 
What PIC are you using? Unless you get lucky with the pre and postscaler settings on a timer that will allow for properly timed periodic interrupts without preloading the timer registers, you are pretty much stuck using a timer with a period register. For most PICs, Timer 2 is the one with that functionality. The dsPIC and PIC24 line have period registers on every timer.

Is Timer 2 available in your application or is it tied up with other resources?
 
Mike said:
I agree. Why bother with all the Timer 1 mess for a one-time delay?
Seemed pretty straight forward, no variables required, easy to solve the timing loop, irq friendly (if you want to do it that way). I call it four times to get the 4 bit mode setup.

Got a decent decfsz version? Here's the LCD init routine

Code:
LCD_INIT          ;send 0x03 three times to enter 4 bit mode
         bcf      STATUS, RP0                ;B0
         bsf      LCD_E                      ;B0 enable bit high
         movlw    0x03                       ;B0 send 03 to PORTA
         movwf    PORTA                      ;B0
         movlw    .240                       ; 15ms delay
         bcf      LCD_E                      ;B0 latch data to LCD PORTA
         call     TMRDLY
         bsf      LCD_E                      ;B0 enable bit high
         movlw    0x03                       ;B0 send 03 to PORTA
         movwf    PORTA                      ;B0 
         movlw    .254                       ; .5ms delay
         bcf      LCD_E                      ;B0 latch data to LCD PORTA
         call     TMRDLY                                
         bsf      LCD_E                      ;B0 enable bit high
         movlw    0x03                       ;B0 send 03 to PORTA
         movwf    PORTA                      ;B0 
         movlw    .250                       ; 5ms delay
         bcf      LCD_E                      ;B0 latch data to LCD PORTA
         call     TMRDLY
         bsf      LCD_E                      ;B0 enable bit high
         movlw    0x02                       ;B0 send 02 (4 bit mode set)
         movwf    PORTA                      ;B0 
         movlw    .254                       ; .5 ms delay
         bcf      LCD_E                      ;B0 latch data to LCD PORTA                                 
         call     TMRDLY
         return
 
Last edited:
You may use the delay code generator on the PICList.
1.024 ms = 2048 cycles @ 8 MHz, you'll need only two variables.
 
Yes, use the delay code generator on the PICList, its nice and easy, it's used in my tutorials. You might also consider looking at my tutorial LCD code, here's the initialisation section for that.

Code:
;Initialise LCD
LCD_Init	movlw	0x20			;Set 4 bit mode
		call	LCD_Cmd

		movlw	0x28			;Set display shift
		call	LCD_Cmd

		movlw	0x06			;Set display character mode
		call	LCD_Cmd

		movlw	0x0d			;Set display on/off and cursor command
		call	LCD_Cmd

		call	LCD_Clr			;clear display

		retlw	0x00
 
William At MyBlueRoom said:
I've tried several, the only reliable way I found to get into 4 bit mode was to send 0x03 three times (or four) as in this example.

That seems really strange?, and has no bearing with what the datasheets say to do?.

My routines work perfectly, and many users all round the world have used them.
 
Those routines reset the controller in software. If the electrical requirements are met, the inizialization is performed by the built-in reset circuitry.
 
eng1 said:
Those routines reset the controller in software. If the electrical requirements are met, the inizialization is performed by the built-in reset circuitry.
Which routines? Nigels or Mykes (3x 0x03)

I've shrunk mine down with a loop...
Code:
LCD_INIT          ;send 0x03 three times to enter 4 bit mode
      movlw    .220                        ; 15ms (255 - 15/0.512) delay (before LCD is ready)
      call     TMRDLY                      ; program will halt till TMR1 overflows
      movlw    0x03                        ;B0 W = 3
      movwf    count                       ;B0 count = 3
      movwf    PORTA                       ;B0 PORTA = 3 (RS = 0)
LCD_loop        
         bsf      LCD_E                      ;B0 enable bit high
         movlw    .245                       ; 5ms delay
         bcf      LCD_E                      ;B0 latch data to LCD PORTA
         call     TMRDLY
         decfsz   count
         goto     LCD_loop
         return
 
Last edited:
eng1 said:
The ones you've posted, with 3x 0x03.


To enter the 4-bit mode, you have to send 0x02.
It appears the 3x 0x3 gets the LCD setup. I usually send a 0x28 (4bit 2line) using a more generic byte to nibble routine (working on the BF code now) and no longer use the delay code.

Still LCD character modules are SLOW devices.
 
William At MyBlueRoom said:
It appears the 3x 0x3 gets the LCD setup.
It's called "Initialization by instructions" in the datasheet. You can always use these instructions to initialize the LCD, but they're not required if the power supply conditions are met.

William At MyBlueRoom said:
I usually send a 0x28 (4bit 2line)
This means 2-lines of 5x8 dots. Before this, the 4 bit mode must be set by sending 0x2 (that is read as an 8-bit command by the LCD, b00100000).
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top