I am using an atmega328p and writing firmware to display the data I receive via i2c in putty.

I read the data I receive as follows:

/* Receive data from slave. */                                                                                      
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);                                                                          
while(!(TWCR & (1<<TWINT)));                                                                                        



 void libuart_send(unsigned char *data, int data_size)                                                               
    for(int i = 0; i < data_size; i++)                                                                                
        /* Wait for empty transmit buffer */                                                                             
        while ( !( UCSR0A & (1<<UDRE0)) );                                                                              

        /* Put data into buffer, sends the data */                                                                      
        UDR0 = data[i];                                                                                               

I can see with my logic analyzer that I receive 0x00: enter image description here

Yet when trying to see the corresponding data with putty, I just get a weird symbol as if I am casting it incorrectly:

enter image description here

I have been trying to find out how the register TWDR is defined in order to try to understand whether or not I am casting something incorrectly, but I didn't find the information I was looking for. Note that my function libuart_send works perfectly fine when I do something like this libuart_send('A', 1);, but not when I replace the first argument by TWDR. In other words the baudrate is perfectly fine.

Does anybody know why I am seing this weird character in stead of the number 0 in putty?



I think you are casting it wrong. Most likely what happens is that you read the value 0x00 in TWDR and cast it as a pointer from where to read the printable character.

Try this :

unsigned char tempval;
tempval = TWDR;
libuart_send(&tempval, 1);

But if the received character value is 0, this will print the NULL character, it won't print the number or character "0" which is what you may want.

char tempstring[6];
libuart_send(&tempstring, 6);
  • \$\begingroup\$ Could you explain what your code actually does? You are doing all sorts of divisions etc... \$\endgroup\$ – traducerad Dec 14 '18 at 19:37
  • \$\begingroup\$ Humans understand values like 219 for example as three successive symbols called decimal digits that in this case represent hundreds (2), tens (1) and ones (9). It calculates the hundreds (2), tens (1) and ones (9) as a number between 0 and 9, converts them to string of three successive ASCII printable characters "2", "1" and "9", adds control characters carriage return and line feed and terminates the string with a null character (which is actually unnecessary as the length is explicitly told to the sending function). \$\endgroup\$ – Justme Dec 14 '18 at 20:18
  • \$\begingroup\$ Seems like there is a waay simpler way: sprintf(my_string, "%u", myuint16t); \$\endgroup\$ – traducerad Dec 16 '18 at 0:14

You are sending a zero, the problem is that you want to see a printable representation of 0 which is character code 0x30, not raw value 0x00.

You'll either need a terminal program which can display raw vales as a hexdump, or to write code on the Atmega side which expands each byte into a two character hex representation or an up to three character decimal one.

  • \$\begingroup\$ Perhaps you could add mention of ASCII codes to clarify why 0x30 yields a printable "0". asciitable.com is my go-to reference. \$\endgroup\$ – Kevin Kruse Dec 14 '18 at 15:22
  • \$\begingroup\$ or to write code on the Atmega side which expands each byte into a two character hex representation or an up to three character decimal one seems like the way to go for that is: sprintf(my_string, "%u", myuint16t) \$\endgroup\$ – traducerad Dec 16 '18 at 0:21
  • \$\begingroup\$ That may be an option, yes, though sprintf() tends to be large. If you only need this there are better ways, if you need a lot of similar things it may make sense. And of course make sure your buffer is large enough. \$\endgroup\$ – Chris Stratton Dec 16 '18 at 2:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.