CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

please help me about CAN protocol
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
dangluong



Joined: 07 May 2010
Posts: 10
Location: vietnam

View user's profile Send private message Yahoo Messenger

please help me about CAN protocol
PostPosted: Mon May 10, 2010 8:33 pm     Reply with quote

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

View user's profile Send private message Visit poster's website

Re: please help me about CAN protocol
PostPosted: Tue May 11, 2010 6:02 am     Reply with quote

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

View user's profile Send private message Yahoo Messenger

PostPosted: Wed May 12, 2010 8:56 pm     Reply with quote

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

View user's profile Send private message Yahoo Messenger

PostPosted: Wed May 12, 2010 9:23 pm     Reply with quote

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

View user's profile Send private message Yahoo Messenger

PostPosted: Wed May 12, 2010 9:36 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu May 13, 2010 11:31 am     Reply with quote

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

View user's profile Send private message Yahoo Messenger

PostPosted: Fri May 14, 2010 1:12 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Fri May 14, 2010 9:25 am     Reply with quote

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

View user's profile Send private message Yahoo Messenger

PostPosted: Fri May 14, 2010 11:10 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Fri May 14, 2010 11:26 am     Reply with quote

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

View user's profile Send private message Yahoo Messenger

PostPosted: Fri May 14, 2010 11:42 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Fri May 14, 2010 11:45 am     Reply with quote

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

View user's profile Send private message Yahoo Messenger

PostPosted: Fri May 14, 2010 12:01 pm     Reply with quote

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

View user's profile Send private message Yahoo Messenger

PostPosted: Fri May 14, 2010 12:07 pm     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Fri May 14, 2010 12:38 pm     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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