Pointer confusion.

Status
Not open for further replies.

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.
 
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?
 
Does it work with a cast?
Serial.println((int)*val);

sending foobar(123); isn't what you want... location 123 may contain 0.
 
fooBar(123);

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);
 
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.
 
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.
 
(*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..
 
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)      *
    }                                     // ********************************
  }                                       // ********************************
 
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.

Mike.
Edit, beer time is why this thread started. Maybe time to re-evaluate my life. Second thought, no.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…