• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Pointer confusion.

Pommie

Well-Known Member
Most Helpful Member
OK, had a few beers but can't understand why this doesn't work and hope the "Beerless" in our ranks can tell me why.

Simple code,
Code:
void setup(){
  Serial.begin(115200);
  Serial.println("\n\n\nStarted.");
  fooBar(123);
}

void loop(){
}

void fooBar(uint16_t val){
  Serial.println(val);
}
As expected, it prints 123 on the monitor.
Change it to pointer,
Code:
void fooBar(uint16_t *val){
  Serial.println(*val);
}
It now prints zero. I know it's an error that sits between keyboard and monitor but can't work it out. What am I missing?

Mike.
 

tumbleweed

Active Member
Is the call the same? Your function now takes a pointer to a uint16_t value... is that what you're passing it?

What do you expect to happen?
 

Pommie

Well-Known Member
Most Helpful Member
You need to pass the address of the variable rather than the literal variable.
(No guarantees it will take a pointer to to a literal number; try that as well).

int x = 123;

foobar(&x);
Yes, that was it. The whole point of making it a pointer was so the function could modify it. Passing a literal was obviously not going to work as it makes no sense. Hopefully, if was the beer clouding my judgement and not a senior moment. Anyway, back to the task in hand.

Thanks,

Mike.
 

Pommie

Well-Known Member
Most Helpful Member
Just a Nano. I'm using a DS1307 board with a 24C32 on board and wanted to write general routines to log various data to the memory. A curious thing I found was a limit of 30 characters that can be sent in one wire transaction - even though the buffer is 32 bytes long. When logging a variable length string I split it into 16 byte chunks. This is the code using the uint16_t pointer,
Code:
void logString(uint16_t *addr,char *str){
  while(strlen(str)>16){
    while(!wireReady(EEPROM_ADDR));
    Wire.beginTransmission(EEPROM_ADDR);
    Wire.write(*addr>>8);
    Wire.write(*addr&0xff);
    for(uint8_t i=0;i<16;i++){
      Wire.write(*str++);
    }
    Wire.endTransmission(); 
    (*addr)+=16;
  }
  while(!wireReady(EEPROM_ADDR));
  Wire.beginTransmission(EEPROM_ADDR);
  Wire.write(*addr>>8);
  Wire.write(*addr&0xff);
  while(*str){
    Wire.write(*str++);
    (*addr)++;
  }
  Wire.write(0);
  (*addr)++;
  Wire.endTransmission(); 
}
One bug I had was on the second line from the end. I had (*addr++) which didn't increment either the pointer of what it pointed to! Not sure what it actually did. All good fun.

Mike.
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
(*addr++) ; is a bit late at the end... But.. incrementing a pointer doesn't need *..

addr++ increments the pointer *addr increments the value at the pointer.. I think that' s why (*addr)++ works... Ho hum.. C sometimes gets messy..
 

Mike - K8LH

Well-Known Member
Just a Nano.
Ok... May I pass along a link to an interesting document describing Uno and Nano register direct routines for I2C, SPI, and Serial? They save a ton of memory and speed up code considerably but no buffering. Sorry! The crude example below also includes an putStr() overload function for printing "flash string helper" strings.

BTW, the ~444-kHz top speed for I2C is kind of disappointing.

Take care. Stay safe. Mike

Code:
 /***************************************************************************
  *  MCP23017_Test                                                          *
  *                                                                         *
  *  Mike McLaren, K8LH                                                     *
  *  Micro Application Consultants                                          *
  *                                                                         *
  *  MCP23017 I2C driver experiment                                         *
  *                                                                         *
  *                                                                         *
  *                                                                         *
  *  05-Jan-2021    Arduino 1.8.13 / Arduino Nano                           *
  ***************************************************************************/

//#include <Wire.h>           // switched to 'direct register'

 /***************************************************************************
  *  hardware constants, helper macros, variables                           *
  ***************************************************************************/

  #define mcpAddr  0x20<<1    // MCP23017 I2C address shifted left 1 bit

  #define IODIRA    0x00      // MCP23017 register locations (BANK = 0)
  #define IODIRB    0x01
  #define POLA      0x02
  #define POLB      0x03
  #define INTENA    0x04
  #define INTENB    0x05
  #define DEFVALA   0x06
  #define DEFVALB   0x07
  #define INTCONA   0x08
  #define INTCONB   0x09
  #define IOCON     0x0A
  #define IOCON2    0x0B
  #define GPPUA     0x0C
  #define GPPUB     0x0D
  #define INTFA     0x0E
  #define INTFB     0x0F
  #define INTCAPA   0x10
  #define INTCAPB   0x11
  #define GPIOA     0x12
  #define GPIOB     0x13
  #define IOLATA    0x14
  #define IOLATB    0x15

   #define hiNibble(x) ((x >> 4) & 0x0F)
   #define loNibble(x) ((x >> 0) & 0x0F)

   const char hex[] = "0123456789ABCDEF";

 /***************************************************************************
  *  low level UART functions                                               *
  ***************************************************************************/

  #define rxAvail    (UCSR0A & 1<<RXC0)
  #define txReady    (UCSR0A & 1<<UDRE0)

  uint8_t get232(void)                    // ********************************
  { if(rxAvail)                           //                                *
    return (uint8_t) UDR0;                //                                *
  }                                       // ********************************

  void put232(uint8_t data)               // ********************************
  { while(!txReady); UDR0 = data;         // send byte or character         *
  }                                       // ********************************

  void putStr(char *data)                 // ********************************
  { while(*data) put232(*data++);         // send string variable           *
  }                                       // ********************************

 /***************************************************************************
  *  overload function for FlashStringHelper string constants               *
  *                                                                         */
  void putStr(const __FlashStringHelper *ifsh)
  { PGM_P p = reinterpret_cast<PGM_P>(ifsh); 
    while(char c = pgm_read_byte(p++)) 
      put232(c);
  }                                       //

  void putHex(byte work)                  // ********************************
  { put232(hex[hiNibble(work)]);          //                                *
    put232(hex[loNibble(work)]);          //                                *
  }                                       // ********************************

 /***************************************************************************
  *  low level I2C functions                                                *
  ***************************************************************************/

  #define TW_START   0xA4                 // (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
  #define TW_READY   (TWCR & 0x80)        // ready when TWINT returns to 1
  #define TW_STATUS  (TWSR & 0xF8)        // returns value of status register
  #define TW_SEND    0x84                 // (1<<TWINT)|(1<<TWEN)
  #define TW_STOP    0x94                 // (1<<TWINT)|(1<<TWSTO)|(1<<TWEN)
  #define TW_ACK     0xC4                 //
  #define TW_NAK     0x84                 // 

  #define I2C_Stop() TWCR = TW_STOP       // macro
   
  void I2C_Init()                         // ********************************
  { TWSR = 0; TWBR = 12;                  // 400-kHz clock?                 *
  }                                       // ********************************

  byte I2C_Start()                        // ********************************
  { TWCR = TW_START; while(!TW_READY);    // send start condition & wait    *
    return(TW_STATUS == 0x08);            // 1 if found, 0 otherwise        *
  }                                       // ********************************

  byte I2C_SendAddr(byte addr)            // ********************************
  { TWDR = addr;                          // load device's I2C bus address  *
    TWCR = TW_SEND; while(!TW_READY);     // send it & wait                 *
    return(TW_STATUS == 0x18);            // 1 if found, 0 otherwise        *
  }                                       // ********************************

  byte I2C_Write(byte data)               // ********************************
  { TWDR = data;                          // send data byte to slave        *
    TWCR = TW_SEND; while(!TW_READY);     // send it & wait                 *
    return(TW_STATUS != 0x28);            //                                *
  }                                       // ********************************

  byte I2C_ReadNAK()                      // ********************************
  { TWCR = TW_NAK; while(!TW_READY);      //                                *
    return TWDR;                          //                                *
  }                                       // ********************************

 /***************************************************************************
  *                                                                         *
  ***************************************************************************/

  void writeReg(byte reg, byte value)     // ********************************
  { I2C_Start();                          //                                *
    I2C_SendAddr(mcpAddr);                //                                *
    I2C_Write(reg);                       //                                *
    I2C_Write(value);                     //                                *
    I2C_Stop();                           //                                *
  }                                       // ********************************

  void writeReg(byte reg, byte valA, byte valB)   // ************************
  { I2C_Start();                          //                                *
    I2C_SendAddr(mcpAddr);                //                                *
    I2C_Write(reg);                       //                                *
    I2C_Write(valA);                      //                                *
    I2C_Write(valB);                      //                                *
    I2C_Stop();                           //                                *
  }                                       // ********************************

  byte readReg(byte reg)                  // ********************************
  { byte value = 0;                       //                                *
    I2C_Start();                          //                                *
    I2C_SendAddr(mcpAddr);                //                                *
    I2C_Write(reg);                       //                                *
    I2C_Start();                          // restart                        *
    I2C_SendAddr(mcpAddr+1);              // read command                   *
    value = I2C_ReadNAK();                //                                *
    I2C_Stop();                           //                                *
    return value;                         //                                *
  }                                       // ********************************

/*void writeReg(uint8_t reg, uint8_t value)
  { Wire.beginTransmission(mcpAddr);      //
    Wire.write(reg);                      //
    Wire.write(value);                    //
    Wire.endTransmission();               //
  }                                       //

  void writeReg(uint8_t reg, uint8_t portA, uint8_t portB)
  { Wire.beginTransmission(mcpAddr);      //
    Wire.write(reg);                      //
    Wire.write(portA);                    //
    Wire.write(portB);                    //
    Wire.endTransmission();               //
  }                                       //

 /***************************************************************************
  *                                                                         *
  ***************************************************************************/

  #define _BAUD (115200/2)                // 57600 or 115200 (double speed)
  #define _UBRR (F_CPU/16)/_BAUD-1        // Used for UBRRL and UBRRH 

  int main()                              // ********************************
  { DDRD |= 0b00000010;                   //                                *
    DDRC |= 0b00100000;                   // PB4(SDA) inp, PB5(SCL) out     *
    PORTC |= 0b00110000;                  // pull-ups                       *
    DDRB |= 0x01;                         // mclr Output                    *
                                          //                                *
    UBRR0 = _UBRR;                        // setup USART                    *
    UCSR0A |= _BV(U2X0);                  //  " (57600 x 2 for 115200 baud) *
    UCSR0B |= _BV(TXEN0);                 //  "                             *
    UCSR0B |= _BV(RXEN0);                 //  "                             *
    UCSR0C  = 3<<UCSZ00;                  // async' 8/N/1                   *
    put232('\n');                         //                                *
    putStr(F(" PIC MCP23017 Test\n"));    //                                *
    putStr(F(" Mike McLaren, K8LH \n"));  //                                *
                                          //                                *
  //Wire.begin();                         //                                *
  //Wire.setClock(400000);                // 400-kHz                        *
    I2C_Init();                           //                                *
    writeReg(IOCON,0b00100000);           // sequential off                 *
    writeReg(IODIRA,0x00);                // port A outputs                 *
    writeReg(IODIRB,0x00);                // port B outputs                 *
    writeReg(IOLATA,0b00000000);          // port A latches                 *
    writeReg(IOLATB,0xAA);                // port B latches                 *

    byte x = 0;

    while(1)                              // **** loop **********************
    { if(rxAvail)                         // get serial working first       *
        put232(get232());                 // ok, got it...                  *
      writeReg(IOLATA, x, x);             // test MCP23017 outputs          *
      _delay_ms(50); x++;                 // ok, it works (at 100-kHz)      *
    }                                     // ********************************
  }                                       // ********************************
 

Pommie

Well-Known Member
Most Helpful Member
Hi Mike,

Thanks for that, will study that when I've got a little spare time. As it happens, speed of code doesn't matter, all I need to do is log two temperatures so I'm writing a 32 bit (linux) time stamp and two 16 bit DS1820 temperature readings every 5 minutes. So that gives me ~500 (in 4kB) readings or about 40 hours worth. As I only need to log for ~10 hours at most then it works and I've no intention of fixing what isn't broken. AND, need to log it tomorrow - in 10 hours. So it's staying as is for now.:) Plus, beer time now.:rolleyes:

Mike.
Edit, beer time is why this thread started. Maybe time to re-evaluate my life. Second thought, no.
 

Latest threads

EE World Online Articles

Loading
Top