Skip to main content
Visitor II
November 14, 2023
Question

ads1115 stm8 integration

  • November 14, 2023
  • 3 replies
  • 2909 views

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);
    }
}







    This topic has been closed for replies.

    3 replies

    Visitor II
    November 15, 2023

    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.

    niko27Author
    Visitor II
    November 16, 2023

    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

    Visitor II
    November 16, 2023

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

    niko27Author
    Visitor II
    November 24, 2023

    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] << 8) | 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
     
    Visitor II
    November 24, 2023

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

    niko27Author
    Visitor II
    November 25, 2023

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