Haremos uso del módulo CAN del MCU R5F562N8 de la tarjeta de evaluación YRDKRX62N. Crearemos 3 nodos para demostrar la comunicación bidireccional entre ambos. Dos nodos serán con mcu pic18f2680. El primero de ellos (enviar) solo enviará un frame de datos de 8 bits el cual el primer byte será el valor analógico de un potenciómetro los demás datos serán fijos. El segundo de ellos (recibir) se encargará de imprimir en el LCD el ID, tamaño de datos y los primeros 5 bytes. Así mismo enviara vía uart a una hypeterminal toda la información de la red CAN. La tarjeta YRDKRX62N será un nodo de envío y recepción de frame de datos. Imprimiendo en la LCD lo del nodo (enviar) y también nyectara a la red CAN un frame de datos donde el primer byte es un incrementador y los demás serán bytes fijos.
- Configuraremos stack de la API CAN BUS
- Imprimiremos en el LCD el ID y valores del nodo que envía frames a la red CAN
DESARROLLO:
- Del documento Renesas RX62N RDK User's Manual ubicamos el conector J6 del puerto CAN de la tarjeta.
- Del YRDKRX62N schematic identificamos el circuito del CAN bus y su transceiver:
PASOS:
- Creación de un proyecto:
2.- New/ C Project / Renesas RXC ToolChain
3.- Seleccionar el target R5F562N8, debug hardware Segger jLink, después next
4.- Seleccionar C/C++ Source file y por ultimo Finish.
5.- Para poder implementar correctamente el protocolo CAN y demostrar su funcionamiento es necesario primeramente crear una red de nodos con microcontroladores.
- La red de nodos propuesta se muestra en la siguiente imagen:
NODO B “ENVIAR”:
El nodo B tiene un identificador ID = 24 y enviara 8 Bytes de prueba = [AN0, 120, 140, 30, 168, 255, 10, 15]. Donde AN0 es el valor de un canal analógico del microcontrolador PIC18F2680.
A su vez envía por medio del UART dichos valores a una hyperterminal.
El nodo A escucha los mensajes de la red e imprime los valores en el LCD, enviando de igual manera vía UART los datos a otra hypeterminal.
La conexión con el USB-Serial para los nodos será:
Conectamos TxD --> RxD, TxD --> RxD y GND --> GND
- CONFIGURACIÓN PARA 500 kbps de loas Nodos A y B:
Para 500 Kbps:
Tq = 0.2 us
Tq = (2 x (PRE + 1))/Fosc
PRE = ((Tq x Fosc) / 2 ) - 1
PRE = ((0.2us x 20Mhz) / 2) - 1 = 1
Baudaje = 10 x 0.2 us = 2 us = 1/(2 us) = 500
kbps
TOTAL-----------> 10 Tq
CAN_BRG_PRESCALAR 1
CAN_BRG_SYNCH_JUMP_WIDTH 0 ---->
1
CAN_BRG_PHASE_SEGMENT_1 2 ---->
3
CAN_BRG_PROPAGATION_TIME 2 ---->
3
CAN_BRG_PHASE_SEGMENT_2 2
----> 3
- SW NODO A:
#include <18F2680.h>
#fuses HS,NOPROTECT,NOLVP,NOWDT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#define LCD_DB4 PIN_C2 //PIN 11 LCD PIN 7,8,9,10 DEL LCD NO SE CONECTAN
#define LCD_DB5 PIN_C3 //PIN 12 LCD PIN 1 A TIERRA
#define LCD_DB6 PIN_C4 //PIN 13 LCD PIN 2 A VCC
#define LCD_DB7 PIN_C5 //PIN 14 LCD PIN 3 R=330 OHMS A TIERRA
#define LCD_RS PIN_C1
//PIN 4 LCD
//#define LCD_RW PIN_A2 // a tierra
#define LCD_E PIN_C0 //PIN 6 LCD
#include "flex_lcd.c"
#include "can-18f4580_mod.c"
int16 cnt=0;
#int_timer2
void isr_timer2(void)
{
if(cnt
>1000)
{
output_toggle(PIN_B5);
cnt
= 0;
}
cnt++;
}
void main()
{
struct
rx_stat rxstat;
int32
rx_id;
int
in_data[8];
int
rx_len;
int i;
//
(4 *
4 * (79+1)*16)/20x10^6 = 1.02 ms
setup_timer_2(T2_DIV_BY_4,79,16);
//setup up timer2 to interrupt every 1ms if using 20Mhz clock
enable_interrupts(INT_TIMER2);
//enable timer2 interrupt
enable_interrupts(GLOBAL);
//enable all interrupts (else timer2 wont happen)
lcd_init();
printf(LCD_PUTC,"\f CAN BUS
500Khz");
printf(LCD_PUTC,"\n Carlos - 2017 ");
delay_ms(3000);
for
(i=0;i<8;i++)
{
in_data[i]=0;
}
printf("\r\n\r\nCCS CAN EXAMPLE
--> MASTER\r\n");
can_init();
//
can_set_mode(CAN_OP_LOOPBACK); // Added this line
printf("\r\nRunning...");
while(TRUE)
{
if
(can_kbhit()) //if data is waiting in
buffer...
{
if(can_getd(rx_id, &in_data[0], rx_len, rxstat))
{ //...then get data from buffer
printf("\r\nGOT: BUFF=%U ID=%LU LEN=%U OVF=%U ",
rxstat.buffer, rx_id, rx_len, rxstat.err_ovfl);
printf("FILT=%U RTR=%U EXT=%U INV=%U", rxstat.filthit,
rxstat.rtr, rxstat.ext, rxstat.inv);
printf("\r\n DATA = ");
for (i=0;i<rx_len;i++)
{
printf("%u ",in_data[i]);
}
printf(LCD_PUTC,"\fID = %Ld, LEN = %d", rx_id, rx_len);
printf(LCD_PUTC,"\n%u %u %u %u %u",in_data[0],in_data[1],in_data[2],in_data[3],in_data[4]);
printf("\r\n");
}
else
{
printf("\r\nFAIL on GETD\r\n");
printf(LCD_PUTC,"\fFAIL on GETD");
}
}
}
}
- SW NODO B (ID = 24):
#include <18F2680.h>
#fuses HS,NOPROTECT,NOLVP,NOWDT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#include "can-18f4580_mod.c"
int16 ms=0, cnt=0;
#int_timer2
void isr_timer2(void)
{
ms++;
//keep a running timer that increments every milli-second
if(cnt
>1000)
{
output_toggle(PIN_B5);
cnt
= 0;
}
cnt++;
}
void main()
{
//send a request (tx_rtr=1) for 8 bytes of data
(tx_len=8) from id 24 (tx_id=24)
int
out_data[8];
int32
tx_id=24;
int1
tx_rtr=0;
int1
tx_ext=1;
int
tx_len=8;
int
tx_pri=3;
int i;
out_data[0]=0;
out_data[1]=120;
out_data[2]=140;
out_data[3]=30;
out_data[4]=168;
out_data[5]=255;
out_data[6]=10;
out_data[7]=15;
//
(4 *
4 * (79+1)*16)/20x10^6 = 1.02 ms
setup_timer_2(T2_DIV_BY_4,79,16);
//setup up timer2 to interrupt every 1ms if using 20Mhz clock
can_init();
enable_interrupts(INT_TIMER2);
//enable timer2 interrupt
enable_interrupts(GLOBAL);
//enable all interrupts (else timer2 wont happen)
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
delay_ms(3000);
printf("\r\n\r\nCCS CAN EXAMPLE --> SLAVE\r\n");
printf("\r\nRunning...");
while(TRUE)
{
//every two seconds, send new data if transmit buffer is empty
if
( can_tbe() && (ms > 1000))
{
ms=0;
out_data[0] =Read_ADC();
for (i=0;i<tx_len;i++)
{
printf("%u ",out_data[i]);
}
printf("\r\n");
i=can_putd(tx_id, out_data, tx_len,tx_pri,tx_ext,tx_rtr); //put data on
transmit buffer
}
}
}
NODO A
(RECIBIENDO)
NODO B (ID = 24)
(ENVIANDO)
1er Byte valor de potenciometro
- NODO A Y B COMUNICANDOSE CORRECTAMENTE!
Toda la información de implementación CAN sobre microcontroladores microchip la puedes encontrar en el siguiente link:
http://www.todopic.com.ar/foros/index.php?topic=19182.0
6.- Conexión entre la tarjeta YRDKRX62N (NODO C) y los Nodos A y B:
7.- El calculo del baudrate para el Nodo C se especifica en el archivo config_r_can_rapi.h:
Calculation of baudrate:
*********************************
* PCLK = 48 MHz = fcan. *
* fcanclk
= fcan/prescale *
*********************************
Example 1)
Desired baudrate 500 kbps.
Selecting
prescale to 4.
fcanclk = 48000000/4
fcanclk
= 12000000 Hz
Bitrate
= fcanclk/Tqtot
or,
Tqtot
= fcanclk/bitrate
Tqtot
= 12000000/500000
Tqtot
= 120/5 = 24.
Tqtot = TSEG1 + TSEG2 + SS (TSEG1 must be > TSEG2)
Using
TSEG1 = 15 Tq
TSEG2 = 8 Tq
SS = 1 Tq always
Re-synchronization Control (SJW) should be
1-4 Tq (must be <=TSEG2). */
#define CAN_BRP 4
#define CAN_TSEG1 15 // 1 1 1 0: 15 Tq
can_block_p->BCR.BIT.TSEG1 = CAN_TSEG1 - 1;
#define CAN_TSEG2 8 // 1 1 1: 8 Tq can_block_p->BCR.BIT.TSEG2 = CAN_TSEG2
- 1;
#define CAN_SJW 2 // 0 1: 2 Tq can_block_p->BCR.BIT.SJW = CAN_SJW - 1;
//Tqtot =
15 + 8 + 1 = 24
8.- Como todos los Nodos A, B y C utilizan el formato extendido ID. En el archivo r_can_api.c se establecerá dicha configuración:
Ln 157: can_block_p->CTLR.BIT.IDFM = 1;
Ln 503: can_block_p->MB[mbox_nr].ID.BIT.SID = 0;
Ln 506: can_block_p->MB[mbox_nr].ID.BIT.EID = frame_p->id;
Ln 718: can_block_p->MB[mbox_nr].ID.BIT.SID = 0;
Ln 721: can_block_p->MB[mbox_nr].ID.BIT.EID = sid;
Ln 818: frame_p->id = can_block_p->MB[mbox_nr].ID.BIT.EID;
Ln 878: can_block_p->MKR[mbox_nr/4].BIT.EID = sid_mask_value;
uint32_t InitCanApp(void);
void CheckCANerrors(void);
void HandleCanBusState(uint8_t ch_nr);
void CanPollDemo(void);
void main(void)
{
set_ipl(0); // enable interrupts
SR_Oscilador(); // F = 96 Mhz
SR_LCD_GRAPH(); // LCD 96x64
SR_TIMER_0(); // Inicializa
el Timer 0 en cascada para 16 bits
SR_CAN_INIT(); // inicializa Bus CAN
while(1)
{
/* Check for CAN errors. */
CheckCANerrors();
if (can_state[0] != R_CAN_STATUS_BUSOFF)
{
CanPollDemo();
}
else
/* Bus Off. */
{
LCDPrintf(0,
0, "App
in ");
LCDPrintf(1,
0, "Bus Off ");
/* HandleCanBusState() will restart app.
*/
delay_ms(3000);
LCDClear();
}
}
}
- Agregar código, compilar y debug:
--> Practica #19
2.- Compilar con el icono del martillo y debug con el icono del insecto:
RESULTADOS:
- Enviando a la red CAN los frames [225, 11, 22, 33, 44, 55, 66, 77] con ID = 33
- Recibiendo de la red CAN los frames [An0, 120, 140, 30, 168, 255, 10, 15] con ID = 24
No hay comentarios.:
Publicar un comentario