void StdCan_SendHeartbeat(uint8_t n) { /* TODO: When a Tx queue is implemented, the heartbeat should * be sent via StdCan_Put instead of directly to lower layer. */ Can_Message_t Heartbeat; /* Set up Heartbeat message format. */ Heartbeat.ExtendedFlag = 1; Heartbeat.RemoteFlag = 0; #ifdef MODULE_APPLICATION Heartbeat.DataLength = 5; Heartbeat.Id = (CAN_NMT << CAN_SHIFT_CLASS) | (CAN_NMT_HEARTBEAT << CAN_SHIFT_NMT_TYPE); Heartbeat.Data.bytes[0] = NODE_HW_ID_BYTE0; Heartbeat.Data.bytes[1] = NODE_HW_ID_BYTE1; Heartbeat.Data.bytes[2] = NODE_HW_ID_BYTE2; Heartbeat.Data.bytes[3] = NODE_HW_ID_BYTE3; Heartbeat.Data.bytes[4] = NUMBER_OF_MODULES; #else Heartbeat.DataLength = 0; Heartbeat.Id = (CAN_NMT << CAN_SHIFT_CLASS) | (CAN_NMT_HEARTBEAT << CAN_SHIFT_NMT_TYPE) | (NODE_ID << CAN_SHIFT_NMT_SID); #endif /* Try to send it. */ Can_Send(&Heartbeat); }
StdCan_Ret_t StdCan_Put(StdCan_Msg_t* msg) { Can_Message_t Can_Msg; unsigned char n; /* Validate message. */ if ((unsigned)msg->Length > 8) return StdCan_Ret_DataErr; /* Copy message directly to lower layer until a proper * queue has been implemented. * TODO: Implement a proper queue. This requires TX interrupt * support in the driver and BIOS. */ Can_Msg.ExtendedFlag = 1; Can_Msg.RemoteFlag = 0; Can_Msg.Id = msg->Id; Can_Msg.DataLength = msg->Length; for (n = 0; n < msg->Length; n++) { Can_Msg.Data.bytes[n] = msg->Data[n]; } if (Can_Send(&Can_Msg) == CAN_OK) { #ifdef MODULE_APPLICATION Can_Process(&Can_Msg); #endif return StdCan_Ret_OK; } else return StdCan_Ret_Full; }
StdCan_Ret_t StdCan_Init(Node_Desc_t* node_desc) { #endif StdCan_Ret_t retval; /* Reset all queue variables. */ RxQ_Rd_idx = 0; RxQ_Wr_idx = 0; RxQ_Len = 0; #if (STDCAN_TX_QUEUE_SIZE > 1) TxQ_Rd_idx = 0; TxQ_Wr_idx = 0; TxQ_Len = 0; #endif #if defined(_AVRLIB_BIOS_) /* Initialize BIOS' interface for CAN. */ BIOS_CanCallback = Can_Process; retval = StdCan_Ret_OK; #else /* Initialize CAN driver. */ if (Can_Init() == CAN_OK) retval = StdCan_Ret_OK; else retval = StdCan_Ret_Fail; #endif //TODO: Do something with the Node Descriptor. //(why have constats passed as parameters? they are defined at compiletime /arune) #if defined(_AVRLIB_BIOS_) /* TODO: When a Tx queue is implemented, the startup message should * be sent via StdCan_Put instead of directly to lower layer. */ Can_Message_t Startup; /* Set up Startup message format. */ Startup.ExtendedFlag = 1; Startup.RemoteFlag = 0; Startup.DataLength = 4; #ifdef MODULE_APPLICATION Startup.Id = (CAN_NMT << CAN_SHIFT_CLASS) | (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE); Startup.Data.bytes[0] = NODE_HW_ID&0xff; Startup.Data.bytes[1] = (NODE_HW_ID>>8)&0xff; Startup.Data.bytes[2] = (NODE_HW_ID>>16)&0xff; Startup.Data.bytes[3] = (NODE_HW_ID>>24)&0xff; #else Startup.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) | (NODE_ID << CAN_SHIFT_NMT_SID); Startup.Data.bytes[1] = APP_TYPE&0xff; Startup.Data.bytes[0] = (APP_TYPE>>8)&0xff; Startup.Data.bytes[3] = APP_VERSION&0xff; Startup.Data.bytes[2] = (APP_VERSION>>8)&0xff; #endif /* Try to send it. */ Can_Send(&Startup); #endif return retval; }
int main(void) { // Enable interrupts as early as possible sei(); Timer_Init(); Serial_Init(); uint8_t returnval = Can_Init(); if (returnval != CAN_OK) { } Can_Message_t txMsg; txMsg.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) | (NODE_ID << CAN_SHIFT_NMT_SID); txMsg.DataLength = 4; txMsg.RemoteFlag = 0; txMsg.ExtendedFlag = 1; txMsg.Data.words[0] = APP_TYPE; txMsg.Data.words[1] = APP_VERSION; // Set up callback for CAN reception, this is optional if only sending is required. BIOS_CanCallback = &can_receive; // Send CAN_NMT_APP_START BIOS_CanSend(&txMsg); while (1) { if (extRxMsgFull) { txMsg.Id = extRxMsg.Id; txMsg.DataLength = extRxMsg.DataLength; txMsg.RemoteFlag = extRxMsg.RemoteFlag; txMsg.ExtendedFlag = extRxMsg.ExtendedFlag; for (uint8_t i = 0; i < txMsg.DataLength; i++) { txMsg.Data.bytes[i] = extRxMsg.Data.bytes[i]; } BIOS_CanSend(&txMsg); extRxMsgFull = 0; // } if (rxMsgFull) { extTxMsg.Id = rxMsg.Id; extTxMsg.DataLength = rxMsg.DataLength; extTxMsg.RemoteFlag = rxMsg.RemoteFlag; extTxMsg.ExtendedFlag = rxMsg.ExtendedFlag; for (uint8_t i = 0; i < extTxMsg.DataLength; i++) { extTxMsg.Data.bytes[i] = rxMsg.Data.bytes[i]; } Can_Send(&extTxMsg); rxMsgFull = 0; // } } return 0; }
/*----------------------------------------------------------------------------- * Main Program *---------------------------------------------------------------------------*/ int main(void) { Mcu_Init(); Timebase_Init(); sei(); #if defined(UART_OUTPUT) Serial_Init(); printf("\n------------------------------------------------------------\n"); printf( " CAN Test:\n"); printf( " Periodic Transmission on CAN\n"); printf( " CAN Dump\n"); printf( " CAN Echo\n"); printf( "------------------------------------------------------------\n"); printf("CanInit..."); if (Can_Init() != CAN_OK) { printf("FAILED!\n"); printf("Check wires between AVR and MCP2515 and the MCP speed (xtal)."); } else { printf("OK!\n"); printf("MCP2515 working fine\n"); } #elif defined(LED_OUTPUT) Can_Init(); #else Can_Init(); #endif uint32_t timeStamp = 0; Can_Message_t txMsg; Can_Message_t rxMsg; txMsg.RemoteFlag = 0; txMsg.ExtendedFlag = 1; txMsg.Id = SENDING_ID; txMsg.DataLength = 2; txMsg.Data.bytes[0] = 0x12; txMsg.Data.bytes[1] = 0x34; /* main loop */ while (1) { /* service the CAN routines */ Can_Service(); /* send CAN message and check for CAN errors once every second */ if (Timebase_PassedTimeMillis(timeStamp) >= 1000) { timeStamp = Timebase_CurrentTime(); /* send txMsg */ txMsg.Id = SENDING_ID; Can_Send(&txMsg); } /* check if any messages have been received */ while (Can_Receive(&rxMsg) == CAN_OK) { #if defined(UART_OUTPUT) /* Dump message data on uart */ printf("\nPKT %#lx %u %u", rxMsg.Id, (uint16_t)(rxMsg.ExtendedFlag), (uint16_t)(rxMsg.RemoteFlag)); for (uint8_t i=0; i<rxMsg.DataLength; i++) { printf(" %#x", rxMsg.Data.bytes[i]); } #endif /* Echo function */ if(rxMsg.Id == ECHO_RECEIVE_ID){ #if defined(UART_OUTPUT) printf("\n\"ping\" received"); txMsg.Id = ECHO_SENDING_ID; /* Send reply */ Can_Send(&txMsg); printf("\nreply sent"); #else txMsg.Id = ECHO_SENDING_ID; /* Send reply */ Can_Send(&txMsg); #endif } } } return 0; }
/*----------------------------------------------------------------------------- * Main Program *---------------------------------------------------------------------------*/ int main(void) { // For calibrating internal oscillator // OSCCAL = eeprom_read_byte(0); Timebase_Init(); Serial_Init(); #if MCP_CS_BIT != PB2 /* If slave select is not set as output it might change SPI hw to slave * See ch 18.3.2 (18.3 SS Pin Functionality) in ATmega48/88/168-datasheet */ DDRB |= (1<<PB2); #endif #if USE_STDCAN == 0 Can_Init(); #else StdCan_Init(0); #endif DDRC |= 1<<PC1 | 1<<PC0; PORTC |= (1<<PC1) | (1<<PC0); sei(); #if SENDTIMESTAMP == 1 #if USE_STDCAN == 0 Can_Message_t timeMsg; #else StdCan_Msg_t timeMsg; #endif uint32_t time = Timebase_CurrentTime(); uint32_t time1 = time; uint32_t unixtime = 0; #endif uint16_t rxByte; uint8_t i = 0; #if SENDTIMESTAMP == 1 #if USE_STDCAN == 0 timeMsg.ExtendedFlag = 1; timeMsg.RemoteFlag = 0; timeMsg.DataLength = 8; #else /* Jag orkar inte fixa in datan i paketen, sätter längd till 0 sålänge */ timeMsg.Length = 0; #endif timeMsg.Id = (CAN_NMT << CAN_SHIFT_CLASS) | (CAN_NMT_TIME << CAN_SHIFT_NMT_TYPE); //timeMsg.Id = 0; //Same thing, and lib's can.h is not updated. #endif #if USE_STDCAN == 1 StdCan_Msg_t rxMsg; #endif /* main loop */ while (1) { /* any new CAN messages received? */ #if USE_STDCAN == 0 if (rxMsgFull) { #else if (StdCan_Get(&rxMsg) == StdCan_Ret_OK) { #endif // Toggle activity LED PORTC ^= (1<<PC1); /* send message to CanWatcher */ uart_putc(UART_START_BYTE); uart_putc((uint8_t)rxMsg.Id); uart_putc((uint8_t)(rxMsg.Id>>8)); uart_putc((uint8_t)(rxMsg.Id>>16)); uart_putc((uint8_t)(rxMsg.Id>>24)); #if USE_STDCAN == 0 uart_putc(rxMsg.ExtendedFlag); uart_putc(rxMsg.RemoteFlag); uart_putc(rxMsg.DataLength); for (i=0; i<8; i++) { uart_putc(rxMsg.Data.bytes[i]); } #else uart_putc(1); uart_putc(0); uart_putc(rxMsg.Length); for (i=0; i<8; i++) { uart_putc(rxMsg.Data[i]); } #endif uart_putc(UART_END_BYTE); #if USE_STDCAN == 0 rxMsgFull = 0; #endif } /* any UART bytes received? */ rxByte = uart_getc(); while (rxByte != UART_NO_DATA) { /* parse byte! */ UartParseByte((uint8_t)(rxByte & 0x00FF)); /* receive next */ rxByte = uart_getc(); } #if SENDTIMESTAMP == 1 time1 = Timebase_CurrentTime(); if ((time1 - time) > 1000) { time = time1; #if USE_STDCAN == 0 timeMsg.Data.dwords[0] = ++unixtime; IncTime(); timeMsg.Data.dwords[1] = date.packed; Can_Send(&timeMsg); #else /* Jag orkar inte fixa in datan i paketen, sätter längd till 0 sålänge */ StdCan_Put(&timeMsg); #endif } #endif } return 0; }
/** * Parses an incoming UART byte by maintaining a state machine. The UART * bytes will build up a CAN message according to the protocol described here: * * http://www.arune.se/projekt/doku.php?id=homeautomation:pc-mjukvara * * @param c * The received UART byte. */ void UartParseByte(uint8_t c) { #if USE_STDCAN == 0 static Can_Message_t cm; #else static StdCan_Msg_t cm; #endif static uint8_t waitingMessage = 0; static uint32_t startTime = 0; static int8_t count = 0; /* 50ms timeout */ if (waitingMessage && Timebase_PassedTimeMillis(startTime) > 50) { waitingMessage = 0; } if (waitingMessage) { /* save start time */ startTime = Timebase_CurrentTime(); /* UART END */ if (count >= 15) { if (c == UART_END_BYTE) { PORTC ^= (1<<PC0); #if USE_STDCAN == 0 Can_Send(&cm); #else StdCan_Put(&cm); #endif } waitingMessage = 0; return; } /* data */ else if (count >= 7) { #if USE_STDCAN == 0 cm.Data.bytes[count-7] = c; #else cm.Data[count-7] = c; #endif count++; return; } /* data length */ else if (count >= 6) { #if USE_STDCAN == 0 cm.DataLength = c; #else cm.Length = c; #endif count++; return; } /* remote request flag */ else if (count >= 5) { #if USE_STDCAN == 0 cm.RemoteFlag = c; #endif count++; return; } /* extended */ else if (count >= 4) { #if USE_STDCAN == 0 cm.ExtendedFlag = c; #endif count++; return; } /* ident */ else if (count >= 0) { cm.Id += ((uint32_t)c << (count*8)); count++; return; } } if (c == UART_START_BYTE && !waitingMessage) { waitingMessage = 1; startTime = Timebase_CurrentTime(); count = 0; cm.Id = 0; return; } }
/*----------------------------------------------------------------------------- * Main Program *---------------------------------------------------------------------------*/ int main(void) { uint8_t nSensors, i; uint8_t subzero, cel, cel_frac_bits; Mcu_Init(); Timebase_Init(); Serial_Init(); sei(); printf( "\nDS18X20 1-Wire-Reader\n" ); printf( "-----------------------" ); nSensors = search_sensors(); printf( "%i DS18X20 Sensor(s) available:\n", (int) nSensors ); for (i=0; i<nSensors; i++) { printf("Sensor# %i is a ", (int) i+1); if ( gSensorIDs[i][0] == DS18S20_ID) printf("DS18S20/DS1820"); else printf("DS18B20"); printf(" which is "); if ( DS18X20_get_power_status( &gSensorIDs[i][0] ) == DS18X20_POWER_PARASITE ) printf( "parasite" ); else printf( "externally" ); printf( " powered\n" ); } printf("CanInit...\n"); if (Can_Init() != CAN_OK) { printf("FAILED!\n"); } else { printf("OK!\n"); } uint32_t timeStamp = 0; Can_Message_t txMsg; Can_Message_t rxMsg; txMsg.DataLength = 2; txMsg.Id = 0; txMsg.RemoteFlag = 0; txMsg.ExtendedFlag = 1; /* main loop */ while (1) { /* service the CAN routines */ Can_Service(); /* check if any messages have been received */ while (Can_Receive(&rxMsg) == CAN_OK) { } /* check temperature and send on CAN once every other second */ if (Timebase_PassedTimeMillis(timeStamp) >= 2000) { timeStamp = Timebase_CurrentTime(); if ( DS18X20_start_meas( DS18X20_POWER_PARASITE, NULL ) == DS18X20_OK) { printf("Measuring temperature... "); delay_ms(DS18B20_TCONV_12BIT); for ( i=0; i<nSensors; i++ ) { if ( DS18X20_read_meas( &gSensorIDs[i][0], &subzero, &cel, &cel_frac_bits) == DS18X20_OK ) { //txMsg.Data.bytes[0] = subzero; if (subzero) { txMsg.Data.bytes[i*2] = -cel; txMsg.Data.bytes[i*2+1] = ~(cel_frac_bits<<4); } else { txMsg.Data.bytes[i*2] = cel; txMsg.Data.bytes[i*2+1] = (cel_frac_bits<<4); } } else printf("CRC Error (lost connection?)\n"); } txMsg.DataLength = nSensors*2; printf("sending...\n"); /* send txMsg */ Can_Send(&txMsg); } else printf("Start meas. failed (short circuit?)\n"); } } return 0; }