// i2c_ads1115.c #include "bsp_i2c_ads1115.h" #include "stdlib.h" #include "stdio.h" #include "elog.h" /* 多路测量的话, 需要配置不同的 config_H config_L */ static I2C_HandleTypeDef *pADS1115_I2C = &hi2c1; osThreadId_t ads1115TaskHandle; const osThreadAttr_t ads1115Task_attributes = { .name = "ads1115Task", .stack_size = 256 * 4, .priority = (osPriority_t) osPriorityNormal, }; osEventFlagsId_t ads1115EventHandle; const osEventFlagsAttr_t ads1115Event_attributes = { .name = "ads1115Event" }; I2C_HELPER_TypeDef *ads1115_i2c_helper; // uint16_t resultbuf[1] = {0}; // double result_double = 0; ADS1115_TypeDef my_ads1115 = { ads1115_init, ads1115_port, ads1115_test, ads1115_start, ads1115_stop, // NULL, ADS1115_REG_CONFIG_OS_START, ADS1115_REG_CONFIG_MUX_SINGLE_0, ADS1115_REG_CONFIG_PGA_4, ADS1115_REG_CONFIG_MODE_SINGLE, ADS1115_REG_CONFIG_DR_128, ADS1115_REG_CONFIG_COMP_MODE_TRADITIONAL, ADS1115_REG_CONFIG_COMP_POL_LOW, ADS1115_REG_CONFIG_COMP_LAT_NONLATCH, ADS1115_REG_CONFIG_COMP_QUE_DIS, 0, 0, 0, { 0, 0, 0 }, ADS1115_OUTPUT_UNIT_mv, // 默认输出毫伏 0, 0.0, // coeff 放大1000 0.0, // voltage——mv ADS1115_WORK_STATE_WAITING, 0, }; void ads1115_task(void) { uint8_t rx_data[2] = {0}; my_ads1115.event_flag = 0; uint64_t ticks; int err_con = 0; int st; for ( ; ; ) { switch (my_ads1115.state) { case ADS1115_WORK_STATE_WAITING: // log_e( " ADS1115 waiting ********** " ); osDelay(20); break; case ADS1115_WORK_STATE_START: break; case ADS1115_WORK_STATE_TEST: log_e( " ADS1115 test ********** %d" ,pADS1115_I2C->State ); ads1115_get_reg_data( ); I2C_HELPER_Set_mem_addr( ads1115_i2c_helper, 0x01 ); st = I2C_HELPER_Trans( ads1115_i2c_helper, my_ads1115.reg_data, 2 ); if ( st != HAL_OK) { log_w( " ADS1115 init ********** trans error " ); my_ads1115.state = ADS1115_WORK_STATE_ERROR;; break; } ticks = osKernelGetTickCount(); err_con = 0; my_ads1115.state = ADS1115_WORK_STATE_TESTING; continue; case ADS1115_WORK_STATE_TESTING: if ( osKernelGetTickCount() - ticks > 1000 ) { err_con++; if( err_con >3) { log_w( " ADS1115 testing ******** error " ); my_ads1115.state = ADS1115_WORK_STATE_ERROR; } my_ads1115.state = ADS1115_WORK_STATE_TEST; } osDelay(1); continue; case ADS1115_WORK_STATE_TEST_OK: log_w( " ADS1115 TEST_OK ********** %d" ,pADS1115_I2C->State ); my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_READY; // TODO Stop DMA continue; case ADS1115_WORK_STATE_GET_DATA_READY: osDelay(1); continue; case ADS1115_WORK_STATE_GET_DATA_START: log_w( " ADS1115 GET_DATA_START ********** %d " , pADS1115_I2C->State ); my_ads1115.result_int16 = 0 ; my_ads1115.voltage_mv = 0.0 ; ads1115_get_reg_data( ); ads1115_get_coeff( ); my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_SET_REG01; continue; case ADS1115_WORK_STATE_GET_DATA_SET_REG01: I2C_HELPER_Set_mem_addr( ads1115_i2c_helper, 0x01 ); st = I2C_HELPER_Trans( ads1115_i2c_helper, my_ads1115.reg_data, 2 ); if ( st != HAL_OK) { log_w( " ADS1115 init ********** trans error " ); my_ads1115.state = ADS1115_WORK_STATE_ERROR;; break; } ticks = osKernelGetTickCount(); err_con = 0; my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_SET_REG01_Wait; continue; case ADS1115_WORK_STATE_GET_DATA_SET_REG01_Wait: if ( osKernelGetTickCount() - ticks > 1000 ) { err_con++; if( err_con >3) { log_w( " ADS1115 set reg ******** error " ); my_ads1115.state = ADS1115_WORK_STATE_ERROR; } my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_START; } osDelay(1); continue; case ADS1115_WORK_STATE_GET_DATA_RCV: log_i( " ADS1115 Ready ********** _DATA_RCV " ); memset( rx_data,0,2); I2C_HELPER_Set_mem_addr(ads1115_i2c_helper, 0x00); st = I2C_HELPER_Start_Rcv(ads1115_i2c_helper, rx_data, 2); if ( st != HAL_OK) { log_w( " ADS1115 init ********** trans error " ); my_ads1115.state = ADS1115_WORK_STATE_ERROR;; break; } ticks = osKernelGetTickCount(); err_con = 0; my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_RCV_Wait; continue; case ADS1115_WORK_STATE_GET_DATA_RCV_Wait: if ( osKernelGetTickCount() - ticks > 1000 ) { err_con++; if( err_con >3) { log_w( " ADS1115 data rcv ******** error " ); my_ads1115.state = ADS1115_WORK_STATE_ERROR; } my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_START; } osDelay(1); continue; case ADS1115_WORK_STATE_GET_DATA_OK: log_i( " ADS1115 ********** DATA_OK %d" ,my_ads1115.result_int16 ); double val; my_ads1115.result_int16 = rx_data[0] * 256 + rx_data[1]; if ( (my_ads1115.result_int16 == 0x7FFF) | (my_ads1115.result_int16 == 0X8000)) // 是否超量程了 { my_ads1115.result_int16 = 0; } my_ads1115.voltage_mv = ((double)my_ads1115.result_int16 *(double) my_ads1115.coeff)/1000.0;; log_i( " voltage mv : %06f",my_ads1115.voltage_mv); my_ads1115.state = ADS1115_WORK_STATE_STOP ; break; case ADS1115_WORK_STATE_ERROR: log_w( " ADS1115 error ..... " ); // my_ads1115.state = ADS1115_WORK_STATE_WAITING ; osDelay(10); continue; case ADS1115_WORK_STATE_STOP: log_w( " ADS1115 stop..... " ); // my_ads1115.state = ADS1115_WORK_STATE_WAITING ; osDelay(10); continue; default: break; } osDelay(200); } } void ads1115_port(void) { ads1115TaskHandle = osThreadNew(ads1115_task, NULL, &ads1115Task_attributes ); // ads1115EventHandle = osEventFlagsNew (&ads1115Event_attributes ); } /** * @brief * @param [in] ads1115_I2cHandle * @param [in] pointADD -- 读的寄存器地址 * @param [in] configH * @param [in] configL * * @details */ int ads1115_init(void) { ads1115_i2c_helper = I2C_HELPER_Init( ); I2C_HELPER_Set_Hi2c( ads1115_i2c_helper, pADS1115_I2C ); I2C_HELPER_Set_dev_addr( ads1115_i2c_helper, ADS1115_WRITE_ADDRESS); I2C_HELPER_Set_mem_addr_size( ads1115_i2c_helper, I2C_MEMADD_SIZE_8BIT ); //I2C_MEMADD_SIZE_16BIT // I2C_HELPER_Set_mem_addr(ads1115_i2c_helper, uint16_t mem_addr); I2C_HELPER_Setup_Trans_mode( ads1115_i2c_helper, I2C_Trans_IT ); // 设置回调 I2C_HELPER_Set_Callback( ads1115_i2c_helper, (void *)&my_ads1115, (i2c_callback_fun) ads1115_callback); // ads1115_get_reg_data( ); // // polling mode test, cfg register : 0x01 // int st = 0; // st = HAL_I2C_Mem_Write( ads1115_i2c_helper->hi2c, ADS1115_WRITE_ADDRESS, 0x01, // ads1115_i2c_helper->mem_addr_size, my_ads1115.reg_data, 2, 0xFFFF ); // if (st != HAL_OK) // { // return -1; // } return 0; } int ads1115_test(void) { my_ads1115.state = ADS1115_WORK_STATE_TEST; } void ads1115_start(void) { my_ads1115.state =ADS1115_WORK_STATE_GET_DATA_START; // osEventFlagsSet( ads1115TaskHandle, ADS1115_Event_Get_Data ); } void ads1115_stop(void) { } int ads1115_setup(ADS1115_REG_CONFIG_MUX_Diff_TypeDef mux) { my_ads1115.config_H &= ~0x70; my_ads1115.config_H &= mux; return 0; } int16_t ads1115_read_data( ) { int16_t data; uint8_t rx_data[2] = {0}; // TODO 阻塞式, 改为 DMA 中断模式 // 读寄存器 0x00 十六位 while (HAL_I2C_Master_Transmit(pADS1115_I2C, ADS1115_WRITE_ADDRESS, 0x00, 1, 2000) != HAL_OK) { if (HAL_I2C_GetError(pADS1115_I2C) != HAL_I2C_ERROR_AF) { printf("ads1115 convert Register error!!!\r\n"); } } // 读两位 while (HAL_I2C_Master_Receive(pADS1115_I2C, ADS1115_READ_ADDRESS, rx_data, 2, 2000) != HAL_OK) { if ( HAL_I2C_GetError(pADS1115_I2C) != HAL_I2C_ERROR_AF ) { printf("ads1115 read data error!!!\r\n"); } } data = rx_data[0] * 256 + rx_data[1]; return data; } double ads1115_get_coeff( ) { my_ads1115.coeff = 1.0; switch ((0x0E & my_ads1115.config_H) >> 1) // 量程对应的分辨率 { case (0x00): my_ads1115.coeff =my_ads1115.coeff * 187.5 ; // break; case (0x01): my_ads1115.coeff = my_ads1115.coeff * 125 ; break; case (0x02): my_ads1115.coeff = my_ads1115.coeff * 62.5; break; case (0x03): my_ads1115.coeff = my_ads1115.coeff * 31.25 ; break; case (0x04): my_ads1115.coeff = my_ads1115.coeff * 15.625; break; case (0x05): my_ads1115.coeff = my_ads1115.coeff * 7.8125; break; } } double ads1115_get_voltage_val( ) { double val; int16_t ad_val; // TODO 去掉延时,使用寄存器的指示, setup 和读取数据分开执行 // ads1115_setup( pADS1115_I2C, pointADD, configH, configL ); ads1115_setup( ADS1115_REG_CONFIG_MUX_SINGLE_0 ); HAL_Delay(10); ad_val = ads1115_read_data( pADS1115_I2C ); if ( (ad_val == 0x7FFF) | (ad_val == 0X8000)) // 是否超量程了 { ad_val = 0; // printf("over PGA\r\n"); } ads1115_get_coeff( ); val = ad_val * my_ads1115.coeff/1000.0; if (my_ads1115.unit == ADS1115_OUTPUT_UNIT_v) { val = val/1000.0; } return val; } void ads1115_get_data_start(void) { // log_w( " ADS1115 ********** start.. " ); // osEventFlagsSet( ads1115TaskHandle, ADS1115_Event_Get_Data ); my_ads1115.state =ADS1115_WORK_STATE_GET_DATA_START; } void ads1115_callback(ADS1115_TypeDef *pAds1115, uint8_t *buf, uint16_t size) { switch (my_ads1115.state) { case ADS1115_WORK_STATE_TESTING : my_ads1115.state++; break; case ADS1115_WORK_STATE_GET_DATA_SET_REG01_Wait : my_ads1115.state++; break; case ADS1115_WORK_STATE_GET_DATA_RCV_Wait : // TODO Check data? my_ads1115.state++; break; default: break; } } // ads1115EventHandle = osEventFlagsNew (&ads1115Event_attributes); // typedef enum // { // EV_READY, /*!< Startup finished. */ // EV_FRAME_RECEIVED, /*!< Frame received. */ // EV_EXECUTE, /*!< Execute function. */ // EV_FRAME_SENT /*!< Frame sent. */ // } eMBEventType; // osEventFlagsSet(modbusEventHandle,eEvent); // osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags) // recvedEvent = osEventFlagsWait (modbusEventHandle, // EV_READY | EV_FRAME_RECEIVED | EV_EXECUTE | // EV_FRAME_SENT, /* 接收任务感兴趣的事件 */ // 0, // portMAX_DELAY); /* 指定超时事件,无限等待 */ // TODO 阻塞式 仅init 使用 // my_ads1115.state = ADS1115_WORK_STATE_INIT; // osEventFlagsSet ( ads1115TaskHandle, ADS1115_Event_INIT ); // I2C_HELPER_Set_mem_addr(ads1115_i2c_helper, 0x01); // st = I2C_HELPER_Trans(ads1115_i2c_helper, reg_data,2); // I2C_HELPER_Set_mem_addr(ads1115_i2c_helper, 0x00); // st = I2C_HELPER_Start_Rcv(ads1115_i2c_helper, rx_data, 2); // st = HAL_I2C_Mem_Write(ads1115_i2c_helper->hi2c, ads1115_i2c_helper->dev_addr, my_ads1115.reg_data[0],ads1115_i2c_helper->mem_addr_type , reg_data,2,0xFFFF); // if (HAL_I2C_Master_Transmit(pADS1115_I2C, ADS1115_WRITE_ADDRESS, my_ads1115.reg_data, 3,1000 ) != HAL_OK) // { // return -1; // } // while (HAL_I2C_Master_Transmit(pADS1115_I2C, ADS1115_WRITE_ADDRESS, 0x00, 1, 2000) != HAL_OK) // { // if (HAL_I2C_GetError(pADS1115_I2C) != HAL_I2C_ERROR_AF) // { // printf("ads1115 convert Register error!!!\r\n"); // } // } // // 读两位 // while (HAL_I2C_Master_Receive(pADS1115_I2C, ADS1115_READ_ADDRESS, rx_data, 2, 2000) != HAL_OK) // { // if ( HAL_I2C_GetError(pADS1115_I2C) != HAL_I2C_ERROR_AF ) // { // printf("ads1115 read data error!!!\r\n"); // } // } // case ADS1115_WORK_STATE_GET_DATA_Convert_Register: // log_i( " ADS1115 Ready ********** Convert_Register " ); // while (HAL_I2C_Master_Transmit(pADS1115_I2C, ADS1115_WRITE_ADDRESS, 0x00, 1, 2000) != HAL_OK) // { // if (HAL_I2C_GetError(pADS1115_I2C) != HAL_I2C_ERROR_AF) // { // printf("ads1115 convert Register error!!!\r\n"); // } // } // my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_RCV; // // // osEventFlagsClear( ads1115TaskHandle, ADS1115_Event_Get_Data ); // // st = HAL_I2C_Master_Transmit (pADS1115_I2C, ADS1115_WRITE_ADDRESS, 0x00, 1 ,1000); // // if ( st != HAL_OK) // // { // // log_e( " ADS1115 init ********** Convert_Register error " ); // // my_ads1115.state = ADS1115_WORK_STATE_ERROR; // // break; // // } // // if ( HAL_I2C_GetError(pADS1115_I2C) != HAL_I2C_ERROR_AF ) // // { // // log_e("ads1115 read data error!!!\r\n"); // // break; // // } // // my_ads1115.state =ADS1115_WORK_STATE_GET_DATA_RCV; // // if (HAL_I2C_Master_Transmit_IT(pADS1115_I2C, ADS1115_WRITE_ADDRESS, 0x00, 1 ) != HAL_OK) { // // my_ads1115.state =ADS1115_WORK_STATE_ERROR; // // } // // if ( HAL_I2C_GetError(pADS1115_I2C) != HAL_I2C_ERROR_AF ) // // { // // printf("ads1115 convert Register error!!!\r\n"); // // } // // event_flags = osEventFlagsWait ( ads1115EventHandle, // // ADS1115_Event_Get_Data_Convert_Register, 0 , portMAX_DELAY ); // // if (event_flags && ADS1115_Event_Get_Data_Convert_Register) // // { // // my_ads1115.state = ADS1115_WORK_STATE_GET_DATA_RCV; // // } // continue;