/******************************************************************************
Online C Compiler.
Code, Compile, Run and Debug C program online.
Write your code in this editor and press "Run" button to compile and execute it.
*******************************************************************************/
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
struct OD_Communication{
uint32_t device_type; /* Index 0x1000 sub index 0x0 */
uint8_t error_register; /* Index 0x1001 sub index 0x0 */
uint32_t manufacturer_status_register; /* Index 0x1002 sub index 0x0 */
uint32_t pre_defined_error_field[11]; /* Index 0x1003 sub index 0x0 -> 0xA */
uint32_t COB_ID_sync_message; /* Index 0x1005 sub index 0x0 */
uint32_t communication_cycle_period; /* Index 0x1006 sub index 0x0 */
uint32_t synchronous_window_length; /* Index 0x1007 sub index 0x0 */
char manufacturer_device_name[30]; /* Index 0x1008 sub index 0x0 */
char manufacturer_hardware_version[30]; /* Index 0x1009 sub index 0x0 */
char manufacturer_software_version[30]; /* Index 0x100A sub index 0x0 */
uint16_t guard_time; /* Index 0x100C sub index 0x0 */
uint8_t life_time_factor; /* Index 0x100D sub index 0x0 */
uint32_t store_parameters[4]; /* Index 0x1010 sub index 0x0 -> 0x3 */
uint32_t restore_default_parameters[4]; /* Index 0x1011 sub index 0x0 -> 0x3 */
uint32_t COB_ID_time_stamp_object; /* Index 0x1012 sub index 0x0 */
uint32_t high_resolution_time_stamp; /* Index 0x1013 sub index 0x0 */
uint32_t COB_ID_emcy; /* Index 0x1014 sub index 0x0 */
uint16_t inhibit_time_emcy; /* Index 0x1015 sub index 0x0 */
uint32_t consumer_heartbeat_time[0x80]; /* Index 0x1016 sub index 0x0 -> 0x7F */
uint16_t producer_heartbeat_time; /* Index 0x1017 sub index 0x0 */
uint32_t identity_object[5]; /* Index 0x1018 sub index 0x0 -> 0x4 */
uint8_t synchronous_counter_overflow_value; /* Index 0x1019 sub index 0x0 */
uint32_t verify_configuration[3]; /* Index 0x1020 sub index 0x0 -> 0x2 */
uint32_t emergency_consumer_object[0x80]; /* Index 0x1028 sub index 0x0 -> 0x7F */
uint8_t error_behavior_object[2]; /* Index 0x1029 sub index 0x0 -> 0x1 */
};
typedef struct {
struct OD_Communication od_communication; /* Communication objects */
} CANopen;
typedef enum{
OD_ACCESS_READ = 0x1,
OD_ACCESS_WRITE = 0x2,
OD_ACCESS_READ_WRITE = OD_ACCESS_READ | OD_ACCESS_WRITE
}OD_ACCESS;
enum{
OD_DATA_TYPE_U8 = 0x3,
OD_DATA_TYPE_U16 = 0x2,
OD_DATA_TYPE_U32 = 0x0
};
typedef enum{
OD_STATUS_OK,
OD_STATUS_NOT_PERMITTED,
OD_STATUS_NOT_FOUND,
OD_STATUS_WRONG_DATA_TYPE
}OD_STATUS;
enum {
/* Communication parameter area */
OD_INDEX_DEVICE_TYPE = 0x1000,
OD_INDEX_ERROR_REGISTER = 0x1001,
OD_INDEX_MANUFACTURER_STATUS_REGISTER = 0x1002,
OD_INDEX_PRE_DEFINED_ERROR_FIELD = 0x1003,
OD_INDEX_COB_ID_SYNC_MESSAGE = 0x1005,
OD_INDEX_COMMUNICATION_CYCLE_PERIOD = 0x1006,
OD_INDEX_SYNCHRONOUS_WINDOW_LENGTH = 0x1007,
OD_INDEX_MANUFACTURER_DEVICE_NAME = 0x1008,
OD_INDEX_MANUFACTURER_HARDWARE_VERSION = 0x1009,
OD_INDEX_MANUFACTURER_SOFTWARE_VERSION = 0x100A,
OD_INDEX_GUARD_TIME_MS = 0x100C,
OD_INDEX_LIFE_FACTOR = 0x100D,
OD_INDEX_STORE_PARAMETERS = 0x1010,
OD_INDEX_RESTORE_DEFAULT_PARAMETERS = 0x1011,
OD_INDEX_COB_ID_TIME_STAMP_OBJECT = 0x1012,
OD_INDEX_HIGH_RESOLUTION_TIME_STAMP = 0x1013,
OD_INDEX_COB_ID_EMCY = 0x1014,
OD_INDEX_INHIBIT_TIME_EMCY = 0x1015,
OD_INDEX_CONSUMER_HEARTBEAT_TIME = 0x1016,
OD_INDEX_PRODUCER_HEARTBEAT_TIME = 0x1017,
OD_INDEX_IDENTITY_OBJECT = 0x1018,
OD_INDEX_SYNCHRONOUS_COUNTER_OVERFLOW_VALUE = 0x1019,
OD_INDEX_VERIFY_CONFIGURATION = 0x1020,
OD_INDEX_EMERGENCY_CONSUMER_OBJECT = 0x1028,
OD_INDEX_ERROR_BEHAVIOR_OBJECT = 0x1029,
};
static OD_STATUS read_or_write(void *value, void *struct_value, bool write_value, OD_ACCESS access, uint8_t byte_size);
OD_STATUS CANopen_OD_set_get_value(CANopen *canopen, uint16_t index, uint8_t sub_index, bool write_value, void *value, uint8_t byte_size){
struct OD_Communication *communication = &canopen->od_communication;
switch(index){
case OD_INDEX_DEVICE_TYPE:
return read_or_write(value, &communication->device_type, write_value, OD_ACCESS_READ, byte_size);
case OD_INDEX_ERROR_REGISTER:
return read_or_write(value, &communication->error_register, write_value, OD_ACCESS_READ, byte_size);
case OD_INDEX_MANUFACTURER_STATUS_REGISTER:
return read_or_write(value, &communication->manufacturer_status_register, write_value, OD_ACCESS_READ, byte_size);
case OD_INDEX_PRE_DEFINED_ERROR_FIELD:
return read_or_write(value, &communication->pre_defined_error_field[sub_index], write_value, OD_ACCESS_READ, byte_size);
case OD_INDEX_COB_ID_SYNC_MESSAGE:
return read_or_write(value, &communication->COB_ID_sync_message, write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_COMMUNICATION_CYCLE_PERIOD:
return read_or_write(value, &communication->communication_cycle_period, write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_SYNCHRONOUS_WINDOW_LENGTH:
return read_or_write(value, &communication->synchronous_window_length, write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_MANUFACTURER_DEVICE_NAME:
return read_or_write(value, &communication->manufacturer_device_name, write_value, OD_ACCESS_READ, byte_size);
case OD_INDEX_MANUFACTURER_HARDWARE_VERSION:
return read_or_write(value, &communication->manufacturer_hardware_version, write_value, OD_ACCESS_READ, byte_size);
case OD_INDEX_MANUFACTURER_SOFTWARE_VERSION:
return read_or_write(value, &communication->manufacturer_software_version, write_value, OD_ACCESS_READ, byte_size);
case OD_INDEX_GUARD_TIME_MS:
return read_or_write(value, &communication->guard_time, write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_LIFE_FACTOR:
return read_or_write(value, &communication->life_time_factor, write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_STORE_PARAMETERS:
return read_or_write(value, &communication->store_parameters[sub_index], write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_RESTORE_DEFAULT_PARAMETERS:
return read_or_write(value, &communication->restore_default_parameters[sub_index], write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_COB_ID_TIME_STAMP_OBJECT:
return read_or_write(value, &communication->COB_ID_time_stamp_object, write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_HIGH_RESOLUTION_TIME_STAMP:
return read_or_write(value, &communication->high_resolution_time_stamp, write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_COB_ID_EMCY:
return read_or_write(value, &communication->COB_ID_emcy, write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_INHIBIT_TIME_EMCY:
return read_or_write(value, &communication->inhibit_time_emcy, write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_CONSUMER_HEARTBEAT_TIME:
return read_or_write(value, &communication->consumer_heartbeat_time[sub_index], write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_PRODUCER_HEARTBEAT_TIME:
return read_or_write(value, &communication->producer_heartbeat_time, write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_IDENTITY_OBJECT:
return read_or_write(value, &communication->identity_object[sub_index], write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_SYNCHRONOUS_COUNTER_OVERFLOW_VALUE:
return read_or_write(value, &communication->synchronous_counter_overflow_value, write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_VERIFY_CONFIGURATION:
return read_or_write(value, &communication->verify_configuration[sub_index], write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_EMERGENCY_CONSUMER_OBJECT:
return read_or_write(value, &communication->emergency_consumer_object[sub_index], write_value, OD_ACCESS_READ_WRITE, byte_size);
case OD_INDEX_ERROR_BEHAVIOR_OBJECT:
return read_or_write(value, &communication->error_behavior_object[sub_index], write_value, OD_ACCESS_READ_WRITE, byte_size);
default:
return OD_STATUS_NOT_FOUND;
}
}
static OD_STATUS read_or_write(void *value, void *struct_value, bool write_value, OD_ACCESS access, uint8_t byte_size){
switch(write_value){
case true:
switch(access | OD_ACCESS_WRITE){
case true:
switch(byte_size){
case OD_DATA_TYPE_U8:
*((uint8_t*) struct_value) = *((uint8_t*) value);
break;
case OD_DATA_TYPE_U16:
*((uint16_t*) struct_value) = *((uint16_t*) value);
break;
case OD_DATA_TYPE_U32:
*((uint32_t*) struct_value) = *((uint32_t*) value);
break;
default:
return OD_STATUS_WRONG_DATA_TYPE;
}
return OD_STATUS_OK;
default:
return OD_STATUS_NOT_PERMITTED;
}
break;
case false:
switch(access | OD_ACCESS_READ){
case true:
switch(byte_size){
case OD_DATA_TYPE_U8:
*((uint8_t*) value) = *((uint8_t*) struct_value);
break;
case OD_DATA_TYPE_U16:
*((uint16_t*) value) = *((uint16_t*) struct_value);
break;
case OD_DATA_TYPE_U32:
*((uint32_t*) value) = *((uint32_t*) struct_value);
break;
default:
return OD_STATUS_WRONG_DATA_TYPE;
}
return OD_STATUS_OK;
default:
return OD_STATUS_NOT_PERMITTED;
}
}
return OD_STATUS_NOT_FOUND;
}
int main(){
/* Deklarera objekt */
CANopen canopen = {0};
/* Sätt ett värde */
canopen.od_communication.device_type = 0xABCDEF;
canopen.od_communication.error_register = 0xFE;
/* Skriv ett värde */
uint32_t value1 = 0x3F;
OD_STATUS status = CANopen_OD_set_get_value(&canopen, OD_INDEX_DEVICE_TYPE, 0, true, &value1, OD_DATA_TYPE_U32);
/* Skriv ut värdet */
printf("value = 0x%X\n", value1);
/* Skriv ut status */
switch(status){
case OD_STATUS_OK:
printf("OK\n");
break;
case OD_STATUS_NOT_FOUND:
printf("NOT FOUND\n");
break;
case OD_STATUS_NOT_PERMITTED:
printf("NOT PERMITTED\n");
break;
case OD_STATUS_WRONG_DATA_TYPE:
printf("WRONG DATA TYPE\n");
break;
}
/* Läs av ett värde */
uint8_t value2 = 0;
status = CANopen_OD_set_get_value(&canopen, OD_INDEX_ERROR_REGISTER, 0, false, &value2, OD_DATA_TYPE_U8);
/* Skriv ut värdet */
printf("value = 0x%X\n", value2);
/* Skriv ut status */
switch(status){
case OD_STATUS_OK:
printf("OK\n");
break;
case OD_STATUS_NOT_FOUND:
printf("NOT FOUND\n");
break;
case OD_STATUS_NOT_PERMITTED:
printf("NOT PERMITTED\n");
break;
case OD_STATUS_WRONG_DATA_TYPE:
printf("WRONG DATA TYPE\n");
break;
}
return 0;
}