PDA

View Full Version : While Loops Slow??



Frozen001
- 29th October 2008, 12:29
I am using a PIC 18F8722 micro to interface an older piece of equipment.

Here is the code I am using to test the proper read of some data:


while Counter1 <200
If PortA = $0B then
Toggle PortB.0
endif

If PortA = $0C then
Toggle PortB.1
endif

If PortA = $0D then
Toggle PortB.2
endif

Counter1=Counter1+1

wend
The pic clock and the equipment clock are operating at different speeds, I think the pic is 2-4 times faster and not in sync with the equipment I am trying to interface to. The problem I have is that I cannot always read the data. I sometimes miss some of the correct conditions. Any thoughts?

skimask
- 29th October 2008, 12:55
Not a lot of information to go on here...clock speed, config fuse information, schematics, ya know, the basics?!?!!?!!!

sayzer
- 29th October 2008, 13:44
<font color="#000080"><b>WHILE </b></font>Counter1 &lt; <font color="#FF0000">200
</font><font color="#000080"><b>IF </b></font>PORTA = <font color="#FF0000">11 </font><font color="#000080"><b>THEN </b></font>PORTB.<font color="#FF0000">0 </font>= PORTB.<font color="#FF0000">0 </font>^<font color="#FF0000">1
</font><font color="#000080"><b>IF </b></font>PORTA = <font color="#FF0000">12 </font><font color="#000080"><b>THEN </b></font>PORTB.<font color="#FF0000">1 </font>= PORTB.<font color="#FF0000">1 </font>^<font color="#FF0000">1
</font><font color="#000080"><b>IF </b></font>PORTA = <font color="#FF0000">13 </font><font color="#000080"><b>THEN </b></font>PORTB.<font color="#FF0000">2 </font>= PORTB.<font color="#FF0000">2 </font>^<font color="#FF0000">1
</font>Counter1 = Counter1 + <font color="#FF0000">1
</font><font color="#000080"><b>WEND
</b></font>


I think that the issue is not with the pic being faster; but with the logic flow of this code.

IF PORTA does not change, it will continue to toggle the pin anyway.

You should save the initial value first, and then if the new value is different then toggle the pin.


----------------------

Frozen001
- 29th October 2008, 18:36
The pic is running at 20MHz.

PortA is connected to the old piece of equipment circa early 80's running 6800 microprocessor to drive an 18-segment display. I am working to replace the display with a newer dot matrix display. I pelieve the 6800 clock is 500KHZ, but could be wrong.

The signals on PortA are TTL level, and change with every clock cycle on the 6800.

The code shown was just test code to see if I can consistantly read the data, which it turns out I cannot.

skimask
- 29th October 2008, 18:59
The pic is running at 20MHz.

PortA is connected to the old piece of equipment circa early 80's running 6800 microprocessor to drive an 18-segment display. I am working to replace the display with a newer dot matrix display. I pelieve the 6800 clock is 500KHZ, but could be wrong.

The signals on PortA are TTL level, and change with every clock cycle on the 6800.

The code shown was just test code to see if I can consistantly read the data, which it turns out I cannot.

Are you sure the PIC is running 20Mhz? Could be running on the internal 'failure' clock.
Does a one-second blinky LED actually blink at one second intervals?

Also, check up on using the LAT register vs. the PORTx register...

How fast is it actually running thru the loop? 1x per second? 100x per second? 10000000000000000000000x per second?
Can you measure it?

mackrackit
- 29th October 2008, 19:00
Just a thought...

How much faster if any would it be to check one pine and not the whole port?

If faster then maybe use a shift register into one pin.

Probably no better.

Frozen001
- 31st October 2008, 13:18
Well I am still having problems, so I have been doing some testing.

Using this exact code:

CMCON = 7 ' Disables the Comparitor Pins
ADCON1 = 15 ' Disables the A/D Converter Pins
TRISF = $F0 ' Define Port F(0-3) as LED Outputs


Define OSC 20 ' Sets Oscillator Speed at 20Mhz
Define BUTTON_PAUSE 100 ' Sets Button Debounce time to 100 ms
Define I2C_SLOW 1 ' Sets I2C Speed to 100KHz



Main_Loop:
PortF.0 = 0
PortF.0 = 1
PortF.1 = 0
PortF.1 = 1
PortF.2 = 0
PortF.2 = 1
PortF.3 = 0
PortF.3 = 1
Goto Main_Loop

The Clock is dead on at 20MHz as measured on an oscilloscope.

Each pin takes about 200nS to go low then return high... Which seems on par with the 18F8722 data sheet stating that it take 4 clock cycles to exicute a command.

I actually measured the old device clock. It is running at 1MHz. Given that the fasted the 18F8722 can run each command, I basically can run 5 commands for each of the old devices clock cycles. Buy looking at my original code a few posts back it looks like I can do what I want to unless the compilier is creating bloated assembly code...

sayzer
- 31st October 2008, 15:52
May be you should try this:




IF PortA = $0B THEN TOGGLE PortB.0
WHILE PORTA = $0B : WEND


This way, your very fast PIC will wait for your very slow old equipment.

If you do not wait in "while" loop, then PIC will loop thousand times until your old equipment changes its state.

-----------------------

falingtrea
- 31st October 2008, 19:52
There is no way your original code could be 5 instructions or less per loop. Each line of code will create at least 1 instruction. You have 4 lines inside the while, so at least 4 instructions plus two for the while (test and branch) will be executed each loop. For every if statement that is true you will get at least 1 additional instruction if not more.

So now you need to look at the old equipment and determine how fast you really need to detect changes. Is the original equipment running on a 1 MHz clock or is the output signal yopu want to monitor changing at a 1 MHz rate? If the signal you are looking at is changing at a 1 MHz rate, you will need a faster solution to detect it.

falingtrea
- 31st October 2008, 20:10
You know, thinking on it more, maybe speed is not an issue. If you are using the PIC to replace a 7 segment display with a dot matrix display, and you are trying to translate 7 segment lines into characters so you can send characters to a dot matrix display, this is something the human eye is looking at and the 7 segment display may not really be changing at a 1 MHz rate. I bet the old design is multiplexing the 7 segment displays at a much lower rate than you think. What you may need to do is detect which 7 segment digit is active, read the data going to that display and then translate it into a character to send to the dot matrix display. Typically that is milliseconds, not nanoseconds that you are dealing with. Unless the 7 segment displays have 7 segment decoders that the processor is writing to. Then you have to capture data when it is clocked into the decoder register. In that case, you could sense the clock edge and then read the data bus.

falingtrea
- 2nd December 2008, 18:35
Hey Frozen001, any luck???

Frozen001
- 3rd December 2008, 14:53
Well I boiled it down to the fact that PICBasic makes bloated code when you finally get to the actual number of inctructions it takes to perform certain tasks. My WHILE loops take more instructions than REPEAT:UNTIL loops. I got it working with a lot of tweaking by trying different commands.

falingtrea
- 29th December 2008, 18:12
Well I boiled it down to the fact that PICBasic makes bloated code when you finally get to the actual number of inctructions it takes to perform certain tasks. My WHILE loops take more instructions than REPEAT:UNTIL loops. I got it working with a lot of tweaking by trying different commands.

That's pretty much true of any "high level language". To get the ease of programming, you take a hit on performance. Unless you pay the big bucks for a "optimizing" compiler. And even optimized code doesn't get quite the performance as hand coding in assembly.

Good to hear you got things to work otherwise.