|
|
View previous topic :: View next topic |
Author |
Message |
Benzino
Joined: 15 Feb 2010 Posts: 24
|
Has anyone use PIC16F690 with MCP2515? |
Posted: Tue Feb 16, 2010 8:32 am |
|
|
Hi all,
I'm trying to get the PIC16F690 to work with MCP2515 and MCP2551 using CCS's example but I don't have any luck with it. The 16F690 is connected to MCP2515 via SPI.
I'm still new with PIC programming so if anyone have any experience with this particular PIC or any 16F series other than the one in the example or demo kit please advice me.
Also the problem that I have with the CCS's example is that the can_init() doesn't go through and I'm using Internal clock of 16F690 and below is my code.
Code: |
#include <16F690.h>
#FUSES INTRC,NOWDT,NOPUT,NOMCLR,NOPROTECT,NOCPD,NOBROWNOUT
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_B7, rcv=PIN_B5, parity=N, bits=8)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#define EXT_CAN_CS PIN_C6
#define EXT_CAN_SI PIN_B4
#define EXT_CAN_SO PIN_C7
#define EXT_CAN_SCK PIN_B6
#include <can-mcp2510.c>
void main() {
struct rx_stat rxstat;
int32 rx_id;
int32 tx_id;
int buffer[8];
int rx_len;
int i;
setup_oscillator(OSC_4MHZ);
set_tris_a(0xFF);
set_tris_b(0x30);
set_tris_c(0x42);
setup_spi(SPI_MASTER);
output_a(0x00);
output_b(0x00);
output_c(0x00);
for(i=0;i<8;i++) {
buffer[i]=0;
output_high(PIN_C0);
delay_ms(250);
output_low(PIN_C0);
delay_ms(250);
}
output_high(PIN_C2);
delay_ms(2000);
output_low(PIN_C2);
delay_ms(2000);
can_init();
output_high(PIN_C0);
delay_ms(2000);
output_low(PIN_C0);
delay_ms(2000);
while(TRUE)
{
output_high(PIN_C2);
delay_ms(2000);
if ( can_kbhit() ) //if data is waiting in buffer...
{
output_high(PIN_C3);
delay_ms(2000);
if(can_getd(rx_id, &buffer[0], rx_len, rxstat)) { //...then get data from buffer
if (rx_id == 0x020) {
}
if (rx_id == 0x021) {
output_high(PIN_C0);
delay_ms(2000);
can_putd(0x021, buffer, 1,1,1,0); //put data on transmit buffer
}
}
}
}
}
|
Much appreciate
-Ben |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Feb 16, 2010 2:47 pm |
|
|
Quote: |
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
set_tris_a(0xFF);
set_tris_b(0x30);
set_tris_c(0x42);
output_a(0x00);
output_b(0x00);
output_c(0x00);
|
There is no reason to use Fast i/o mode. It just makes it more difficult.
Delete all 9 lines above.
Quote: |
#define EXT_CAN_CS PIN_C6
#define EXT_CAN_SI PIN_B4
#define EXT_CAN_SO PIN_C7
#define EXT_CAN_SCK PIN_B6
|
Just to make sure the connections are correct, post a list of the
connections between the PIC and the MCP2515. Don't post the signal
names. Just post, pin XX on the PIC goes to pin YY on the MCP2515, etc.
Quote: | setup_oscillator(OSC_4MHZ); |
This is not necessary. The compiler automatically sets up the oscillator
once it sees the INTRC fuse and the #use delay() statement.
Quote: | setup_spi(SPI_MASTER); |
This is incomplete. You need to set the SPI mode and the clock speed.
According to the first page in the MCP2515 data sheet,
http://ww1.microchip.com/downloads/en/DeviceDoc/21801e.pdf
the chip can use SPI mode 0,0 or 1,1 (meaning modes 0 and 3).
Here are the SPI mode definitions. Place this block of code above main():
Code: |
// SPI mode definitions.
#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)
|
The MCP2515 data sheet also says the max SPI clock speed is 10 MHz.
The 16F690.h file says these 3 SPI clock divisors are available:
Code: |
#define SPI_CLK_DIV_4 0
#define SPI_CLK_DIV_16 1
#define SPI_CLK_DIV_64 2
|
Since your PIC is running at 4 MHz, we can use the minimum divisor.
With this information, we can now write the setup_spi() statement:
Code: |
setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_4);
|
Quote: | output_high(PIN_C2);
delay_ms(2000);
output_low(PIN_C2);
delay_ms(2000); |
It's clear that you're using LEDs to provide a progress report of code
execution. It would be better if you used the serial port to send status
messages to a terminal window on your PC. Then you could use
printf to say something like:
Code: |
can_init();
printf("can_init done \n\r");
|
|
|
|
Benzino
Joined: 15 Feb 2010 Posts: 24
|
|
Posted: Wed Feb 17, 2010 8:51 am |
|
|
Thank you for your reply PCM programmer.
The PIN diagram of
Quote: | #define EXT_CAN_CS PIN_C6
#define EXT_CAN_SI PIN_B4
#define EXT_CAN_SO PIN_C7
#define EXT_CAN_SCK PIN_B6 |
is the following:
Code: |
PIN description 16F690 MCP2515
EXT_CAN_CS RC6 CS (18)
EXT_CAN_SI RB4 SO (17)
EXT_CAN_SO RC7 SI (16)
EXT_CAN_SCK RB6 SCK (14)
|
Also for the serial RS232, I couldn't get it to work before.
I'm using 3 pin from the 16F690 to the serial cable i.e. Tx, Rx, and GND.
I setup the baud rate for the COM port to be the same as the PIC i.e. 9600 and connect it using Hyper Terminal at the same baud rate.
Am I doing anything differently?
Edited
I found solution this discussion on the forum
http://www.ccsinfo.com/forum/viewtopic.php?t=32455
and with this FAQ
http://www.ccsinfo.com/faq.php?4
It works with the following line
Code: | #use rs232(baud=9600, xmit=PIN_C4, rcv=PIN_C5, INVERT) |
Now, I have to continue with CAN bus issue.
Thank you, |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Feb 17, 2010 12:43 pm |
|
|
Based on your hardware connections, you have the #define statements
for the SI and the SO pins swapped. You need to edit those two
statements so they look like this:
Quote: |
#define EXT_CAN_CS PIN_C6
#define EXT_CAN_SI PIN_C7
#define EXT_CAN_SO PIN_B4
#define EXT_CAN_SCK PIN_B6
|
|
|
|
Benzino
Joined: 15 Feb 2010 Posts: 24
|
|
Posted: Wed Feb 17, 2010 12:55 pm |
|
|
Hi,
I did change the SI and SO pin according to your suggestion.
However, when I did that, the program didn't go through the can_init() function.
It works before when I had it the other way around.
Any suggestion of what might be wrong?
Also I did look into the bit timing stuff according to this discussion
http://www.ccsinfo.com/forum/viewtopic.php?t=22138
I'm not sure if I'm doing it correctly. Here is part of my code on the mcp2510.c that I revised
Code: | void can_set_baud(void) {
struct struct_CNF1 new_CNF1;
struct struct_CNF2 new_CNF2;
struct struct_CNF3 new_CNF3;
new_CNF1 = 0x03;
new_CNF2 = 0x91;
new_CNF3 = 0x01;
/*
new_CNF1.brp=CAN_BRG_PRESCALAR;
new_CNF1.sjw=CAN_BRG_SYNCH_JUMP_WIDTH;
new_CNF2.prseg=CAN_BRG_PROPAGATION_TIME;
new_CNF2.phseg1=CAN_BRG_PHASE_SEGMENT_1;
new_CNF2.sam=CAN_BRG_SAM;
new_CNF2.btlmode=CAN_BRG_SEG_2_PHASE_TS;
new_CNF3.phseg2=CAN_BRG_PHASE_SEGMENT_2;
new_CNF3.wakfil=CAN_BRG_WAKE_FILTER;
*/
mcp2510_write(CNF1, (int)new_CNF1);
mcp2510_write(CNF2, (int)new_CNF2);
mcp2510_write(CNF3, (int)new_CNF3);
} |
I wanted to have CAN baud rate of 250 Kbit/s. I'm not sure if I'm setting it up correctly using Microchip Bit Timer Calculator.
Thank you, |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Feb 17, 2010 1:06 pm |
|
|
According to your list of connections, you have a wire between pin RC7
on the PIC, and the "SI" pin on the MCP2515. Well, the way that the
CCS "defines" work, is that when they say "EXT_CAN_SI", they mean
you should specify the PIC pin that is connected to the SI pin on the
CAN chip. The correct define statement is this:
Code: | #define EXT_CAN_SI PIN_C7 |
CCS doesn't expect you to do the mental "SDO goes to SI" signal swap.
That's a key point to understand. Most people are expecting to have to
do that. In other words, if you're smart, and you understand the
connections, the CCS method is a mental step downwards. It will wack
you if you don't watch it. |
|
|
Benzino
Joined: 15 Feb 2010 Posts: 24
|
|
Posted: Wed Feb 17, 2010 1:46 pm |
|
|
Hi,
So EXT_CAN_SI means the external to CAN SI pin?
If that is the case then I understand what you mean.
But we still have to swap SI to SDO and SO to SDI when we wire them, correct?
However when I changed the PIN define, I still have the same problem that can_init() function didn't run through. I'm not sure what could cause it.
Here is my current code
Code: |
#include <16F690.h>
#FUSES INTRC_IO,NOWDT,PUT,NOMCLR,NOBROWNOUT
#use delay(clock=8000000)
#use rs232(baud=9600, xmit=PIN_C4, rcv=PIN_C5, INVERT)
//#define CAN_DO_DEBUG TRUE
#define EXT_CAN_CS PIN_C6
#define EXT_CAN_SI PIN_C7
#define EXT_CAN_SO PIN_B4
#define EXT_CAN_SCK PIN_B6
// SPI mode definitions.
#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)
#include "can-mcp2510.c"
void main() {
struct rx_stat rxstat;
int32 rx_id;
int32 tx_id;
int buffer[8];
int rx_len;
int i;
setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_4);
printf("Start buffer initialization \n\r");
delay_ms(50);
for(i=0;i<8;i++) {
buffer[i]=i+1;
}
output_high(PIN_C2);
delay_ms(2000);
output_low(PIN_C2);
delay_ms(2000);
printf("can_init start \n\r");
delay_ms(50);
can_init();
printf("can_init done \n\r");
delay_ms(50);
while(TRUE)
{
printf("Inside while loop \n\r");
delay_ms(500);
if ( can_kbhit() ) //if data is waiting in buffer...
{
printf("Inside first IF statement \n\r");
delay_ms(500);
if(can_getd(rx_id, &buffer[0], rx_len, rxstat)) { //...then get data from buffer
if (rx_id == 0x020) {
printf("Receive CAN ID 20h \n\r");
delay_ms(500);
}
if (rx_id == 0x021) {
printf("Receive CAN ID 21h \n\r");
delay_ms(500);
can_putd(0x021, buffer, 1,1,1,0); //put data on transmit buffer
delay_ms(100);
printf("Transmitted CAN ID 21h \n\r");
delay_ms(500);
}
printf("Transmit CAN ID 22h \n\r");
delay_ms(500);
can_putd(0x022, buffer, 1,1,1,0); //put data on transmit buffer
delay_ms(100);
printf("Transmitted CAN ID 22h \n\r");
delay_ms(500);
}
}
}
} |
With the way I had EXT_CAN_SI swap with EXT_CAN_SO before, it ran through the program but nothing transmits on the CANbus (though I'm not sure the baud rate).
I wanted to use your example from another discussion but I'm using different PIC series so I'm not sure if it will work.
Please advice, |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Feb 17, 2010 1:51 pm |
|
|
Quote: | But we still have to swap SI to SDO and SO to SDI when we wire them, correct? |
Look at the CCS driver file, mcp-2510.c. It doesn't use hardware SPI.
It's doing bit-banging:
Quote: |
void mcp2510_command(int8 command) {
int8 i;
output_low(EXT_CAN_CS);
for (i=0;i<8;i++) {
output_bit(EXT_CAN_SI, shift_left(&command,1,0));
output_high(EXT_CAN_SCK);
output_low(EXT_CAN_SCK);
}
output_high(EXT_CAN_CS);
} |
You think you're using the hardware SPI pins on the 16F690. In fact,
the CCS driver is using them as ordinary i/o pins, and it's bit-banging them. |
|
|
Benzino
Joined: 15 Feb 2010 Posts: 24
|
|
Posted: Wed Feb 17, 2010 1:59 pm |
|
|
Does it affect the configuration of CAN causing it to not function?
i.e. go through can_init()
I'm not sure if I setup something incorrectly causing the CAN to fail or I need extra circuitry to make the CAN function work.
Please advice, |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Feb 17, 2010 2:50 pm |
|
|
What do you have connected to the \Reset pin and the OSC1 and OSC2
pins on the MCP2515 ? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Feb 17, 2010 4:14 pm |
|
|
I have a 3M breadboard with a 16F690 already on it. I added a MCP2510
chip and jumpered it so it would similar to your board. I have a Max232A
on my breadboard, so I used the hardware UART pins on the 16F690.
I'm using a 20 MHz crystal on the MCP2510, with 22 pf caps to ground
on each side of the crystal. I have the \Reset pin on the MCP2510
connected to a 10K pull-up resistor. The can-mcp2510.c driver does
a software controlled reset of the MCP2510, so the hardware \Reset
pin is not used (it's pulled up to +5v).
The Loopback test code shown below works. It displays the following in
a terminal window on the PC:
Quote: |
Starting
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
|
Code: |
#include <16F690.h>
#fuses INTRC_IO,NOWDT,BROWNOUT,PUT
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_B7, rcv=PIN_B5, ERRORS)
//#use rs232(baud=9600, xmit=PIN_C4, rcv=PIN_C5, INVERT)
#define EXT_CAN_CS PIN_C6
#define EXT_CAN_SI PIN_C7
#define EXT_CAN_SO PIN_B4
#define EXT_CAN_SCK PIN_B6
#include <can-mcp2510.c>
//=================================
void main(void)
{
int32 can_id;
int8 can_data[8];
int8 can_length;
struct rx_stat rxstat;
can_init();
can_set_mode(CAN_OP_LOOPBACK);
printf("Starting\n\r");
can_data[0] = 0x55;
while(1)
{
if(can_putd(42, can_data, 1, 3, TRUE, FALSE))
printf("Tx OK, ");
else
printf("Tx failed, ");
while(!can_kbhit());
if(can_getd(can_id, &can_data[0], can_length, rxstat))
printf("Rx OK, ");
else
printf("Rx failed, ");
printf("Rx data = %x \n\r", can_data[0]);
delay_ms(500);
}
}
|
This was tested with compiler vs. 4.104. |
|
|
Benzino
Joined: 15 Feb 2010 Posts: 24
|
|
Posted: Thu Feb 18, 2010 8:06 am |
|
|
Hi,
PCM programmer wrote: | What do you have connected to the \Reset pin and the OSC1 and OSC2
pins on the MCP2515 ? |
I have my \Reset pin series with 10kohm resistor and connected to +5 V.
The OSC1 and OSC2 are connected to 16MHz crystal with two .1 uF capacitor grounded on each side of the crystal.
I am actually using the MCP2515 PICtail Demo Board from Microchip and program the 16F676 with a blank code for the MCP2515 and MCP2551.
For PIC 16F690 I use the Low Pin Count Board from PICKit 2 and wire selected pin to the PICtail Demo board.
The reason I have to do this is because this is all I was given to work with.
One question about the CAN baud rate on your code. Which baud rate that you're using?
My CCS compiler version is 4.093. I will try out your code and see if it works. |
|
|
Ttelmah Guest
|
|
Posted: Thu Feb 18, 2010 8:16 am |
|
|
Benzino wrote: | Hi,
PCM programmer wrote: | What do you have connected to the \Reset pin and the OSC1 and OSC2
pins on the MCP2515 ? |
I have my \Reset pin series with 10kohm resistor and connected to +5 V.
The OSC1 and OSC2 are connected to 16MHz crystal with two .1 uF capacitor grounded on each side of the crystal.
I am actually using the MCP2515 PICtail Demo Board from Microchip and program the 16F676 with a blank code for the MCP2515 and MCP2551.
For PIC 16F690 I use the Low Pin Count Board from PICKit 2 and wire selected pin to the PICtail Demo board.
The reason I have to do this is because this is all I was given to work with.
One question about the CAN baud rate on your code. Which baud rate that you're using?
My CCS compiler version is 4.093. I will try out your code and see if it works. |
Aaargh......
You want capacitors like 0.1uF, on the _supply_, _not_ the crystal.
The normal loading capacitance for a crystal, is in the order of perhaps 20pF. 0.1uF, will stop it running.....
Best Wishes |
|
|
Benzino
Joined: 15 Feb 2010 Posts: 24
|
|
Posted: Thu Feb 18, 2010 8:23 am |
|
|
Ttelmah wrote: | Benzino wrote: | Hi,
PCM programmer wrote: | What do you have connected to the \Reset pin and the OSC1 and OSC2
pins on the MCP2515 ? |
I have my \Reset pin series with 10kohm resistor and connected to +5 V.
The OSC1 and OSC2 are connected to 16MHz crystal with two .1 uF capacitor grounded on each side of the crystal.
I am actually using the MCP2515 PICtail Demo Board from Microchip and program the 16F676 with a blank code for the MCP2515 and MCP2551.
For PIC 16F690 I use the Low Pin Count Board from PICKit 2 and wire selected pin to the PICtail Demo board.
The reason I have to do this is because this is all I was given to work with.
One question about the CAN baud rate on your code. Which baud rate that you're using?
My CCS compiler version is 4.093. I will try out your code and see if it works. |
Aaargh......
You want capacitors like 0.1uF, on the _supply_, _not_ the crystal.
The normal loading capacitance for a crystal, is in the order of perhaps 20pF. 0.1uF, will stop it running.....
Best Wishes |
Thank you for your respond.
I looked into the datasheet again and I was wrong. The data sheet shows that there is two capacitors connected to the crystal and grounded on each side but it doesn't specifically say the parameter.
The .1uF was for other part of the schematic according to the PDF below
http://ww1.microchip.com/downloads/en/DeviceDoc/51572a.pdf |
|
|
Benzino
Joined: 15 Feb 2010 Posts: 24
|
|
Posted: Thu Feb 18, 2010 9:44 am |
|
|
Hi PCM programmer,
I tried your code with slightly changes so it produces the following data.
Code: |
Begin
Starting
Tx OK, Rx failed, Rx data = 55
Tx OK, Rx failed, Rx data = 55
Tx OK, Rx failed, Rx data = 55
Tx OK, Rx failed, Rx data = 55
Tx OK, Rx failed, Rx data = 55
...
|
and here is my PIC code
Code: |
#include <16F690.h>
#FUSES INTRC_IO,NOWDT,PUT,NOMCLR, BROWNOUT
#use delay(clock=4000000)
//#use rs232(baud=9600, xmit=PIN_B7, rcv=PIN_B5, ERRORS)
#use rs232(baud=9600, xmit=PIN_C4, rcv=PIN_C5, INVERT)
#define EXT_CAN_CS PIN_C6
#define EXT_CAN_SI PIN_C7
#define EXT_CAN_SO PIN_B4
#define EXT_CAN_SCK PIN_B6
#include <can-mcp2510.c>
//=================================
void main(void)
{
int32 can_id;
int8 can_data[8];
int8 can_length;
struct rx_stat rxstat;
printf("Begin\n\r");
can_init();
can_set_mode(CAN_OP_LOOPBACK);
printf("Starting\n\r");
can_data[0] = 0x55;
while(1)
{
if(can_putd(42, can_data, 1, 3, TRUE, FALSE))
printf("Tx OK, ");
else
printf("Tx failed, ");
while(!can_kbhit());
if(can_getd(can_id, &can_data[0], can_length, rxstat))
printf("Rx OK, ");
else
printf("Rx failed, ");
printf("Rx data = %x \n\r", can_data[0]);
delay_ms(500);
}
}
|
I'm not sure if this has anything to do with the NOMCLR that I added. If I don't have it then it would not go through can_init().
Please advise, |
|
|
|
|
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
|