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.

programming a byte on one pin

Status
Not open for further replies.

MrDEB

Well-Known Member
I have a CONST array written in Swordfish and am experimenting using TLC5916 as the constant sink but I need to input my data for the LED display in serial form. Is there a way to just use
PORTA.1 = %00000111 then go with portA.bits(x) = SDI or something similar??
am trying to use the timing diagram to get the TLC5916 to operate correctly.
If I can put the byte on one pin instead of 8 it would cut down on my pin usage.
 
Swordfish Basic has several commands to shift data out in a serial stream. Check the documentation.

There are a number of things you must consider but this is all simple programming:

1. Number of bits to shift

2. The order of the bits - MSB or LSB

3. Rising or falling edge detect


If you are going to any chance of making this work, you need to read and understand the Swordfish documentation AND appropriate tutorial material.
 
Researching the SPI

Am I correct in assuming that I can load all my bytes into the EEprom instead of directly into ports then access the EEprom for my LED data via SPI?
This would prevent having to use 8 pins vers 1 pin for the bytes then use the SPI?
NEW ground for me to be sure
 
Please read the documentation for the shift command in Swordfish.

You will need 4 pins:

1. Clock

2. Data

3. Latch (I think the data sheet specifies this as LE)

4. /OE (output enable)

Using the shift command, you'll specify a value representing which of the eight output bits you want on, where 0 = on and 1 = off. %00001111 would turn the first four outputs on, the second four outputs off.

After the shift command, you strobe LE from low to high and back to low to latch the data to the output bits.

/OE will be low to enable the output. You may be able to leave it continuously low, or you may take it high to shut off the outputs. Remember, the slash means it's active low.


Follow the format of the shift command in the Swordfish documentation. I don't have it here or I would explain it.

There is no need to store anything in EEPROM.
 
You have to include the shift module:

Include "shift.bas"

The command will be either

OUT (MSB_FIRST,data,8)

Or

OUT (LSB_FIRST,data,8)

Depending on the order you want the bits. It doesn't matter you just have to map the values to send correctly.

The value 8 is how many bits to shift.
 
I understand so I don't need the SPI.bas just the shift.bas
will give it a go
THANKS
been pondering this all morning, didn't get much sleep last night. My knee is really giving me problems. Them hydrocodone pills really zap the energy out of you.
THANKS again
 
I hope this is the right one?

written by Barker
Code:
{
****************************************************************
*  Name    : Shift Module                                      *
*  Author  : David John Barker                                 *
*  Notice  : Copyright (c) 2006 Mecanique                      *
*          : All Rights Reserved                               *
*  Date    : 04/02/2006                                        *
*  Version : 1.5                                               *
*  Notes   :                                                   *
*          :                                                   *
****************************************************************
}
module Shift

// import modules...
include "utils.bas"
include "system.bas"

// shiftin modes...
public const 
   MSB_PRE = $00,       // MSB first, sample before clock
   MSB_POST = $02,      // MSB first, sample after clock
   LSB_PRE = $01,       // LSB first, sample before clock
   LSB_POST = $03       // LSB first, sample after clock

// shiftout modes...
public const 
   LSB_FIRST = $00,     // LSB first
   MSB_FIRST = $01      // MSB first

// a pin structure...
structure TPin
   Address as word
   Pin as byte
   PinMask as byte
end structure  

// local working variables...
dim 
   FDataIn as TPin,
   FDataOut as TPin,
   FClock as TPin

// maximum shift size can be 8, 16 or 32 bits. Using a smaller
// maximum shift size will reduce code overhead. The default
// is 16 bits.
#if IsOption(SHIFT_MAX) and not (SHIFT_MAX in (8, 16, 32))
   #error SHIFT_MAX, "Invalid option. MAX must be 8, 16 or 32 bits."
#endif
#option SHIFT_MAX = 16
   
#if SHIFT_MAX = 8
type TType = byte
#elseif SHIFT_MAX = 16
type TType = word
#else
type TType = longword
#endif 

// delay speed of shift clock....
#if IsOption(SHIFT_CLOCK) and not (SHIFT_CLOCK in (1, 2))
   #error SHIFT_CLOCK, "Invalid option. CLOCK must be 1 or 2 (us)."
#endif
#option SHIFT_CLOCK = 1
{
****************************************************************************
* Name    : ToggleClock (PRIVATE)                                          *
* Purpose : Toggle the shift clock.                                        *
*         : The default minimum clock width will be 1us for frequencies    *
*         : above 4MHz. For 4Mhz and below, the minimum clock width will   *
*         : be 2us. Using the #define SHIFT_CLOCK = 2US option will force  *
*         : a minimum clock width of 2us for all frequencies. NOTE : These *
*         : figures assume a perfect clock. A plus or minus variation of   *
*         : the clock width will be observed for all real world clock      *
*         : frequencies that deviate from the theoretical ideal            *
****************************************************************************
}
inline sub ToggleClock()
   // toggle clock...
   INDF1 = INDF1 xor FClock.Pin 
   
   // force minimum 2us...  
   #if SHIFT_CLOCK = 2
   #if _clock >= 8 
   delayus(1)
   #endif
   #endif
   
   // burn 8... 
   #if _clock > 36
   asm-
   bra $ + 2
   bra $ + 2
   bra $ + 2
   bra $ + 2   
   end asm
   
   // burn 7...
   #elseif _clock > 32
   asm-
   bra $ + 2
   bra $ + 2
   bra $ + 2
   Nop
   end asm
   
   // burn 6...
   #elseif _clock > 28
   asm-
   bra $ + 2
   bra $ + 2
   bra $ + 2
   end asm
   
   // burn 5...
   #elseif _clock > 24
   asm-
   bra $ + 2
   bra $ + 2
   Nop
   end asm
   
   // burn 4...
   #elseif _clock > 20
   asm-
   bra $ + 2
   bra $ + 2
   end asm
   
   // burn 3...
   #elseif _clock > 16
   asm-
   bra $ + 2
   Nop
   end asm
   
   // burn 2...
   #elseif _clock > 12
   asm-
   bra $ + 2
   end asm
   
   // burn 1...
   #elseif _clock > 8
   asm-
   Nop
   end asm
   #endif
   
   // toggle clock...
   INDF1 = INDF1 xor FClock.Pin
end sub   
{
****************************************************************************
* Name    : MakeOutput(PRIVATE)                                            *
* Purpose : Make the data pin an output. Data out address points to latch  *
*         : so just offset by 9                                            *
****************************************************************************
}
inline sub MakeOutput()
   FSR1 = FDataOut.Address + 9
   INDF1 = INDF1 and FDataOut.PinMask
end sub   
{
****************************************************************************
* Name    : MakeInput (PRIVATE)                                            *
* Purpose : Make the data pin an input. Data in address points to port     *
*         : so offset by 18                                                *
****************************************************************************
}
inline sub MakeInput()
   FSR1 = FDataIn.Address + 18
   INDF1 = INDF1 or FDataIn.Pin
end sub 
{
****************************************************************************
* Name    : LoadDataInAndClockAddr (PRIVATE)                               *
* Purpose : Load the data and clock pin address into FSR(x)                *
****************************************************************************
}
inline sub LoadDataInAndClockAddr()
   FSR0 = FDataIn.Address
   FSR1 = FClock.Address
end sub   
{
****************************************************************************
* Name    : LoadDataOutAndClockAddr (PRIVATE)                              *
* Purpose : Load the data and clock pin address into FSR(x)                *
****************************************************************************
}
inline sub LoadDataOutAndClockAddr()
   FSR0 = FDataOut.Address
   FSR1 = FClock.Address
end sub   
{
****************************************************************************
* Name    : SetInput                                                       *
* Purpose : Sets the shift data in pin                                     *
****************************************************************************
}
public sub SetInput(byref pDataPin as bit)
   FDataIn.Address = addressof(pDataPin)     // point address to port
   FDataIn.Pin = bitof(pDataPin)
   FDataIn.PinMask = not FDataIn.Pin
end sub
{
****************************************************************************
* Name    : SetOutput                                                      *
* Purpose : Sets the shift data out clock pin.                             *
****************************************************************************
}
public sub SetOutput(byref pDataPin as bit)
   FDataOut.Address = addressof(pDataPin) + 9 // point address to latch
   FDataOut.Pin = bitof(pDataPin)
   FDataOut.PinMask = not FDataOut.Pin
end sub
{
****************************************************************************
* Name    : Set                                                            *
* Purpose : Sets the clock pins. An optional idle high determines if the   *
*         : clock pin idles high or low. The default is to idle low        *
*         : The clock address points to a port latch                       *
****************************************************************************
}
public sub SetClock(byref pClockPin as bit,pIdleHigh as boolean = false)
   FClock.Address = addressof(pClockPin) + 9
   FClock.Pin = bitof(pClockPin)
   FClock.PinMask = not FClock.Pin  
   
   // set clock idle mode...
   FSR1 = FClock.Address
   if pIdleHigh then
      INDF1 = INDF1 or FClock.Pin
   else
      INDF1 = INDF1 and FClock.PinMask   
   endif
   
   // make clock pin an output...
   inc(FSR1,9)
   INDF1 = INDF1 and FClock.PinMask
end sub
{
****************************************************************************
* Name    : Out                                                            *
* Purpose : Shift out a value by pShift bits. Date values can be up to 32  *
*         : bits in size. Mode can be either LSB_FIRST or MSB_FIRST        *
****************************************************************************
}
public sub Out(pMode as byte,pData as TType, pShift as byte)
   
   // set data pin to output and load
   // data and clock address...
   MakeOutput
   LoadDataOutAndClockAddr
   
   // MSB first...
   if pMode.0 = 1 then
      pData = Reverse(pData, pShift)
   endif
    
   // shift out...  
   while pShift > 0
      if pData.0 = 0 then
         INDF0 = INDF0 and FDataOut.PinMask
      else
         INDF0 = INDF0 or FDataOut.Pin
      endif      
      ToggleClock
      pData = pData >> 1
      dec(pShift)
   wend
   ClrWDT
end sub
{
****************************************************************************
* Name    : In                                                             *
* Purpose : Shift in a value by pShift bits. Date values can be up to 32   *
*         : bits in size. Mode can be MSB_PRE, MSB_POST, LSB_PRE or        *
*         : LSB_POST                                                       *
****************************************************************************
}
public function In(pMode as byte, pShift as byte) as TType
   dim Index as byte

   // set data pin to input and load
   // data and clock address...
   MakeInput
   LoadDataInAndClockAddr
   
   // shift in...
   Result = 0
   Index = pShift
   while Index > 0
      Result = Result << 1
      
      // sample before clock...
      if pMode.1 = 0 then
         if (INDF0 and FDataIn.Pin) = 0 then
            Result.0 = 0
         else
            Result.0 = 1
         endif      
         ToggleClock
      
      // sample after clock...
      else
         ToggleClock
         if (INDF0 and FDataIn.Pin) = 0 then
            Result.0 = 0
         else
            Result.0 = 1
         endif      
      endif   
      dec(Index)
   wend
   
   // LSB first...
   if pMode.0 = 1 then
      Result = Reverse(Result,pShift)
   endif 
   ClrWDT  
end function
 
As I said, read the documentation. It's all there.

Note, as shown in the documentation, you must define the data (out) pin and the clock pin.

This is as helpful as I am going to be.
 
I read through the documentation, changed the array size to 8
using a tap-28 for testing out the code.
 
On Brad's Project Forum, MrDEB has made two posts:

If I understand your question correctly, it was suggested to use the shift.bas in swordfish. The data is from the CONST arrays. For the "data" using wireless I am going with the HT12E and HT12D chips.
I tried using a "BIT BANG" approach to shifting the TLC5916 regesters but no luck. bad idea. Even contemplated using SPI but Jon over at DDIY suggested using SHIFT.bas. Hav't got that far yet but will start "hacking" today.

and

After reading I believe your right. I need to store the bytes of data somewhere so I can input into the TLC5916 bit by bit. Going with the method of loading the bytes into a PORT would use 8 pins.
BUT it was suggested to go with the sHIFT.bas instead of SPI. WHY?? no clue but will give it a go.

Let me try and explain a little more thoroughly before I smash my head against the floor.

The Swordfish modules shift.bas and SPI.bas are similar. Shift is more generic, a little easier to use and is the interface used by the constant current sink chip.. Either would work. Just pick one and figure out how it works.

You don't need to use constant arrays. You seem to ascribe some magic to them that's just not there. If I have any understanding of what you are doing now, the constant current chip is driving the columns. What you need to do is:

1. Set the data for the rows in column 1.
2. Turn on column 1.
3. Delayms(10)
4. Turn off column 1.

5. Set the data for the rows in column 2
6. Turn on column 2.
7. Delayms(10)
8. Turn off column 2.

Repeat this for column 3, 4, 5 and start at top.

The column commands will be:

Shift(MSB, %10000000,8) 'Turn on column 1
Shift(MSB, %00000000,8) 'Turn off all columns

Shift(MSB, %01000000,8) 'Turn on column 2
Shift(MSB, %00100000,8) 'Turn on column 3
Shift(MSB, %00010000,8) 'Turn on column 4
Shift(MSB, %00001000,8) 'Turn on column 5

The data for the rows is just as simple. Say you want a right arrow....

Portx=%10000010 'The top and bottom dots in column 1
Portx=%01000100 'The 2nd dots in column 2
Portx=%00101000 'The 3rd dots in column 3
Portx=%00010000 'The top and bottom dots in column 4
Portx=%00000000. 'Nothing in column 5

Make this work and understand it before going all whacko. Putting the values in an array or even defining them as constants is ok after you understand what you're doing.


I'm sorry I got sucked into trying to help you again. I cannot do this anymore. All of the steps needed have been outlined. Either you can make sense of this or not. For the sake of my sanity, I'm out.
 
Last edited:
Crap....I think the way you are doing the, the row and column data would be reversed...several columns on at a time, one row.

End of my worry about you or your project. Sorry and good luck.
 
I read you description and I get a better understanding

Here is the SHIFT .BAS that I hope to get working but will review your post as I copied the code from what I conjured up.. BIG question is in the Swordfish library reference it has interface (see my code) am assuming these are sub routines I need to add as I did.
As for the CONST arrays, I plan to start with just one to use for testing to see how this code actually works. Reason for the arrays - easier to see what is going on and use a FOR NEXT loop to access the arrays. Have seen this done and so far it seems easier.
This posted code compiles correctly, no errors BUT have yet to run it. But first will print out your code flow explaniation and decipher to make heads or tails of what is going on.
Code:
{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2012 [select VIEW...EDITOR OPTIONS]              *
*          : All Rights Reserved                                            *
*  Date    : 11/5/2012                                                      *
*  Version : 1.0                                                            *
*  Notes   :                                                                *
*          :                                                                *
*****************************************************************************
}
{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2012 [select VIEW...EDITOR OPTIONS]              *
*          : All Rights Reserved                                            *
*  Date    : 10/26/2012                                                     *
*  Version : 1.0                                                            *
*  Notes   : needs better definition of when pulse train is received                                                               *
*          :                                                                *
*****************************************************************************
}
 Device = 18F2420
Clock = 8
Config MCLRE = Off


'*********************************************************************
'Includes
//Include "InternalOscillator.bas"
Include "shift.bas"
Include "utils.bas"
Include "convert.bas"
Dim sdi As PORTC.6    // data
Dim clk As PORTC.7
Dim Latch_E As PORTB.0
Dim Out_E As  PORTC.3      // output enable
Dim row1 As PORTB.3       // HIGH  driver chip output

//Dim led_data As Byte
Dim sd_out As PORTC.6

Dim x As Byte
                 
 Const Red_Data(7) As Byte =   (%0010001, %00001010, %00000100 ,%00010001, %00001010,%00000100, %00010001)// 5 colums left to right
 Const R_ows(8) As Byte =      (%00000001, %00000010, %000000100 ,%00001000, %00010000, %00100000, %01000000,%00111110)// 7 rows top to bottom
 { as per timing diagram, clock outputs 8 pulses while output enable(Out_E) is held HIGH
 Latch enable(Latch_E) is held LOW. The data is shifted in one bit per clk pulse.
 }
   Sub load()    
       Out_E = 1               // output enable HIGH
       Shift.Out(LSB_FIRST, $ee,8)
       Out_E=0                 // output enable LOW
       DelayMS(1000)
   End Sub
   
   function get_data() as word
       Out_E = 1               // output enable HIGH
       Shift.Out(LSB_FIRST, red_data(1),8)
       Out_E=0                 // output enable LOW
   end function
 //  INTERFACE?? on Swordfish reference library  
   sub setinput(byref sdi as bit)
   end sub 
   sub setoutput(byref sdi as bit)
   end sub
   sub setclock(byref clk as bit)
   end sub         

   
  // start of program
  // set ports as outputs
TRISA = %00000000
TRISB = %00000000
TRISC = %00000000 
SetAllDigital 
shift.setinput(portc.6)
shift.setoutput(portc.6)
shift.setclock(portc.7)
output (portc.5)       //output enable
output (portb.0)       //latch enable
  load()
 
In this statement "Shift(MSB, %01000000,8) " I guess that MSB you read the byte in the opposite direction? I have been using %00000011 reading from right to left.
Is this what MSB defines?
Going to develop a code as per Jonseas post and hopefully get something working that I can use to experiment with for hands on learning.
 
If I was using this chip for the first time, I would start simple. Set all of the anodes high, and switch on one cathode (one bit of this current driver chip) at a time. Once you have figured out how to control this chip, then move on to all the rest.

The code you have posted here is deficient in more ways than I can count. Yes, it may compile. No, it will not do what you expect in any way, shape or form. If you would post your "best effort" after you have done all you can to make it work, people might be better able to help you.
 
What was that code to do set some ports and stop is what it's doing
 
Last edited:
I got frustrated and decided to start from ground zero (started this at 6am but my wife keeps pulling me off to do other things) so am using the diagram using the 555 as pictured on the bottom of this page https://www.electro-tech-online.com/custompdfs/2012/11/slva346.pdf
Got tied up with another project but found I wasn't getting any clock pulse from the pic. Need to find out why before going any further. I used a code that flashed 5 rows at a time but not using the shift.bas.
After I find out why I have no clock pulse and a ground issue will get back to you. Couldn't even get an LED to flash on the Tap-28. It worked before???
As for the last code I posted, It was using the example code from the Swordfish Library reference but rewritten for my app which I need to debug.
 
*smashing head into wall with considerable force*

Excuse me for asking an incredibly stupid question. The linked ap note uses a 555 timer to turn ALL of the outputs on, which has exactly what to do with what you are trying to archeive? Please explain in great detail because one of us is lost and I'd like to think it's not me.

If I understand your project (and admittedly I may not after hundreds of contradictory posts), you are trying to drive a 5x7 LED matrix array. If this is true and you insist on using the constant current sink, you need to be able to control which bits are on.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top