2013-07-12 11:46 PM
I ported the printf functions to UART3. I am reading some gyro data from a digital chip that gives it's results in 2's compliment. So I get the raw data and print the integer that I stored it in. But the printf function is not converting to a decimal number, so I never get negative numbers.
So I have to convert it manually with the code below. the printf statement I use is printf(''%f'',data); why does it not see that the integer is negative and just print an unsigned value?For example: 0xFFFF = -1 in 2's compliment. But the printf will print 65535.<code>float get_gyro(char axis) //Get the gyro data at that axis in degrees/sec{ unsigned int high; //I have changed these to a signed int and had the same results unsigned int low; int data = 0; float dps = 0; float offset = 0x00; switch(axis) { case 'x': low = gyro_read(OUT_X_L); high = gyro_read(OUT_X_H); data = (low | (high<<8)); //Put high and low bytes into one 16 bit number offset = gyro_x_offset; break; case 'y': low = gyro_read(OUT_Y_L); high = gyro_read(OUT_Y_H); data = (low | (high<<8)); offset = gyro_y_offset; break; case 'z': low = gyro_read(OUT_Z_L); high = gyro_read(OUT_Z_H); data = (low | (high<<8)); offset = gyro_z_offset; break; default: break; } /**** For some reason printf does not do convertion of 2's complement. This data will always be a 16 bit number from the gyro ****/ if(data&0x8000)//If its a negative number { data = ((data ^ 0xFFFF) +1)*-1; //Convert From 2's Comp to Decimal } if(data < 0) { data = data + offset; }else{ data = data - offset; } dps = data*gyro_sens; return (dps);}</code> #printf #2's-compliment2013-07-13 03:37 AM
int is a 32-bit type, perhaps you want short?
printf(''%d\n'',sizeof(int)); The lack of sign propagation suggests some down stream casting/conversion issues.2013-07-13 11:14 AM
That makes total sense! The MSB has to be one to be a negative number. My 16 bit number in a 32 bit int will never have it's MSB a one. Can't believe I missed that even after I wrote code to convert it.....
Thanks for that. It works now. But I have another problem with the printf function. When I put my printf function in my SysTick_Handle ISR the interrupt seems to never clear and will enter the ISR as soon as it's done. The printf function should not take that much time to have the 10ms tick ready again before it executes should it? That seems like an excessive amount of time even for printf.Here is my ISR for the system_tick. The system tick is set for every 10ms. I even made this 100ms and 1Sec but with the same results.void SysTick_Handler(void){if(current_ms > 0x00)
// This decrements a variable I use for a delay function { --current_ms; } data_not_ready(); //Wait for gyro data to be available gyro_x = get_gyro('z'); //Read gyro data printf(''x_axis = %f \n\r'',gyro_x); //Print it out. }My solution:I just put the printf function in the main() while(1) loop and have a flag in software tell it that the system tick handler read new data to print out. And this works great. What could make it do that in the ISR?2013-07-13 12:04 PM
Doing printf() or USART stuff out of an interrupt is generally not recommended. You kind of want your output buffered and allow the USART to service this buffer on the TXE interrupt.
You might also want to monitor the buffer fill level before sending additional strings. printf()/scanf() also have a large stack footprint, so watch your stack allocation.