Tool/software:
Hi I can make 8 analog input work with 8 bit , but I tried 16 bits have some problem.
/* * app_generic_device.c * * Generic device profile declarations. * LED behavior unchanged: 0x0308 is LED index (1..8) → one LED on. * Analogs are 16-bit at 0x0300..0x0307 (scaled 0..32767). */ #include "osal.h" #include "osal_error.h" #include "drivers/CUST_drivers.h" #include "EI_API.h" #include "EI_API_def.h" #include "appLed.h" #include "app8AI.h" #include "appNV.h" #include "appCfg.h" #include <device_profiles/app_device_profile.h> #include <device_profiles/app_device_profile_intern.h> #include <device_profiles/generic_device/app_generic_device_cfg.h> #include <device_profiles/generic_device/app_generic_device.h> static uint16_t EI_APP_GENERIC_DEVICE_extendedStatus_s[255] = {0}; static bool EI_APP_GENERIC_DEVICE_init (EI_API_ADP_T *pAdapter, EI_API_CIP_NODE_T *pCipNode); static void EI_APP_GENERIC_DEVICE_run (EI_API_CIP_NODE_T *pCipNode); static bool EI_APP_GENERIC_DEVICE_cipSetup (EI_API_CIP_NODE_T *pCipNode); static void EI_APP_GENERIC_DEVICE_cipGenerateContent (EI_API_CIP_NODE_T *pCipNode, uint16_t classId, uint16_t instanceId); /* Boot default: one LED ON (index = 1 => LED0 bit) */ static const uint8_t kBootLedIndex = 1; /* Track class-1 (scanner) connection state (optional, not required for LED) */ static volatile bool s_cnxOpen = false; /* ---------------- Connection Manager callback ---------------- */ EI_API_ADP_SEipStatus_t EI_APP_GENERIC_DEVICE_cmgrCb(uint32_t serviceCode, EI_API_ADP_UCmgrInfo_u cmgrInfo) { (void)cmgrInfo; EI_API_ADP_SEipStatus_t ret_val = { .gen_status = 0, .extended_status_size = 0, .extended_status_arr = EI_APP_GENERIC_DEVICE_extendedStatus_s }; switch (serviceCode) { case 0x54: /* Forward Open */ s_cnxOpen = true; break; case 0x5b: /* Large Forward Open */ s_cnxOpen = true; break; case 0x4e: /* Forward Close */ s_cnxOpen = false; break; default: OSAL_printf("unknown service code %x\r\n", serviceCode); break; } return ret_val; } /* ---------------- Register profile ---------------- */ uint32_t EI_APP_DEVICE_PROFILE_register(EI_APP_DEVICE_PROFILE_Interface_t *pIntf) { uint32_t error = EI_APP_DEVICE_PROFILE_ERR_General; if (NULL == pIntf) { error = EI_APP_DEVICE_PROFILE_ERR_PtrInvalid; goto laError; } pIntf->task.init = EI_APP_GENERIC_DEVICE_init; pIntf->task.run = EI_APP_GENERIC_DEVICE_run; pIntf->cfg.init = EI_APP_GENERIC_DEVICE_CFG_init; pIntf->cfg.isValid = EI_APP_GENERIC_DEVICE_CFG_isValid; pIntf->cfg.setHeader = EI_APP_GENERIC_DEVICE_CFG_setHeader; pIntf->cfg.apply = EI_APP_GENERIC_DEVICE_CFG_apply; pIntf->cfg.setDefaultWithoutComm = EI_APP_GENERIC_DEVICE_CFG_setDefaultWithoutComm; pIntf->cfg.callback = EI_APP_GENERIC_DEVICE_CFG_callback; pIntf->cfg.getRuntimeData = EI_APP_GENERIC_DEVICE_CFG_getRuntimeData; pIntf->cfg.getFactoryResetData = EI_APP_GENERIC_DEVICE_CFG_getFactoryResetData; pIntf->cfg.getLength = EI_APP_GENERIC_DEVICE_CFG_getLength; error = EI_APP_DEVICE_PROFILE_ERR_OK; laError: return error; } /* ---------------- Init ---------------- * - Build class/instance/attributes/assemblies * - Seed 0x0308 = 1 and light one LED so power-up shows LED ON */ bool EI_APP_GENERIC_DEVICE_init(EI_API_ADP_T *pAdapter, EI_API_CIP_NODE_T *pCipNode) { (void)pAdapter; if (!EI_APP_GENERIC_DEVICE_cipSetup(pCipNode)) return false; /* Initialize LED attribute and hardware (keep same address/semantics) */ (void)EI_API_CIP_setAttr_usint(pCipNode, 0x0070, 0x0001, 0x0308, kBootLedIndex); /* Convert index 1..8 → single-bit mask */ if (kBootLedIndex >= 1 && kBootLedIndex <= 8) EI_APP_LED_industrialSet((uint16_t)(1U << (kBootLedIndex - 1U))); else EI_APP_LED_industrialSet(0x0001U); return true; } /* ---------------- Run (cyclic) ---------------- * Produce: 0x300..0x307 (8 × UINT16, 0..32767 from 0..5000 mV) * Consume: 0x308 (USINT LED index 1..8) → light exactly one LED */ void EI_APP_GENERIC_DEVICE_run(EI_API_CIP_NODE_T *pCipNode) { /* ----- 8 analog inputs as UINT (0..32767) ----- */ for (uint16_t ch = 0; ch < 8; ch++) { uint32_t mv = 0; /* millivolts */ EI_APP_8AI_industrialGet(ch, &mv); if (mv > 5000U) mv = 5000U; /* 0..5000 mV → 0..32767 */ uint16_t scaled = (uint16_t)((mv * 32767U) / 5000U); (void)EI_API_CIP_setAttr_uint(pCipNode, 0x0070, 0x0001, (uint16_t)(0x0300U + ch), scaled); } /* ----- LED index at 0x308 (keep exact semantics/addr) ----- */ uint8_t ledIndex = kBootLedIndex; /* default if read fails or out-of-range */ if (EI_API_CIP_getAttr_usint(pCipNode, 0x0070, 0x0001, 0x0308, &ledIndex) != EI_API_CIP_eERR_OK) { ledIndex = kBootLedIndex; } if (ledIndex < 1 || ledIndex > 8) { ledIndex = kBootLedIndex; } EI_APP_LED_industrialSet((uint16_t)(1U << (ledIndex - 1U))); } /* ---------------- CIP setup ---------------- * Matches EDS: * - Class 0x70, Instance 0x01 * - 0x300..0x307 : UINT (GET) → Producing/Input (assembly 0x65) * - 0x308..0x30C : USINT (GET&SET) → Consuming/Output (assembly 0x64) */ static bool EI_APP_GENERIC_DEVICE_cipSetup(EI_API_CIP_NODE_T *pCipNode) { const uint16_t classId = 0x0070; const uint16_t instanceId = 0x0001; EI_APP_GENERIC_DEVICE_cipGenerateContent(pCipNode, classId, instanceId); /* Optional */ (void)EI_API_CIP_createAssembly(pCipNode, 0x00FE, EI_API_CIP_eAR_GET); (void)EI_API_CIP_createAssembly(pCipNode, 0x00FF, EI_API_CIP_eAR_GET); /* Create assemblies with matching roles */ (void)EI_API_CIP_createAssembly(pCipNode, 0x0065, EI_API_CIP_eAR_GET); /* Producing / Input (T→O) */ (void)EI_API_CIP_createAssembly(pCipNode, 0x0064, EI_API_CIP_eAR_GET_AND_SET); /* Consuming / Output (O→T) */ /* Assembly 0x65: inputs 0x300..0x307 (8 × UINT) */ for (uint16_t attr = 0x0300; attr < 0x0308; attr++) { uint32_t ec = EI_API_CIP_addAssemblyMember(pCipNode, 0x0065, classId, instanceId, attr); if (ec != EI_API_CIP_eERR_OK) OSAL_printf("Add member 0x%04X to asm 0x65 failed: 0x%08X\r\n", attr, ec); } /* Assembly 0x64: outputs 0x308..0x30C (5 × USINT) */ for (uint16_t attr = 0x0308; attr <= 0x030C; attr++) { uint32_t ec = EI_API_CIP_addAssemblyMember(pCipNode, 0x0064, classId, instanceId, attr); if (ec != EI_API_CIP_eERR_OK) OSAL_printf("Add member 0x%04X to asm 0x64 failed: 0x%08X\r\n", attr, ec); } return true; } /* ---------------- CIP class/instance/attributes ---------------- * Only create exactly what the EDS and app use: * - 0x300..0x307 : UINT (GET) * - 0x308..0x30C : USINT (GET&SET) with 0x308 default = 1 */ static void EI_APP_GENERIC_DEVICE_cipGenerateContent(EI_API_CIP_NODE_T *cipNode, uint16_t classId, uint16_t instanceId) { EI_API_CIP_SService_t service; (void)EI_API_CIP_createClass(cipNode, classId); service.getAttrAllResponseCnt = 0; service.callback = NULL; service.code = EI_API_CIP_eSC_GETATTRSINGLE; (void)EI_API_CIP_addClassService(cipNode, classId, &service); service.code = EI_API_CIP_eSC_SETATTRSINGLE; (void)EI_API_CIP_addClassService(cipNode, classId, &service); (void)EI_API_CIP_createInstance(cipNode, classId, instanceId); service.code = EI_API_CIP_eSC_GETATTRSINGLE; (void)EI_API_CIP_addInstanceService(cipNode, classId, instanceId, &service); service.code = EI_API_CIP_eSC_SETATTRSINGLE; (void)EI_API_CIP_addInstanceService(cipNode, classId, instanceId, &service); /* 0x300..0x307 : UINT (GET) */ for (uint16_t attrId = 0x0300; attrId < 0x0308; attrId++) { EI_API_CIP_SAttr_t a; OSAL_MEMORY_memset(&a, 0, sizeof(a)); a.id = attrId; a.edt = EI_API_CIP_eEDT_UINT; /* 16-bit */ a.accessRule = EI_API_CIP_eAR_GET; /* produced only */ a.pvValue = OSAL_MEMORY_calloc(1, sizeof(uint16_t)); if (!a.pvValue) OSAL_printf("calloc failed for AI attr 0x%04X\r\n", attrId); (void)EI_API_CIP_addInstanceAttr(cipNode, classId, instanceId, &a); } /* 0x308..0x30C : USINT (GET&SET) → outputs/LEDs */ for (uint16_t attrId = 0x0308; attrId <= 0x030C; attrId++) { EI_API_CIP_SAttr_t a; OSAL_MEMORY_memset(&a, 0, sizeof(a)); a.id = attrId; a.edt = EI_API_CIP_eEDT_USINT; /* 8-bit */ a.accessRule = EI_API_CIP_eAR_GET_AND_SET; /* consumed */ a.pvValue = OSAL_MEMORY_calloc(1, sizeof(uint8_t)); if (!a.pvValue) { OSAL_printf("calloc failed for OUT attr 0x%04X\r\n", attrId); } else if (attrId == 0x0308) { /* Default LED index = 1 so one LED is on at boot */ *((uint8_t*)a.pvValue) = kBootLedIndex; } (void)EI_API_CIP_addInstanceAttr(cipNode, classId, instanceId, &a); if (attrId == 0x0308) { (void)EI_API_CIP_setInstanceAttr(cipNode, classId, instanceId, &a); } } } /* * app8AI.c * * Created on: Jul 20, 2025 * Author: Thien Tran */ #include <stdbool.h> #include <stdint.h> #include "osal_error.h" #include "ti_board_open_close.h" #include "board/led.h" #include "app8AI.h" #include "appMutex.h" typedef struct EI_APP8AI_Industrial { uint32_t instance; uint32_t value[8]; }EI_APP8AI_Industrial_t; /* Global variables and objects */ static HwiP_Object gAdcHwiObject; static SemaphoreP_Object gAdcSyncSemObject; /* Function prototypes */ static void App_adcISR(void *handle); static void App_adcInit(uint32_t baseAddr); static void App_adcConfig(uint32_t baseAddr); static void App_adcStart(uint32_t baseAddr); static void App_adcStop(uint32_t baseAddr); static void App_adcDeInit(uint32_t baseAddr); static EI_APP8AI_Industrial_t EI_APP_8AI_industrial_s; void App_adcISR(void *handle) { uint32_t status; uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR; /* Get interrupt status and clear */ status = ADCGetIntrStatus(baseAddr); ADCClearIntrStatus(baseAddr, status); /* Process ISR */ SemaphoreP_post(&gAdcSyncSemObject); /* Set EOI to generate next interrupt if any */ ADCWriteEOI(baseAddr); } void App_adcConfig(uint32_t baseAddr) { int32_t configStatus; uint32_t chCnt, adcStep; adcStepConfig_t adcConfig; /* Enable interrupts */ ADCEnableIntr(baseAddr, (ADC_INTR_SRC_END_OF_SEQUENCE | ADC_INTR_SRC_FIFO0_THRESHOLD | ADC_INTR_SRC_FIFO0_OVERRUN | ADC_INTR_SRC_FIFO0_UNDERFLOW | ADC_INTR_SRC_FIFO1_THRESHOLD | ADC_INTR_SRC_FIFO1_OVERRUN | ADC_INTR_SRC_FIFO1_UNDERFLOW | ADC_INTR_SRC_OUT_OF_RANGE)); /* * Configure all ADC Steps */ /* Initialize ADC configuration params */ adcConfig.mode = ADC_OPERATION_MODE_SINGLE_SHOT; adcConfig.openDelay = 0x1U; adcConfig.sampleDelay = 0U; adcConfig.rangeCheckEnable = 0U; adcConfig.averaging = ADC_AVERAGING_16_SAMPLES; adcConfig.fifoNum = ADC_FIFO_NUM_0; /* Configure all required steps - Step 1 to N mapped to Channel 1 to N */ for(chCnt = 0U; chCnt < APP_ADC_NUM_CH; chCnt++) { adcConfig.channel = ADC_CHANNEL_1 + chCnt; adcStep = ADC_STEP_1 + chCnt; /* Step -> Channel one to one mapped */ configStatus = ADCSetStepParams(baseAddr, adcStep, &adcConfig); DebugP_assert(SystemP_SUCCESS == configStatus); } ADCStepIdTagEnable(baseAddr, TRUE); configStatus = ADCSetCPUFIFOThresholdLevel(baseAddr, ADC_FIFO_NUM_0, 40U); DebugP_assert(SystemP_SUCCESS == configStatus); /* Step enable */ for(chCnt = 0U; chCnt < APP_ADC_NUM_CH; chCnt++) { adcStep = ADC_STEP_1 + chCnt; /* Step -> Channel one to one mapped */ ADCStepEnable(baseAddr, adcStep, TRUE); } } static void App_adcInit(uint32_t baseAddr) { /* Clear All interrupt status */ ADCClearIntrStatus(baseAddr, ADC_INTR_STATUS_ALL); /* Power up AFE */ ADCPowerUp(baseAddr, TRUE); /* Wait for 4us at least */ ClockP_usleep(5U); /* Do the internal calibration */ ADCInit(baseAddr, FALSE, 0U, 0U); } static void App_adcStart(uint32_t baseAddr) { adcSequencerStatus_t status; /* Check if FSM is idle */ ADCGetSequencerStatus(baseAddr, &status); while ((ADC_ADCSTAT_FSM_BUSY_IDLE != status.fsmBusy) && ADC_ADCSTAT_STEP_ID_IDLE != status.stepId) { ADCGetSequencerStatus(baseAddr, &status); } /* Start ADC conversion */ ADCStart(baseAddr, TRUE); } static void App_adcStop(uint32_t baseAddr) { uint32_t chCnt, adcStep; adcSequencerStatus_t status; /* Disable all/enabled steps */ for(chCnt = 0U; chCnt < APP_ADC_NUM_CH; chCnt++) { adcStep = ADC_STEP_1 + chCnt; /* Step -> Channel one to one mapped */ ADCStepEnable(baseAddr, adcStep, FALSE); } /* Wait for FSM to go IDLE */ ADCGetSequencerStatus(baseAddr, &status); while((ADC_ADCSTAT_FSM_BUSY_IDLE != status.fsmBusy) && ADC_ADCSTAT_STEP_ID_IDLE != status.stepId) { ADCGetSequencerStatus(baseAddr, &status); } /* Stop ADC */ ADCStart(baseAddr, FALSE); /* Wait for FSM to go IDLE */ ADCGetSequencerStatus(baseAddr, &status); while ((ADC_ADCSTAT_FSM_BUSY_IDLE != status.fsmBusy) && ADC_ADCSTAT_STEP_ID_IDLE != status.stepId) { ADCGetSequencerStatus(baseAddr, &status); } } static void App_adcDeInit(uint32_t baseAddr) { ADCPowerUp(baseAddr, FALSE); } /*! * * \brief * Initialize application LED's. * * \param[in] LED initialization parameters. * * \return error code as uint32_t * * \retval #OSAL_NO_ERROR Success. * \retval #OSAL_GENERAL_ERROR Negative default value. * \retval #OSAL_LED_DRV_HANDLE_INVALID LED handle is NULL. * \retval #OSAL_LED_DRV_GETATTR LED_getAttrs call returns NULL. * \retval #OSAL_LED_DRV_SETMASK LED_setMask call failed. * */ uint32_t EI_APP_8AI_init(EI_APP_8AI_SInit_t* pParams) { uint32_t result = (uint32_t) OSAL_GENERAL_ERROR; uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR; HwiP_Params hwiPrms; int32_t status = SystemP_FAILURE; // Initialize industrial 8AI's object EI_APP_8AI_industrial_s.instance = pParams->industrial8AIsInst; for (uint32_t i = 0; i < APP_ADC_NUM_CH; i++){ EI_APP_8AI_industrial_s.value[i] = 0; } status = SemaphoreP_constructBinary(&gAdcSyncSemObject, 0); DebugP_assert(SystemP_SUCCESS == status); /* Register & enable interrupt */ HwiP_Params_init(&hwiPrms); hwiPrms.intNum = CONFIG_ADC0_INTR; hwiPrms.callback = &App_adcISR; hwiPrms.priority = 1U; status = HwiP_construct(&gAdcHwiObject, &hwiPrms); DebugP_assert(SystemP_SUCCESS == status); /* Initialize, Configure and Start the ADC module */ App_adcInit(baseAddr); result = OSAL_NO_ERROR; goto laError; laError: return result; } /*! * * \brief * De-initialize application LED's. * * \return error code as uint32_t * * \retval #OSAL_NO_ERROR Success. * \retval #OSAL_GENERAL_ERROR Negative default value. * \retval #OSAL_LED_DRV_HANDLE_INVALID LED handle is NULL. * \retval #OSAL_LED_DRV_SETMASK LED_setMask call failed. * */ uint32_t EI_APP_8AI_deInit(void) { uint32_t result = (uint32_t) OSAL_GENERAL_ERROR; uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR; /* Stop and power down the ADC*/ App_adcStop(baseAddr); App_adcDeInit(baseAddr); HwiP_destruct(&gAdcHwiObject); SemaphoreP_destruct(&gAdcSyncSemObject); result = OSAL_NO_ERROR; goto laError; laError: return result; } /*! * * \brief * Set industrial LEDs controlled by TPIC2810 * * \param[in] pattern LED pattern. * */ void EI_APP_8AI_industrialGet (uint32_t channel, uint32_t *value) { uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR; uint32_t loopcnt, fifoData, fifoWordCnt, stepID, voltageLvl[APP_ADC_NUM_CH]; App_adcConfig(baseAddr); App_adcStart(baseAddr); /* Wait for the interrupt to occur */ SemaphoreP_pend(&gAdcSyncSemObject, SystemP_WAIT_FOREVER); /* Get FIFO data */ fifoWordCnt = ADCGetFIFOWordCount(baseAddr, ADC_FIFO_NUM_0); for (loopcnt = 0U; loopcnt < fifoWordCnt; loopcnt++) { fifoData = ADCGetFIFOData(baseAddr, ADC_FIFO_NUM_0); stepID = ((fifoData & ADC_FIFODATA_ADCCHNLID_MASK) >> ADC_FIFODATA_ADCCHNLID_SHIFT); fifoData = ((fifoData & ADC_FIFODATA_ADCDATA_MASK) >> ADC_FIFODATA_ADCDATA_SHIFT); voltageLvl[loopcnt] = fifoData * (uint32_t) APP_ADC_REF_VOLTAGE; voltageLvl[loopcnt] /= (uint32_t) ADC_GET_RANGE(CONFIG_ADC0_NUM_BITS); } *value = voltageLvl[channel]; return; }