Slow speed display using 74HC595

frank_p

Member
I'm building a an 8x8 matrix moving display.

I'm using 2 595 IC in the circuit one used for rows and the other for columns.

I only have a single pause of 300ms between each character displayed but the display is so slow i can see column by column display.

Any ideas please how i can handle this speed issue?

Can POV be achieved using 18X MC at 4Mhz?

My thoughts are that it is either impossible to achieve or else i have something extremely wrong in the code.

Any help greatly appreciated!!!!!!!
 

Dippy

Moderator
"My thoughts are that it is either impossible to achieve or else i have something extremely wrong in the code"

- why not post your code as it is probably the latter.

And post your schematic too.

BTW: There have been several POVs here. Search using "Persistence". Be persistent :)
 
Last edited:

frank_p

Member
There you go:

' target PICAXE - 18X
SYMBOL mem = b1
SYMBOL char = b2
SYMBOL pos = b3
SYMBOL col = b5
SYMBOL temp = b6
SYMBOL n2 = b13
SYMBOL tempbyte = b12
SYMBOL outByte = b11

' output pins
SYMBOL row_clock = 0
SYMBOL row_data = 1
SYMBOL row_latch = 2

SYMBOL col_clock = 7
SYMBOL col_data = 6
SYMBOL col_latch = 5


eeprom 0,("AB")
low row_latch
low row_clock
low row_data
low col_latch
low col_clock
low col_data


main:
for mem = 0 to 3
read mem, char
outByte = 0
if char = 0 then goto next_byte

' get index of character
lookdown char,("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","1","2","3","4","5","6","7","8","9","0"),pos

' multiply by 5 to retrieve first index in 5*7 grid
pos = pos * 5

for col = 1 to 8
outByte = 0
' 8x8 matrix and chars = 7x5 matrix
if col = 1 or col = 2 or col = 8 then goto skip

' get first value for index
if pos < 105 then
lookup pos,($1F,$24,$44,$24,$1F,$7F,$49,$49,$49,$36,$3E,$41,$41,$41,$22,$7F,$41,$41,$41,$3E,$7F,$49,$49,$41,$41,$7F,$48,$48,$40,$40,$3E,$41,$49,$49,$2E,$7F,$08,$08,$08,$7F,$00,$41,$7F,$41,$00,$02,$01,$41,$7E,$40,$7F,$08,$14,$22,$41,$7F,$01,$01,$01,$01,$7F,$20,$10,$20,$7F,$7F,$10,$08,$04,$7F,$3E,$41,$41,$41,$3E,$7F,$48,$48,$48,$30,$3E,$41,$45,$42,$3D,$7F,$48,$4C,$4A,$31,$32,$49,$49,$49,$26,$40,$40,$7F,$40,$40,$7E,$01,$01,$01,$7E),outByte
else
temp = pos - 105
lookup temp,($7C,$02,$01,$02,$7C,$7F,$02,$04,$02,$7F,$63,$14,$08,$14,$63,$60,$10,$0F,$10,$60,$43,$45,$49,$51,$61,$00,$21,$7F,$01,$00,$21,$43,$45,$49,$31,$41,$41,$49,$49,$36,$0C,$14,$24,$7F,$04,$71,$49,$49,$49,$46,$3E,$45,$49,$49,$26,$40,$40,$40,$40,$7F,$36,$49,$49,$49,$36,$30,$48,$48,$48,$3F,$3E,$51,$7F,$45,$3E,$00,$08,$08,$08,$00,$00,$7F,$41,$00,$00,$00,$00,$41,$7F,$00,$00,$08,$1C,$08,$00,$62,$64,$08,$13,$23),outByte
end if

pos = pos + 1 ' move pos to next char
skip: ' skip to next column
gosub row595
select col
case 1
outByte = $7F
case 2
outByte = $BF
case 3
outByte = $DF
case 4
outByte = $EF
case 5
outByte = $F7
case 6
outByte = $FB
case 7
outByte = $FD
case 8
outByte = $FE
endselect
gosub col595
next col
next_byte:
pause 300
next mem
goto main



row595:
tempbyte = outByte
for n2 = 1 to 8
if tempbyte >= 128 then ' most sig bit (neg temp)
high row_data
else
low row_data
endif
pulsout row_clock,1 ' clock pulse
tempbyte = tempbyte * 2 ' next bit in most sig bit position
next n2
pulsout row_latch,1 ' transfer shift register to latch
return


col595:
tempbyte = outByte
for n2 = 1 to 8
if tempbyte >= 128 then ' most sig bit (neg temp)
high col_data
else
low col_data
endif
pulsout col_clock,1 ' clock pulse
tempbyte = tempbyte * 2 ' next bit in most sig bit position
next n2
pulsout col_latch,1 ' transfer shift register to latch
return
 

hippy

Ex-Staff (retired)
A 300mS pause for each column is a third of a second, so it will take near three seconds to do all eight columns. In addition to that 300mS there's the time it takes to determine what to put up on the next column before you switch to that.

You need to reduce your pause and may even be able to take it out. Your LED's will become dimmer but that can be compensated for by reducing the current limiting resistors.

You're also using LookUp, LookDown and Case and all these are slow to execute. Ideally you want to store your data in Data Eeprom or external I2C Eeprom so you can read it quickly based on just a simply calculated index.

On top of that you are bit-banging out two sets of 595 serial streams. For each update you have to send 16 bits ( eight for the row, eight for the column ), eight rows means 128 bits. To get a flicker-free display you need to update in around 20mS, so that gives just 156uS per bit. That's the time of just one PICAXE command at 4MHz and you're doing a lot more than that.

What you really need to be doing is updating your row and column drivers 'in parallel', that is having 16 output lines, but the 18X doesn't have that many. A 28X1 does, and SPI hardware could be used to do fast updates of the 595's, but it will still take some time to refresh the display, even running at 20MHz. Updating a whole column at a time would still mean 2.5mS per column, but that's more feasible, allowing perhaps 50 PICAXE commands between each update at 20Mhz.

Dedicated multiplexing chips run at very high speeds to ensure flicker free displays and the PICAXE is really just too slow to match their performance. The bottom line is that this type of project isn't suited to the PICAXE, and certainly not without a lot of highly optimised design.
 

frank_p

Member
Thought i can do it with Picaxe like other people were saying in other threads on this forum.

anyway i'm restructuring the code to make it run faster as much as possible.

I'm rather new to picaxe so i haven't discovered how to use the 18X at 8Mhz because probably i can do it at that speed.

BTW. the 300mS is for each character not each column!!
 
Last edited:

hippy

Ex-Staff (retired)
Go for it

Thought i can do it with Picaxe like other people were saying in other threads on this forum.
Never believe anyone who says it can or cannot be done ( and that includes me - I'm always pleased to be proven wrong ) unless they've actually got some proof it can or solid evidence that it cannot.

Even if it doesn't work you'll learn an awful lot along the way.

BTW. the 300mS is for each character not each column!!
My mis-reading of the code there :)
 

BCJKiwi

Senior Member
Tests carried out on speed for a different application showed that lookup/down were very slow once the number of elements got over 5 to 10.

The fastest routine found was to place all the values in consecutive eeprom addresses, then simply read the required data directly from the eeprom address based on the value;

i.e.
Code:
eeprom 1 = $1F
eeprom 2 = $24
eeprom 3 = $44
eeprom 4 = $24
.
.
.
if pos < 105 then
read pos,outbyte
where pos represents the eeprom address - do some math on pos to match it to the eeprom address
e.g. if the starting address of the range is 1, and the lowest pos value is say 10, then pos = pos-9 to offset the pos value range starting point to match the eeprom address range starting point.

This example is from a working program which writes to an mcp23017 i/o expander (2 x 8 bit banks) to turn on LEDs
Code:
eeprom 206,(%11111110)    '0
eeprom 207,(%11111101)    '1
eeprom 208,(%11111011)    '2
eeprom 209,(%11110111)    '3
eeprom 210,(%11101111)    '4
eeprom 211,(%11011111)    '5
eeprom 212,(%10111111)    '6
eeprom 213,(%01111111)    '7
.
.
.
' b0 holds current dynamic value
  b1=b0+206      ' bit patterns start at eeprom 206
  read b1,b4      'read stored bit pattern
 hi2cout [IO_0],$12,(b4)
The program has over 150 values stored in eeprom and half are used in this manner.
The 18X has 256 eeprom addresses available.

Trust this may help
 

frank_p

Member
I restructured the code significantly but the display is still slow???? Below is the new code. Any other ideas?? I'm a professional programmer but i'm new to picaxe and i'm trying out this because it is fairly easy to program using them and something new is always challenging.

' target PICAXE - 18X
SYMBOL mem = b1
SYMBOL char = b2
SYMBOL pos = b3
SYMBOL col = b5
SYMBOL temp = b6
SYMBOL n2 = b13 ' first gosub level scratch variable
SYMBOL tempbyte = b12
SYMBOL outByte = b11
SYMBOL outCol = b10

' output pins
SYMBOL row_clock = 0
SYMBOL row_data = 1
SYMBOL row_latch = 2

SYMBOL col_clock = 7
SYMBOL col_data = 6
SYMBOL col_latch = 5


eeprom 0,($1F,$24,$44,$24,$1F,$7F,$49,$49,$49,$36,$3E,$41,$41,$41,$22,$7F,$41,$41,$41,$3E)
eeprom 20,($7F,$49,$49,$41,$41,$7F,$48,$48,$40,$40,$3E,$41,$49,$49,$2E,$7F,$08,$08,$08,$7F)
eeprom 40,($00,$41,$7F,$41,$00,$02,$01,$41,$7E,$40,$7F,$08,$14,$22,$41,$7F,$01,$01,$01,$01)
eeprom 60,($7F,$20,$10,$20,$7F,$7F,$10,$08,$04,$7F,$3E,$41,$41,$41,$3E,$7F,$48,$48,$48,$30)
eeprom 80,($3E,$41,$45,$42,$3D,$7F,$48,$4C,$4A,$31,$32,$49,$49,$49,$26,$40,$40,$7F,$40,$40)
eeprom 100,($7E,$01,$01,$01,$7E,$7C,$02,$01,$02,$7C,$7F,$02,$04,$02,$7F,$63,$14,$08,$14,$63)
eeprom 120,($60,$10,$0F,$10,$60,$43,$45,$49,$51,$61,$00,$21,$7F,$01,$00,$21,$43,$45,$49,$31)
eeprom 140,($41,$41,$49,$49,$36,$0C,$14,$24,$7F,$04,$71,$49,$49,$49,$46,$3E,$45,$49,$49,$26)
eeprom 160,($40,$40,$40,$40,$7F,$36,$49,$49,$49,$36,$30,$48,$48,$48,$3F,$3E,$51,$7F,$45,$3E)
eeprom 180,($00,$08,$08,$08,$00,$00,$7F,$41,$00,$00,$00,$00,$41,$7F,$00,$00,$08,$1C,$08,$00)
eeprom 200,($62,$64,$08,$13,$23)
eeprom 248,($7F,$BF,$DF,$EF,$F7,$FB,$FD,$FE)

low row_latch
low row_clock
low row_data
low col_latch
low col_clock
low col_data

char = 65
main:

if char >= 65 and char <= 90 then
pos = char-65 * 5
end if

for col = 1 to 8
outByte = 0
' 8x8 matrix and chars = 7x5 matrix
if col = 1 or col = 2 or col = 8 then goto skip
read pos,outByte
pos = pos + 1 ' move pos to next char
skip:
mem = col+247
read mem,outCol
gosub HC595
next col

goto main

HC595:

tempbyte = outByte
temp = outCol

for n2 = 1 to 8
if tempbyte >= 128 then
high row_data
else
low row_data
endif
pulsout row_clock,1
tempbyte = tempbyte * 2 ' next bit in most sig bit position
next n2


for n2 = 1 to 8
if temp >= 128 then
high col_data
else
low col_data
endif
pulsout col_clock,1
temp = temp * 2
next n2

pulsout row_latch,1
pulsout col_latch,1

return
 

BCJKiwi

Senior Member
I'm not familiar with the 595 so can't really offer any other suggestions.

For next loops can be slower than repeated code so where you are doing a loop from 1 to 8, you could try the code repeated 8 times. It takes more program space but if you have the room, it should be quicker.
But this does depend on what is happening inside the loop - yours seem to be quite busy so you may not see much advantage.

Would suggest you test the code to see where it's busy (slow).

Pick out one small logical block of code at a time and place it in a for next loop of say 1000 or 10000 cycles and time it. Then test the next section.

It shouldn't take long to find where the bottleneck is. If it's in the 595's then there won't much you can do about it. If its elsewhere then you can focus on alternatives to the slow code.

This was how I found lookup was so much slower than reading eeprom.
 

frank_p

Member
I am doing changes again to remove a whole loop, the one for the column which will also include the removal of 1 595 and change it to a Johnson counter which i will reset after 8 clocks instead of 10. Hope this will help but now i need NPN transistors and don't know yet which type i'm going to use.

The 595 runs at 59Mhz while the Johnson (4017) runs at 10Mhz. I hope this will not be the new bottleneck.

Is there anyone on this forum who has done this before?? I've seen some discussions but don't really know if anyone ever tried it or not. I hope it was not just a discussion.
 

hippy

Ex-Staff (retired)
Use of a Johnson counter is a good idea. You may be able to avoid the need for transistors if you wire the LED's+R's between that and the 595 outputs, making the 595 outputs active low in software. If you can find a Johnson counter which has active low outputs that would also work but you may need to swap rows / columns or rotate the LED's 90 degree.

Another trick with the 18X is to use the on-chip SPI hardware to give a very fast update of the 595. This isn't documented nor are there any PICAXE commands to do that, it means poking around with on-chip registers (SFR).
 

frank_p

Member
Good idea Hippy about the SPI. But i'm new to Picaxe so i might need some more time.

I'm still stuck what transistor i'm going to use to connect the output of the 4017 to switch the GND on for every pulse of the counter. I currently only have 2N3904 but these are not good, so the change i've did i don't know yet if it works.
 

frank_p

Member
I modified the circuit to use the 4017 for columns and the 595 for rows. The problem is that now nearly all matrix lights up at the same time. I also swapped the bytes in the HC595 from high to low so the 595 will act as ground and the column as +ve. Any ideas what the problem might be. The code i have is below. This should display letter 'A'.
**********************************************************
' output pins
SYMBOL row_clock = 0 '74HC595 pin 11
SYMBOL row_data = 1 '74HC595 pin 14
SYMBOL row_latch = 2 '74HC595 pin 12
SYMBOL col_clock = 4 'HCF4017 pin 14
SYMBOL col_reset = 5 'HCF4017 pin 15

char = 65 ' now A = $60,$5B,$3B,$5B,$60
main:

if char >= 65 and char <= 90 then
pos = char-65 * 5
end if
pulsout col_reset,1 'reset 4017 to clear counter
for col = 1 to 8
outByte = 0
' 8x8 matrix and chars = 7x5 matrix
if col = 1 or col = 2 or col = 8 then goto skip
read pos,outByte
pos = pos + 1 ' move pos to next char
skip: gosub HC595
next col
goto main

HC595:
tempbyte = outByte
for n2 = 1 to 8
if tempbyte >= 128 then
high row_data
else
low row_data
endif
pulsout row_clock,1
tempbyte = tempbyte * 2 ' next bit in most sig bit position
next n2
high row_latch
pulsout col_clock,1
low row_latch
return
 

moxhamj

New Member
Neat chip, Rickharris.

I don't think you will get POV with a picaxe. I couldn't even get two 7seg displays to multiplex fast enough. Real POV needs raw machine code which for a 4Mhz chip is at least 4000 times faster than a picaxe.

There might be a solution using the old 8k SDRAM chips and a picaxe - feed in all your pictures slowly then read them out at Mhz speeds. Having learnt machine code in the past, this RAM circuit might actually be simpler.

All the leds are lighting up at once? Do you have blocking diodes, and could you post a schematic?

If the update speed is very slow (eg every few seconds) you could have rows and rows of HC595s driving individual leds. Or HC373s and a common 8 bit data bus.

Can you tell us more about the application - there might be other cunning solutions.
 

hippy

Ex-Staff (retired)
I got POV working fairly well with an 08M but that was just a single row of LED's and a long sequence of "pins=$xx" commands for a strip-board 'wand' which I swiped across my eyes, a primitive 'propeller clock'.

@ Frank : Although contrary to what you finally want to have, adding delays to slow things down so you can see what's happening onthe LED's at each step is one way to check everything is working.

Trim the code right back to something which puts out exactly what it should put out, only then add in the extra code which gets what should be put out from lookup tables etc. Otherwise it becomes hard to determine where any bugs may be, in the LED outputting routines or in the 'pixel' fetching routines.

Get all possible LED combinations working on a single row or column first, then working on all rows and columns simulateneously. Build up you code increementally. SERTXD is very useful for reporting back to the PC what's in each variable as running, for example a welll placed SERTXD(#bit7,#bit6..#bit1,#bit0,CR,LF) can be used to display pixels held in b0, so if you see ...

00111100
01100110
11000011
11000011
11111111
11111111
11000011
11000011

You know you should be seeing an "A" etc
 

frank_p

Member
I'm sorry but i don't have a software to design the circuit. From your responses it looks impossible to do it with a Picaxe!! So it was just a waste of 3 days trying. I'll go the hard way i think and write it in assembly on a normal PIC.

I still believe i'm very near of making it work but i have a deadline by Wednesday so i'll write it on a PIC to resolve the issue. I might follow up later if i have the time and tell you if i managed. I think the only problem is the current sinking issue which should be resolved if i had an appropriate transistor to do it. I have to just find the correct type and buy them. The 595 signals the gate and drives the row to ground and the 4017 will provide the positive column.
 

moxhamj

New Member
The transistor is any small signal one like a BC547. But you need the right resistor on the base and the right current sinking resistors for the leds. You don't have to draw the best circuit diagram in autocad - just draw it on a piece of paper with a marker pen and take a digital photo and post it here. There will be something simple that isn't right and we can certainly all help with that. It actually will help to get it working slowly on a picaxe, then you can port it to a pic and run it faster.
 

frank_p

Member
This is a rough schematic. I didn't include the other connections for the Picaxe.

Hope that this picture is clear enough.

Any suggestions are welcome.

frank_p
 

Attachments

moxhamj

New Member
This might work. The led current is limited to 3mA or so by the 1k resistors and if 8 leds are on in one column the total will be 24mA which is well under the BC547's limit of 100mA.

I'm pretty sure that diodes are not needed in series with the leds as the led can handle reverse voltages if they are current limited. There seems to be differing opinions out there in the data sheets though. If not sure, perhaps put 914 diodes in series with each of the leds.
 

Attachments

Last edited:

frank_p

Member
Thanks for your suggestion Dr.Acula....
So the column will be pulled down using the BC547 and the positive is supplied via the 595.
I'll try this is a couple of days since i'll be going home to europe tonight and i don't have those transistors available here.
Anyway i'll keep you posted.
 

moxhamj

New Member
Any NPN transistor will do. BC547. BC337. 2N2222. It doesn't really matter. Your 2N3904's should work fine. Just watch the pinouts as they are different. Looking at the front of a BC547 they go CBE. A 2N3904 goes EBC. Maybe that is why they are not working as expected?
 
Last edited:

frank_p

Member
Dr.Acula thanks for the suggestions. I did the change to the circuit and it works perfect. The problem is still a question of speed. I crunched the code as much as possible but the row scan is still quite visible.

I'm not sure now if it is possible to make it faster.

I also wrote the same code in assembly and burnt the firmware into a 16F628A also running @ 4Mhz, using exactly the same circuit, it works perfect.

Any opinion about other improvements i can make? The idea is that in assembler it takes much longer to write code and test it. If this can work on a picaxe with a dozen lines this would be perfect both in terms of development speed and also in terms of explaining the code to the layman who is not much familiar with assembly coding.

If you want i can also provide the code i'm currently using to have a look at it yourself.

frank_p
 

hippy

Ex-Staff (retired)
That's the PICAXE versus Assembler trade-off; easier to code but slower to run versus harder to write but runs much quicker. PICAXE usually has the advantage of debugging and ease of program downloading.

The main thing is determining where the lack of speed is and optimising that as best one can. If it's a loop for bit-banging out the 595 settings it may be possible to un-roll the loop and make it a linear sequence of instructions. Using on-chip SPI hardware and fiddling with SFR's will be even faster but more complicated to develop.
 

inglewoodpete

Senior Member
I have used the ShiftOut command to great advantage with 74xx595s and 74xx164s. My guess is that it runs up to 3 times the speed of discrete code. The catch is that the command is only available in the X1 (and, one day, X2) parts
 

BCJKiwi

Senior Member
Manual2 reports ShiftOut and ShiftIn available on all PICAXEs.
Hardware version of command only available on 28/40X1/2.

IPete, are you using hardware version or basic version?
 

hippy

Ex-Staff (retired)
I find the manual very poorly presented regarding support for the ShiftIn and ShiftOut command. It gives the impression that there is some sort of support for those commands on non X1/X2 parts when there isn't. What is available are subroutines which can implement the functionality.

I've been caught out by this - One looks for the command then looks to see what PICAXE vraiants are listed in the pinout icons in the left margin. It's easy to read that as "this command is implemented" ( as is the case elsewhere ) but it doesn't mean that in these particular casea.
 

demonicpicaxeguy

Senior Member
to get the hardware spi side of the 18x going have a look around page 91 in the pic16f88 datasheet it explains a fairly good detail what to set to what and using the poke command it shouldn't take that much code

i'm not sure how the interpreter will react and wether the picaxe is fast enough for it are the only problems.
 

jodicalhon

New Member
The original code seems to shift out the column and row signals using a for/next loop, and multiplication by 2 to shift up the next bit to be output.

(Err...at least I think so, I ain't no expert...) :)

I came across a post by a Michael Walsh over at the Yahoo Picaxe group some time ago that may help speed up the output.



By making the byte to be output (tempbyte) b0 or b1, you can access the individual bits (bit0 to bit7) or (bit8 to bit15) directly. You can then unroll the loop and send it out like this:


row_data=bit7
pulsout row_clock,1
row_data=bit6
pulsout row_clock,1
row_data=bit5
pulsout row_clock,1
row_data=bit4
pulsout row_clock,1
....etc....
row_data=bit0
pulsout row_clock,1

Does that help at all, or have I lost the plot?
 
Last edited:

BCJKiwi

Senior Member
Thanks IPete,
Have you any code samples you might share? I've had trouble with hspi on the VDrive2 and not seen any hspi working code snippets reported to date (could easily have missed them though!).

Thanks
 

hippy

Ex-Staff (retired)
to get the hardware spi side of the 18x going have a look around page 91 in the pic16f88 datasheet it explains a fairly good detail what to set to what and using the poke command it shouldn't take that much code

i'm not sure how the interpreter will react and wether the picaxe is fast enough for it are the only problems.
I did that and it works. Somewhere on the forum there should be some documentation on what I achieved ( I'll try and find it ). It effectively creates a high-speed SPI out as available on the X1/X2 but doesn't provide a simple command to do it. It's not however that hard to do.

This will give very high-speed SPI, up to 1MHz clocking probably, certainly quick. The entire SPI bit-banging loop can be condensed to what is, if I remember right, a single Poke command. It could show something like a 100-fold speed-up.
 

hippy

Ex-Staff (retired)
Here's the code to do high-speed SPI on the 18X ...


Code:
; *****************************************************************************
; *                                                                           *
; *     High-Speed 8-Bit SPI Output for the PICAXE-18X                        *
; *                                                                           *
; *****************************************************************************

;        PICAXE-18X                          7   6   5   4   3   2   1   0
;       .----------.                         _   _   _   _   _   _   _   _
;       |       O4 |-10---> SCK     ________| |_| |_| |_| |_| |_| |_| |_| |__
;       |          |                  _
;       |       O3 |-9----> SYN     _| |_____________________________________
;       |          |                        __      _______     __________
;       |       O2 |-8----> SDO     _______|  |____|       |___|          |__
;       `----------'
;
;                           Note that SYN is generated for scope sync only and
;                           is not produced by the on-chip SSP hardware itself

;       SFR Addresses

        SYMBOL  PIR1            = $0C
        SYMBOL  SSPBUF          = $13
        SYMBOL  SSPCON          = $14
        SYMBOL  SSPSTAT         = $94

;       PIR1

        SYMBOL  ADIF_BIT        = bit6
        SYMBOL  RCIF_BIT        = bit5
        SYMBOL  TXIF_BIT        = bit4
        SYMBOL  SSPIF_BIT       = bit3
        SYMBOL  CCP1IF_BIT      = bit2
        SYMBOL  TMR2IF_BIT      = bit1
        SYMBOL  TMR1IF_BIT      = bit0

;       SSPCON

        SYMBOL  WCOL_BIT        = bit7
        SYMBOL  SSPOV_BIT       = bit6
        SYMBOL  SSPEN_BIT       = bit5
        SYMBOL  CKP_BIT         = bit4
        SYMBOL  SSPM3_BIT       = bit3
        SYMBOL  SSPM2_BIT       = bit2
        SYMBOL  SSPM1_BIT       = bit1
        SYMBOL  SSPM0_BIT       = bit0

;       SSPSTAT

        SYMBOL  SMP_BIT         = bit7
        SYMBOL  CKE_BIT         = bit6
        SYMBOL  D_BIT           = bit5
        SYMBOL  I2C_DATA_BIT    = bit5
        SYMBOL  I2C_STOP_BIT    = bit4
        SYMBOL  I2C_START_BIT   = bit3
        SYMBOL  I2C_READ_BIT    = bit2
        SYMBOL  NOT_WRITE_BIT   = bit2
        SYMBOL  READ_WRITE_BIT  = bit2
        SYMBOL  UA_BIT          = bit1
        SYMBOL  BF_BIT          = bit0

; *****************************************************************************
; *                                                                           *
; *     Clock Modes                                                           *
; *                                                                           *
; *****************************************************************************

;       CKP  CKE
;                              _   _   _   _   _   _   _   _
;        0    0     SCK     __| |_| |_| |_| |_| |_| |_| |_| |___
;                             : _   _   _   _   _   _   _   _
;        0    1     SCK     ___| |_| |_| |_| |_| |_| |_| |_| |__
;                             :  :
;                             :__:     _______     __________
;                   SDO     __|  |____|       |___|          |__
;
;                              MSB                        LSB

; *****************************************************************************
; *                                                                           *
; *     Main Program Loop                                                     *
; *                                                                           *
; *****************************************************************************

        WCOL_BIT        = 0             ; Clear Write Collision
        SSPOV_BIT       = 0             ; Clear Receive Overflow
        SSPEN_BIT       = 1             ; Enable SSP
        CKP_BIT         = 0             ; Idle = 0
        SSPM3_BIT       = 0             ; Set SPI Master Mode, Clock Rate ...
        SSPM2_BIT       = 0             ; ... O/4  O/8  O/64  TMR2/2
        SSPM1_BIT       = 1             ;      0    0    1      1
        SSPM0_BIT       = 0             ;      0    1    0      1

        POKE SSPCON,b0

        CKE_BIT         = 1             ; Clock on active to idle transition

        POKE SSPSTAT,b0

        DO
          PULSOUT 3,1                   ; Scope sync pulse
          POKE SSPBUF,%10110111         ; Send %10110111
          DO                            ; Wait for SPI Sent Interrupt
            PEEK PIR1,b0
          LOOP UNTIL SSPIF_BIT = 1
          SSPIF_BIT = 0                 ; Clear Interrupt flag
          POKE PIR1,b0
          PAUSE 1                       ; Short delay for scope sync
        LOOP

; *****************************************************************************
; *                                                                           *
; *     End of Program                                                        *
; *                                                                           *
; *****************************************************************************
 

frank_p

Member
Thanks for the great ideas you are presenting in this forum. I never expected this discussion to evolve so much about the issue i had.

Unfortunately i had to travel to Europe so i cannot really test the new ideas you have provided but i will, as soon as i get back to Asia after Easter holidays.

The shiftout looks to be a plausible solution as much as the bit reference although i have to first try out the different options available. Unfortunately the 18X IC does not support bit shifting so multiplication was the other option that came to mind, though on any MCU multiplication is much slower than bit shifting.

I was using the AXE090 programmer test board with the USB to Serial cable, but if anyone can tell me how i can wire the picaxe on a breadboard without the programmer i can still try it here even before i go back. A reference to some page how to do this would be enough and i can get back with the results very soon.

Thanks again.

frank_p
 

sjremington

New Member
Being new to Picaxe but an old hand at PICs, I was puzzled as to why Hippy's elegant SPI code example should work. Careful reading of the 16F88 data sheet suggests that it will, but I haven't tried it.

The point is that b0 is used for pokes to two different control registers in the hardware, SSPCON and SSPSTAT and the bits in these registers have completely different meanings. Prior to the first poke, all bits in b0 are clearly defined. Prior to the second POKE, only CKE_BIT is modified. This should work because most of the bits in SSPSTAT are don't care or read only for SPI mode. However, WCOL_BIT (0) becomes SMP (0) which means sample at the middle of the interval.

When presenting examples to the less wary, I believe it is useful to acknowledge such subtleties in a comment, or to set up all bits in each register explicitly (e.g. b0=something, then poke).

Cheers, Jim



WCOL_BIT = 0 ; Clear Write Collision
SSPOV_BIT = 0 ; Clear Receive Overflow
SSPEN_BIT = 1 ; Enable SSP
CKP_BIT = 0 ; Idle = 0
SSPM3_BIT = 0 ; Set SPI Master Mode, Clock Rate ...
SSPM2_BIT = 0 ; ... O/4 O/8 O/64 TMR2/2
SSPM1_BIT = 1 ; 0 0 1 1
SSPM0_BIT = 0 ; 0 1 0 1

POKE SSPCON,b0

CKE_BIT = 1 ; Clock on active to idle transition

POKE SSPSTAT,b0
 

hippy

Ex-Staff (retired)
@ Jim : Well spotted. The "SMP_BIT" would normally be set or cleared as desired prior to a Poke to SSPSTAT.

It took me a while to work out why it wasn't, and why I'd missed that out, always hard trying to recall what was in ones mind a year or so ago. The most logical reasoning I can apply retrospectively is that SMP only applies to input, and as this is output only code, it doesn't matter how SMP is set so I left it out entirely.

It's only "don't care" bits I usually leave out and would set all the necessary bits rather than use previous settings, although I'm sure some may at times slip through. I guess I categorised SMP as "don't care" for this case.

Code should be well documented, so point taken.
 

inglewoodpete

Senior Member
BCJK: There is no mystery to using the ShiftOut command on the 28X1 or 40X1. Here is my code, almost directly from Manual 2.

Code:
Symbol ClockPin     = 3
Symbol DataPin      = 5
Symbol StrobePin    = 7
Sumbol MSBFirst_L   = 1     ' (MSB first, idles low)
Symbol PulseLen     = 1     ' 10uS units
Symbol SerialData   = b24   ' byte to transmit


OutByte:	ShiftOut ClockPin, DataPin, MSBFirst_L, (SerialData)
		PulsOut StrobePin, PulseLen		'10uS Pulse
		Return
 

frank_p

Member
inglewoodpete: i tried to use your ShiftOut example but it gives me a syntax error.

I also assume i need to use MSBFirst_L but anyway i used it it always returned a syntax error.

Also used another suggestion to assign each individual bit to row_data but the assignment doesn't work because row_data is a pin assignment not a variable.

Any further ideas??? Why does the shiftout doesn't work on 18X??? I probably need to send each bit individually.

frank_p
 

hippy

Ex-Staff (retired)
@ frank_p : As per inglewoodpete's psting, that example code only works for the 28X1 and 40X1.

For those, delete the entire "Sumbol MSBFirst_L = 1" line, there's a typo and MSBFirst_L is now a pre-defined constant in the latest Programming Editor.
 
Top