Hi.
I wrote a subroutine to control a SPI connection with a software emulation on 12F683 pic, but I think that there's some problem with the AND logical operator, because the signal written on port isn't correct as should be with logic algoritm.
That's the code:
;Chip Settings
#chip 12F683,4
#config OSC=INTRC_OSC_NOCLKOUT
;Defines (Constants)
#define MOSI GPIO.0
#define CS GPIO.1
#define CLK GPIO.3
#define SPISPEED 15
;Variables
Dim data(2)
Dim mask As byte
;Data tables
Table maskade
b'10000000'
b'01000000'
b'00100000'
b'00010000'
b'00001000'
b'00000100'
b'00000010'
b'00000001'
End Table
init
Main:
goto Main
demo
Wait 1 s
clear
Wait 1 s
demo
Sub SPIWriteData
'Set MOSI Off
'Set CLK Off
Set CS Off
'Wait 3 us
For i = 1 To 8
ReadTable maskade, i, mask
If data(2) & mask Then
Set MOSI On
Else
Set MOSI Off
End If
Set CLK On
Wait SPISPEED us
Set CLK Off
Wait SPISPEED us
Next
For i = 1 To 8
ReadTable maskade, i, mask
If data(1) & mask Then
Set MOSI On
Else
Set MOSI Off
End If
Set CLK On
Wait SPISPEED us
Set CLK Off
Wait SPISPEED us
Next
'Wait 3 us
Set CS On
'Set CLK Off
'Set MOSI Off
End Sub
Sub demo
data(2) = 0x01
data(1) = 0x55
SPIWriteData
data(2) = 0x02
data(1) = 0xAA
SPIWriteData
data(2) = 0x03
data(1) = 0x55
SPIWriteData
data(2) = 0x04
data(1) = 0xAA
SPIWriteData
data(2) = 0x05
data(1) = 0x55
SPIWriteData
data(2) = 0x06
data(1) = 0xAA
SPIWriteData
data(2) = 0x07
data(1) = 0x55
SPIWriteData
data(2) = 0x08
data(1) = 0xAA
SPIWriteData
End Sub
Sub init
Wait 3 s
'Ts = 30 uS
'Freq.=30khz
Set CS On
data(2) = 0x09
data(1) = 0x00
SPIWriteData
data(2) = 0x0B
data(1) = 0x07
SPIWriteData
data(2) = 0x0A
data(1) = 0xFF
SPIWriteData
data(2) = 0x0C
data(1) = 0x01
SPIWriteData
End Sub
Sub clear
For i = 1 To 8
data(2) = i
data(1) = 0x00
SPIWriteData
Next
End Sub
Is there a different way to use the AND logical operator?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Compile error, GPIO.3 is the MCLR pin and input only. So place the CLK on a different pin.
There is a way to not use a table and the & command. Just get a bit value from the data variable and then perform the Rotate command. So for instance:
sub SPI_Xfer(xfer)
For clocks = 1 to 8
If xfer.7 = 1 Then
MOSI = 1
Else
MOSI = 0
End If
Rotate xfer Left Simple
SCK = 1
If MISO = 1 Then
xfer.0 = 1
Else
xfer.0 = 0
End If
SCK = 0
Next
end sub
May have pinched this code from Hugh's library/source, I honestly forget.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Many thanks to everyone, but the program isn't playing!
To prevent every possible misunderstanding, I tell you some additional info.
It's necessary to send 2 bytes over SPI to drive the display!
It isn't a LCD display.
So, after inverted CS output it's possible to send the 2 bytes (command and data), then set up the CS ON to close the SPI communication. As reported on MAX7219 datasheet.
So, going back to the point, this is what happen.
After the initiation, 3s after, the code turns on all leds of 8x8 display connected (ah, I forgot... the MAX7219 drives a 8x8 led display).
That's all, what do you think about? Where is the problem? ...into temporization?
;Chip Settings
#chip 12F683,4
#config OSC=INTRC_OSC_NOCLKOUT
;Defines (Constants)
#define MOSI GPIO.0
#define CS GPIO.1
#define CLK GPIO.2
#define SPISPEED 15
init
Main:
demo
Wait 1 s
clear
Wait 1 s
goto Main
Sub init
Wait 3 s
'Ts = 30 uS
'Freq.=30khz
Set CS On
SPIwrite 0x09, 0x00
SPIwrite 0x0B, 0x07
SPIwrite 0x0A, 0xFF
'SPIwrite 0x0C, 0x01
End Sub
Sub demo
SPIwrite 0x01, 0x55
SPIwrite 0x02, 0xAA
SPIwrite 0x03, 0x55
SPIwrite 0x04, 0xAA
SPIwrite 0x05, 0x55
SPIwrite 0x06, 0xAA
SPIwrite 0x07, 0x55
SPIwrite 0x08, 0xAA
End Sub
Sub clear
For i = 1 To 8
SPIwrite i, 0x00
Next
End Sub
Sub SPIwrite (command, data)
Set CS Off
'Wait 3 us
For i = 1 To 8
If command.7 On Then
Set MOSI On
Else
Set MOSI Off
End If
Rotate command Left
Set CLK On
'Wait SPISPEED us
Set CLK Off
'Wait SPISPEED us
Next
For i = 1 To 8
If data.7 On Then
Set MOSI On
Else
Set MOSI Off
End If
Rotate data Left
Set CLK On
'Wait SPISPEED us
Set CLK Off
'Wait SPISPEED us
Next
Set CS On
End Sub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Have you tried the "Rotate xxxx Left Simple" command like in my example? It definitely affects the assembler. You have PIC MOSI going to MAX chip MISO? had to ask :). Otherwise, the code and toggle of CS looks correct.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Even now there's some problem. I used your code (even changing MOSI and CLK pins) with no change.
Then, I try to change the configuration of SPI and I used 2 pullup reristors of 10K ohm in addition at one capacitor of 100nF between VCC and GND to subtract every noice on ground.
But, even now the code not transmit the correct data on MOSI (I think) because I see the leds on screen all ON, but in updating (their flicker over and over again).
That's the new code.
;Chip Settings
#chip 12F683,4
#config OSC=INTRC_OSC_NOCLKOUT
;Defines (Constants)
#define MOSI GPIO.4
#define CS GPIO.1
#define CLK GPIO.2
#define SPISPEED 15
init
Main:
demo
Wait 10 s
clear
Wait 10 s
goto Main
Sub init
Wait 3 s
'Ts = 30 uS
'Freq.=30khz
'Dir MOSI Out
Dir CS Out
'Dir CLK Out
Set CS On
SPIwrite 0x09, 0x00
SPIwrite 0x0B, 0x07
SPIwrite 0x0A, 0xFF
SPIwrite 0x0C, 0x01
End Sub
Sub demo
SPIwrite 0x01, 0x55
SPIwrite 0x02, 0xAA
SPIwrite 0x03, 0x55
SPIwrite 0x04, 0xAA
SPIwrite 0x05, 0x55
SPIwrite 0x06, 0xAA
SPIwrite 0x07, 0x55
SPIwrite 0x08, 0xAA
End Sub
Sub clear
For i = 1 To 8
SPIwrite i, 0x00
Next
End Sub
Sub WriteByte (byte)
For i = 1 To 8
If byte.7 On Then
'Set MOSI On
Dir MOSI In
Else
Dir MOSI Out
Set MOSI Off
End If
Rotate byte Left Simple
Dir CLK In
'Set CLK On
'Wait SPISPEED us
Dir CLK Out
Set CLK Off
'Wait SPISPEED us
Next
End Sub
Sub SPIwrite (address, data)
Set CS Off
WriteByte address
WriteByte data
Set CS On
Wait 1 us
End Sub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I checked this last release with a mini oscilloscope and the problem look like on MOSI. After a pick on start, the signal on MOSI is always at zero state!
I think that the command Rotate and xxx.7 have no effect!
For that, when I disconnect the MOSI pin from circuit, the display go all ON (as before) and when I reconnect the MOSI pin the display swich off.
That's all, do you know other operators that I can use? (ex. AND command or SHIFT command on byte)...
#config OSC=INTRC_OSC_NOCLKOUT
;Defines (Constants)
#define CS GPIO.0
#define MOSI GPIO.4
#define CLK GPIO.5
#define SPISPEED 15
init
Main:
clear
Wait 2 s
demo
Wait 2 s
goto Main
Sub init
Wait 3 s
'Ts = 30 uS
'Freq.=30khz
Dir MOSI Out
Dir CS Out
Dir CLK Out
SPIwrite 0x09, 0x00
SPIwrite 0x0B, 0x07
SPIwrite 0x0A, 0xFF
SPIwrite 0x0C, 0x01
Wait 1 s
End Sub
Sub demo
SPIwrite 0x01, 0x55
SPIwrite 0x02, 0xAA
SPIwrite 0x03, 0x55
SPIwrite 0x04, 0xAA
SPIwrite 0x05, 0x55
SPIwrite 0x06, 0xAA
SPIwrite 0x07, 0x55
SPIwrite 0x08, 0xAA
End Sub
Sub clear
'For i = 1 To 8
SPIwrite 0x01, 0x00
SPIwrite 0x02, 0x00
SPIwrite 0x03, 0x00
SPIwrite 0x04, 0x00
SPIwrite 0x05, 0x00
SPIwrite 0x06, 0x00
SPIwrite 0x07, 0x00
SPIwrite 0x08, 0x00
'Next
End Sub
Sub WriteByte (In byte)
Set CLK Off
For i = 1 To 8
If byte.7 On Then
Set MOSI On
Else
Set MOSI Off
End If
Set CLK On
Set CLK Off
Rotate byte Left
Next
End Sub
Sub SPIwrite (In address, In data)
Set CS Off
WriteByte address
WriteByte data
Set CS On
End Sub
Last edit: cosmok82 2013-11-20
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Took a look at the data sheet today. The test register mode has to be reset for normal operation each time (SPIwrite 0x0F, 0x00) in the init sub, otherwise the segments are all on at startup (see table 10).
The code example using the rotate command is from a working SPI project.
I would revert back to having no pullups and the previous code. Using byte as a variable is playing with fire, as it is likely reserved for GCB source.
EDIT: The way I have devised the software SPI sub with the GCB Rotate command, it depends on the rotate value being saved backed to the data register. The GCB "Rotate [variable] Left Simple" command does this. Without the Simple option, the value is only saved backed to the W register, and the Status.C register is updated.
Last edit: kent_twt4 2013-11-20
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
' Works via MAX232 on pin8 of PIC
' #define SendAHigh Set PORTe.0 Off
' #define SendALow Set PORTe.0 On
' Dir PORTe.0 Out
' #define SerSendDelayms 5
' 'Set up serial connection
' InitSer 1, r1200, 1+128, 8, 1, none, invert
' wait SerSendDelayms ms
' sersend 1,0x55
'
' ANSIERASECREEN_SW
' ANSI_SW ( 0,0)
Dir PORTC.3 OUT
Dir PORTC.4 IN
Dir PORTC.5 OUT
dir porta.0 out
dir porta.1 in
dim DataList(16)
' See the MAX7219 data sheet - Table 6. No-Decode Mode Data Bits and Corresponding Segment Lines
' this the data for the characters to be displayed. 0-F hex or you can simply use 0-9
'Datalist = 0x7e,0x30, 0x6d, 0x79, 0x33, 0x5b, 0x5f, 0x70, 0x7f, 0x7b, 0x77, 0x1f, 0x4e, 0x3d, 0x4f, 0x47
Datalist = 0,79,b'00111110',91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
dim outword as word
dim maxreg as byte
dim outbyte as byte
dim charcode as Byte
define ug_data latc.5
define ug_clock latc.3
define ug_loaddata lata.0
set ug_data off
set ug_loaddata off
set ug_clock off
for iindex = 1 to 16 ' MAX7219 specifies a 16-bit word
if outword.15 = 1 then ' set ug_data to correspond to bit15
set ug_data on
else
set ug_data off
end if
pulseout ug_clock, clockdelaytime us ' pulse clock line
outword = outword * 2 ' shift outword left for next MSB
next
pulseout ug_loaddata, loaddelaytime us ' load the data word into MAX7219
wait 3 ms ' Data-to-Segment Delay
end sub
~~~~~~
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
After a check-up of circuit I have to admit that gone out the reason of previous problems reported.
I ask to excuse me, but it was all caused from a cutting of a connection wire (invisible in my defence!). So, thanks in particular to Anobium for his code, but there are two SPIwrite code version that can working, that is:
Sub SPIwrite (In address, In data)
outword = (address * 256) + data
Set CS Off
Set CLK Off
for i = 1 to 16
if outword.15 = 1 then
set MOSI On
else
set MOSI Off
end if
Set CLK On
Set CLK Off
outword = outword * 2
next
Set CS On
End Sub
(even with one byte wrote at a time, see previously) and;
Sub SPIwrite (In address, In data)
outword = (address * 256) + data
for i = 1 to 16
if outword.15 = 1 then
set MOSI On
else
set MOSI Off
end if
PulseOut CLK, CLOCKTIME us
outword = outword * 2
next
PulseOut CS, LOADTIME us
End Sub
The advantage of second code is that you can set the time of CLOCKTIME and LOADTIME, whereas the first is the fastest that the microchip can play (at its time of cicle determinated from clock speed).
You can choose what you prefer.
Many thanks!... another time...
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Would you be willing to post the complete final code with #defines as well?
I'd like to build it, since I have a MAX7219 board already, and then add it as a free demo at greatcowbasic.com if you don't mind.
I think others would find the finished working code helpful.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Using multiplication on words adds dozens of extra lines of code. No big deal perhaps, unless you are doing a multiplexed led array as fast as you can.
Using rotate simple, and byte variables (or word alias), has no multiply routines.
Don't get me wrong, I have had the need to use word variables for SPI device registers or data, but still used the rotate simple.
Using the Alias command reduces a call to the SYSMULTSUB16, like so:
dim outword as word Alias address, data
Here is the extra assembler for cosmok82 example using the multiply word. Notice the consecutive calls to SYSCOMPLESSTHAN16 each time thru SYSMULTSUB16.
Good, very good point. I will change my code and test this weekend. I will let you know how I get on but I do think if we want to showcase the code then we should use ROTATE.
:-)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
As you request, I post here my last demo code, even if I would like to talking about on my blog site.
Anyway, maybe we examine in depth it also there, but now I post it right here.
So, I used my old structure and I optimized the code in depth. I compress the code from 6.46KB to 4.53KB (about .asm file), just 2/3 of original code!
I think it's a good enough solution.
It work perfectly with no crashes and no bugs!
;Chip Settings
#chip 12F683,4
#config OSC=INTRC_OSC_NOCLKOUT
;Defines (Constants)
#define CS GPIO.0
#define MOSI GPIO.4
#define CLK GPIO.5
#define CLOCKTIME 1
;Variables
Dim line As byte
Dim index As byte
init
Main:
clear
Wait 250 ms
demoA
Wait 250 ms
demoB
Wait 250 ms
goto Main
Sub init
Wait 3 s
'Ts = 1 uS
'Freq = 1 MHz
Dir CS Out
Set CS On
Dir CLK Out
Set CLK Off
Dir MOSI Out
Set MOSI Off
'NO Decode-Mode Register
SPIwrite 0x09, 0x00
'MAX Scan-Limit Register [8 bits]
SPIwrite 0x0B, 0x07
'28% Intensity of Brightness
SPIwrite 0x0A, 0x04
'Normal Operation
SPIwrite 0x0C, 0x01
End Sub
Sub demoA
line = 0x55
For index = 1 To 8
SPIwrite index, line
Rotate line Left Simple
Next
End Sub
Sub demoB
line = 0x55
For index = 1 To 8
Rotate line Left Simple
SPIwrite index, line
Next
End Sub
Sub clear
For index = 1 To 8
SPIwrite index, 0x00
Next
End Sub
Sub SPIwrite (In address, In data)
set CS Off
WriteByte address
WriteByte data
set CS On
End Sub
Sub WriteByte (In byte)
For i = 1 To 8
If byte.7 = 1 Then
set MOSI On
else
set MOSI Off
end if
PulseOut CLK, CLOCKTIME us
byte = byte * 2
next
End Sub
For any question and comment, please refer to www.creativityslashdesign.tk when I will post it into a new project. Bye...
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi.
I wrote a subroutine to control a SPI connection with a software emulation on 12F683 pic, but I think that there's some problem with the AND logical operator, because the signal written on port isn't correct as should be with logic algoritm.
That's the code:
Is there a different way to use the AND logical operator?
Can you output the value to LCD or a PC terminal? this would help.
I have had no issues with operators. This is my experience.
Please also post ASM.
Compile error, GPIO.3 is the MCLR pin and input only. So place the CLK on a different pin.
There is a way to not use a table and the & command. Just get a bit value from the data variable and then perform the Rotate command. So for instance:
May have pinched this code from Hugh's library/source, I honestly forget.
Many thanks to everyone, but the program isn't playing!
To prevent every possible misunderstanding, I tell you some additional info.
It's necessary to send 2 bytes over SPI to drive the display!
It isn't a LCD display.
So, after inverted CS output it's possible to send the 2 bytes (command and data), then set up the CS ON to close the SPI communication. As reported on MAX7219 datasheet.
So, going back to the point, this is what happen.
After the initiation, 3s after, the code turns on all leds of 8x8 display connected (ah, I forgot... the MAX7219 drives a 8x8 led display).
That's all, what do you think about? Where is the problem? ...into temporization?
Have you tried the "Rotate xxxx Left Simple" command like in my example? It definitely affects the assembler. You have PIC MOSI going to MAX chip MISO? had to ask :). Otherwise, the code and toggle of CS looks correct.
Even now there's some problem. I used your code (even changing MOSI and CLK pins) with no change.
Then, I try to change the configuration of SPI and I used 2 pullup reristors of 10K ohm in addition at one capacitor of 100nF between VCC and GND to subtract every noice on ground.
But, even now the code not transmit the correct data on MOSI (I think) because I see the leds on screen all ON, but in updating (their flicker over and over again).
That's the new code.
I checked this last release with a mini oscilloscope and the problem look like on MOSI. After a pick on start, the signal on MOSI is always at zero state!
I think that the command Rotate and xxx.7 have no effect!
For that, when I disconnect the MOSI pin from circuit, the display go all ON (as before) and when I reconnect the MOSI pin the display swich off.
That's all, do you know other operators that I can use? (ex. AND command or SHIFT command on byte)...
Last edit: cosmok82 2013-11-20
Took a look at the data sheet today. The test register mode has to be reset for normal operation each time (SPIwrite 0x0F, 0x00) in the init sub, otherwise the segments are all on at startup (see table 10).
The code example using the rotate command is from a working SPI project.
I would revert back to having no pullups and the previous code. Using byte as a variable is playing with fire, as it is likely reserved for GCB source.
EDIT: The way I have devised the software SPI sub with the GCB Rotate command, it depends on the rotate value being saved backed to the data register. The GCB "Rotate [variable] Left Simple" command does this. Without the Simple option, the value is only saved backed to the W register, and the Status.C register is updated.
Last edit: kent_twt4 2013-11-20
To support Kent. I wrote this at the weekend for my MAX7219 device. TGCB and the device Works very well.
~~~~~
#chip 16F1937, 32
#config Osc = intOSC
#define clockdelaytime 5
#define loaddelaytime 10
#include "D:\Others\GCB@Syn\GreatCowBasic\include\outputserial.h"
#include "D:\Others\GCB@Syn\GreatCowBasic\include\utils.h"
' Works via MAX232 on pin8 of PIC
' #define SendAHigh Set PORTe.0 Off
' #define SendALow Set PORTe.0 On
' Dir PORTe.0 Out
' #define SerSendDelayms 5
' 'Set up serial connection
' InitSer 1, r1200, 1+128, 8, 1, none, invert
' wait SerSendDelayms ms
' sersend 1,0x55
'
' ANSIERASECREEN_SW
' ANSI_SW ( 0,0)
Dir PORTC.3 OUT
Dir PORTC.4 IN
Dir PORTC.5 OUT
dir porta.0 out
dir porta.1 in
dim DataList(16)
' See the MAX7219 data sheet - Table 6. No-Decode Mode Data Bits and Corresponding Segment Lines
' this the data for the characters to be displayed. 0-F hex or you can simply use 0-9
'Datalist = 0x7e,0x30, 0x6d, 0x79, 0x33, 0x5b, 0x5f, 0x70, 0x7f, 0x7b, 0x77, 0x1f, 0x4e, 0x3d, 0x4f, 0x47
Datalist = 0,79,b'00111110',91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
dim outword as word
dim maxreg as byte
dim outbyte as byte
dim charcode as Byte
define ug_data latc.5
define ug_clock latc.3
define ug_loaddata lata.0
set ug_data off
set ug_loaddata off
set ug_clock off
decode = 0x09 ' decode register; specify digits to decode
brite = 0x0A ' intensity (brightness) register; 15 = 100%
scan = 0x0B ' scan-limit register; specify how many digits
on_off = 0x0C ' 1 = display on; 0 = display off
displaytest = 0x0F
do while ( 1 )
bcount = 1
for ccount = 0 to 4
Loop
end
' === End Main Program - Subroutines Follow ===============================
' ===== SendWordtoMax7219 Subroutine ==================================================
' Shift out the 16-bit data word to the MAX7219 (MSB first)
sub SendWordtoMax7219 ( in deviceregister, in outbyte )
' SerPrint 1, deviceregister
' SerSend 1,9
' SerPrint 1, str(outbyte)
' SerSend 1,9
' SerPrint 1, hex(outword_h)
' SerPrint 1, hex(outword)
' crlf
end sub
~~~~~~
Thanks to everyone.
After a check-up of circuit I have to admit that gone out the reason of previous problems reported.
I ask to excuse me, but it was all caused from a cutting of a connection wire (invisible in my defence!). So, thanks in particular to Anobium for his code, but there are two SPIwrite code version that can working, that is:
(even with one byte wrote at a time, see previously) and;
The advantage of second code is that you can set the time of CLOCKTIME and LOADTIME, whereas the first is the fastest that the microchip can play (at its time of cicle determinated from clock speed).
You can choose what you prefer.
Many thanks!... another time...
Would you be willing to post the complete final code with #defines as well?
I'd like to build it, since I have a MAX7219 board already, and then add it as a free demo at greatcowbasic.com if you don't mind.
I think others would find the finished working code helpful.
Check the code I posted works. It is a demonstrator also... when you get the code working.... you will see my partners name displayed! See https://sourceforge.net/p/gcbasic/discussion/596084/thread/026da590/#af08.
Whaaa, no love for the Rotate Simple?
Using multiplication on words adds dozens of extra lines of code. No big deal perhaps, unless you are doing a multiplexed led array as fast as you can.
Using rotate simple, and byte variables (or word alias), has no multiply routines.
Don't get me wrong, I have had the need to use word variables for SPI device registers or data, but still used the rotate simple.
Using the Alias command reduces a call to the SYSMULTSUB16, like so:
Here is the extra assembler for cosmok82 example using the multiply word. Notice the consecutive calls to SYSCOMPLESSTHAN16 each time thru SYSMULTSUB16.
Good, very good point. I will change my code and test this weekend. I will let you know how I get on but I do think if we want to showcase the code then we should use ROTATE.
:-)
Hi to everyone.
As you request, I post here my last demo code, even if I would like to talking about on my blog site.
Anyway, maybe we examine in depth it also there, but now I post it right here.
So, I used my old structure and I optimized the code in depth. I compress the code from 6.46KB to 4.53KB (about .asm file), just 2/3 of original code!
I think it's a good enough solution.
It work perfectly with no crashes and no bugs!
For any question and comment, please refer to www.creativityslashdesign.tk when I will post it into a new project. Bye...