|
|
View previous topic :: View next topic |
Author |
Message |
Kasper
Joined: 14 Jan 2004 Posts: 88 Location: Aurora, Ontario, Canada
|
Assembly to C. Code not working right :( |
Posted: Thu Jan 19, 2006 3:25 pm |
|
|
Hi.
I am trying to make a pic16F639 talk to its internal Low Frequency front end via software SPI.
The 639 is identical to a 636 but has an MCP2030 chip in the same package, connected via RC1,2,3.
I have sample code from microchip for their demo board, which is in assembler. I am therefor trying to rewrite it in C. This is where I am running into trouble.
I hooked up a couple of unused IO's to an RS232 port in so I can monitor the what is happening internally, which tells me this
AFE[0] = 0xA0 -- SPI_READ[0] = 0x0000
AFE[1] = 0x00 -- SPI_READ[1] = 0x0000
AFE[2] = 0x00 -- SPI_READ[2] = 0x0000
AFE[3] = 0x00 -- SPI_READ[3] = 0x0000
AFE[4] = 0x00 -- SPI_READ[4] = 0x0000
AFE[5] = 0x10 -- SPI_READ[5] = 0x0000
AFE[6] = 0x4F -- SPI_READ[6] = 0x0000
the SPI_reads should return the AFE data, shifted left one bit. As you can see, it is not happening.. I think I have stared myself blind looking at this, so if anyone has any suggestions it would be most welcome
I can upload the entire Assembly if needed, but it is rather long. These are the sections which I have failing :(
Code: |
#define AFECS PORTC,1 ; Chip select output
#define SCK PORTC,2 ; SPI Clock Output
#define SDIO PORTC,3 ; Serial Data Input/Output
#define LFDATA PORTC,3 ; Low Frequency Data IN
|
pin defines.
Code: |
Set_up_AFE_Registers
bsf STATUS,RP0
movfw TRISC
andlw b'11000000' ; chuck, Setup SDIO,SCLK, and CS as outputs
movwf TRISC ;
bcf STATUS,RP0
; Register 0: 0000-0001 - 0 (parity)
;----------------------------------------------------
movlw WriteCommand+GeneralOptions+((AFEConfig0>>8)&0x01)
movwf SPIBufH
movlw AFEConfig0&0xFF
movwf SPIBufL
call ShiftOutSPIBuffer
; Verify Register 0
movlw ReadCommand+GeneralOptions
movwf SPIBufH
movlw 0x00
movwf SPIBufL
call ShiftOutSPIBuffer
call ShiftInSPIBuffer
movfw SPIBufL
xorlw AFEConfig0&0xFF
btfss STATUS,Z
retlw 0x01
; Register 1: 0000-0000 - 1 (parity)
;-------------------------------------------
|
this repeats for each register, trying to save space here
Code: | ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Subroutine: ShiftOutSPIBuffer
;
; Description: This routine is used to shift data out of the microcontroller
; onto the SPI bus.
;
;Notes:
;1. This routine assumes 16-bit data is in SSPBufH and SSPBufL already.
;3. Control the ports as follows:
; Clear SCK/ALERT
; Clear chip select
;Loop
; Set or clear LFDATA/SDIO pin.
; Set SCK/ALERT
; Clear SCK/ALERT
; Goto Loop 16 times
; Set chip select
;Count00
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ShiftOutSPIBuffer
movlw .16
movwf Count00
bcf SCK
bcf AFECS
ShiftOutLoop
rlf SPIBufL, f
rlf SPIBufH, f
btfss STATUS, C
bcf SDIO
btfsc STATUS, C
bsf SDIO
bsf SCK
bcf SCK
; CLRWDT
decfsz Count00, f
goto ShiftOutLoop
bsf AFECS
bcf AFECS
return
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Subroutine: ShiftInSPIBuffer
;
; Description: This routine is used to shift data into the microcontroller
; from the SPI bus.
;
;Notes:
;1. This routine loads 16-bit data into the SSPBufH and SSPBufL registers.
;3. Control the ports as follows:
; Clear SCK/ALERT
; Clear chip select
;Loop
; Set SCK/ALERT
; Shift in the LFDATA/SDIO pin value.
; Clear SCK/ALERT
; Goto Loop 16 times
; Set chip select
;Count00
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ShiftInSPIBuffer
movlw .16
movwf Count00
bsf STATUS,RP0
bsf TRISC,3 ;Set SDIO as an input
bcf STATUS,RP0
bcf SCK
bcf AFECS
ShiftInLoop
bsf SCK
btfss SDIO
bcf STATUS, C
btfsc SDIO
bsf STATUS, C
rlf SPIBufL, f
rlf SPIBufH, f
bcf SCK
; CLRWDT
decfsz Count00, f
goto ShiftInLoop
bsf AFECS
bcf SCK
bsf STATUS,RP0
bcf TRISC,3 ;Set SDIO as an output
bcf STATUS,RP0
return
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
So here is my C code. as my first attempt using fancier looking functions failed, I tried duplicating the assembly as much as possible, yet I am still failing :(
Code: |
#use rs232(baud=9600,parity=N,xmit=PIN_C0,rcv=PIN_C4,bits=8)
#include "interupt.c" // file with the Interrupt Service Routines in it.
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
setup_timer_1(T1_DISABLED);
setup_comparator(NC_NC_NC_NC);
output_high(LF_CS);
// output_low(LF_ALERT);
// output_float(LF_ALERT);//
if( Set_Up_AFE_Registers()==0) {
output_low(PIN_A5);
}
// port_a_pullups(true);
// set_tris_a(0x01); // only pin 1 is input.used to wake up the processor from the low frequency front end.
// enable_interrupts(INT_EXT);
// enable_interrupts(GLOBAL);
printf("\n\r");
while(TRUE) {
sleep();
}//END WHILE
}// END MAIN
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int Set_Up_AFE_Registers(void) {
int errorlevel=0;
int16 SPIREAD,TXDATA;
int i,address;
for(i=0;i<7;i++) {
address = SPI_WRITE_COMMAND | i; //WRITE AFE Registers
TXDATA = make16(address,AFE[i]);
TXDATA = TXDATA << 1;
TXDATA = parity16(TXDATA);
shift_out_SPI(TXDATA); //READ AFE Registers
address = SPI_READ_COMMAND | i; // Generate the SPI Read command
TXDATA = make16(address,0x00);
TXDATA = TXDATA << 1;
//TXDATA = parity16(TXDATA); .. seems the sample source code does not have parity on the read byte.
shift_out_SPI(TXDATA); // Send the read command
SPIREAD=shift_in_spi();// now clock the data back in
delay_ms(100);
printf("\r\nAFE[%d] = 0x%X -- ",i,AFE[i]);
printf("SPI_READ[%d] = 0x%LX",i,SPIREAD);
}
return errorlevel;
}
///////////////////////////////////////////////////////////////////////////////
void shift_out_SPI(int16 DATA) {
int i;
output_low(LF_ALERT);
output_low(LF_CS);
for(i=0;i<16;i++) {
if(bit_test(DATA,0)) {
output_high(LF_DATA);
}
else {
output_low(LF_DATA);
}
output_high(LF_ALERT);
output_low(LF_ALERT);
DATA = DATA >> 1;
}//end for
output_high(LF_CS);
//output_low(LF_CS);
output_float(LF_ALERT);
}//end function
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
int16 shift_in_spi(void){
int16 RETDATA;
int DATA[2];
int i;
//set_tris_c(SPI_READ_Direction);
//output_float(LF_DATA);
output_low(LF_ALERT);
output_low(LF_CS);
for(i=0;i<16;i++) {
shift_left(DATA,2,input(LF_DATA));
output_high(LF_ALERT);
output_low(LF_ALERT);
}
output_high(LF_CS);
output_low(LF_ALERT);
//set_tris_c(SPI_WRITE_Direction);
RETDATA=make16(DATA[1],DATA[0]);
return RETDATA;
} // end function
///////////////////////////////////////////////////////////////////////////////
//**************************************************************************//
int16 parity16(int16 DATA) {
// Add parity to the DATA to be send to the Low frequency front end.
// the parity is ODD, and only on the 8 data bits, which are located at'D' "CCCAAAADDDDDDDDP"
//the parity is added in the LSB position.
int i;
int count=0;
int16 ReturnData;
ReturnData= DATA;
for(i=0;i<8;i++) {
if(DATA& 0x0001) {
count++;
}
DATA=DATA>>1;
}
if(count%2 == 0){
ReturnData = (ReturnData | 0x0001); // the 0x0002 is because we check the lsb of the data, which is not in the right most position, as that is where the parity bit is.
}
return ReturnData;
}
|
here is my pinout.h file
Code: |
//RA_TRIS EQU B'00111111'
//RC_TRIS EQU B'00001110'
// ENDIF
// IFDEF P16F639
// _________
// Vdd | 1 20 | Vss
// S0 | 2 19 | S5/SlowFall
// S1 | 3 18 | S4/LFDint
// S2 | 4 17 | S3/SHIFT/RFEN
// DATA | 5 16 | LED1n 16F639
// LED2n | 6 15 | RC1/CSn
// RC3/LFDATA/SDIO | 7 14 | RC2/SCLK/Alert
// Vddt | 8 13 | Vsst
// LCZ | 9 12 | LCCOM
// LCY | 10 11 | LCX
// ---------
#define S0 PORTA,5 // S0 BUTTON INPUT
#define S1 PORTA,4 // S1 BUTTON INPUT
#define S2 PORTA,3 // S2 BUTTON INPUT
#define S3 PORTA,2 // S3 BUTTON INPUT
#define S4 PORTA,1 // S4 BUTTON INPUT
#define LFDint PORTA,1
#define S5 PORTA,0 // S5 BUTTON INPUT
#define RFEN PORTA,2 // RF ENABLE OUTPUT
#define RFENtris TRISA,2
#define SHIFT PORTA,2 // SHIFT BUTTON INPUT
#define LED PORTC,0 // LED output
#define AFECS PORTC,1 // Chip select output
#define SCK PORTC,2 // SPI Clock Output
#define SDIO PORTC,3 // Serial Data Input/Output
#define LFDATA PORTC,3 // Low Frequency Data IN
#define ValidLED PORTC,4 // LED output
#define RFOUT PORTC,5 // RF DATA OUTPUT
#define LF_CS PIN_C1
#define LF_ALERT PIN_C2
#define LF_DATA PIN_C3
#define SPI_CLK_DELAY 1
//Command(3 bits) address(4 bits) parity(1 bit) Odd Parity
#define SPI_CLAMP_ON 0x00
#define SPI_CLAMP_OFF 0x10
#define SPI_ENTER_SLEEP 0x20
#define SPI_AGC_PRESERVE_ON 0x30
#define SPI_AGC_PRESERVE_OFF 0x40
#define SPI_SOFT_RESET 0x50
#define SPI_READ_COMMAND 0x60
#define SPI_WRITE_COMMAND 0x70 // first 3 bits should be 111, followed by 4 address bits
// SPI Addresses
#define Config_Byte_0 0x00
#define Config_Byte_1 0x01
#define Config_Byte_2 0x02
#define Config_Byte_3 0x03
#define Config_Byte_4 0x04
#define Config_Byte_5 0x05
#define Colum_Parity 0x06
#define AFE_Status 0x07
#define STX 0x02
#define EOT 0x03
//#define TRUE 0x01
#define SPI_READ_Direction 0x08
#define SPI_WRITE_Direction 0x00
//******************************************************************************************
// Analogue Front End Configuration Table
//******************************************************************************************
// SGAFE Default Register Values
// Default Mode:Wake-up filter disabled. MODSIG= 0, Enable Ch-X only. 25% mod depth.
// Register 0: 1010-0001 - 0 (parity)
// #define AFEConfig0 0b10100000 //filter=enabled --> 2ms+2ms
#define AFEConfig0 0b10100000 //filter=enabled --> 2ms+2ms
// Register 1: 0000-0000 - 1 (parity)
#define AFEConfig1 0b00000000
// Register 2: 0000-0000 - 1 (parity)
#define AFEConfig2 0b00000000
// Register 3: 0000-0000 - 1 (parity)
#define AFEConfig3 0b00000000
// Register 4: 0000-0000 - 1 (parity)
#define AFEConfig4 0b00000000
// Register 5: 0001-0000 - 0 (parity)
#define AFEConfig5 0b00010000 // modulation depth, default = 75%
// Register 6: 0100-1111 - 0 (Parity) // column parity bits
#define AFEConfig6 0b01001111 // column parity at defalt mode (75%)
char AFE[7]={AFEConfig0,AFEConfig1,AFEConfig2,AFEConfig3,AFEConfig4,AFEConfig5,AFEConfig6};
#define AFECOLPARITY AFEConfig0 xor AFEConfig1 xor AFEConfig2 xor AFEConfig3 xor AFEConfig4 xor AFEConfig0
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jan 19, 2006 9:00 pm |
|
|
I think you should just post one routine that's not working.
Post the assembly, and then the one C routine that doesn't work.
Explain how you know that it doesn't work. Show the
expected output and the actual output. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Jan 20, 2006 2:23 am |
|
|
I agree with PCM Programmer. I had a look at the code but didn't spot any obvious errors. It is a lot of code and I don't know what to look for so I stopped checking after 1 minute. If you want quick and usefull responses than give us a small compilable program that shows your problem. |
|
|
Kasper
Joined: 14 Jan 2004 Posts: 88 Location: Aurora, Ontario, Canada
|
|
Posted: Fri Jan 20, 2006 12:08 pm |
|
|
PCM programmer wrote: | I think you should just post one routine that's not working.
Post the assembly, and then the one C routine that doesn't work.
Explain how you know that it doesn't work. Show the
expected output and the actual output. |
I expected this:
Code: |
AFE[0] = 0xA0 -- SPI_READ[0] = 0x0000
AFE[1] = 0x00 -- SPI_READ[1] = 0x0000
AFE[2] = 0x00 -- SPI_READ[2] = 0x0000
AFE[3] = 0x00 -- SPI_READ[3] = 0x0000
AFE[4] = 0x00 -- SPI_READ[4] = 0x0000
AFE[5] = 0x10 -- SPI_READ[5] = 0x0000
AFE[6] = 0x4F -- SPI_READ[6] = 0x0000
|
as in I program in 0xA0 and read back 0x0000 ( the LSB << 1 contains the data)
I know I posted alot of code but I am not sure if it is the write or the read routine which is not working. I verify by using a spare pin as a software RS232 port, printing out debug information..
I will work on it a bit more and see if I can spot where it goes wrong.
Thanks again for looking at it
Kasper |
|
|
Kasper
Joined: 14 Jan 2004 Posts: 88 Location: Aurora, Ontario, Canada
|
|
Posted: Fri Jan 20, 2006 12:16 pm |
|
|
Code: |
ShiftOutSPIBuffer
movlw .16
movwf Count00
bcf SCK
bcf AFECS
ShiftOutLoop
rlf SPIBufL, f
rlf SPIBufH, f
btfss STATUS, C
bcf SDIO
btfsc STATUS, C
bsf SDIO
bsf SCK
bcf SCK
; CLRWDT
decfsz Count00, f
goto ShiftOutLoop
bsf AFECS
bcf AFECS
return
|
versus
Code: | void shift_out_SPI(int16 DATA) {
int i;
output_low(LF_ALERT);
output_low(LF_CS);
for(i=0;i<16;i++) {
if(bit_test(DATA,0)) {
output_high(LF_DATA);
}
else {
output_low(LF_DATA);
}
output_high(LF_ALERT);
output_low(LF_ALERT);
DATA = DATA >> 1;
}//end for
output_high(LF_CS);
//output_low(LF_CS);
output_float(LF_ALERT);
}//end function |
Anything which stands out as being blatantly wrong?
Looking at the disassembly listing, wow is C ever creating alot more code than assembly
Code: | 82: void shift_out_SPI(int16 DATA) {
83: int i;
84: output_low(LF_ALERT);
0D4 1683 BSF 0x3, 0x5
0D5 1107 BCF 0x7, 0x2
0D6 1283 BCF 0x3, 0x5
0D7 1107 BCF 0x7, 0x2
85: output_low(LF_CS);
0D8 1683 BSF 0x3, 0x5
0D9 1087 BCF 0x7, 0x1
0DA 1283 BCF 0x3, 0x5
0DB 1087 BCF 0x7, 0x1
86: for(i=0;i<16;i++) {
0DC 01BF CLRF 0x3f
0DD 083F MOVF 0x3f, W
0DE 3C0F SUBLW 0xf
0DF 1C03 BTFSS 0x3, 0
0E0 28F9 GOTO 0xf9
87: if(bit_test(DATA,0)) {
0E1 1C3D BTFSS 0x3d, 0
0E2 28E8 GOTO 0xe8
88: output_high(LF_DATA);
0E3 1683 BSF 0x3, 0x5
0E4 1187 BCF 0x7, 0x3
0E5 1283 BCF 0x3, 0x5
0E6 1587 BSF 0x7, 0x3
89: }
90: else {
0E7 28EC GOTO 0xec
91: output_low(LF_DATA);
0E8 1683 BSF 0x3, 0x5
0E9 1187 BCF 0x7, 0x3
0EA 1283 BCF 0x3, 0x5
0EB 1187 BCF 0x7, 0x3
92: }
93: output_high(LF_ALERT);
0EC 1683 BSF 0x3, 0x5
0ED 1107 BCF 0x7, 0x2
0EE 1283 BCF 0x3, 0x5
0EF 1507 BSF 0x7, 0x2
94: output_low(LF_ALERT);
0F0 1683 BSF 0x3, 0x5
0F1 1107 BCF 0x7, 0x2
0F2 1283 BCF 0x3, 0x5
0F3 1107 BCF 0x7, 0x2
95: DATA = DATA >> 1;
0F4 1003 BCF 0x3, 0
0F5 0CBE RRF 0x3e, F
0F6 0CBD RRF 0x3d, F
96: }//end for
0F7 0ABF INCF 0x3f, F
0F8 28DD GOTO 0xdd
97: output_high(LF_CS);
0F9 1683 BSF 0x3, 0x5
0FA 1087 BCF 0x7, 0x1
0FB 1283 BCF 0x3, 0x5
0FC 1487 BSF 0x7, 0x1
98: //output_low(LF_CS);
99: output_float(LF_ALERT);
0FD 1683 BSF 0x3, 0x5
0FE 1507 BSF 0x7, 0x2
100: }//end function
0FF 1283 BCF 0x3, 0x5
100 3400 RETLW 0 | |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jan 20, 2006 12:45 pm |
|
|
Yes. The ASM code is shifting the 16-bit value to the left.
It shifts the MSB into the CY flag, and then tests it.
So it's shifting out the word "MSB first".
Code: |
rlf SPIBufL, f
rlf SPIBufH, f
btfss STATUS, C
|
But your C code is shifting it out "LSB first". You're doing a right-shift
and you're testing the LSB. You're doing the opposite of what the ASM
code is doing.
Code: |
DATA = DATA >> 1;
if(bit_test(DATA,0))
|
|
|
|
Kasper
Joined: 14 Jan 2004 Posts: 88 Location: Aurora, Ontario, Canada
|
|
Posted: Fri Jan 20, 2006 1:07 pm |
|
|
PCM programmer wrote: | Yes. The ASM code is shifting the 16-bit value to the left.
It shifts the MSB into the CY flag, and then tests it.
So it's shifting out the word "MSB first".
Code: |
rlf SPIBufL, f
rlf SPIBufH, f
btfss STATUS, C
|
But your C code is shifting it out "LSB first". You're doing a right-shift
and you're testing the LSB. You're doing the opposite of what the ASM
code is doing.
Code: |
DATA = DATA >> 1;
if(bit_test(DATA,0))
|
|
Quoting a famous Cartoon Caracter...
DOH!
thanks PCM.. I am sure that will make one hell of a difference |
|
|
|
|
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
|