LPC11C14 + CAN + example

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC11C14 + CAN + example

4,572 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by yanvasilij on Tue Nov 29 05:44:46 MST 2011
Hi! I'm trying to execute an CAN example project on LPC11C14 with 16 MHz external crystal oscillator (not 12 MHz!). I reconfigured the pll (m = 3, p = 2),so Fcpu = 48 MHz. Then I connected LPCexpresso's RxCAN and TxCAN to an CAN<=>UART converter (I use a CANhacker to work with can), selected 500kb speed, and finally send a simple CAN message to LPCexpresso. But I didn't get an answer, but I see by oscilloscope that LPCexpresso generate a pulses. There is probably wrong speed on board, isn't it? what should I do?
0 Kudos
Reply
27 Replies

3,510 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mahalinr on Fri Nov 15 00:15:31 MST 2013
Thanks

How to tranmit message from PCAN USB to LPC11C14
0 Kudos
Reply

3,510 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Thu Nov 14 08:08:15 MST 2013

Quote: mahalinr
How is the value calculated


As described in User Manual UM10398:


Quote:
16.6.1.4 CAN bit timing register


and in good old LPCXpresso forum already here:

http://www.lpcware.com/content/forum/lpc11cxx-can-baud-rate-calculation

0 Kudos
Reply

3,510 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mahalinr on Thu Nov 14 07:19:45 MST 2013
How is the value calculated
0 Kudos
Reply

3,510 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Thu Nov 14 06:56:31 MST 2013

Quote: mahalinr
Can you tell me how the value of CAN_BTR is 0x00000103UL



So the question (is it a question?) is:

How is this value calculated?

Or:

How fast is this value?

Or:

How is this value in octal?
0 Kudos
Reply

3,510 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mahalinr on Thu Nov 14 05:57:04 MST 2013
Hallo

uint32_t ClkInitTable[2] = {
0x00000005UL, // CANCLKDIV
0x00000103UL // CAN_BTR

Can you tell me how the value of CAN_BTR is 0x00000103UL

Thx in advance
0 Kudos
Reply

3,510 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Thu Nov 14 05:51:32 MST 2013

Quote: mahalinr
Hallo

uint32_t ClkInitTable[2] = {
  0x00000005UL, // CANCLKDIV
  0x00000103UL  // CAN_BTR


Can you tell me ho CAN_BTR is 0x00000103UL


Thx in advance



Sorry, don't understand this. Who is ho? Is this a kind of question?
0 Kudos
Reply

3,510 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mahalinr on Thu Nov 14 05:37:01 MST 2013
Hallo

uint32_t ClkInitTable[2] = {
  0x00000005UL, // CANCLKDIV
  0x00000103UL  // CAN_BTR


Can you tell me ho CAN_BTR is 0x00000103UL


Thx in advance
0 Kudos
Reply

3,510 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Wed Nov 13 15:16:43 MST 2013
Just use something like:

http://de.tek.com/oszilloskop#all

Some of them even have CAN protocol analyzer / decoder:

http://www.picoscope.tv/general/serial-decoding-can.html

0 Kudos
Reply

3,511 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mahalinr on Wed Nov 13 06:32:37 MST 2013


#2 It's easier to transmit via LPCXpresso and read via CanHacker (or just scope it) :rolleyes:

#3 Your clock setting calculation is correct, if you are not sure if you really changed them, use Clockout to scope it :)





What is  meant by scope?[/quote]
0 Kudos
Reply

3,511 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mahalinr on Wed Nov 13 06:31:49 MST 2013

Quote: Ex-Zero
#1 Don't know which example you are using, but usually CAN default speed is 125k :eek:

See: http://knowledgebase.nxp.com/showthread.php?t=2452

#2 It's easier to transmit via LPCXpresso and read via CanHacker (or just scope it) :rolleyes:

#3 Your clock setting calculation is correct, if you are not sure if you really changed them, use Clockout to scope it

    /* Output the Clk onto the CLKOUT Pin PIO0_1 to monitor the freq on a scope */
    LPC_IOCON->PIO0_1    = (1<<0);
    /* Select the MAIN clock as the clock out selection since it's driving the core */
    LPC_SYSCON->CLKOUTCLKSEL = 3;
    /* Set CLKOUTDIV to 10 */
    LPC_SYSCON->CLKOUTDIV = 10;        //    CLKOUT Divider = 10
    /* Enable CLKOUT */
    LPC_SYSCON->CLKOUTUEN = 0;
    LPC_SYSCON->CLKOUTUEN = 1;
    while (!(LPC_SYSCON->CLKOUTUEN & 0x01));





What is  meant by scope?
0 Kudos
Reply

3,511 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by yanvasilij on Sat Dec 03 05:21:32 MST 2011
It helped! thanks very much!  The last one question... Do you mind?

Why the interrupts don't work with  RTX? Here a code. CAN_task doesn't execute because a CAN_rx interrupt don't send the semaphore


#include "LPC11xx.h"
#include "type.h"
#include "RTL.h"
#include "rom_drivers.h"

#ifndef NULL
#define NULL    ((void *)0)
#endif

OS_TID empty;  //&#1087;&#1091;&#1089;&#1090;&#1072;&#1103; &#1079;&#1072;&#1076;&#1072;&#1095;&#1072;
OS_TID can;
OS_SEM can1_rx_interrupted;//

uint8_t flag;

ROM **rom = (ROM **)0x1fff1ff8;

CAN_MSG_OBJ msg_obj;

/* Initialize CAN Controller */
uint32_t ClkInitTable[2] = {
  0x00000005UL, // CANCLKDIV
  0x00000103UL  // CAN_BTR
};

/* Callback function prototypes */
void CAN_rx(uint8_t msg_obj_num);
void CAN_tx(uint8_t msg_obj_num);
void CAN_error(uint32_t error_info);

/* Publish CAN Callback Functions */
CAN_CALLBACKS callbacks = {
   CAN_rx,
   CAN_tx,
   CAN_error,
   NULL,
   NULL,
   NULL,
   NULL,
   NULL,
};

/*CAN receive callback */
/*Function is executed by the Callback handler after
a CAN message has been received */
void CAN_rx(uint8_t msg_obj_num){
  
  /* Determine which CAN message has been received */
  msg_obj.msgobj = msg_obj_num;

  /* Now load up the msg_obj structure with the CAN message */
  (*rom)->pCAND->can_receive(&msg_obj);

  if (msg_obj_num == 1)
  {
    /* Simply transmit CAN frame (echo) with with ID +0x100 via buffer 2 */
    msg_obj.msgobj = 2;
    //msg_obj.mode_id += 0x100;
    (*rom)->pCAND->can_transmit(&msg_obj);
isr_sem_send(can1_rx_interrupted);
  }

  return;
}

/*CAN transmit callback */
/*Function is executed by the Callback handler after
a CAN message has been transmitted */
void CAN_tx(uint8_t msg_obj_num){
  return;
}

/*CAN error callback */
/*Function is executed by the Callback handler after
an error has occured on the CAN bus */
void CAN_error(uint32_t error_info){
  return;
}

/*CAN interrupt handler */
/*The CAN interrupt handler must be provided by the user application.
It's function is to call the isr() API located in the ROM */
void CAN_IRQHandler (void){
  (*rom)->pCAND->isr();
}

//&#1079;&#1072;&#1076;&#1072;&#1095;&#1080;===============================================================================================================
__task void empty_task (void);
__task void can_task (void);
//---------------------------------------------------------------------
__task void can_task (void)
{
for(;;)
{
/* Send a simple one time CAN message */
msg_obj.msgobj  = 0;
msg_obj.mode_id = 0x345;
msg_obj.mask    = 0x0;
msg_obj.dlc     = 4;
msg_obj.data[0] = 'T';//0x54
msg_obj.data[1] = 'E';//0x45
msg_obj.data[2] = 'S';//0x53
msg_obj.data[3] = 'T';//0x54
(*rom)->pCAND->can_transmit(&msg_obj);
os_sem_wait(can1_rx_interrupted, 0xffff);
}
os_tsk_delete_self ();
}

__task void empty_task (void)
{
for(;;)
{

}
}
//&#1080;&#1085;&#1080;&#1094;&#1080;&#1072;&#1083;&#1080;&#1079;&#1080;&#1088;&#1091;&#1102;&#1097;&#1072;&#1103; &#1079;&#1072;&#1076;&#1072;&#1095;&#1072; ---------------------------------------------------------------
__task void init (void)
{
    os_sem_init(can1_rx_interrupted, 0);
   os_tsk_prio_self (100);
   empty = os_tsk_create (empty_task, 1);
   can =  os_tsk_create (can_task, 2);
   os_tsk_delete_self ();
}
//=====================================================================================================================

int main(void) {

SystemInit();

/* Output the Clk onto the CLKOUT Pin PIO0_1 to monitor the freq on a scope */
LPC_IOCON->PIO0_1= (1<<0);
/* Select the MAIN clock as the clock out selection since it's driving the core */
LPC_SYSCON->CLKOUTCLKSEL = 3;
/* Set CLKOUTDIV to 6 */
LPC_SYSCON->CLKOUTDIV = 10;//CLKOUT Divider = 10
/* Enable CLKOUT */
LPC_SYSCON->CLKOUTUEN = 0;
LPC_SYSCON->CLKOUTUEN = 1;
while (!(LPC_SYSCON->CLKOUTUEN & 0x01));

/* Initialize the CAN controller */
(*rom)->pCAND->init_can(&ClkInitTable[0], 1);

/* Configure the CAN callback functions */
(*rom)->pCAND->config_calb(&callbacks);

/* Enable the CAN Interrupt */
NVIC_EnableIRQ(CAN_IRQn);

/* Send a simple one time CAN message */
msg_obj.msgobj  = 0;
msg_obj.mode_id = 0x345;
msg_obj.mask    = 0x0;
msg_obj.dlc     = 4;
msg_obj.data[0] = 'T';//0x54
msg_obj.data[1] = 'E';//0x45
msg_obj.data[2] = 'S';//0x53
msg_obj.data[3] = 'T';//0x54
(*rom)->pCAND->can_transmit(&msg_obj);


/* Configure message object 1 to receive all 11-bit messages 0x400-0x4FF */
msg_obj.msgobj = 1;
msg_obj.mode_id = 0x400;
msg_obj.mask = 0x00;
(*rom)->pCAND->config_rxmsgobj(&msg_obj);

os_sys_init(init);

while(1);
return 0;
}

0 Kudos
Reply

3,511 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Sat Dec 03 04:24:14 MST 2011
#1 Could help if you use volatile for flags in interrupts :eek:

volatile uint8_t flag;
See http://support.code-red-tech.com/CodeRedWiki/CompilerOptimization?highlight=%28volatile%29

#2 That's changing all bits of port 2

 LPC_GPIO2->DATA = 1;
#3 Why are you setting id and mask after receiving in receive interrupt?

 msg_obj.mode_id = 0x400;
 msg_obj.mask = 0x000;    //no masking
#4 You don't need to disable and enable CAN Interrupt in IRQ Handler.

void CAN_IRQHandler (void){
   NVIC_DisableIRQ(CAN_IRQn);
  (*rom)->pCAND->isr();
  NVIC_EnableIRQ(CAN_IRQn);
}
Please stop mutilating this example. If something isn't working as desired, your code is wrong and there's no need to change basics in this sample.
Your filling a working example with problems :rolleyes:

Don't know why you've deleted CAN_tx callback, but this callback is usually used to count transmitted messaged (via volatile counter) and compare it with receive counter :eek:
0 Kudos
Reply

3,511 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by yanvasilij on Sat Dec 03 03:28:16 MST 2011
So, here is my programm. When CAN_rx interrupt is occur it shuold send a simple massege by can. And it does. But it doesn't send the massage all the time, when incoming messages come.

#include "LPC11xx.h"
#include "rom_drivers.h"

#ifndef NULL
#define NULL    ((void *)0)
#endif

uint8_t flag;

ROM **rom = (ROM **)0x1fff1ff8;

CAN_MSG_OBJ msg_obj;

/* Initialize CAN Controller */
uint32_t ClkInitTable[2] = {
  0x00000005UL, // CANCLKDIV
  0x00000103UL  // CAN_BTR
};

/* Callback function prototypes */
void CAN_rx(uint8_t msg_obj_num);
void CAN_tx(uint8_t msg_obj_num);
void CAN_error(uint32_t error_info);

/* Publish CAN Callback Functions */
CAN_CALLBACKS callbacks = {
   CAN_rx,
   NULL,
   CAN_error,
   NULL,
   NULL,
   NULL,
   NULL,
   NULL,
};

/*CAN receive callback */
/*Function is executed by the Callback handler after
a CAN message has been received */
void CAN_rx(uint8_t msg_obj_num){
  
  /* Determine which CAN message has been received */
  msg_obj.msgobj = msg_obj_num;

  /* Now load up the msg_obj structure with the CAN message */
  (*rom)->pCAND->can_receive(&msg_obj);
  LPC_GPIO2->DATA = 1;
  flag = 1;
  msg_obj.mode_id = 0x400;
  msg_obj.mask = 0x000;    //no masking
 //(*rom)->pCAND->config_rxmsgobj(&msg_obj);
  //if (msg_obj_num == 1)
  //{

  //}

  return;
}

/*CAN transmit callback */
/*Function is executed by the Callback handler after
a CAN message has been transmitted */
//void CAN_tx(uint8_t msg_obj_num){
//  LPC_GPIO2->DATA = 1;
//  return;
//}

/*CAN error callback */
/*Function is executed by the Callback handler after
an error has occured on the CAN bus */
void CAN_error(uint32_t error_info){
  LPC_GPIO2->DATA = 1;
  return;
}

/*CAN interrupt handler */
/*The CAN interrupt handler must be provided by the user application.
It's function is to call the isr() API located in the ROM */
void CAN_IRQHandler (void){
   NVIC_DisableIRQ(CAN_IRQn);
  (*rom)->pCAND->isr();
  NVIC_EnableIRQ(CAN_IRQn);
}

int main(void) {
uint8_t i;
SystemInit();

/* Output the Clk onto the CLKOUT Pin PIO0_1 to monitor the freq on a scope */
LPC_IOCON->PIO0_1= (1<<0);
/* Select the MAIN clock as the clock out selection since it's driving the core */
LPC_SYSCON->CLKOUTCLKSEL = 3;
/* Set CLKOUTDIV to 6 */
LPC_SYSCON->CLKOUTDIV = 10;//CLKOUT Divider = 10
/* Enable CLKOUT */
LPC_SYSCON->CLKOUTUEN = 0;
LPC_SYSCON->CLKOUTUEN = 1;
while (!(LPC_SYSCON->CLKOUTUEN & 0x01));

/* Initialize the CAN controller */
(*rom)->pCAND->init_can(&ClkInitTable[0], 1);

/* Configure the CAN callback functions */
(*rom)->pCAND->config_calb(&callbacks);

/* Enable the CAN Interrupt */
NVIC_EnableIRQ(CAN_IRQn);

/* Send a simple one time CAN message */
msg_obj.msgobj  = 2;
msg_obj.mode_id = 0x345;
msg_obj.mask    = 0x0;
msg_obj.dlc     = 4;
msg_obj.data[0] = 'T';//0x54
msg_obj.data[1] = 'E';//0x45
msg_obj.data[2] = 'S';//0x53
msg_obj.data[3] = 'T';//0x54
(*rom)->pCAND->can_transmit(&msg_obj);

/* Configure message object 1 to receive all 11-bit messages 0x400-0x4FF */
//for(i = 1; i < 33; i ++)
msg_obj.msgobj = 0;
msg_obj.mode_id = 0x400;
msg_obj.mask = 0x000;
(*rom)->pCAND->config_rxmsgobj(&msg_obj);

LPC_GPIO2->DIR = 1;
while(1){
if(flag)
{
flag = 0;

/* Simply transmit CAN frame (echo) with with ID +0x100 via buffer 2 */
msg_obj.msgobj = 2;
    msg_obj.mask = 0x000;
    msg_obj.mode_id = 0x345;
msg_obj.mask    = 0x0;
msg_obj.dlc     = 4;
msg_obj.data[0] = 1;//0x54
msg_obj.data[1] = 1;//0x45
msg_obj.data[2] = 1;//0x53
msg_obj.data[3] = 1;//0x54
    (*rom)->pCAND->can_transmit(&msg_obj);
LPC_GPIO2->DATA &= ~1;
}
;//__WFI();/* Go to Sleep */
}
}
0 Kudos
Reply

3,511 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by yanvasilij on Fri Dec 02 22:33:25 MST 2011

Quote: Zero
Resetting mask register should do that (transmit received message ID + 0x100)

 //Configure message object 1 to receive every damned 11-bit message
 msg_obj.msgobj = 1;
 msg_obj.mode_id = 0x400;
 msg_obj.mask = 0x000;    //no masking
 (*rom)->pCAND->config_rxmsgobj(&msg_obj);    



I did all as you said. But the board don't send back all messages. It doesn't always work. For example: the board sent 3 messages, after I had sent  7 messages (they're all the same). What's wrong? Is there a more detailed manual, where I can read about API functions?
0 Kudos
Reply

3,511 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Wed Nov 30 11:43:57 MST 2011

Quote:

Again I am going to do simple program that will send back all incimings massages.

Resetting mask register should do that (transmit received message ID + 0x100)

 //Configure message object 1 to receive every damned 11-bit message
 msg_obj.msgobj = 1;
 msg_obj.mode_id = 0x400;
 msg_obj.mask = 0x000;    //no masking
 (*rom)->pCAND->config_rxmsgobj(&msg_obj);    
0 Kudos
Reply

3,511 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by yanvasilij on Wed Nov 30 11:24:13 MST 2011

Quote: Zero
This sample is working here (responding 500kbit 0x101 message) :eek:
You could also reset your LPC_CAN->IF1_MSK1/2 registers to receive more incoming messages, but using can_onchip sample is less complicated and is reducing code size about 50%.
This on-chip driver is really doing a good job :)
Is can_onchip sample working with your hardware?



Yes it is. But I've not finished stading can_onchip. I reconfigured sample on 16 MHz and it work. I think my questions will come later :). Again I am going to do simple program that will send back all incimings massages.
0 Kudos
Reply

3,511 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Wed Nov 30 10:58:29 MST 2011
This sample is working here (responding 500kbit 0x101 message) :eek:
You could also reset your LPC_CAN->IF1_MSK1/2 registers to receive more incoming messages, but using can_onchip sample is less complicated and is reducing code size about 50%.
This on-chip driver is really doing a good job :)
Is can_onchip sample working with your hardware?
0 Kudos
Reply

3,511 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by yanvasilij on Wed Nov 30 09:53:10 MST 2011

Quote: Zero
#1 You don't follow my advice to start with an easy example :rolleyes:

#2 You don't understand how CAN is working in this sample :eek:

What do you think is happening here:

...

This sample is setting up 4 objects, and only 1 is receiving an 11bit ID. So please [B][SIZE=4][COLOR=Red]send [/COLOR][/SIZE][SIZE=4][COLOR=Red]this ID (0x101)[/COLOR][/SIZE][/B] to get a 0x202 message back :eek:



Yes it is. But why do the interrupt handler not execute (I send mesaage with that ID) in this sample after it is being changed? And yes, I took your advice. I'm stading can on-chip and it really easier. Thanks.
0 Kudos
Reply

3,511 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by yanvasilij on Wed Nov 30 09:46:07 MST 2011

Quote: Polux rsv
You mention RxCAN and TxCAN connected to the converter. Where is the transceiver? :rolleyes:
You should use LPC11C24 in order to connect directly the pins to the canbus. With LPC11C14, you should add a transceiver between RxCAN/TxCAN and CAN-H/CAN-L.

Angelo



there is transivers between 11&#1089;14 and can bus. I seid before that it worked with 1768
0 Kudos
Reply

3,511 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Polux rsv on Wed Nov 30 07:11:48 MST 2011

Quote: yanvasilij
Then I connected LPCexpresso's RxCAN and TxCAN to an CAN<=>UART converter



You mention RxCAN and TxCAN connected to the converter. Where is the transceiver? :rolleyes:
You should use LPC11C24 in order to connect directly the pins to the canbus. With LPC11C14, you should add a transceiver between RxCAN/TxCAN and CAN-H/CAN-L.

Angelo
0 Kudos
Reply