![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
vinniewryan
Joined: 29 Jul 2009 Posts: 154 Location: at work
|
Spi comm with ISD1740 |
Posted: Mon Apr 25, 2011 3:02 pm |
|
|
Compiler 4.119
PIC16f677
MISO-SDI
MOSI-SDO
SCLK-SCL
SS-SS
I've searched the forums and the entire internet for source code using this chip but I haven't found anything or even anyone else with my particular problem. I'm using the ISD1740 in SPI mode, and I can't even so much as correctly read the device ID. I also tried contacting the engineers for Nuvoton but they don't seem to exist in the US.
My problem is that I'm not getting the proper responses from the chip when I send commands. I'm sending 0x09 for Device ID, which is followed by 1 blank byte and the third byte holds the device ID information, but I'm getting nothing but 10000000 back in the third byte. My code:
Code: | #include "16f677.h"
#use delay(clock=4000000)
#Fuses NOFCMEN,NOPROTECT,NOBROWNOUT,NOCPD,NOPUT,NOIESO,INTRC_IO,NOWDT,NOMCLR
#use rs232(baud=9600, INVERT, xmit=pin_a0, errors)
//#define RECORD 0x41
//#define PLAY 0x40
//#define STOP 0x02
//#define ERASE 0x42
//#define NEXT 0x48
#define CS pin_c6
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
int8 id=0;
int8 i=0;
unsigned int8 command=0;
unsigned int8 data=0;
/*
POWER UP 0x01
STOP 0x02
RESET 0x03
CLR_INT 0x04
RD_STATUS 0x05
POWER DOWN 0X07
DEVICE ID 0X09
*/
void main()
{
setup_oscillator(OSC_4MHZ);
setup_spi(SPI_MASTER | SPI_MODE_3 | SPI_CLK_DIV_16);
output_high(CS);
delay_ms(50);
output_low(CS);
spi_write(0x01);
spi_write(0x00);
output_high(CS);
delay_ms(50);
while(1)
{
output_low(CS);
delay_us(1);
command=(0x09);
bit_set(command,3); //bit4 = LED, 1=on
spi_write(command);
spi_write(0x00);
id=spi_read(0x00);
output_high(CS);
if(i>0)
{
if(bit_test(id,i))
{
printf("1");
}
else
{
printf("0");
}
i--;
}
else
{
if(bit_test(id,i))
{
printf("1>");
}
else
{
printf("0>");
}
i=7;
printf("id=%d,<", id); //id is returning 10000000, 128, 0x80
delay_ms(50);
}
}
} |
The program sends 0x01 0x00 which should power up the SPI mode, then after delay sends 0x09 0x00 0x00 and reads the last byte. Is this the correct way to do it?
My program prints "10000000>id=-128,<" in hyper terminal, and if I press the play button it starts printing random numbers "10000100>id=-124,<10000010>id=-126,<10000010>id=-126,<10000110>id=-122,<10000110>id=-122,<10000001>id=-127,<"
Then when I release the play button, it continues to send the LAST number "127". The only way this is possible is if when I press 'play', there's a lot of noise on the MOSI line which is writing into the chip then when I read back that's what I get.
Any ideas? I don't care about the jarbled numbers so much as not getting the correct DEVID. The noise I can filter out later. Connections are exactly as shown above, V+ is 3.6V.
Thanks
EDIT; also, I tried using software SPI with the exact same result. _________________ Vinnie Ryan |
|
![](templates/subSilver/images/spacer.gif) |
vinniewryan
Joined: 29 Jul 2009 Posts: 154 Location: at work
|
|
Posted: Mon Apr 25, 2011 4:18 pm |
|
|
I just found a reference that said none of the 4 hardware SPI modes are compatible with the ISD1700 chipcorders, is there a way to add a new mode to the current hardware SPI function that simply changes the order bits are sampled and such? Otherwise I'll have to bit bang this whole thing which is no big deal, but slightly annoying. _________________ Vinnie Ryan |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9174 Location: Greensville,Ontario
|
|
Posted: Mon Apr 25, 2011 5:50 pm |
|
|
Well it's not the end of the world writing your own driver but how can they say it's SPI interface if it's not one of the 4 known SPI modes?
Good news is their 'design notes' PDF is very well documented so you might only have to make 2 pots of coffee to get it up and running. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Apr 25, 2011 6:29 pm |
|
|
For hardware SPI, you can reverse the bits by calling a routine before
you send data to the chip, and after you receive it. See the end of
this post for an example, and a link to some routines that reverse the bits:
http://www.ccsinfo.com/forum/viewtopic.php?t=35566&start=3 |
|
![](templates/subSilver/images/spacer.gif) |
vinniewryan
Joined: 29 Jul 2009 Posts: 154 Location: at work
|
|
Posted: Tue Apr 26, 2011 12:40 pm |
|
|
I was trying to use SDO, but the data sheet states that SDO is unavailable on the 16f677. I have to use SDA as the SPI I/O. I've never done this before, is there any special care or extra setup I should consider? Tips always help :D _________________ Vinnie Ryan |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 26, 2011 12:47 pm |
|
|
The data sheet shows the pinout for the DIP package has SDO on pin 9:
http://ww1.microchip.com/downloads/en/DeviceDoc/41262E.pdf
Connect SDO on the PIC, to SDI on the slave device.
Connect SDI on the PIC, to SDO on the slave.
Connect SCLK on the PIC, to SCLK on the slave.
Connect \CS on the PIC to \CS on the slave.
You can use any output pin on the PIC as the \CS pin, since it's
manually controlled by your code. (The hardware SPI Master module
in the PIC doesn't control \CS). |
|
![](templates/subSilver/images/spacer.gif) |
vinniewryan
Joined: 29 Jul 2009 Posts: 154 Location: at work
|
|
Posted: Tue Apr 26, 2011 1:06 pm |
|
|
That's exactly what I thought, but then I tested the output of SDO with my scope and there was nothing coming out. The pin is just held high no matter what I send. Then I saw this note:
Code: | Note 1: SDO is available on PIC16F687/
PIC16F689/PIC16F690 only. | Page 79 (81 acrobat) Section 4.5.8
No output on SDO, the only thing that would cause that is incorrect setup in my code, but my setup is as follows:
Code: |
#use delay(clock=4000000)
#Fuses NOFCMEN,NOPROTECT,NOBROWNOUT,NOCPD,NOPUT,NOIESO,INTRC_IO,NOWDT,NOMCLR
#use rs232(baud=9600, INVERT, xmit=pin_a0, errors)
#define CS pin_c3
// MISO pin_b4
// MOSI pin_c7
// SCL pin_b6
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
unsigned int8 command=0;
unsigned int8 id=0;
|
Code: |
...
setup_oscillator(OSC_4MHZ);
setup_spi(SPI_MASTER | SPI_MODE_3 | SPI_CLK_DIV_16);
|
and my data transfer code is:
Code: |
command=(0x09); //00001001
swap_bits(command);
output_low(CS);
spi_write(command);
spi_write(0x00);
spi_write(0x00);
output_high(CS);
|
_________________ Vinnie Ryan |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 26, 2011 1:36 pm |
|
|
I think there is a problem with the 16F677 data sheet.
In the pinout diagram, at the beginning of the data sheet, it says SDO
is available. In this table it lists SDO on pin 9.
Quote: | TABLE 2: PIC16F677 PIN SUMMARY |
But then, in the I/O Ports section, it has a gray box with this note:
Quote: | Note 1:
SDO is available on PIC16F687/ PIC16F689/PIC16F690 only. |
If true, then you must use software SPI with this PIC. |
|
![](templates/subSilver/images/spacer.gif) |
vinniewryan
Joined: 29 Jul 2009 Posts: 154 Location: at work
|
|
Posted: Tue Apr 26, 2011 1:46 pm |
|
|
ah, and you know I tried software SPI with the same result, but I was using SPI1 to define the SPI pins as the hardware pins, so it would have had the exact same result. I'll try again using all defined pins, thanks for confirming my confusion! _________________ Vinnie Ryan |
|
![](templates/subSilver/images/spacer.gif) |
vinniewryan
Joined: 29 Jul 2009 Posts: 154 Location: at work
|
|
Posted: Tue Apr 26, 2011 2:51 pm |
|
|
I'm getting output on SDO now, but still no device ID returned. when I send 0x09 all I get back is 10000000 00000000 but when I press the PLAY button that number changes randomly while the sound is playing.
Here's an example:
comm = the number I send to the ISD
ID = the number received from the ISD
Code: |
<1000000000000000>id=32768<comm=144>
<1000000000000000>id=32768<comm=144>
<1000000000000000>id=32768<comm=144>
<1000000000000000>id=32768<comm=144>
<1000000000000000>id=32768<comm=144>
<1000000000000000>id=32768<comm=144>
<1000000000000000>id=32768<comm=144>
<1000000000000000>id=32768<comm=144>
<1000011100100000>id=34592<comm=144> - Pressed PLAY
<1000011100100000>id=32928<comm=144>
<1000000010100000>id=32928<comm=144>
<1000010010100000>id=33952<comm=144>
<1000001010100000>id=33440<comm=144>
<1000011010100000>id=34464<comm=144>
<1000000110100000>id=33184<comm=144>
<1000000110100000>id=34208<comm=144>
<1000010110100000>id=33696<comm=144>
<1000001110100000>id=33696<comm=144>
<1000011110100000>id=34720<comm=144> - Playback stopped
<1000011110100000>id=34720<comm=144>
<1000011110100000>id=34720<comm=144>
<1000011110100000>id=34720<comm=144>
<1000011110100000>id=34720<comm=144>
... |
I've tested with 2 different ISD chips and 677's so I know it's not a bad chip.
This is the program I'm using:
Code: | #include "16f677.h"
#use delay(clock=4000000)
#Fuses NOFCMEN,NOPROTECT,NOBROWNOUT,NOCPD,NOPUT,NOIESO,INTRC_IO,NOWDT,NOMCLR
#use rs232(baud=9600, INVERT, xmit=pin_a0, errors)
#use spi(MASTER,DO=pin_c7,DI=pin_b4,CLK=pin_b6,MODE=3)
#define CS pin_c3
unsigned int16 id=0;
int8 i=0;
unsigned int8 command=0;
/*
POWER UP 0x01
STOP 0x02
RESET 0x03
CLR_INT 0x04
RD_STATUS 0x05
POWER DOWN 0X07
DEVICE ID 0X09
*/
int8 swap_bits( int8 data )
{
int8 result=0;
if(bit_test(data,0)) bit_set(result,7);
if(bit_test(data,1)) bit_set(result,6);
if(bit_test(data,2)) bit_set(result,5);
if(bit_test(data,3)) bit_set(result,4);
if(bit_test(data,4)) bit_set(result,3);
if(bit_test(data,5)) bit_set(result,2);
if(bit_test(data,6)) bit_set(result,1);
if(bit_test(data,7)) bit_set(result,0);
command=result;
}
void main()
{
setup_oscillator(OSC_4MHZ);
output_high(CS);
delay_ms(50);
command=(0x01);
swap_bits(command);
output_low(CS);
spi_xfer(command);
spi_xfer(0x00);
output_high(CS);
delay_ms(50);
while(1)
{
command=0x09; //00001001 0x09
swap_bits(command);
output_low(CS);
spi_xfer(command);
id=spi_xfer(0x00);
output_high(CS);
if(i>0)
{
if(bit_test(id,i))
{
printf("1");
}
else
{
printf("0");
}
i--;
}
else
{
if(bit_test(id,i))
{
printf("1>");
}
else
{
printf("0>");
}
i=15; //7,31
printf("id=%lu<comm=%u><", id,command); //id is returning 10000000, 128, 0x80
delay_ms(50);
}
}
} |
going on coffee pot 7 _________________ Vinnie Ryan |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 26, 2011 3:00 pm |
|
|
I have to go help build some boards but will look at this later in the afternoon. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 26, 2011 6:19 pm |
|
|
I did some testing with a 16F690 with your version of the compiler.
(I don't have the 16F677, but they are in the same family).
I discovered that you need to make the changes shown in bold below:
Quote: |
#use spi(MASTER, DO=PIN_C7, DI=PIN_B4, CLK=PIN_B6, MODE=3, LSB_FIRST, BITS=8) |
The #use spi() library defaults to 32-bit transfers. I saw that on the
scope. So definitely you need to add the BITS=8. Then, it has the feature
to do LSB-first transfers. I tested this and looked at the waveforms on the
scope, and it does work. So add that parameter as well.
With the LSB-first feature, you don't need the swap_bits() function and
you can delete that from your program, completely.
These may not be the only things that needed to be corrected, but I'm
sure they will help a lot. If it still doesn't work, I can work on it again
tomorrow. |
|
![](templates/subSilver/images/spacer.gif) |
vinniewryan
Joined: 29 Jul 2009 Posts: 154 Location: at work
|
|
Posted: Tue Apr 26, 2011 11:55 pm |
|
|
Great catch, I made both changes. Still absolutely no response from the ISD unfortunately, but I'm confident the program is correct now. I wasn't sure the speed which SPI is running without specifying the baud, so I did a little experimenting with rates from 20,000 to 200,000, to no baud (fastest possible), with no success. It seems the ISD just doesn't like to cooperate. Thanks for your help so far, I've tested the output from the pic with a scope and all looks perfect. Now I wonder if I'm setting CS incorrectly to receive data from the ISD.
Looks like my head will be buried in this design guide for a while. _________________ Vinnie Ryan |
|
![](templates/subSilver/images/spacer.gif) |
vinniewryan
Joined: 29 Jul 2009 Posts: 154 Location: at work
|
|
Posted: Wed Jun 01, 2011 12:56 pm |
|
|
I finally got this chip working, though when I read the DEVID it seems to think its a 1760 rather than a 1740 (receiving 10100000, expecting 10110000). I can live with that, everything else is checking out perfectly. I now have successful 2-way communication with the ISD. Thanks again for the help!
Code: | #include "16f688.h"
#use delay(clock=4000000)
#Fuses NOFCMEN,NOPROTECT,NOBROWNOUT,NOCPD,NOPUT,NOIESO,INTRC_IO,NOWDT,NOMCLR
#use rs232(baud=9600, INVERT, xmit=pin_a0, errors)
#use spi(MASTER,DO=pin_c2,DI=pin_c1,CLK=pin_c4,MODE=3,BITS=8,LSB_FIRST)
#define CS pin_c3
int8 sr0=0;
int8 row=0;
int8 id=0;
int8 i=0;
int8 command=0;
int1 button=0;
int8 request=0;
/*
POWER UP 0x01
STOP 0x02
RESET 0x03
CLR_INT 0x04
RD_STATUS 0x05
POWER DOWN 0X07
DEVICE ID 0X09
*/
int8 swap_bits( int8 data )
{
int8 result=0;
if(bit_test(data,0)) bit_set(result,7);
if(bit_test(data,1)) bit_set(result,6);
if(bit_test(data,2)) bit_set(result,5);
if(bit_test(data,3)) bit_set(result,4);
if(bit_test(data,4)) bit_set(result,3);
if(bit_test(data,5)) bit_set(result,2);
if(bit_test(data,6)) bit_set(result,1);
if(bit_test(data,7)) bit_set(result,0);
return result;
}
int8 pb(int8 data)
{
if(bit_test(data,0)) printf("1");
else printf("0");
if(bit_test(data,1)) printf("1");
else printf("0");
if(bit_test(data,2)) printf("1");
else printf("0");
if(bit_test(data,3)) printf("1");
else printf("0");
if(bit_test(data,4)) printf("1");
else printf("0");
if(bit_test(data,5)) printf("1");
else printf("0");
if(bit_test(data,6)) printf("1");
else printf("0");
if(bit_test(data,7)) printf("1");
else printf("0");
}
void main()
{
setup_oscillator(OSC_4MHZ);
while(1)
{
command=0;
sr0=0;
row=0;
id=0;
if(!input(pin_a5))
{
button=1;
delay_ms(200);
}
if(button==1)
{
if(request<5)
{
if(request==0)
{
command=0x01; //00000001 0x01
printf("PU \r");
}
if(request==1)
{
command=0x03; //00000011 0x03
printf("RESET \r");
}
if(request==2)
{
command=0x04; //00000100 0x04
printf("CLEAR INT \r");
}
if(request==3)
{
command=0x05; //00000101 0x05
printf("STATUS \r");
}
if(request==4)
{
command=0x09; //00001001 0x09
printf("ID \r");
}
request++;
output_low(CS);
spi_xfer(command);
sr0=spi_xfer(0); // SR0
row=spi_xfer(0); // SR0
id=spi_xfer(0); // Data
output_high(CS);
printf("command=%d sr0=%d row=%d id=%d \r", command,sr0,row,id);
command=swap_bits(command); //not needed anymore
pb(command);
row=swap_bits(row);
pb(row);
command=0;
sr0=0;
row=0;
id=0;
button=0;
}
else
{
printf("...\r...\r");
request=0;
button=0;
}
}
}
}
|
_________________ Vinnie Ryan |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9174 Location: Greensville,Ontario
|
|
Posted: Wed Jun 01, 2011 2:23 pm |
|
|
Quick...printout a hard copy of your work !!make a few backups, here and there, just to be safe !!
Maybe even upload onto the 'working programs' forum here, for others...
Nothing is more frustating than losing several dayze hard labour to a computer hiccup ....
Maybe the devid is for the 'family' of devices and not specific to the device you have ?
Heck, it's working...be happy ! |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|