lpc2148 RTC print issue - c

enter code here
void DateTimeConversion (void)
{
unsigned char TempDay,TempMonth,TempYear,i;
unsigned char TempHour,TempMinute,TempSecond;
TempDay=0;TempMonth=0;TempYear=0;TempHour=0;TempHour=0;TempSecond=0;
col=1;
for(i=0;i<10;i++)
{
sprintf(MyStr,"%c",(unsigned int)StoreUserID[i]);
ClcdGoto(col,2);ClcdPutS_P(MyStr);
col++;
}
TempDay=((unsigned int)(StoreUserID[6] * 10) + (unsigned int)(StoreUserID[7] * 1));
TempMonth=((unsigned int)(StoreUserID[8] * 10) + (unsigned int)(StoreUserID[9] * 1));
TempYear=((unsigned int)(StoreUserID[4] * 10) + (unsigned int)(StoreUserID[5] * 1));
TempHour = ((unsigned int)(StoreUserID[0] *10) + (unsigned int)(StoreUserID[1] * 1));
TempMinute = ((unsigned int)(StoreUserID[2] *10) + (unsigned int)(StoreUserID[3] * 1));
TempSecond = ((unsigned int)(StoreUserID[4] *10) + (unsigned int)(StoreUserID[5] * 1));
}
I am using LPC 2148 for RTC.
description:
I have used singlekey to read multiple values(0-9)on same column (2 line LCD display used).
The read value is stored in StoreUserId array(as col++ array also increased)
Above function is called to save value for SEC,MINUTE,HOUR.
StoreUserid is print to crosscheck value enter correctly.
But after conversion(check multiply *10) TempSecond, TempMinute, TempHour shows random value after conversion not getting where is issue?.

Your problem is almost certainly here:
{sprintf(MyStr,"%c",(unsigned int)StoreUserID[i]);
I'm not able to know how you declared the StoreUserID array (as char? as int?) and why did you consistently cast to unsigned int (for small positive numbers as year or seconds it has no meaning) but there are these 2 most probable corrections:
{sprintf(MyStr,"%c", StoreUserID[i]); // for character representation in StoreUserID[]
or - and I think that this is your case -
{sprintf(MyStr,"%c",StoreUserID[i] + '0'); // for numerical one - the conversion is needed
Explanation:
Number 0 has character representation '0', which is some number (in ASCII it is 48).
Number 1 has character representation '1', which is the next number (in ASCII it is 49).
... and so on.
So you need to add value '0' to obtain the character representation from the bare number.

Related

atoi(happens with strtol as well) why add in the array '0'?

Im trying to study a code that has
array[0] = digitalRead(pin1);
array[1] = digitalRead(pin2);
array[2] = digitalRead(pin3);
array[3] = digitalRead(pin3);
array[4] = digitalRead(pin4);
array[5] = digitalRead(pin5);
array[6] = digitalRead(pin6);
array[7] = digitalRead(pin7);
for(i=0; i<8 ; i++){
data[i] = array[i] + '0';
}
input = atoi(data);
im curious why did they add a '0'? when i try to run the code without the '0' it returns 0 which i assume is saying it can't be converted
Short answer: '0' is added to convert interger values to ascii character values.
Explanation:
It's important to know that integer values like 0, 1, 2, ... are not the same as characters like '0', '1', '2', ... Characters do have an integer value that are defined in ascii-tables, see https://en.wikipedia.org/wiki/ASCII, but that value differs from the integer value. For instance the character '0' has the integer value 48. So to convert between an integer value (less than 10) and the corresponding character. There need to be some "conversion" - see later.
For your code:
digitalRead(pin1) returns an integer value being either 0 or 1
The purpose of the for loop is to generate a string that represents the value of the 8 pins. For instance like "10010110".
And finally the atoi call is to convert the string to an integer value. For instance converting the string "10010110" to the integer value 10010110 (decimal).
In order to construct the string from integer values that are 0 or 1, you need to calculate the integer value that represents the characters '0' and '1'. If you look-up ascii values, e.g. https://en.wikipedia.org/wiki/ASCII#Printable_characters , you can see that the character '0' has the decimal integer value 48 and the character '1' has the decimal integer value 49. So to go from integer value 0 to character '0' you need to add 48. Likewise - to go from integer value 1 to character '1' you need to add 48. So the code could be:
data[i] = array[i] + 48;
However, in C a character is considered an integer value. So instead of writing 48, C allows you to simply write the character that has the ascii-value 48. In other words:
data[i] = array[i] + 48;
is the same as
data[i] = array[i] + '0';
The compiler will automatically convert + '0' to + 48.
BTW: Make sure that data is defined as (at least) a 9 character array and that data[8] is already zero. Like char data[9] = {0};
That said... if array and data isn't used in other places, it seems a strange and complex way to calculate input. An alternative could be:
input = 0;
input = 10 * input + digitalRead(pin1);
input = 10 * input + digitalRead(pin2);
input = 10 * input + digitalRead(pin3);
input = 10 * input + digitalRead(pin3); // pin3 twice in OPs code. typo??
input = 10 * input + digitalRead(pin4);
input = 10 * input + digitalRead(pin5);
input = 10 * input + digitalRead(pin6);
input = 10 * input + digitalRead(pin7);
and if the pins could be placed in an array the above could be placed in a simple and short for-loop
The code shown is silly. Why are (presumed) values of 0-1 being stored to a not-null-terminated array (NOT a string) then passed to a function to do this? :
unsigned char input = 0;
input = (input << 1) + digitalRead(pin1);
input = (input << 1) + digitalRead(pin2);
input = (input << 1) + digitalRead(pin3); // << THIS IS ORIGINAL OP CODE
input = (input << 1) + digitalRead(pin3); // << THIS IS ORIGINAL OP CODE
input = (input << 1) + digitalRead(pin4);
input = (input << 1) + digitalRead(pin5);
input = (input << 1) + digitalRead(pin6);
input = (input << 1) + digitalRead(pin7);
/* input's value now 0 to 11111111 (0-255) as an integer value. */
/* User assumes responsibility for LSB <=> MSB ordering of pins */

Array contains garbage values not input values

I am writing a basic program to compute the binary eq of a decimal value. I'm storing the individual bits or 0 and 1 values into an array so I can eventually reverse the array and print the accurate binary representation. However when I print the array contents to check if array has been properly filled I see garbage values, or 0 if arr[]={0}
My code
int main() {
int i = 0, j = 0, k, decimal, binary = 0, remainder, divider;
int bin[10];
printf("Enter decimal value");
scanf("%d", &decimal);
while ((decimal != 0) && (i < decimal)) {
remainder = decimal % 2;
decimal = decimal / 2;
bin[i] = remainder;
j++;
printf("%d", bin[i]);
}
printf("\n%d", j);
printf("\n%d", bin[0]);
printf("\n%d", bin[1]);
printf("\n%d", bin[2]);
printf("\n%d", bin[3]);
printf("%d", bin);
return 0;
}
.exe
enter image description here
If you are still having problems with the conversion, it may be helpful to consider a couple of points. First, you are over-thinking the conversion from decimal to binary. For any given integer value, the value is already stored in memory in binary.
For example, when you have the integer 10, the computer stores it as 1010 in memory. So for all practical purposes, all you need to do is read the memory for value and set your array values to 1 for each bit that is 1 and 0 for each bit that is 0. You can even go one better, since what you are most likely after is the binary representation of the number, there is no need to store the 1s and 0s as a full 4-byte integer value in bin, why not make bin a character array and store the characters '1' or '0' in the character array (which when nul-terminated) allows a simple printing of the binary representation as a string.
This provides several benefits. Rather than converting from base 10 to base 2 and the divisions and modulo calls required for the base conversion, you can simply shift decimal to the right by one and check whether the least-significant-bit is 0 or 1 and store the desired character '0' or '1' based on the results of a simple unary and operation.
For example, in you case with an integer, you can determine the number of bits required to represent any integer value in binary with sizeof (int) * CHAR_BIT (where CHAR_BIT is a constant provided in limits.h and specifies the number of bits in a character (e.g. byte)). For an integer you could use:
#include <stdio.h>
#include <limits.h> /* for CHAR_BIT */
#define NBITS sizeof(int) * CHAR_BIT /* constant for bits in int */
To store the character representations of the binary number (or you could store the integers 1, 0 if desired), you can simply declare a character array:
char bin[NBITS + 1] = ""; /* declare storage for NBITS + 1 char */
char *p = bin + NBITS; /* initialize to the nul-terminating char */
(initialized to all zero and the +1 to allow for the nul-terminating character to allow the array to be treated as a string when filled)
Next, as you have discovered, whether you perform the base conversion or shift and and the resulting order of the individual bit values will be in reverse order. To handle that, you can simply declare a pointer pointing to the last character in your array and fill the array with 1s and 0s from the back toward the front.
Here too the character array/string representation makes things easier. Having initialized your array to all zero, you can start writing to your array beginning at the next to last character and working from the end to the beginning will insure you have a nul-terminated string when done. Further, regardless of the number of bits that make up decimal, you are always left with a pointer to the start of the binary representation.
Depending on how you loop over each bit in decimal, you may need to handle the case where decimal = 0; separately. (since you loop while there are bits in decimal, the loop won't execute if decimal = 0;) A simple if can handle the case and your else can simply loop over all bits in decimal:
if (decimal == 0) /* handle decimal == 0 separately */
*--p = '0';
else /* loop shifting decimal right by one until 0 */
for (; decimal && p > bin; decimal >>= 1)
*--p = (decimal & 1) ? '1' : '0'; /* decrement p and set
* char to '1' or '0' */
(note: since p was pointing to the nul-terminating character, you must decrement p with the pre-decrement operator (e.g. --p) before dereferencing and assigning the character or value)
All that remains is outputting your binary representation, and if done as above, it is a simple printf ("%s\n", p);. Putting all the pieces together, you could do something like the following:
#include <stdio.h>
#include <limits.h> /* for CHAR_BIT */
#define NBITS sizeof(int) * CHAR_BIT /* constant for bits in int */
int main (void) {
int decimal = 0;
char bin[NBITS + 1] = ""; /* declare storage for NBITS + 1 char */
char *p = bin + NBITS; /* initialize to the nul-terminating char */
printf ("enter a integer value: "); /* prompt for input */
if (scanf ("%d", &decimal) != 1) { /* validate ALL user input */
fputs ("error: invalid input.\n", stderr);
return 1;
}
if (decimal == 0) /* handle decimal == 0 separately */
*--p = '0';
else /* loop shifting decimal right by one until 0 */
for (; decimal && p > bin; decimal >>= 1)
*--p = (decimal & 1) ? '1' : '0'; /* decrement p and set
* char to '1' or '0' */
printf ("binary: %s\n", p); /* output the binary string */
return 0;
}
(note: the comment on validating ALL user input -- especially when using the scanf family of functions. Otherwise you can easily stray off into Undefined Behavior on an accidental entry of something that doesn't begin with a digit)
Example Use/Output
$ ./bin/int2bin
enter a integer value: 0
binary: 0
$ ./bin/int2bin
enter a integer value: 2
binary: 10
$ ./bin/int2bin
enter a integer value: 15
binary: 1111
Two's-complement of negative values:
$ ./bin/int2bin
enter a integer value: -15
binary: 11111111111111111111111111110001
Look things over and let me know if you have any questions, or if you really need bin to be an array of int. Having an integer array holding the individual bit values doesn't make a whole lot of sense, but if that is what you have to do, I'm happy to help.

Circular buffer increment using alternate method

I am not able to understand how does the last statement increments the pointer.Can somebody explain me with few examples?
The code, as shown:
aptr = (aptr + 1) & (void *)(BUFFERSIZE - 1);
// |________| incremented here
Since it is a circular buffer AND the buffer size is a power of 2, then the & is an easy and fast way to roll over by simply masking. Assuming that the BUFFERSIZE is 256, then:
num & (256 - 1) == num % 256
num & (0x100 - 1) == num % 0x100
num & (0x0ff) == num % 0x100
When the number is not a power of 2, then you can't use the masking technique:
num & (257 - 1) != num % 257
num & (0x101 - 1) != num % 0x101
num & 0x100 != num % 0x101
The (void *) allows the compiler to choose an appropriate width for the BUFFERSIZE constant based on your pointer width... although it is generally best to know - and use! - the width before a statement like this.
I added the hex notation so to make more clear why the & results in an emulated rollover event. Note that 0xff is binary 0x11111111, so the AND operation is simply masking off the upper bits.
2 problems with this approach.
A) Using a pointer with a bit-wise operation is not portable code. #Ilja Everilä
char *aptr;
// error: invalid operands to binary & (have 'char *' and 'void *')
// The following increments the index: (not really)
// aptr = (aptr + 1) & (void *)(BUFFERSIZE-1);
B) With compilers that support the non-standard math on a void * akin to a char *, the math is wrong if aptr point to an object wider than char and BUFFERSIZE is the number of elements in the buffer and not the byte-size. Of course this depends on how the non-standard complier implements some_type * & void *. Why bother to unnecessarily code to use some implementation specific behavior?
Instead use i % BUFFERSIZE. This portable approach works when BUFFERSIZE is a power-of-2 and well as when it is not. When a compiler sees i % power-of-2 and i is some unsigned type, then the same code is certainly emitted as i & (power-of-2 - 1).
For compilers that do not recognize this optimization, then one should consider a better compiler.
#define BUFFERSIZE 256
int main(void) {
char buf[BUFFERSIZE];
// pointer solution
char *aptr = buf;
aptr = &buf[(aptr - buf + 1) % BUFFERSIZE];
// index solution
size_t index = 0;
index = (index + 1) % BUFFERSIZE;
}

Placing '0' and '1' character in C string

I've recently begun working with C again (haven't touched it since my first couple semesters of school) and have been dealing with strings.
Currently, I'm writing a function that will convert an integer into its binary representation in the form of a string.
Here is the code I have to do this:
#include <stdio.h>
float power(int, int); //My version of the pow() function from math.h
char* itob(int);
int main ()
{
int x = 63;
const char * bin_x = itob(x);
printf("x = %d (%s)",x,bin_x);
return 0;
}
char* itob(int a){
static char bin[100];
int i;
for(i=0;((int) power(2,i) < a);i++){
bin[i] = (int)((a & ((int) power(2,i))) >> i);
}
bin[i] = '\0';
return (char*)&bin;
}
The issue I'm having is that the result of the binary operations on a I'm storing into an element of bin[] seems to be '\001' or '\000' as opposed to simply '1' or '0'. Because of this, when I printf() the result in main(), the output looks like a missing character box or if there is a 0 (if x=62 instead of 63) this is interpreted as an end of string character '\0'.
Am I storing these elements into my string incorrectly?
Yes, you are storing it incorrectly. You are storing either a 0 or a 1, but you need to store its encoding instead.
Try to replace this line:
bin[i] = (int)((a & ((int) power(2,i))) >> i);
With:
bin[i] = (int)((a & ((int) power(2,i))) >> i) ? '1' : '0';
And you can simply return bin;, there is no need neither for the cast, nor for the use of the address of operator.
Do not use pow for powers of 2, that's very inefficient, just a shift is enough. Your program wastes lots of time converting between int and float, and another tens of hundreds of cycles for the power while shifting generally takes only 1 cycle (or a little more depending on architecture). And no need to cast to int, any type shorter or equal to int will be automatically promoted to int
bin[i] = a & (1 << i) ? '1' : '0'; // or:
bin[i] = (a >> i) & 1 ? '1' : '0';
Much cleaner, shorter and faster. Another way if branching results in bad performance
bin[i] = ((a >> i) & 1) + '0';

Parsing string toother data types in C

If I read the contents of the buffer into a string, how do i parse it in C?
lets say, I wish to parse a string in the following format:
store first 16 bits in an integer,
store next 32 bits in another integer,
store remaining string data as hex.
Basically you want something like the following (don't forget validations)
int first = (text[0] << CHAR_BIT) + text[1];
int second = (text[2] << (CHAR_BIT * 3)) +
(text[3] << (CHAR_BIT * 2)) +
(text[4] << CHAR_BIT) +
text[5];
char *rest = text + 6;
Assumptions:
int1 & int2 integers are the same endian as in the buffer.
s alignment may not meet int needs.
#include <stdint.h>
void codeara_parse(const char *s, int16_t *int1, int32_t *int2, int8_t **rest) {
memcpy(int1, &s[0] , sizeof *int1);
memcpy(int2, &s[sizeof *int1], sizeof *int2);
*rest = &s[sizeof *int1 + sizeof *int2];
}
Otherwise OP needs to specify the endian-ness of the buffer.

Resources