|
|
View previous topic :: View next topic |
Author |
Message |
Jim Oram
Joined: 01 Jan 2010 Posts: 24 Location: Charlotte
|
SPI not working on 18F26J50 |
Posted: Sat Mar 30, 2013 7:31 am |
|
|
Support, using my new PCW compiler:
For several days I have been trying to get the SPI to work on a 18F26J50, (28 pin dip).
I am using:
Code: |
#use SPI (MASTER, di=pin_b5, do=pin_c7, clk=pin_b4)
// pin 26 pin 18 pin 25
#use rs232 (baud=4800,parity=N,xmit=PIN_C0,rcv=PIN_C1,bits=8,errors)
setup_spi(SPI_MASTER | SPI_L_TO_H | spi_clk_div_16);
|
On the digital storage scope I can see the 8 clocks on pin 25 but no data on the data output pin_c7 pin 18 which remains high all the time.
I tested the output on pin_c7 using another simple program that toggles pin_c7 high and low to make sure it was able to work ok.
Some of the code:
Code: |
spi_write('X'); // write X to to the SPI pin 18.
while (bit_test(PIR1,SSP1IF) == 0)
{ }; //wait till data is sent out RCSTA1
bit_clear(PIR1,SSP1IF);
spi_data_in = spi_read(0xFF);
// required to use "0xFF" to generate a clock
bit_clear(PIR1,SSP1IF);
delay_ms(2);
TXREG1 = 'R';
// send 'R' debug info to PC Comm Operator via mcp2200 USB chip.
|
I get the debug 'R' on the PC indicating the program got to the "Read".
Is there something I am doing wrong in the way I am using SPI?
I hope you can help, time is becoming short.
Thanks Kindly,
Jim _________________ Jim Oram |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Sat Mar 30, 2013 8:38 am |
|
|
setup_spi, only works with the hardware SPI. No need to tell it the pins
except where you have re-mappable pins.
So:
Code: |
//Get rid of #use spi- Use it if you want streams, or software
//spi. Only use setup_spi, or #use, not both.
//Device headers etc..
//Now setup the UART pins
#pin_select TX2=PIN_C0
#pin_select RX2=PIN_C1 //Uart 2
#use rs232 (baud=4800,parity=N,UART2,bits=8,errors)
//Tell the compiler you want to use the hardware UART - note 'UART2'
//Only UART2 can be mapped to the pins you want. Might as well use the
//hardware since it is there!...
void main(void)
{
int8 spi_data_in;
setup_uart(FALSE); //Should be default, but this will override
//pins C6/7, so better to be safe.
setup_spi(SPI_MASTER | SPI_L_TO_H | spi_clk_div_16);
while (TRUE)
{
spi_write('X'); // write X to to the SPI pin 18.
//If you do want to wait, that is what the spi_data_is_in function is for
while (!spi_data_is_in()) ;
//wait till data is sent out RCSTA1
//You don't actually need this the CCS function defaults to testing
//The interrupt flag is also cleared by the compiler when a new
//transfer is done
spi_data_in = spi_read(0xFF);
//required to use "0xFF" to generate a clock
//No - _any_ byte will generate a clock
delay_ms(1);
}
}
|
'Setup_spi' only works with the hardware SPI. #use spi can be used instead, but then you should use sfi_xfer to do the I/O. Mixing both gets into 'black arts'. They are two different ways of doing things, and you will find they don't refer to each other in the manual entries. This is reported now to work, but can be asking for problems (especially on TRIS control, with chips with re-mappable peripherals), and depending on the compiler version.
So this may be the problem.
Other things, would depend on the code around. A small compilable 'demo', is the way to go. One classic would be if you have the USB driver loading, and debugging enabled. This defaults to using UART1, which would override the SDO pin.
I've added, showing how to use the second hardware UART for your serial output, which will avoid the timing errors that will otherwise appear if interrupts occur....
Best Wishes |
|
|
Jim Oram
Joined: 01 Jan 2010 Posts: 24 Location: Charlotte
|
SPI not working on 18F26J50 |
Posted: Sun Mar 31, 2013 11:20 pm |
|
|
Support,
Thank you for the suggested code to get SPI running.
The SPI does output data now, but the reassignment of UART2 port pins to C0 and C1 does not seem to work. Is is something with the Tris setting?
I think I need more explanation about pin reassignments.
Thank You Very Kindly,
Jim
Here is what you suggested ... but I added some LED test code.
Code: |
// ---------- from CCS - modified with test LEDs ------------
//
//Get rid of #use spi- Use it if you want streams, or software
//spi. Only use setup_spi, or #use, not both.
//Device headers etc..
//Now setup the UART pins
#pin_select TX2=PIN_C0
#pin_select RX2=PIN_C1 //Uart 2
#use rs232 (baud=4800,parity=N,UART2,bits=8,errors)
//Tell the compiler you want to use the hardware UART - note 'UART2'
//Only UART2 can be mapped to the pins you want. Might as well use the
//hardware since it is there!...
void main(void)
{
int8 spi_data_in;
int8 x;
set_tris_a(0x07); // 07);
set_tris_b(0xE3); // E3); // 1110 0011
set_tris_c(0x36); // ); // 0011 0110
setup_uart(FALSE); // Should be default, but this will override
// pins C6/7, so better to be safe.
setup_spi(SPI_MASTER | SPI_L_TO_H | spi_clk_div_16);
TXREG2 = '1'; // output S to Comm Operator for start.
output_high(REDLED); // indicator off
while (TRUE)
{
TXREG2 = 'S'; // output S to Comm Operator for Start. (does not show up on pin_c0)
for(x = 0 ; x < 5 ; x++){
output_low(GRNLED); // green led on.
delay_ms(100);
output_high(GRNLED); // green led off.
delay_ms(100);
}
output_low(REDLED); // red led on.
delay_ms(200);
spi_write('X'); // write X to to the SPI pin 18.
output_high(REDLED); // red led off
//If you do want to wait, that is what the spi_data_is_in function is for.
bit_clear(SSP1CON1, SSPOV); // clear any overflo, may not be needed.
while (!spi_data_is_in());
//
//wait till data is sent out RCSTA1
//You don't actually need this the CCS function defaults to testing
//The interrupt flag is also cleared by the compiler when a new
//transfer is done
spi_data_in = spi_read(0xFF);
output_low(REDLED); // red led on.
delay_ms(50);
output_high(REDLED); // red led off.
delay_ms(50);
//required to use "0xFF" to generate a clock
//No - _any_ byte will generate a clock
restart_wdt();
}
} |
_________________ Jim Oram |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Mon Apr 01, 2013 1:14 am |
|
|
Yes. Forgot this (I often use use fast_io, and set the tris myself). Because the compiler doesn't 'know' what pin your UART it on, it doesn't handle TRIS for you. So you need to specify 'output_float' for the RX pin, and 'output_drive' for the TX pin.
Use fputc, rather than sending values directly to TXREG. You are not checking the buffer is empty before sending, so could overflow the UART. fputc does this for you.
Best Wishes |
|
|
Jim Oram
Joined: 01 Jan 2010 Posts: 24 Location: Charlotte
|
SPI not working on 18F26J50, but TX2 using fputc('x') hangs |
Posted: Mon Apr 01, 2013 6:52 am |
|
|
Dear Ttelmah,
I tried as you suggested using fputc(char) ... but the program hangs right there. This is strange. Looking up fputc in the new PCW compiler manual on page 175 does not seem to have anything about fputc .
As suggested I am using:
Code: |
#use fast_io(C)
//Now setup the UART pins
#pin_select TX2=PIN_C0 // (no data seen there)
#pin_select RX2=PIN_C1 // Uart 2
set_tris_c(0x36); // 0011 0110
#use rs232 (baud=4800,parity=N,UART2,bits=8,errors)
using TXREG2 = '1'; // (0xFA9)
// but no data from UART2 on C0, and using fputc('1') hangs;
|
SPI does work thanks to you! Now the USART2 must be made to work.
But I still must be doing something wrong on the USART2. Any of your suggestions are very helpful.
Thank You Very Kindly,
Jim _________________ Jim Oram |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1355
|
Re: SPI not working on 18F26J50 |
Posted: Mon Apr 01, 2013 8:08 am |
|
|
Just as a quick note, to avoid confusion, we are not members of support. This is a user forum. CCS support is reached by email/phone. We'll definitely try to help, but please be aware that per the note on the top left corner of this webpage that CCS doesn't always monitor these threads on a regular basis.
In terms of the UART issue: perhaps take a step back and just do a simply UART only program on your chip to see if you can get it working at all. Something simple:
Code: |
#include for your pic
#FUSES
#use delay() call
#pin_select lines
#use rs232() call
void main(){
printf("hello world\r\n");
while(TRUE);
} |
That's mostly pseudo code. Leave out things like fast I/O and TRIS settings and just pare it down to a very simple program to test out the UART. If you still have issues, post that small code (in full...FUSES and all) so we can see it. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Mon Apr 01, 2013 8:19 am |
|
|
fputc needs a stream name. so you use:
Code: |
#use rs232 (baud=4800,parity=N,UART2,bits=8,errors,stream=COMM2)
fputc('1',COMM2);
|
fputc, is under putc in the manual. It's what allows you to have multiple UARTs (software of hardware) enabled, and use the right one.
However the TXREG2 approach should give data. It just risks corruption....
The second UART should work. I'm using it on my own code (but routed to different pins, with:
Code: |
#pin_select TX2=PIN_B2
#pin_select RX2=PIN_B3 //Uart 2
#use rs232(baud=57600,parity=N,UART2,bits=8,stream=PORT2,errors) //controller
fputc(temp,PORT2);
//where temp is the character I'm sending - it's in INT_TBE2,
//since I'm using interurpt driven TX/RX.
|
Only thing that would stop it, is if some other peripheral is on the pins. Just like with the SPI, where I make 'sure' the UART is off. The one that could apply here is Timer1.
Best Wishes |
|
|
Jim Oram
Joined: 01 Jan 2010 Posts: 24 Location: Charlotte
|
"hello world" is working, but now the SPI does not |
Posted: Mon Apr 01, 2013 4:30 pm |
|
|
Hello Ttelmah,
The "hello world" is working, but now the SPI does not work.
Redirecting pin assignments seem to work.
Prior to adding the "hello world" the SPI WAS working.
So something is not right.... I thought I could use UART2 with pin assignments and SPI at the same time.
Your comments are most needed and appreciated.
Here is the whole code as constructed from helpful CCS forum comments:
// ---------- from CCS user forum - modified with test LEDs ------------
//
//Get rid of #use spi- Use it if you want streams, or software
//spi. Only use setup_spi, or #use, not both.
//Tell the compiler you want to use the hardware UART - note 'UART2'
//Only UART2 can be mapped to the pins you want. Might as well use the
//hardware since it is there!...
#include <18F26J50.h>
#FUSES wdt,noprotect //,HS
#use fast_io(C)
#use delay(clock=8000000,RESTART_WDT)
#byte OSCCON = 0x0FD3
#byte BAUDCON1 = 0x0F7E
#byte BAUDCON2 = 0x0F7C
#byte SPBRG1 = 0x0FB0 // low byte
#byte SPBRG2 = 0x0FAB // low byte
#byte SPBRGH1 = 0x0F7F // EUSART1 Baud Rate Generator Register High Byte
#byte SPBRGH2 = 0x0F7D // EUSART2 Baud Rate Generator Register High Byte
#byte SSP1CON1 = 0x0FC6
#pin_select TX2=PIN_C0 // I/O pin assignment:
#pin_select RX2=PIN_C1 // use Uart 2 connect to PIN_C0 and C1
#use rs232 (baud=4800,parity=N,UART2,bits=8,errors,stream=COMM2)
#define STREAM_ARRAY_SIZE 35 // array size yet to be used.
#define GRNLED PIN_B6
#define REDLED PIN_B7
#define SSPOV 6
int8 x; // Test program to sort out UART2 and SPI
void main(){
OSCCON = 0x70; // 8mhz
SPBRGH2 = 0; // Data sheet Page 329
SPBRG2 = 103; // 103;
BAUDCON2 = 0x00; // 0x08; BRG16 bit 3
SPBRGH1 = 0; //
SPBRG1 = 103; // 103;
setup_spi(SPI_MASTER | SPI_L_TO_H | spi_clk_div_16);
while(TRUE){
fputc('1',COMM2); // fputc to COMM2 works.
delay_ms(1);
printf("hello CCS\r\n");
// bit_clear(SSP1CON1, SSPOV); // clear any overflo, may not be needed.
// Hangs on the next line when uncommented:
// spi_write('X'); // write X to to the SPI pin 18. HANGS !
delay_ms(500);
for(x = 0 ; x < 3 ; x++){
output_low(GRNLED); // green led on.
delay_ms(100);
output_high(GRNLED); // green led off.
delay_ms(100);
}
}
}
Thanks Kindly,
Jim _________________ Jim Oram |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1355
|
|
Posted: Mon Apr 01, 2013 5:26 pm |
|
|
You should still simplify it. You are doing a lot of things that CCS can handle and you still have some code not needed to test out SPI and UART (such as WDT)
Also, please use "code" tags so your code is more readable. I don't have your chip to test on, but try this out:
Code: |
#case
#include <18F26J50.h>
#FUSES NOWDT,NOPROTECT,INTRC
#use delay(clock=8000000)
#pin_select TX2=PIN_C0 // I/O pin assignment:
#pin_select RX2=PIN_C1 // use Uart 2 connect to PIN_C0 and C1
#use rs232 (baud=4800,parity=N,UART2,bits=8,errors,stream=COMM2)
void main(){
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16);
while(TRUE){
fputc('1',COMM2); // fputc to COMM2 works.
fprintf(COMM2," hello CCS\r\n");
spi_write('X'); // write X to to the SPI pin 18. HANGS !
delay_ms(500);
}
}
|
Take a look at the fuses I specified. Also take a look at your SPI setup and make sure it is in the mode you want it to be (can do a search on this forum for SPI mode to find out about how to set those). I didn't make changes to the SPI setup. I took out a lot of direct register code and the fast IO
This code should just print out stuff continuously and also spew out some SPI data every so often. |
|
|
Jim Oram
Joined: 01 Jan 2010 Posts: 24 Location: Charlotte
|
Code for the 18F26J50 to use USART2 and spi_write() together |
Posted: Mon Apr 01, 2013 8:08 pm |
|
|
jeremiah,
Thank you for the test code. Most appreciated.
I used your code and included LEDs for DeBug.
The code hangs on spi_write('X') . (Green LED stays on)
The pin assignments work, and data appears on C0 and is sent to Comm Operator at 4800 baud through a MCP2200 USB chip.
The MCP2200 chip will offload the 18F chip when I load the TCP/IP stack with TLS. That is why I need USART2 and SPI at the same time.
Code: | // ---- test code from jeremiah CCS forum, modified with LEDs for DeBug ------
// Hangs on spi_write('X')
#case
#include <18F26J50.h>
#FUSES NOWDT,NOPROTECT,INTRC
#use delay(clock=8000000)
#byte OSCCON = 0x0FD3
#byte BAUDCON1 = 0x0F7E
#byte BAUDCON2 = 0x0F7C
#byte SPBRG1 = 0x0FB0 // low byte
#byte SPBRG2 = 0x0FAB // low byte
#byte SPBRGH1 = 0x0F7F // EUSART1 Baud Rate Generator Register High Byte
#byte SPBRGH2 = 0x0F7D // EUSART2 Baud Rate Generator Register High Byte
#byte SSP1CON1 = 0x0FC6
#pin_select TX2=PIN_C0 // I/O pin assignment:
#pin_select RX2=PIN_C1 // use Uart 2 connect to PIN_C0 and C1
#use rs232 (baud=4800,parity=N,UART2,bits=8,errors,stream=COMM2)
#define GRNLED PIN_B6
#define REDLED PIN_B7
int8 x; // Test program to sort out UART2 and SPI
void main(){
OSCCON = 0x70; // 8mhz
SPBRGH2 = 0; // Data sheet Page 329
SPBRG2 = 103; // 103;
BAUDCON2 = 0x00; // 0x08; BRG16 bit 3
SPBRGH1 = 0; //
SPBRG1 = 103; // 103;
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16);
while(TRUE){
fputc('1',COMM2); // fputc to COMM2 ~works. (a ÿ character appears "ÿ1 hello CCS")
delay_ms(5);
fprintf(COMM2," hello CCS\r\n");
delay_ms(15);
output_low(GRNLED); // LED 'on' to indicate SPI write.
spi_write('X'); // Hangs ... write X to to the SPI pin 18. HANGS here!
output_high(GRNLED); // green led off.
delay_ms(150);
// delay_ms(500);
for(x = 0 ; x < 3 ; x++){
output_low(GRNLED); // green led on.
delay_ms(100);
output_high(GRNLED); // green led off.
delay_ms(100);
}
}
}
|
I need the USART2 and SPI to both be active as needed in the program.
Any suggestions?
Thank You Very Kindly,
Jim _________________ Jim Oram |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1355
|
|
Posted: Mon Apr 01, 2013 8:15 pm |
|
|
What compiler revision are you using?
The next step would be to look at the LST file and see where the assembly for that spi_write call would hang up. Also, you might explicitly turn off any other peripherals using the same pins as your SPI interface |
|
|
Jim Oram
Joined: 01 Jan 2010 Posts: 24 Location: Charlotte
|
Versions |
Posted: Mon Apr 01, 2013 8:28 pm |
|
|
Using Versions:
PCW versions:
IDE 4.138
PCB 4.138
PCM 4.141
PCH 4.141 _________________ Jim Oram |
|
|
Jim Oram
Joined: 01 Jan 2010 Posts: 24 Location: Charlotte
|
List file section for spi_write |
Posted: Mon Apr 01, 2013 8:38 pm |
|
|
jeremiah, here is the list for spi_write:
Code: |
.................... spi_write('X'); // recompile, now not hanging, but no clock signal. ?
00FA: MOVF FC9,W
00FC: MOVLW 58
00FE: MOVWF FC9
0100: RRCF FC7,W
0102: BNC 0100
.................... output_high(GRNLED); // green led off.
0104: BCF F93.6
0106: BSF F8A.6
|
Jim _________________ Jim Oram |
|
|
Jim Oram
Joined: 01 Jan 2010 Posts: 24 Location: Charlotte
|
spi_write() no clock... |
Posted: Mon Apr 01, 2013 8:47 pm |
|
|
jeremiah,
As far as I know, with this simple program, I do not have any extra
peripherals using the same pins as the SPI interface.
It seems that it is possible to get the spi running, or the uasrt2 running, but not both. Any ideas?
Thanks Kindly,
Jim _________________ Jim Oram |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Tue Apr 02, 2013 12:31 am |
|
|
Stop talking to the registers...
This is the assembler approach, and is not needed/wanted. There are a few (very few) occasions, when accessing registers directly is wanted/needed. This is not one of them.
You are programming part of UART1. You must not do this, since UART1 uses the same pins as the SPI. This is why I had the line 'setup_uart(FALSE)', to make _sure_ UART1 was turned off, since otherwise it'll stop the SPI from working. This is the line missing from Jeremiah's code.
Code: |
#case
#include <18F26J50.h>
#FUSES NOWDT,NOPROTECT,INTRC
#use delay(clock=8000000)
#pin_select TX2=PIN_C0 // I/O pin assignment:
#pin_select RX2=PIN_C1 // use Uart 2 connect to PIN_C0 and C1
#use rs232 (baud=4800,parity=N,UART2,bits=8,errors,stream=COMM2)
void main(){
setup_uart(FALSE); //needs to be here.
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16);
while(TRUE){
fputc('1',COMM2); // fputc to COMM2 works.
fprintf(COMM2," hello CCS\r\n");
spi_write('X'); // write X to to the SPI pin 18. HANGS !
delay_ms(500);
}
}
|
Best Wishes |
|
|
|
|
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
|