Hello, I did a quick search for SPI on Atmega (Arduino Uno) using GCB. I was not able to find anything useful. Is there example code for master set up?
Thanks!
Nick
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I want to use the SPI to drive a 3-wire communication interface to a PLL. The interface is not SPI or I2C. basically Clk, data and LE. I thought maybe I can use Hardware SPI in master mode just sending data one way (no need to read back) utilizing 3 out of the 4 interfaces in SPI.
-Nick
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You can do that. Nothing to stop you. Create you own SPI command and call it. Note: Dependent on your chip you may have to clear flags even if do not read the incoming buffer - use the HWPSI.H as a source.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I looked at the examples, still confused. I don't know how to load the TX buffer. Nor do I know how to send out 3 bytes. I want to find an example for the arduino that uses the hardware SPI. No offense to whomever wrote the manual for GCB, but the example for SPI is confusing and unclear.
-Nick
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Here is how to do it. See glcd_ILI9340.h as an example
The method below sends either a hardware or software SPI command - this depends on ILI9340_HardwareSPI being defined. Using the hardware as the example SPITransfer ILI9340SendByte, ILI9340TempOut sends one byte and get a byte. As I stated before the low level code handles the PIC variants and AVR in terms of the actual code.
But, I you think... what is FastHWSPITransfer compared to SPITransfer? FastHWSPITransfer is an undocumented but supported method that is faster by only handling SPI Master mode and one out byte - So, in your code you could use FastHWSPITransfer - but, dont.
So, how do you send three bytes? I would do the following. In your main code add.
Or, to be compliant with the Open documented methods call SPITransfer three times. :-)
SPITransfer(byte1,temp)'send a byte and throw any the incoming byte.SPITransfer(byte2,temp)'send a byte and throw any the incoming byte.SPITransfer(byte3,temp)'send a byte and throw any the incoming byte.
Hope this helps.
And, once you have this working - I would be truly grateful for any updates to the Help to make this easier for the next person.
Anobium
Last edit: Anobium 2017-03-31
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for the examples. Trying to make sense of it, please bear with me.
I am going to grab one example and run with it. I am unsure how to force master mode or if the routine would send 3 bytes every 100ms they way I wrote it....Please see below.
'#chip mega328p, 16
'variable defines
dim Data1 as byte
dim Data2 as byte
dim Data3 as byte
Data1 = 100 ' these later will be values seeded from A/D pots
Data2 = 150
Data3 = 200
Do
'Master mode only
Do
SPDR = SPITxData1
Loop While SPSR.WCOL
'Read buffer
'Same for master and slave
Wait While SPSR.SPIF = Off
'Master mode onlyDo SPDR = SPITxData2Loop While SPSR.WCOL'Read buffer'Same for master and slaveWait While SPSR.SPIF = Off'Master mode onlyDo SPDR = SPITxData3Loop While SPSR.WCOL'Read buffer'Same for master and slaveWait While SPSR.SPIF = Offwait 100msLoop
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I will try that. So the TX mechanism is that simple, just unsure of what support files need to be called. Any .h or initialization files need to be included? Anything that determines LSB first? Master/slave mode? Speed of transmission?....etc.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
When you have this working... you can help rewrite the Help. :-)
The LSB is determined by the order that youy send. MasterSlave (see the Help) but SPIMode MasterFast, 0 will use MasterMode at clocked at 1/4 of the frequency of the microcontroller, speed of transmission is dependent on the chips clock speed, clock polarity and clock edge is set by the second parameter. I am copying thos from the help.
So, this is all that is needed.
SPIMode MasterFast, 0 'which equates to SPIMode ( MasterFast, SPI_CPOL_0 + SPI_CPHA_0 ) you need to determine the correct clock polarity and clock edge from your device.
FastHWSPITransfer (byte1)
FastHWSPITransfer (byte2)
FastHWSPITransfer (byte3)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Use the GLCD_ILI934x as the source as I am not sure how you determined the CLK, MOSI and MISO. Please review ..\GreatCowBasic\Demos\GLCD Solutions\GLCD Simple Demonstration Solutions\GLCD_Simple_Demonstation_mega328p_for_ILI9341@16.gcb
'ChipSettings.#chip mega328p, 16#option explicit#include<glcd.h>#include<UNO_mega328p.h >#define GLCD_TYPE GLCD_TYPE_ILI9341'PinmappingsforSPI-thisGLCDdriversupportsHardwareSPI#define GLCD_DC DIGITAL_8 ' Data command line#define GLCD_CS DIGITAL_10 ' Chip select line#define GLCD_RESET DIGITAL_9 ' Reset line#define GLCD_DI DIGITAL_12 ' Data in | MISO#define GLCD_DO DIGITAL_11 ' Data out | MOSI#define GLCD_SCK DIGITAL_13 ' Clock LineDIMbyte1AsbyteDIMbyte2AsbyteDIMbyte3Asbytebyte1=100'tempvalues(willcomefrompotentiometerlater)byte2=150byte3=200SPIMode(MasterFast,SPI_CPOL_0+SPI_CPHA_0)doforeverFastHWSPITransfer(byte1)FastHWSPITransfer(byte2)FastHWSPITransfer(byte3)wait100msloop
And, are you testing with a protocol analyser? (Just checking how you are determining if things are working).
Anobium
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
See my exact code attached. If your code does not work please provide source GCB file, the ASM related to the source file (generated with error), restate your build version (I have assumed you are using v0.97.00 or greater).
#include<UNO_mega328p.h >'PinmappingsforSPI-thisGLCDdriversupportsHardwareSPI#define GLCD_DC DIGITAL_8 ' Data command line#define GLCD_CS DIGITAL_10 ' Chip select line#define GLCD_RESET DIGITAL_9 ' Reset line#define GLCD_DI DIGITAL_12 ' Data in | MISO#define GLCD_DO DIGITAL_11 ' Data out | MOSI#define GLCD_SCK DIGITAL_13 ' Clock Line
'port direction configuration
dir PortB.5 out
dir PortB.4 out
dir PortB.3 out
dir PortB.2 out
dir PortB.1 out
DIM byte1 As byte
DIM byte2 As byte
DIM byte3 As byte
byte1 = 100 ' temp values (will come from potentiometer later)
byte2 = 150
byte3 = 200
SPIMode ( MasterFast, SPI_CPOL_0 + SPI_CPHA_0 )
do forever
FastHWSPITransfer (byte1)
FastHWSPITransfer (byte2)
FastHWSPITransfer (byte3)
wait 100 ms
loop
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Here is complete posting, totally based upon your good work. So, thank you! The HELP will get improved as a result.
This shows how the MEGA328p can support hardware and software SPI. To use hardware make sure the #define SPI_HardwareSPI is not commented out.
To use software comment out #define SPI_HardwareSPI.
To use the hardware SPI the Data Out, Data In and Clock (DO/DI and SCK) cannot be moved but the optional Data Command, Chip Select and Reset are all moveable.
To use the hardware SPI the Data Out, Data In and Clock (DO/DI and SCK), Data Command, Chip Select and Reset are all moveable.
I have called InitSPIMode to call SPIMode if needed, and set the lines.
I have also define a sub called SendByteviaSPI to handle whether to call the Hardware or use Software (bit-banging) SPI.
Enjoy - really sorry for not getting this right in the first place!
'ChipSettings.#chip mega328p, 16#option explicit#include<UNO_mega328p.h >#define SPI_HardwareSPI 'comment this out to make into Software SPI but, you may have to change clock lines'PinmappingsforSPI-thisSPIdriversupportsHardwareSPI#define SPI_DC DIGITAL_8 ' Data command line#define SPI_CS DIGITAL_4 ' Chip select line#define SPI_RESET DIGITAL_9 ' Reset line'mandatedforhardware#define SPI_DI DIGITAL_12 ' Data in | MISO #define SPI_DO DIGITAL_11 ' Data out | MOSI#define SPI_SCK DIGITAL_13 ' Clock LinedirSPI_DCoutdirSPI_CSoutdirSPI_RESEToutdirSPI_DOOutdirSPI_DIIndirSPI_SCKOutdirDIGITAL_10Out'neededandIamnotsurewhy!DIMbyte1AsbyteDIMbyte2AsbyteDIMbyte3AsbyteDIMttasbyteDIMSPISendByteasbytebyte1=100'tempvalues(willcomefrompotentiometerlater)byte2=150byte3=200InitSPIModedoforeversetSPI_CSOFF;setSPI_DCOFF;SendByteviaSPI(byte1)setSPI_CSON;setSPI_DCONsetSPI_CSOFF;setSPI_DCOFF;SendByteviaSPI(byte2)setSPI_CSON;setSPI_DCONsetSPI_CSOFF;setSPI_DCOFF;SendByteviaSPI(byte3)setSPI_CSON;setSPI_DCONwait100msloopsubInitSPIMode#ifdef SPI_HardwareSPISPIMode(MasterFast,SPI_CPOL_0+SPI_CPHA_0)#endifsetSPI_DOOFF;setSPI_CSON;thereforeCPOL=0setSPI_DCON;deselectEndsubsubSendByteviaSPI(inSPISendByte)setSPI_CSOFFsetSPI_DCOFF;#ifdef SPI_HardwareSPIFastHWSPITransferSPISendBytesetSPI_CSON;exitsub#endif#ifndef SPI_HardwareSPIrepeat8ifSPISendByte.7=ONthensetSPI_DOON;elsesetSPI_DOOFF;endifSETSPI_SCKOn;;thereforeCPOL=0==ON,and,whereCPOL=1==ONrotateSPISendByteleftsetSPI_SCKOff;;thereforeCPOL=0=OFF,and,whereCPOL=1==OFFendrepeatsetSPI_CSON;setSPI_DOOFF;#endifendSub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
weird data on the scope. byte1 = 255, byte2= 0 and byte3 = 255....looking at the clock edges the 255 on the right side of the scope is high all the way through. if I use anything less than 255 in byte1 then the waveform starts low before the clock pulses start. When set to 255 it starts off as high before the clock pulses.....why is this?
Hello, I did a quick search for SPI on Atmega (Arduino Uno) using GCB. I was not able to find anything useful. Is there example code for master set up?
Thanks!
Nick
In the demo folder...C:\GCB@Syn\GreatCowBasic\Demos\SPI Digital Pot Solutions\MCP4xxx SPI Pot
The HELP file covers SPI pretty well. CmmandReference> SPI.
Is there a specific problem or question?
I want to use the SPI to drive a 3-wire communication interface to a PLL. The interface is not SPI or I2C. basically Clk, data and LE. I thought maybe I can use Hardware SPI in master mode just sending data one way (no need to read back) utilizing 3 out of the 4 interfaces in SPI.
-Nick
You can do that. Nothing to stop you. Create you own SPI command and call it. Note: Dependent on your chip you may have to clear flags even if do not read the incoming buffer - use the HWPSI.H as a source.
I looked at the examples, still confused. I don't know how to load the TX buffer. Nor do I know how to send out 3 bytes. I want to find an example for the arduino that uses the hardware SPI. No offense to whomever wrote the manual for GCB, but the example for SPI is confusing and unclear.
-Nick
That's OK. Always looking for feedback.
Here is how to do it. See glcd_ILI9340.h as an example
The method below sends either a hardware or software SPI command - this depends on ILI9340_HardwareSPI being defined. Using the hardware as the example SPITransfer ILI9340SendByte, ILI9340TempOut sends one byte and get a byte. As I stated before the low level code handles the PIC variants and AVR in terms of the actual code.
Now, if I look at the Ethernet driver - I need to send two bytes. There are two calls to FastHWSPITransfer.
But, I you think... what is FastHWSPITransfer compared to SPITransfer? FastHWSPITransfer is an undocumented but supported method that is faster by only handling SPI Master mode and one out byte - So, in your code you could use FastHWSPITransfer - but, dont.
So, how do you send three bytes? I would do the following. In your main code add.
Or, simply call FastHWSPITransfer three times. :-)
Or,
Or, to be compliant with the Open documented methods call SPITransfer three times. :-)
Hope this helps.
And, once you have this working - I would be truly grateful for any updates to the Help to make this easier for the next person.
Anobium
Last edit: Anobium 2017-03-31
Hello Anobium,
Thanks for the examples. Trying to make sense of it, please bear with me.
I am going to grab one example and run with it. I am unsure how to force master mode or if the routine would send 3 bytes every 100ms they way I wrote it....Please see below.
'#chip mega328p, 16
'variable defines
dim Data1 as byte
dim Data2 as byte
dim Data3 as byte
Data1 = 100 ' these later will be values seeded from A/D pots
Data2 = 150
Data3 = 200
Do
'Master mode only
Do
SPDR = SPITxData1
Loop While SPSR.WCOL
'Read buffer
'Same for master and slave
Wait While SPSR.SPIF = Off
I guess so. Not sure why this would not work.
FastHWSPITransfer (byte1)
FastHWSPITransfer (byte2)
FastHWSPITransfer (byte3)
Last edit: Anobium 2017-04-01
I will try that. So the TX mechanism is that simple, just unsure of what support files need to be called. Any .h or initialization files need to be included? Anything that determines LSB first? Master/slave mode? Speed of transmission?....etc.
When you have this working... you can help rewrite the Help. :-)
The LSB is determined by the order that youy send. MasterSlave (see the Help) but SPIMode MasterFast, 0 will use MasterMode at clocked at 1/4 of the frequency of the microcontroller, speed of transmission is dependent on the chips clock speed, clock polarity and clock edge is set by the second parameter. I am copying thos from the help.
So, this is all that is needed.
Hello Anobium,
This is what I have so far and it does not output anything. Not sure where I have gone wrong...
chip mega328p, 16
#config osc = Ext
'port direction configuration
dir PortC.7 out ' CLK
dir PortD.6 out ' MISO
dir PortB.7 out ' MOSI
dir PortB.6 out ' SS
DIM byte1 As byte
DIM byte2 As byte
DIM byte3 As byte
byte1 = 100 ' temp values (will come from potentiometer later)
byte2 = 150
byte3 = 200
SPIMode ( MasterFast, SPI_CPOL_0 + SPI_CPHA_0 )
do forever
loop
Use the GLCD_ILI934x as the source as I am not sure how you determined the CLK, MOSI and MISO. Please review ..\GreatCowBasic\Demos\GLCD Solutions\GLCD Simple Demonstration Solutions\GLCD_Simple_Demonstation_mega328p_for_ILI9341@16.gcb
And, are you testing with a protocol analyser? (Just checking how you are determining if things are working).
Anobium
I have assummed you have your connections on the hardware SPI ports. If not, we need to give you the software SPI methods.
😃
I am getting this error....SPI2.gcb (27): Error: Variable SPICLOCKMODE was not explicitly declared
Sorry, I cannot reproduce that error.
See my exact code attached. If your code does not work please provide source GCB file, the ASM related to the source file (generated with error), restate your build version (I have assumed you are using v0.97.00 or greater).
Puzzled here.
I downloaded v0.97. It compiles. Neither your code nor mine is outputting a signal on SPI....not sure what is going on.
I will spin up a test rig now. Check back in 10 mins.
OK...I had to initialize port direction....now it works. The data needs to be inverted though....
'Chip Settings.
#chip mega328p, 16
#option explicit
'port direction configuration
dir PortB.5 out
dir PortB.4 out
dir PortB.3 out
dir PortB.2 out
dir PortB.1 out
Very good. Well done.
Here is complete posting, totally based upon your good work. So, thank you! The HELP will get improved as a result.
This shows how the MEGA328p can support hardware and software SPI. To use hardware make sure the #define SPI_HardwareSPI is not commented out.
To use software comment out #define SPI_HardwareSPI.
To use the hardware SPI the Data Out, Data In and Clock (DO/DI and SCK) cannot be moved but the optional Data Command, Chip Select and Reset are all moveable.
To use the hardware SPI the Data Out, Data In and Clock (DO/DI and SCK), Data Command, Chip Select and Reset are all moveable.
I have called InitSPIMode to call SPIMode if needed, and set the lines.
I have also define a sub called SendByteviaSPI to handle whether to call the Hardware or use Software (bit-banging) SPI.
Enjoy - really sorry for not getting this right in the first place!
weird data on the scope. byte1 = 255, byte2= 0 and byte3 = 255....looking at the clock edges the 255 on the right side of the scope is high all the way through. if I use anything less than 255 in byte1 then the waveform starts low before the clock pulses start. When set to 255 it starts off as high before the clock pulses.....why is this?
Mine sample code looks ok, but, I am set CS line.
Let me try you code.
Your code works here.
I did make the change to code to support my lines and implement the CS line to get my analyser to work.
@Macgman2000 . You were so right. HELP was meaningless!
Updated - check tomorrow. :-)
Is there an easy way to flip bits around to send LSB first?
You want to flip the bits? Assign the bits to a temporary variable and send the temporary variable.