adc3208 - c code - problems...
Hello all,
Hopefully somebody can spot what I can't see!
Channel 0 works 100% ok - the others return gibberish.· Checked the circuit and the inputs as far as I can.· I guess something is going out of sequence here - but why then is channel 0 working all the time?· The loops appear to be outputing/inputting the correct number of bits.
Thanks!
James
Edit -> Included variable declarations & pins.
Post Edited (Javalin) : 9/2/2009 5:44:13 AM GMT
Hopefully somebody can spot what I can't see!
Channel 0 works 100% ok - the others return gibberish.· Checked the circuit and the inputs as far as I can.· I guess something is going out of sequence here - but why then is channel 0 working all the time?· The loops appear to be outputing/inputting the correct number of bits.
Thanks!
[color=#008000][color=#008000]// pins...[/color][/color]
[color=black]int adc_clk = 15;
int adc_di = 14;
int adc_do = 13;
int adc_cs = 12;[/color]
[color=#000000]//code[/color]
[color=black]void main(void)[/color]
[color=black]{[/color]
[color=black]
int i = 0;
int result = 0;
int spiData = 0;
int adcMUX = 0;
int adcData = 0;
int adcChannel[noparse][[/noparse]8];
[/color] SET (DIRA, adc_cs); [color=#008000][color=#008000]// output [/color][/color]
SET (DIRA, adc_do); [color=#008000][color=#008000]// output [/color][/color]
SET (DIRA, adc_clk); [color=#008000][color=#008000]// output [/color][/color]
CLR (DIRA, adc_di); [color=#008000][color=#008000]// input[/color][/color]
CLR (OUTA,adc_cs); [color=#008000][color=#008000]// low[/color][/color]
msleep(10); [color=#008000][color=#008000]// wait a tick[/color][/color]
SET (OUTA,adc_cs); [color=#008000][color=#008000]// high [/color][/color]
[color=#008000][color=#008000] // ADC![/color][/color]
while(TRUE)
{
printf([i]"is -> "[/i]);
putchar(32);
for (i=0; i<8; i++)
{
adcMUX = 0b00011000 + i; [color=#008000][color=#008000]// command byte[/color][/color]
CLR (OUTA,adc_cs); [color=#008000][color=#008000]// low [/color][/color]
CLR (OUTA,adc_do); [color=#008000][color=#008000]// low[/color][/color]
CLR (OUTA,adc_clk); [color=#008000][color=#008000]// low[/color][/color]
shiftout (adcMUX,8); [color=#008000][color=#008000]// output the cmd byte [/color][/color]
CLR (OUTA,adc_clk); [color=#008000][color=#008000]// low[/color][/color]
SET (OUTA,adc_clk); [color=#008000][color=#008000]// high [/color][/color]
CLR (OUTA,adc_clk); [color=#008000][color=#008000]// low[/color][/color]
SET (OUTA,adc_clk); [color=#008000][color=#008000]// high[/color][/color]
CLR (OUTA,adc_clk); [color=#008000][color=#008000]// low [/color][/color]
adcChannel[noparse][[/noparse]i] = shiftin(12); [color=#008000][color=#008000]// clock in the data[/color][/color]
SET (OUTA,adc_cs); [color=#008000][color=#008000]// high [/color][/color]
FdSerial_dec(adcChannel[noparse][[/noparse]i]);
putchar(32);
msleep(10);
}
putchar(13);
msleep(500);
}
}
int shiftin(short bitCnt)
{
short i=0;
int data=0;
int inputpinMask = 1 << adc_di;
for(i=0; i<bitCnt; i++)
{
CLR (OUTA,adc_clk); [color=#008000][color=#008000]// low[/color][/color]
SET (OUTA,adc_clk); [color=#008000][color=#008000]// high [/color][/color]
data <<= 1; [color=#008000][color=#008000]// shift-left the data [/color][/color]
[color=#008000][color=#008000] //data |= ((INA & inputpinMask) != 0); // read the port[/color][/color]
if (INA & inputpinMask)
{
data |= 1;
}
}
return data;
}
void shiftout(int spiData,short bitCnt)
{
short i=0;
for(i=0; i<bitCnt; i++)
{
[color=#008000][color=#008000] // test for state of bit (n) [/color][/color]
if (spiData & (1 << i))
{
SET (OUTA,adc_do);
}
else
{
CLR (OUTA,adc_do);
}
[color=#008000][color=#008000] // pulse the clock[/color][/color]
SET (OUTA,adc_clk); [color=#008000][color=#008000]// high[/color][/color]
CLR (OUTA,adc_clk); [color=#008000][color=#008000]// low [/color][/color]
}
}
James
Edit -> Included variable declarations & pins.
Post Edited (Javalin) : 9/2/2009 5:44:13 AM GMT

Comments
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
April, 2008: when I discovered the answers to all my micro-computational-botherations!
And I'll kill you[noparse][[/noparse]tm] if you are using a global 'i' for the counter in main.
I'll kill you:
<
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
There's no way to tell whether this is a problem without seeing your circuit. The mystery why the channel #0 works remains unexplained so I'd expect that you have the wires right.
BTW, you need to have analog signal connected to a channel pin, if you just leave the pin unconnected it won't show 0 (or close to 0), it will produce numbers all over the range. Could this be the case?
Also I am not sure you have your pre clocks correct. If I were you I would let the shift in routine take care of the null bit by adcChannel = shiftin(13); and dropping the extra clocks between.
Last time I debugged communication with this chip I used jazzed's prop based logic program to look at the pattern.
I have no clue about hardware issues, but regarding global i vs. local i, the compiler "does the right thing" (tm)
The original program is incomplete so we can only guess that main() does in fact use a global i. Regardless, that should not cause any issue either way.
// richard
I'm not!· The code isn't finished either way!
Erik
Tried that - no joy.
All,
The output is weird - ch0 works nicely goes from 0 (ish) to 4095 but the other 7 channels all seems to move with the change when I vary the input to channel 3 for example!
Hardware wise its on·a PPDB board - I currently have a pot on ch0 and 3.· Tried 3.3v and 5v voltage sources - didn't help.· Tried different I/O pins.
Its almost like its reading differential channels or reading the LSB first data somehow.
I'll re-write the code in SPIN to test the circuit.· I have some PASM that works well - that this is based on.· Found some weirdness looking at the I/O via an O-scope.
Thanks all,
James
Post Edited (Javalin) : 9/2/2009 7:19:58 AM GMT
Richard - if I use local variables are they kept within the cog that piece of code runs under? I.e. like PASM? I ask cause SPIN obviously has no local variables.
Cheers,
James
Spin has local variables in methods ... i.e. pub start(codep, parmp) | j, k ... guess which ones are local (normally kept in the stack).
There is nothing in the code you posted that suggests you are using multiple cogs. What do you have connected to the ADC channels?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
Propeller Tools
I think Achmed, the dead terrorist is funny enough for that quote. Hope none took it too serious.
But a global counter is really something that needs punishment. If he would have used the same i in the other functions, the result would have been quite confusing.
@James:
Use #defines for adc_clk etc.
These are constants, not variables.
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
Post Edited (Nick Mueller) : 9/2/2009 7:12:28 AM GMT
(yeah the 0b is probably a microchip thing for binary)
It explains why channel0 works - as the code is the same both ways arround (i.e. 00011000)!
Doh. Good spot.
I'll post the fixed C code and the SPIN equivalent tonight
Cheers again all,
James
the compiler doesn't like:
#define adc_clk 15 /* or whatever */
Help?
james
Did he say "I don't like that"?
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
I'll post the exact error tonight
James
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
Propeller Tools
James
#define adc_cs=15;
#define adc_cs 15;
and then (which worked)
#define adc_cs 15
(no ";")
James
Out of interest I took some timing's via O'scope from when CS goes LOW to when it returns to HIGH - a single channel read!
C·= 175us
SPIN = 1.89ms
#include <propeller.h> #include <stdio.h> #include "FdSerial.h" [color=#008000][color=#008000]// define pins (constants) [/color][/color] const short adc_clk=15; const short adc_di=14; const short adc_do=13; const short adc_cs=12; [color=green]// fwd declarations[/color] void shiftout(int spiData,short bitCnt); int shiftin(short bitCnt); void main(void) { int result = 0; int spiData = 0; int adcMUX = 0; int adcData = 0; int adcChannel[noparse][[/noparse]8]; int channel=0; FdSerial_start(31,30,0,115200); putchar(0); // clear screen [color=#008000][color=#008000] // pins...[/color][/color] SET (DIRA, adc_cs); [color=#008000][color=#008000]// output [/color][/color] SET (DIRA, adc_do); [color=#008000][color=#008000]// output [/color][/color] SET (DIRA, adc_clk); [color=#008000][color=#008000]// output [/color][/color] CLR (DIRA, adc_di); [color=#008000][color=#008000]// input[/color][/color] CLR (OUTA,adc_cs); [color=#008000][color=#008000]// low[/color][/color] msleep(10); [color=#008000][color=#008000]// wait a tick[/color][/color] SET (OUTA,adc_cs); [color=#008000][color=#008000]// high [/color][/color] [color=#008000][color=#008000] // ADC![/color][/color] while(TRUE) { for (channel=0; channel<8; channel++) { adcMUX = 24 + channel; [color=#008000][color=#008000]// mux [/color][/color] printf([i]"ch %d\t"[/i], channel); FdSerial_bin(adcMUX,8); putchar([i]' '[/i]); CLR (OUTA,adc_cs); [color=#008000][color=#008000]// low [/color][/color] CLR (OUTA,adc_do); [color=#008000][color=#008000]// low[/color][/color] CLR (OUTA,adc_clk); [color=#008000][color=#008000]// low[/color][/color] shiftout (adcMUX,8); [color=#008000][color=#008000]// output the cmd byte [/color][/color] CLR (OUTA,adc_clk); [color=#008000][color=#008000]// low[/color][/color] SET (OUTA,adc_clk); [color=#008000][color=#008000]// high [/color][/color] CLR (OUTA,adc_clk); [color=#008000][color=#008000]// low[/color][/color] SET (OUTA,adc_clk); [color=#008000][color=#008000]// high[/color][/color] CLR (OUTA,adc_clk); [color=#008000][color=#008000]// low [/color][/color] adcChannel[noparse][[/noparse]channel] = shiftin(12); [color=#008000][color=#008000]// clock in the data [/color][/color] SET (OUTA,adc_cs); [color=#008000][color=#008000]// high [/color][/color] printf([i]"\t%d"[/i], adcChannel[noparse][[/noparse]channel]); printf([i]"\r"[/i]); } printf([i]"\r"[/i]); [color=#008000][color=#008000]// new line [/color][/color] msleep(500); [color=green]// wait a tick[/color] } } int shiftin(short bitCnt) { short i3=0; int data=0; int inputpinMask = 1 << adc_di; [color=#008000][color=#008000] // shift in the data (MSB first) [/color][/color] for(i3=0; i3<bitCnt; i3++) { CLR (OUTA,adc_clk); [color=#008000][color=#008000]// low[/color][/color] SET (OUTA,adc_clk); [color=#008000][color=#008000]// high [/color][/color] data <<= 1; [color=#008000][color=#008000]// shift-left the data (MSB First) [/color][/color] data |= ((INA & inputpinMask) != 0); [color=#008000][color=#008000]// read the port[/color][/color] } return data; } void shiftout(int spiData,short spiBitCnt) { short i2=0; [color=#008000][color=#008000] // shift out the data (MSB first)[/color][/color] for(i2=spiBitCnt; i2>=0; i2--) { [color=#008000][color=#008000] // test for state of bit (n) [/color][/color] if (spiData & (1 << i2)) { SET (OUTA,adc_do); } else { CLR (OUTA,adc_do); } [color=#008000][color=#008000] // pulse the clock[/color][/color] SET (OUTA,adc_clk); [color=#008000][color=#008000]// high[/color][/color] CLR (OUTA,adc_clk); [color=#008000][color=#008000]// low [/color][/color] } }The output (Parallax Serial Terminal) looks like:
And the SPIN code:
'' ************************************************************************************** '' ************************************************************************************** '' * editor-tabs: 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 * '' ************************************************************************************** CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 _stack = 500 ' ADC MCP3208 pins mcp3208clk = 15 mcp3208di = 14 mcp3208do = 13 mcp3208cs = 12 ' debug - USE onboard pins pcDebugRX = 31 pcDebugTX = 30 ' serial baud rates pcDebugBaud = 115200 ' 57600, 115200 or 256000 only OBJ debug : "Debug_PC" VAR long channel, adcMUX, data1 PUB Start ' start the PC debug object debug.startx(pcDebugRX,pcDebugTX,pcDebugBaud) dira[noparse][[/noparse]mcp3208clk]~~ dira[noparse][[/noparse]mcp3208cs]~~ dira[noparse][[/noparse]mcp3208do]~~ dira[noparse][[/noparse]mcp3208di]~ outa[noparse][[/noparse]mcp3208cs]~ waitcnt(clkfreq/5+cnt) outa[noparse][[/noparse]mcp3208cs]~~ repeat repeat channel from 0 to 7 debug.str(string("is -> ch")) debug.dec(channel) debug.str(string(", ")) adcMUX := %0001_1000 + channel debug.bin(adcMUX,8) outa[noparse][[/noparse]mcp3208clk]~ outa[noparse][[/noparse]mcp3208cs]~ outa[noparse][[/noparse]mcp3208do]~ shiftout(adcMUX,8) debug.str(string(", ")) outa[noparse][[/noparse]mcp3208clk]~ outa[noparse][[/noparse]mcp3208clk]~~ outa[noparse][[/noparse]mcp3208clk]~ outa[noparse][[/noparse]mcp3208clk]~~ outa[noparse][[/noparse]mcp3208clk]~ data1 := shiftin(12) outa[noparse][[/noparse]mcp3208cs]~~ debug.str(string(", ")) debug.dec(data1) debug.putc(13) debug.putc(13) PRI ShiftIn(spiBitCnt) : result | i3, spidata1 spidata1 := 0 repeat i3 from 0 to spiBitCnt-1 ' clock outa[noparse][[/noparse]mcp3208clk]~ outa[noparse][[/noparse]mcp3208clk]~~ ' data spidata1 <<= 1 spidata1 |= ina[noparse][[/noparse]mcp3208di] return spiData1 PRI ShiftOut(spiData,spiBitCnt) | i2, data, mask mask := %1 << spiBitCnt debug.putc(" ") repeat i2 from 0 to spiBitCnt-1 ' data mask >>= 1 if spiData & mask debug.putc("x") outa[noparse][[/noparse]mcp3208do]~~ else debug.putc("o") outa[noparse][[/noparse]mcp3208do]~ ' clock outa[noparse][[/noparse]mcp3208clk]~~ outa[noparse][[/noparse]mcp3208clk]~output is:
I've left the debug in the SPIN object.
James
Post Edited (Javalin) : 9/3/2009 8:03:03 PM GMT
But I wrote that.
printf("ch"); // serial debug putchar(32); FdSerial_dec(channel); putchar(9); FdSerial_bin(adcMUX,8);That would be:
printf("ch %d\t0X%x", channel, adcMUX);You shouldn't mix printf and FdSerial_bin etc. Albeit it doesn't matter here, the is no guaranty that the two make some buffering or not.
OK, %x doesn't print a binary, only a hex. And the stdio with format specifiers (length etc.) is quite expensive size-wise.
putchar(9); // tab FdSerial_dec(adcChannel[noparse][[/noparse]channel]); // serial debug putchar(32); putchar(13);thats:
printf("\t%d \n", adcChannel[noparse][[/noparse]channel]);putchar(32); would be putchar(' '); and putchar(9); putchar('\t');
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
One of my biggest ICC frustrations is that some format specifiers just don't work at all ... I could be mistaken, but I don't remember %04x working at all in any printf mode.
Using printf, sprintf, snprintf, vfprintf, yada yada carries a big cost. If you are using it, make sure you take full advantage of it. It's not entirely clear how ICC interprets the format specifiers (perhaps the ICC on-line manual addresses this), but you can get a feel by looking at a sprintf man page like this: linux.die.net/man/3/sprintf
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
Propeller Tools
Thanks for the formatting suggestions - hadn't thought of that!
That would be:
printf("ch %d\t0X%x", channel, adcMUX);Is there a binary formatter for printf?· Google wasn't my friend on that one!
Post updated with the rest though!
James
But I wrote that, right?
> One of my biggest ICC frustrations is that some format specifiers just don't work at all ... I could be mistaken,
> but I don't remember %04x working at all in any printf mode.
No, that works! You have to select the printf-lib one level higher (project settings IIRC). There are three: with float (not that one), full format specifiers (or something like this) and "primitive". Default is primitive, and this one doesn't understand field lengths.
But, as I said, it is quite bigger in code-size!
> Is there a binary formatter for printf?
Officially not. Maybe ICC has one but I really don't remember. I guess not. But programmers can translate hex to bin anyhow.
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
The '#define someConstant' is one way. An other way (and more up to date) is to write 'const int 4711'.
Some compilers might emmit less code with '#define'. I didn't check with ICC.
But anyhow, you have to learn that #define, #ifdef, #endif stuff, it's good for debugging, production code, different versions (language, platform, etc).
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
> You shouldn't mix printf and FdSerial_bin etc. Albeit it doesn't matter here, the is no guaranty that the two make some buffering or not.
I prefer using const int ...; over #define since you avoid "label" collision problems in large projects. I prefer static const int ...; where possible of course.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
Propeller Tools
Label!? That sounds like a four letter word, like 'goto'. I'm shocked!
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
Propeller Tools