|
|
View previous topic :: View next topic |
Author |
Message |
dangluong
Joined: 07 May 2010 Posts: 10 Location: vietnam
|
please help me about CAN protocol |
Posted: Mon May 10, 2010 8:33 pm |
|
|
Hi everybody I come from Vietnam so sorry about my english and now I am doing a project about CAN protocol using PIC18F4580. My circuit includes 2 boards. In there board 2 read data from adc and transmit it to board1. Board 1 receive data from the Board1 though CAN and transmit to PC. I also use Hyper terminal of CCS but I only see
Quote: |
ÁÅ……¤¤ÅçÄ…„„bðÁÅ……¤¤ÅçÄ…„„bðÁÅ……¤¤ÅçÄ…„„bðÁÅ……¤¤ÅçÄ…„„bðÁÅ……¤¤ÅçÄ…„„bðÁÅ……¤¤ÅçÄ…„„bðÁÅ……¤¤ÅçÄ…„„bðÁÅ……¤¤ÅçÄ…„¤bñÁÅ……¤¤ÅçÄ…„„bð
|
Here is my code for board1
Code: |
#include <18F4580.h>
#fuses HS, NOPROTECT, PUT, BROWNOUT, NOWDT, NOLVP
#use delay(clock=20000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#include <can-18xxx8.c>
#include <lcd.c>
#define BOARD1_ID 24
#define BOARD2_ID 25
//======================================
void main()
{
struct rx_stat rxstat;
int32 rx_id;
int32 tx_id;
int8 rx_len;
int8 Can_buffer[12];
int i;
can_init();
lcd_init(); // Always call this first.
printf(lcd_putc,"starting");
delay_ms(10000);
lcd_putc("\f");
while(1)
{
// Wait for the char to be echoed back.
if(can_kbhit())
{
if(can_getd(rx_id, &Can_buffer[0], rx_len, rxstat))
{
if(rx_id == BOARD1_ID) // Is it for this board ?
{
lcd_putc("\f");
printf(lcd_putc,"complete\r\n");
printf("Firmware version is %4X\r\n",Can_buffer[0]);
putc(Can_buffer[0]); // If so, display the char
delay_ms(1000);
}
}
}
}
}
|
Here is my code for Board2
Code: |
#include <18F4580.h>
#device* = 16 ADC=8
#fuses HS,NOPROTECT,NOLVP,NOWDT
#use delay(clock=2000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7)
#define CAN_USE_EXTENDED_ID FALSE
#include <can-18xxx8.c>
#define BOARD1_ID 24
#define BOARD2_ID 25
int16 ms;
#int_TIMER2
void TIMER2_isr(void)
{
ms++ ;
}
void main()
{
while(1)
{
int8 ADC_buffer[8];
setup_timer_2(T2_DIV_BY_4,53,3);
can_init();
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
set_ADC_channel(1);
delay_us(10);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
if ( can_tbe() && (ms > 5000))
{
ADC_buffer[0]=read_adc();
ms=0;
can_putd(BOARD1_ID,&ADC_buffer[0], 2, 3, 1, 0);
ADC_buffer[0] = 0;
}
}
}
|
I've read code in http://www.ccsinfo.com/forum/viewtopic.php?t=29627&start=7 that PCM programmer wrote. It's very useful however when I try do following it, it is not succeed.
Please help me solve this problem soon. |
|
|
collink
Joined: 08 Jan 2010 Posts: 137 Location: Michigan
|
Re: please help me about CAN protocol |
Posted: Tue May 11, 2010 6:02 am |
|
|
Hmm...
Your code has
Code: |
putc(Can_buffer[0]);
|
Which would just output the character corresponding to the ADC reading. So you could get funny characters like you are seeing. Are you sure that's not the correct output? Have you tried changing the way that the data are displayed? Maybe switch that line to
Code: |
printf("%u", Can_buffer[0]);
|
Unrelated notes:
1:
When getting the address of an array you don't even need a subscript unless it's not zero. In other words, you can make a line like this:
Code: |
if(can_getd(rx_id, &Can_buffer, rx_len, rxstat))
|
2:
You really should not have delays within the canbus code. Why delay 1000ms?
Code: |
if(rx_id == BOARD1_ID) // Is it for this board ?
{
lcd_putc("\f");
printf(lcd_putc,"complete\r\n");
printf("Firmware version is %4X\r\n",Can_buffer[0]);
putc(Can_buffer[0]); // If so, display the char
delay_ms(1000);
}
|
3:
In the below referenced code you set that you are sending an extended frame but earlier in the code you set CAN_USE_EXTENDED_ID to false so I assume you really want to send standard frames
Code: |
if ( can_tbe() && (ms > 5000))
{
ADC_buffer[0]=read_adc();
ms=0;
can_putd(BOARD1_ID,&ADC_buffer[0], 2, 3, 1, 0);
ADC_buffer[0] = 0;
}
|
Also, you are sending two bytes of data here but you only ever use one byte at the other board. Did you mean to do that? |
|
|
dangluong
Joined: 07 May 2010 Posts: 10 Location: vietnam
|
|
Posted: Wed May 12, 2010 8:56 pm |
|
|
Thanks you for your help vey much. Now I've solved my problem. But I don't know how to transmit a byte of data from PC to PIC. I want to control PortB in my board2, nevertheless I only transmit a character from PC and it can't control portB. Could anybody help me to give some advice? Thank you!
Here is my code for board1
Code: |
#include <18F4580.h>
#fuses HS, NOPROTECT, PUT, BROWNOUT, NOWDT, NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#include <can-18xxx8.c>
#include <lcd.c>
#define BOARD1_ID 24
#define BOARD2_ID 25
//======================================
void main()
{
struct rx_stat rxstat;
int32 rx_id;
int32 tx_id;
int8 rx_len;
int8 Can_buffer[12];
int i;
int1 c;
can_init();
lcd_init(); // Always call this first.
printf(lcd_putc,"preparing");
delay_ms(3000);
while(1)
{
if(can_kbhit())
{
if(can_getd(rx_id, Can_buffer, rx_len, rxstat))
{
if(rx_id == BOARD1_ID) // Is it for this board ?
{
lcd_putc("\f");
printf(lcd_putc,"running");
printf("input analog 0 received is %8X\r\n",Can_buffer[0]);
printf("input analog 1 received is %8X\r\n",Can_buffer[1]);
printf("input analog 2 received is %8X\r\n",Can_buffer[2]);
printf("input analog 3 received is %8X\r\n",Can_buffer[3]);
printf("input analog 4 received is %8X\r\n",Can_buffer[4]);
printf("input analog 5 received is %8X\r\n",Can_buffer[5]);
printf("input analog 6 received is %8X\r\n",Can_buffer[6]);
printf("input analog 7 received is %8X\r\n",Can_buffer[7]);
puts("rx ok");
for (i=0;i<8;i++)
{
Can_buffer[i] = 0;
}
}
}
}
if(can_tbe())
{
if (kbhit())
{
for(i=0;i<8;i++)
{
c = getc();
if(c=='1'|c=='0')
{
lcd_gotoxy(i+1,2);
lcd_putc(c+0x30);
}
else
{
lcd_gotoxy(1,2);
printf(lcd_putc,"input error");
}
}
}
}
}
}
|
Finally code for board2
Code: |
#include <18F4580.h>
#device* = 16 ADC=8
#fuses HS,NOPROTECT,NOLVP,NOWDT
#use delay(clock=2000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#define CAN_USE_EXTENDED_ID FALSE
#include <can-18xxx8.c>
#define BOARD1_ID 24
#define BOARD2_ID 25
int16 ms;
#int_TIMER2
void TIMER2_isr(void)
{
ms++ ;
}
void main()
{ int32 tx_id;
int8 Can_buffer[12];
struct rx_stat rxstat;
int8 rx_len,i;
int8 ADC_buffer[8];
setup_timer_2(T2_DIV_BY_4,53,3);
can_init();
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
set_ADC_channel(1);
delay_us(10);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
while(1)
{
if( can_tbe() && (ms > 50000))
{
ADC_buffer[0]=read_adc();
ms=0;
can_putd(BOARD1_ID,ADC_buffer, 8, 3, 1, 0);
for (i=0;i<8;i++)
{
ADC_buffer[i] = 0;
}
}
if(can_kbhit())
{
if(can_getd(tx_id , &Can_buffer[11], rx_len, rxstat))
{if(tx_id == BOARD1_ID)
{
output_B(Can_buffer[11]);
}
}
}
}
}
|
|
|
|
dangluong
Joined: 07 May 2010 Posts: 10 Location: vietnam
|
|
Posted: Wed May 12, 2010 9:23 pm |
|
|
I want to send standard frames.last time I also try to use
Code: | can_putd(BOARD1_ID,ADC_buffer, 8, 3, 0, 0);
|
but in the Hyper terminal ccs don't receive anything.I don't know why?
Could you help me explain.
I also try to use
Code: | if(can_getd(rx_id, &Can_buffer, rx_len, rxstat)) |
however when I compile it's error.I want to receive data from 8 input analog in board2 and transmit to board1 so board1 could receive 8 byte data if I write
Code: | can_getd(rx_id, Can_buffer, rx_len, rxstat |
|
|
|
dangluong
Joined: 07 May 2010 Posts: 10 Location: vietnam
|
|
Posted: Wed May 12, 2010 9:36 pm |
|
|
To collink you have nick chat on yahoo if you don't mind could you send me. I want exchange direct with you or you can add my yahoo is dangluong_bk3i. Thank you very much. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu May 13, 2010 11:31 am |
|
|
Code: |
Finally code for board2
#include <18F4580.h>
#device* = 16 ADC=8
#fuses HS,NOPROTECT,NOLVP,NOWDT
#use delay(clock=[b]2000000[/b])
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
|
Your #use delay is set for 2 MHz. You probably intend it to be 20 MHz. |
|
|
dangluong
Joined: 07 May 2010 Posts: 10 Location: vietnam
|
|
Posted: Fri May 14, 2010 1:12 am |
|
|
Thank you PCM programmer. Now i have other problem with my program. I want receive not only 8byte data but also more than 8byte how will i do? Could you give some advices? |
|
|
collink
Joined: 08 Jan 2010 Posts: 137 Location: Michigan
|
|
Posted: Fri May 14, 2010 9:25 am |
|
|
dangluong wrote: | Thank you PCM programmer. Now i have other problem with my program. I want receive not only 8byte data but also more than 8byte how will i do? Could you give some advices? |
Send as multiple frames with incremental IDs. For instance, if you have 24 bytes to send you can send 8 bytes as frame ID X then 8 more as frame ID X+1, then the last 8 as frame ID X+2. You recombine the data at the receiving end.
Otherwise you could use one of the higher end protocols that support larger frame payloads. You could look up CANOpen or J1939 but I don't see any reason for you to bother with all the complication. |
|
|
dangluong
Joined: 07 May 2010 Posts: 10 Location: vietnam
|
|
Posted: Fri May 14, 2010 11:10 am |
|
|
Thank you very much. I also solved that problem by setting another ID. But I don't still know how to do to send a byte from PC to board1, then board1 send to board2 through Can bus to control PortB.
Example, when send a byte 255 (or 11111111) from PC then portB =11111111. Could you help me solve this problem. |
|
|
collink
Joined: 08 Jan 2010 Posts: 137 Location: Michigan
|
|
Posted: Fri May 14, 2010 11:26 am |
|
|
dangluong wrote: | Thank you very much. I also solved that problem by setting another ID. But I don't still know how to do to send a byte from PC to board1, then board1 send to board2 through Can bus to control PortB.
Example, when send a byte 255 (or 11111111) from PC then portB =11111111. Could you help me solve this problem. |
You seem to practically already have it in your code.
What you do is get a byte from the PC with getc(); then you send it out with can_putd (for one byte it would be) can_putd(ID, &Variable, 1,3,0,0); The receiving board uses can_getd to receive the byte and output_b(Value); to set the port directions. You seem to already have other things running over canbus so you should set a special frame ID for the port changing operation. |
|
|
dangluong
Joined: 07 May 2010 Posts: 10 Location: vietnam
|
|
Posted: Fri May 14, 2010 11:42 am |
|
|
I also tried it before.but when I use getc() then on the terminal CCS if I send 255 it will understand that are 3 char not abyte |
|
|
collink
Joined: 08 Jan 2010 Posts: 137 Location: Michigan
|
|
Posted: Fri May 14, 2010 11:45 am |
|
|
dangluong wrote: | I also tried it before.but when I use getc() then on the terminal CCS if I send 255 it will understand that are 3 char not abyte |
By any chance are those three characters: 255 13 10 (character codes)? It sounds like you are receiving CRLF (line feed) characters as well.
Or do you mean you literally send "2" "5" "5"? In that case you need to read in the characters and then use atoi to convert the string to an integer |
|
|
dangluong
Joined: 07 May 2010 Posts: 10 Location: vietnam
|
|
Posted: Fri May 14, 2010 12:01 pm |
|
|
I think also only way or must build up other interface. Now I am studying how to build an interface that includes receiving, transmitting frame. Especially it also have interface consist of 8 led corresponds 8bit in portB. |
|
|
dangluong
Joined: 07 May 2010 Posts: 10 Location: vietnam
|
|
Posted: Fri May 14, 2010 12:07 pm |
|
|
In the CCS only has command getc() or Gets() so PIC will understand that is char or string not a numeric data. Did you understand my opinion? |
|
|
collink
Joined: 08 Jan 2010 Posts: 137 Location: Michigan
|
|
Posted: Fri May 14, 2010 12:38 pm |
|
|
dangluong wrote: | In the CCS only has command getc() or Gets() so PIC will understand that is char or string not a numeric data. Did you understand my opinion? |
Maybe... I'm having trouble completely understanding what you mean.
Yes, the pic will only get one byte when you call getc().
Do you mean that you intend to send three characters when you send 255? That is, you send a 2, a 5, and another 5 or you want to send 255 as a character code (that is, send the value 0xFF through the serial port)?
If you want to just type 2, 5, 5 on the keyboard and have it work then you will need to maybe call getc three times or use gets and you'll have to push the enter/return key on the PC to send the number off to the pic. Once you get all of the characters you can interpret them into an integer value with atoi. |
|
|
|
|
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
|