cancel
Showing results for 
Search instead for 
Did you mean: 

ads1115 stm8 integration

niko27
Associate II

hello,i am a beginner & i am trying integrate an external adc "ads1115" with stm8. the adc is an i2c device . i tried using peripheral library and also the register way. but its not working can anyone guide me the corect way to integrate this.this is my code

#include "main.h"
#include <stdio.h>

/*void I2C_Init(void);
void I2C_Write(uint8_t addr, uint8_t reg, uint8_t data);
void I2C_Read(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len);
void delay_ms(uint16_t ms);*/

#define ADS1115_ADDRESS 0x48
#define ADS1115_CONFIG_REG 0x01

        uint8_t data[2];
               
        int16_t adcValue=0;
                uint8_t i=0;

void delay_ms(uint16_t ms) {
    // Assuming a 16 MHz clock frequency
    uint16_t cycles = (uint16_t)(16000 * ms);

    while (cycles--) {
        // Do nothing
    }
}
void main(void) {
    // Initialize I2C
     GPIOC->DDR |= GPIO_Pin_0 | GPIO_Pin_1;   // Set SDA and SCL as output
    GPIOC->CR1 |= GPIO_Pin_0 | GPIO_Pin_1;   // Set open-drain mode
    GPIOC->CR2 |= GPIO_Pin_0 | GPIO_Pin_1;   // Set fast mode

    // Configure I2C
    I2C1->FREQR = 16;  // Set clock frequency to 16 MHz
    I2C1->CR1 |= I2C_CR1_PE;  // Enable I2C

    // Set I2C clock control register
    I2C1->CCRL = 0x50;  // Set clock control register low-byte
    I2C1->TRISER = 0x11;  // Set maximum rise time in fast/standard mode

    while (1) {
        // Read ADC value from channel 0
        I2C1->CR2 |= I2C_CR2_START;
    while ((I2C1->SR1 & I2C_SR1_SB));

    // Send device address for write
    I2C1->DR = 0x48 << 1;
    while (!(I2C1->SR1 & I2C_SR1_ADDR));
    (void)I2C1->SR2;

    // Send register address
    I2C1->DR = 0x01;
    while (!(I2C1->SR1 & I2C_SR1_TXE));

    // Send data
    I2C1->DR = 0xc3;
    while (!(I2C1->SR1 & I2C_SR1_TXE));

    // Generate stop condition
    I2C1->CR2 |= I2C_CR2_STOP;
        delay_ms(10);  // Wait for the conversion to complete (approx. 8ms for single-shot mode)

        I2C1->CR2 |= I2C_CR2_START;
    while (!(I2C1->SR1 & I2C_SR1_SB));

    // Send device address for write
    I2C1->DR = 0x48<< 1;
    while (!(I2C1->SR1 & I2C_SR1_ADDR));
    (void)I2C1->SR2;

    // Send register address
    I2C1->DR = 0x01;
    while (!(I2C1->SR1 & I2C_SR1_TXE));

    // Generate repeated start condition
    I2C1->CR2 |= I2C_CR2_START;
    while (!(I2C1->SR1 & I2C_SR1_SB));

    // Send device address for read
    I2C1->DR = (0x48 << 1) | 1;
    while (!(I2C1->SR1 & I2C_SR1_ADDR));
    (void)I2C1->SR2;

    // Receive data
    for ( i = 0; i < 2; ++i) {
        while (!(I2C1->SR1 & I2C_SR1_RXNE));
        data[i] = I2C1->DR;
    }

    // Generate stop condition
    I2C1->CR2 |= I2C_CR2_STOP;

         adcValue = (data[0] << 8) | data[1];

        // Print the result (you might want to use USART for proper communication)
        printf("AIN0: %d\n", adcValue);

        // Wait for a moment before the next reading
        delay_ms(1000);
    }
}







7 REPLIES 7
AA1
Senior III

First while ((I2C1->SR1 & I2C_SR1_SB));

should be: while (!(I2C1->SR1 & I2C_SR1_SB));

Missing !

 

You are not reading SR3 register. See RM0016 page 295:

Then the master waits for a read of the SR1 register followed by a read in the SR3 register.

niko27
Associate II

I HAVE ADDED THE ! TO THE LINE , AND WHEN DEBUGGING THE CODE STOPS AT       while (!(I2C1->SR1 & I2C_SR1_SB));

I AM USING STM8L052C6 MCU

AA1
Senior III

On STM8L family, before work with a peripheral, you must enable the peripheral clock. It is called Peripheral clock gating.

niko27
Associate II

i have made another project for the ads1115 integration for stm8l052c6 ..with peripheral clock and all

#include "stm8l15x.h"
#include "stm8l15x_clk.h"
#include "stm8l15x_i2c.h"
#include <stdio.h>
// ADS1115 I2C address
#define ADS1115_ADDRESS 0x48
 
// ADS1115 configuration registers
#define CONFIG_REG_ADDR 0x01
#define AIN0_CONFIG 0xC3  // Example configuration for AIN0
uint8_t i;
   uint16_t adcValue=0;
// Function prototypes
void I2C_Init(I2C_TypeDef* I2Cx, uint32_t OutputClockFrequency, uint16_t OwnAddress,
              I2C_Mode_TypeDef I2C_Mode, I2C_DutyCycle_TypeDef I2C_DutyCycle,
              I2C_Ack_TypeDef I2C_Ack, I2C_AcknowledgedAddress_TypeDef I2C_AcknowledgedAddress);
 
void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, I2C_Direction_TypeDef I2C_Direction);
void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);
uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);
 
// Delay function
 
void delay(uint16_t ms) {
    // Assuming a 16 MHz clock frequency
    uint16_t cycles = (uint16_t)(16000 * ms);
 
    while (cycles--) {
        // Do nothing
    }
}
 
void Clock_Init(void) {
    CLK_DeInit();
    CLK_LSICmd(DISABLE);  // Disable Low-Speed Internal clock
    CLK_HSICmd(ENABLE);   // Enable High-Speed Internal clock
 
    while (CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == FALSE);
    CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI);
 
    // Enable peripheral clocks
    CLK_PeripheralClockConfig(CLK_Peripheral_I2C1, ENABLE);
    CLK_PeripheralClockConfig(CLK_Peripheral_USART1, ENABLE);
}
 
/*void USART_Configuration(void) {
    // UART initialization
    USART_Init(USART1, (uint32_t)19200, USART_WordLength_8b, 
               USART_StopBits_1, USART_Parity_No, (USART_Mode_TypeDef)(USART_Mode_Tx|USART_Mode_Rx));
}*/
 
void I2C_Configuration(void) {
    // I2C initialization
    I2C_Init(I2C1, 100000, 0, I2C_Mode_I2C, I2C_DutyCycle_2, I2C_Ack_Enable, I2C_AcknowledgedAddress_7bit);
}
 
void ADS1115_Configuration(void) {
    // Initialize clock
    Clock_Init();
 
    // Initialize I2C
    I2C_Configuration();
 
    // Start I2C communication
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
 
    I2C_GenerateSTART(I2C1, ENABLE);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
 
    // Send ADS1115 address for write operation
    I2C_Send7bitAddress(I2C1, (ADS1115_ADDRESS << 1 & 0xFE), I2C_Direction_Transmitter);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
 
    // Send configuration register address
    I2C_SendData(I2C1, CONFIG_REG_ADDR);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
 
    // Send configuration data
    I2C_SendData(I2C1, AIN0_CONFIG);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
 
    // End I2C communication
    I2C_GenerateSTOP(I2C1, ENABLE);
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF));
}
 
uint16_t ADS1115_Read_A0(void) {
    uint8_t data[2] = {0};
 
    // Start I2C communication
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
 
    I2C_GenerateSTART(I2C1, ENABLE);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
 
    // Send ADS1115 address for write operation
    I2C_Send7bitAddress(I2C1, (ADS1115_ADDRESS << 1& 0xFE), I2C_Direction_Transmitter);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
 
    // Send register address to read from (Config register)
    I2C_SendData(I2C1, CONFIG_REG_ADDR);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
 
    // Repeated start
    I2C_GenerateSTART(I2C1, ENABLE);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
 
    // Send ADS1115 address for read operation
    I2C_Send7bitAddress(I2C1, (ADS1115_ADDRESS << 1| 0x01), I2C_Direction_Receiver);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
 
    // Receive data
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
    data[0] = I2C_ReceiveData(I2C1);
 
    // Acknowledge disable
    I2C_AcknowledgeConfig(I2C1, DISABLE);
 
    // Generate stop condition
    I2C_GenerateSTOP(I2C1, ENABLE);
 
    // Receive data
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
    data[1] = I2C_ReceiveData(I2C1);
 
    return (data[0] << 😎 | data[1];
}
 
void GPIO_Configuration(void) {
    // Remap USART1 to PA2 (TX) and PA3 (RX)
    GPIO_DeInit(GPIOA);
    SYSCFG_REMAPPinConfig(REMAP_Pin_USART1TxRxPortA, ENABLE);
 
    // Configure PA2 (TX) as alternate function push-pull
    GPIO_Init(GPIOA, GPIO_Pin_2, GPIO_Mode_Out_PP_Low_Slow);
 
    // Configure PA3 (RX) as input floating
    GPIO_Init(GPIOA, GPIO_Pin_3, GPIO_Mode_In_FL_No_IT);
}
 
 
int main(void) {
enableInterrupts();
    // Call ADS1115 configuration function
    ADS1115_Configuration();
 
    // Your main code here
// USART_Configuration();
 
 
    while (1) {
        // Read value from A0 using ADS1115
adcValue = ADS1115_Read_A0();
 
        // Your code to process the ADC value
 /*char buffer[50];  // Adjust the array size based on the expected length of your values
        sprintf(buffer, "ADC Value: %u", adcValue);
         i = 0;
        while (buffer[i] != '\0') {
            USART_SendData8(USART1, buffer[i++]);
            while (!USART_GetFlagStatus(USART1, USART_FLAG_TC)); */ // Wait for transmission to complete
        // Introduce a delay if necessary
        delay(1000);
    }
 
}

in this code also stops aftr the i2c is started , when the address is being send to slave 

I2C_Send7bitAddress(I2C1, (ADS1115_ADDRESS << 1 & 0xFE), I2C_Direction_Transmitter);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));


have any suggetion 

also can anyone provide a i2c scanner code for stm8l052c6 mcu
 

I2C needs two external pull-up resistors of about 4K7 on SDA and SCL pins. Do you have the resistors?

niko27
Associate II

Yes, I have on board  10k pull-up resistors for both SDA and SCL 

I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED tests flags BUSY, MSL, ADDR, TXE and TRA

RM0031 page 511:
ADDR is cleared by software reading SR1 register followed reading SR3. If tested flags don't appear at same time, ADDR is cleared and condition is always false.

You must improve your code. Follow RM0031 I2C steps.