On Thu, 28 Aug 1997 12:43:03 GMT Andrew Farrar writes: >Hello, > >I have a time critical application where each bit to be sent out >serially is to have duration of 69uS (.02/288 to be precise, but 69uS >will do). I have a routine for serial transmission, modified from >the embedded control applications book. However, I wish the time for >each bit to be the same duration. Is there a good way of doing this? There are a few good ways to do this. Using a timer interrupt, with the PIC crystal 14.7456 MHz (a standard value) and no prescaler, will give interrupts every 288 * 50 Hz = 14.4 KHz. For lower PIC clocks, the TMR0 could be reset during the ISR to speed up the time to the next interrupt. This will of course leave less time for the main program, if there is one. Once interrupts are occurring at the proper rate, the ISR would do all the work, sending out a bit (at a constant interval into the ISR) and preparing the next bit for next time. Here is a hastily written, not optimized, and possibly erroneous ISR to do that: isr movwf isrsavew ;Standard save of W and STATUS swapf STATUS,w movwf isrsaves bcf STATUS,RP0 ;Be sure in page 0 (may not be req'd) movlw b'00000000' ;Assume sending 0 btfsc mgsr,0 ;Yes, send 0 iorlw b'00000001' ;No, send 1. movwf PORTB ; (Modify constants above depending on the bit position of output pin ; in port B. If other B outputs are used, can store value in RAM ; and load instead of constant 0) rrf mgsr,f ;Move next bit into position decfsz mgbtcnt,f ;Out of bits? goto isrout ;No. OK to return. ;Here if need to fetch another byte of data from the table. movlw .8 movwf mgbtcnt ;Reset the bit counter. movlw .36 ;1 less than # of bytes in the table. decf mgbycnt,f ;index of next byte. btfsc mgbycnt,7 ;Did count roll under? movwf mgbycnt ;Yes, reset it. movfw mgbycnt ;Get index call magic ;Get another byte ; (The table is sent in reverse order, i.e. the last byte in the table ; is sent first. Bits within a byte are sent LSB first) movwf mgsr ;Store new byte in SR. isrout bcf INTCON,T0IF ;Reset flag for next time swapf isrsaves,w ;Standard recall of W and S movwf STATUS swapf isrsavew,f swapf isrsavew,w retfie The main program needs to: Set OPTION for TMR0 to run in timer mode with no prescaler. Set the PORTB tri-state register so bit 0 is an output. Set PCLATH to the 256-byte 'page' in which the "magic" table must reside completely. The program can't change PCLATH unless provision is added in the ISR to save and restore it. Initialize RAM locations mgbycnt to 0 and mgbtcnt to 1. The program will crash if mgbycnt is not in range of the table. However, it will count out of an invalid mgbtcnt. Set INTCON to enable TMR0 interrupts and global interrupts. Once this is done the bits will be shifted out constantly without further action by the program. >Also when fetching another data byte to be sent and then converting >serially, although I expect some padding can be done when sending >bits to allow for the overhead involved in fetching the next byte. > The ISR gets around this by sending a bit first, then working (for a variable time) on the one for next time. If using a software loop to time the sending, it would need to be compensated so all possible situations take the same time. This is not too hard since there are really only 2 situations: a new byte must be fetched from the table, or bits remain in the shift register. [most code removed except this troublesome part] > BTFSC STATUS,C > BSF TX_0 ;TRANSMIT A ONE > BTFSS STATUS,C > BCF TX_0 ;TRANSMIT A ZERO > >The program is by no means complete but any help or suggestions, on >the problem of a '1' having duration of 10uS and a '0' of 6uS would >be appreciated, please correct me if these figures are wrong! This is how it will work, because the method of skipping the bsf/bcf instructions makes (possibly) setting the pin high occur earlier than (possibly) clearing it low. So the last one in a sequence of ones is extended by 2 instruction cycles and the last zero is similarly shortened. My approach is to prepare a new port value in W and always write it to the port in the same phase of the sending process. The changes in level therefore always occur at the same time regardless of the value of the data.