/////////////////////////////////////////////////////////////////////////
//// EX_CAN_CCS_A_4580.C ////
//// ////
//// Example of CCS's CAN library, using the PIC18Fxx8. This ////
//// example was tested with and written for the CCS CAN Prototype ////
//// board. ////
//// ////
//// The CCS CAN Prototype board has four CAN nodes that communicate ////
//// to each other. Node A is the 18F458 with it's internal CAN ////
//// peripheral, Node B is a PIC16F87x connected to an external ////
//// MCP2510 CAN peripheral, and Node C and Node D are both MCP250xx ////
//// stand-alone CAN I/O expanders. This example is the firmware ////
//// for Node A. ////
//// ////
//// Every two seconds this firmware sends out a command to node B ////
//// to change it's leds (CAN ID 0x202) ////
//// ////
//// Upon change of the A/D reading, a value of 0-9 is sent to ////
//// Node D which is displayed on the 8-seg LCD (CAN ID 0x400) ////
//// ////
//// Pressing the Node A button sends a request to Node B (CAN ID ////
//// 0x201) for Node B's A/D reading, which Node B will respond ////
//// with a CAN message with it's A/D reading (with CAN ID 0x201). ////
//// Also, pressing the Node A button will change the LEDs on Node ////
//// C (CAN ID 0x300) ////
//// ////
//// Pressing Node C's buttons will cause Node A's buttons to change ////
//// (Node C transmits button changes with CAN ID 0x303) ////
//// ////
//// Using a serial port, you can examine all the CAN traffic as ////
//// seen by the 18xxx8. ////
//// ////
//// For more documentation on the CCS CAN library, see can-18xxx8.c ////
//// ////
//// Jumpers: ////
//// PCH pin C7 to RS232 RX, pin C6 to RS232 TX ////
//// ////
//// This example will work with the PCH compiler. ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// Baud rate settings to use to connect to the CCS CAN Prototype ////
//// board at 20Mhz: ////
//// ////
//// Baud Rate Prescalar: 4 ////
//// Propagation Segment: 3xTq ////
//// Phase Segment 1: 6xTq ////
//// Phase Segment 2: 6xTq ////
//// Synchronized Jump Width: 1xTq ////
//// Sample Rate: 1x ////
//// Wakeup Filter: Off ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// Node C and D are seperate stand-alone MCP250xx CAN I/O ////
//// expanders. The CCS CAN Prototype board has these chips already ////
//// programmed correctly. However, if you wish to program your own ////
//// to work with this example, then use the provided .HEX files ////
//// a programmer capable of programming these chips. Or, make a ////
//// a new HEX file with these properties: ////
//// ////
//// NODE C: Set RX ID mask and buffers to receive ID 0x3**. (The ** ////
//// means make the least signifcant 8bits no-care in the mask). ////
//// Set TX1 buffer to ID 0x301, TX2 buffer to ID 0x302, TX3 buffer ////
//// to ID 0x303. Set GP0 to analog (and enable the A/D). Set GP1, ////
//// GP2 and GP3 to OUTPUT. Set GP4, GP5 and GP6 as INPUT with edge ////
//// trigger enable. Leave OPTREG2 clear, disable PWM1 and PWM2, ////
//// and disable scheduled transmission. Also, see the baud rate ////
//// settings above. ////
//// ////
//// NODE D: Set RX ID mask and buffers to receive ID 0x4**. (The ** ////
//// means make the least signifcant 8bits no-care in the mask). ////
//// Set TX1 buffer to ID 0x401, TX2 buffer to ID 0x402, TX3 buffer ////
//// to ID 0x403. Configure all ports as OUTPUT. Leave OPTREG2 ////
//// clear, disable PWM1 and PWM2, and disable scheduled ////
//// transmission. Also, see the baud rate settings above. ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS ////
//// C compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, ////
//// reproduction or distribution is permitted without written ////
//// permission. Derivative programs created using this software ////
//// in object code form are not restricted in any way. ////
/////////////////////////////////////////////////////////////////////////
#include <18F4580.h>
#device ICD=TRUE
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOPROTECT //Code not protected from reading
#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV21 //Brownout reset at 2.1V
#FUSES PUT //Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOIESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES PBADEN //PORTB pins are configured as analog input channels on RESET
#FUSES BBSIZ1K //1K words Boot Block size
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES NOLPT1OSC //Timer1 is not configured for low-power operation
#FUSES MCLR //Master Clear pin enabled
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
//#include <18F4580.h>
//#fuses HS,NOPROTECT,NOLVP,NOWDT
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#define CAN_DO_DEBUG TRUE
#define Set_250K_Baud TRUE /// Aqui configuro que velocidad del BUS utilizo
#include "can-18F4580.c"
#include <lcd.c>
#define PIN_LED1 PIN_E2
#define PIN_LED2 PIN_E0
#define PIN_LED3 PIN_E1
#define LED1_LOW output_low(PIN_LED1)
#define LED1_HIGH output_high(PIN_LED1)
#define LED2_LOW output_low(PIN_LED2)
#define LED2_HIGH output_high(PIN_LED2)
#define LED3_LOW output_low(PIN_LED3)
#define LED3_HIGH output_high(PIN_LED3)
#define BOTON_ENTER PIN_A5
#define BOTON_ESC PIN_A4
#define BOTON_PROG PIN_A3
#define BOTON_UP PIN_A2
#define BOTON_DOWN PIN_A1
#define BOTON_ENTER_PRES !input(BOTON_ENTER)
#define BOTON_ESC_PRES !input(BOTON_ESC)
#define BOTON_PROG_PRES !input(BOTON_PROG)
#define BOTON_UP_PRES !input(BOTON_UP)
#define BOTON_DOWN_PRES !input(BOTON_DOWN)
int16 ms;
const char lcd_seg[16]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0E}; //0 for on, 1 for off
#int_timer2
void isr_timer2(void) {
ms++; //keep a running timer that increments every milli-second
}
#define ASK_FOR_ID_AD_B 0x201 //ask for AD info from CAN port B
#define SET_LED_ID_B 0x202 //set LEDs for CAN port B
#define RESPOND_TO_LED_C_ID 0x303
#define WRITE_REGISTER_C_ID 0x300
#define WRITE_REGISTER_D_ID 0x80400
#define WRITE_PWM2_D_ID 0x301
void main() {
int b_leds=0;
int c_leds=1;
int a_leds=0;
int AD_NodoB=0;
struct rx_stat rxstat;
int32 rx_id;
int buffer[8];
int rx_len;
int last_lcd_output=0xFF;
int i,curr_lcd_output;
int16 curr_pwm2_duty, last_pwm2_duty;
int byte8_2_pwm2, byte1_0_pwm2;
setup_port_a(AN0);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
for(i=0;i<8;i++) {
buffer[i]=0;
}
LED1_HIGH;
LED2_HIGH;
LED3_HIGH;
printf("\r\n\r\nEjemplo CAN CCS\r\n"); delay_ms(1000);
LED1_LOW;
LED2_LOW;
LED3_LOW;
setup_timer_2(T2_DIV_BY_16,53,3); //setup up timer2 to interrupt every 1ms if using 20Mhz clock
lcd_init();
can_init();
lcd_putc("\f"); //borrar display
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
lcd_gotoxy(1,1);
lcd_putc("Marchando..."); ///escribo en el LCD
lcd_gotoxy(1,2);
lcd_putc("GRACIAS ARIEL!!!"); ///escribo en el LCD
while(TRUE)
{
if ( can_kbhit() )
{
if(can_getd(rx_id, &buffer[0], rx_len, rxstat)) {
if (rx_id == ASK_FOR_ID_AD_B) {
printf("Conversión AD Nodo B: %X\r\n",buffer
[0]); AD_NodoB = buffer[0]; //guardo valor del conversor AD
}
else if (rx_id == RESPOND_TO_LED_C_ID) { //nodo C es un mcp25050 que envía un a mensaje ante la deteccion de un flanco
printf("Cambiando LEDs\r\n"); //in_data[0]=iointfl, in_data[1]=gpio a_leds=(buffer[0]);
//a_leds=~(buffer[1]); //cambiado para poder leer los bits enviados desde Nodo B
if (bit_test(a_leds,0)) {LED1_HIGH;} else {LED1_LOW;}
if (bit_test(a_leds,1)) {LED2_HIGH;} else {LED2_LOW;} //idem anterior
if (bit_test(a_leds,2)) {LED3_HIGH;} else {LED3_LOW;}
}
}
}
if ( can_tbe() && (ms > 2000)) //every two seconds, send new data if transmit buffer is empty
{
ms=0;
//change leds on port b
printf("\r\n\r\nEscribe LEDs en Nodo B a %U",b_leds
); can_putd(SET_LED_ID_B, &b_leds, 1, 1, 1, 0);
/* if (bit_test(b_leds,0)) {LED1_HIGH;} else {LED1_LOW;}
if (bit_test(b_leds,1)) {LED2_HIGH;} else {LED2_LOW;} //envio el dato a mis leds
if (bit_test(b_leds,2)) {LED3_HIGH;} else {LED3_LOW;}*/
lcd_putc("\f"); //borrar display
printf(lcd_putc
,"Leds Nodo B : %02u",b_leds
); ///escribo en el LCD lcd_gotoxy(1,2);
printf(lcd_putc
,"Dato Conv.AD:%03u",AD_NodoB
); ///escribo en el LCD
b_leds++;
if (b_leds > 7) {b_leds=0;}
// cuenta para enviar al nodo D
curr_lcd_output++;
if (curr_lcd_output > 15) {curr_lcd_output=0;}
}
if (BOTON_ESC_PRES) {
while (BOTON_ESC_PRES) {}
delay_ms(200);
//ask for AD on port B
printf("\r\n\r\nPidiendo lectura conversor A/D en Nodo B..."); can_putd(ASK_FOR_ID_AD_B, 0, 1, 1, 1, 1);
//change LEDs on port C
buffer[0]=0x1E; //addr of gplat on 25050
buffer[1]=0x0E; //mask
// buffer[2]=~(c_leds << 1); //new gplat
buffer[2]=(c_leds << 1); //new gplat values
printf("\r\nIncrementar LED en Nodo C"); can_putd(WRITE_REGISTER_C_ID, &buffer[0], 3, 1, 1, 0);
c_leds++;
if (c_leds > 7) {c_leds=0;}
}
if (BOTON_PROG_PRES) { // APAGAR EL PWM 2
while (BOTON_PROG_PRES) {}
delay_ms(100);
//Reprogramar el MCP25050 del Nodo C a todo salida digital
printf("\r\n\r\nReprogramando el Nodo C..."); buffer[0]=0x22; //direccion de timer de pwm2
buffer[1]=0x80; //mask
buffer[2]=0x00; //apagar el timer de pwm2
can_putd(WRITE_REGISTER_C_ID, &buffer[0], 3, 1, 1, 0);
}
if (BOTON_DOWN_PRES) { // ENCENDER EL PWM 2
while (BOTON_DOWN_PRES) {}
delay_ms(100);
//Reprogramar el MCP25050 del Nodo C a PWM2
printf("\r\n\r\nReprogramando el Nodo C..."); buffer[0]=0x22; //direccion de timer de pwm2
buffer[1]=0x80; //mask
buffer[2]=0x80; //apagar el timer de pwm2
can_putd(WRITE_REGISTER_C_ID, &buffer[0], 3, 1, 1, 0);
}
//change lcd segment on port d
i=read_adc();
// curr_lcd_output=i/26; //scale to 0-9
if (curr_lcd_output != last_lcd_output) {
last_lcd_output=curr_lcd_output;
printf("\r\nCambiando Display 7-seg Nodo D a cuentas del canal A/D (%X, %X)",i
,curr_lcd_output
); buffer[0]=0x1E; //addr of gplat
buffer[1]=0x7F; //mask
buffer[2]=lcd_seg[curr_lcd_output]; //new gplat values
can_putd(WRITE_REGISTER_D_ID, &buffer[0], 3, 1, 1, 0);
}
// escribe nuevo valor en PWM2 Nodo C
if (curr_pwm2_duty != last_pwm2_duty) {
last_pwm2_duty=curr_pwm2_duty;
printf("\r\nCambiando Display 7-seg Nodo D a cuentas del canal A/D (%X, %X)",i
,curr_lcd_output
); // Escribe los 8 bits altos del PWM2
byte1_0_pwm2= MAKE8((curr_pwm2_duty & 0x03),0); //carga el valor del byte bajo
byte8_2_pwm2= MAKE8((curr_pwm2_duty << 6),1); //carga el valor del byte alto
buffer[0]=0x26; //direccion de valor de pwm2
buffer[1]=0xFF; //mask
buffer[2]=byte8_2_pwm2; //new pwm2 values
can_putd(WRITE_REGISTER_C_ID, &buffer[0], 3, 1, 1, 0);
// Escribe los 2 bits bajos del PWM2
buffer[0]=0x22; //direccion de timer de pwm2
buffer[1]=0x03; //mask
buffer[2]=byte1_0_pwm2; //new pwm2 values
can_putd(WRITE_REGISTER_C_ID, &buffer[0], 3, 1, 1, 0);
}
if ((curr_pwm2_duty += 5) > 1023) {curr_pwm2_duty=0;}
}
}