Question
To achieve the basic calculator functionality, individual characters need to be read from the UART. These characters will be received in ASCII format. (Hint: Lookup
To achieve the basic calculator functionality, individual characters need to be read from the UART. These characters will be received in ASCII format. (Hint: Lookup at an ASCII table for reference!) The individual ASCII characters need to be converted into a numeric value to support the math operations. In ASCII formatting, digits are represented by the number+0x30. For example the decimal number 1976 will come in as 0x31, 0x39, 0x37, 0x36. To convert the separate ASCII characters to a single value, the ASCII offset (0x30) needs to be removed and the individual values need to be weighted by its decimal place and summed. The number 1976 can be thought of as: 1 * 1000 + 9 * 100 + 7 * 10 + 6 = 1976 This method can be coded directly but an alternative way to approach the solution is to use a loop like the one depicted in Figure 42. In this method, the value is built up as digits are entered and the loop is terminated when an ASCII value that is not a digit is entered. Page | 62 Figure 42 - GetNum Block Diagram The algorithm for the GetNum routine can be thought of as: ((((0 * 10 + 1) * 10 + 9) * 10 + 7) * 10 + 6) = 1976 GetNum can be called twice and the two returned numbers can be added. Then the result needs to be displayed. For display on the serial terminal, the result needs to be converter back to individual ASCII characters representing each digit. For example, the value 76543 would be displayed as ASCII characters 0x37, 0x36, 0x35, 0x34 0x33. Two similar approaches can be taken to generate this output. For the first, the value is divided by subsequently smaller powers of ten (e.g. 10000, 1000, 100, 10, 1). The quotient from the division yields the digit to be converted to ASCII (add 0x30) for output and the remainder from the division yields the next value to be divided. myNum = 0 myChar = char_in() Is myChar between 0x30 and 0x39 myNum = myNum * 10 + myChar- 0x30 No Yes GetNum return myNum Page | 63 76543 / 10000 = Q: 7, R: 6543, Output Q + 0x30 = 0x37 6543 / 1000 = Q: 6, R: 543, Output Q + 0x30 = 0x36 543 / 100 = Q: 5, R: 43, Output Q + 0x30 = 0x35 43 / 10 = Q: 4, R: 3, Output Q + 0x30 = 0x34 3 / 1 = Q: 3, R: 0, Output Q + 0x30 = 0x33 Note that this method requires setting the initial divisor equal to or larger than the power of largest value to be outputted. If it is larger than the value, leading zeros will be outputted. This can be avoided by either sizing the initial divisor appropriately for the value being outputted or by suppressing the leading zeros until a non-zero digit comes out. 543 / 10000 = Q: 0, R: 543, Output Q + 0x30 = 0x30 543 / 1000 = Q: 0, R: 543, Output Q + 0x30 = 0x30 543 / 100 = Q: 5, R: 43, Output Q + 0x30 = 0x35 43 / 10 = Q: 4, R: 3, Output Q + 0x30 = 0x34 3 / 1 = Q: 3, R: 0, Output Q + 0x30 = 0x33 An alternative way to output the result is to always divide by 10, the remainder yields the digit to be converted to ASCII for output and the quotient gives the next value to be divided. The process stops once the quotient equals zero. Note the values come out in reverse order and need to be stored until the division is complete and the results can be output in reverse order. 76543 / 10 = Q: 7654, R: 3, Output R + 0x30 = 0x33 7654 / 10 = Q: 765, R: 4, Output R + 0x30 = 0x34 765 / 10 = Q: 76, R: 5, Output R + 0x30 = 0x35 76 / 10 = Q: 7, R: 6, Output R + 0x30 = 0x36 7 / 10 = Q: 0, R: 7, Output R + 0x30 = 0x37 Note that this technique has the benefit of inherently suppressing any leading zeros. Page | 64 Either of the methods requires the use of C instructions to get the quotient and remainder. The quotient is returned by the division operator (/) and the remainder is returned by the modulus operator (%). quotient = dividend / divisor; remainder = dividend % divisor;
C Language and no use of libraries allowed!!
Provide code that will return a negative result using the ascii format provided above. Examples: 10-1=9
20-23=-3
9999-9999=0
0-9999=-9999
This is my current code:
#include
extern void asm_main(void);
extern void UART0Init(void);
extern unsigned char char_in(void);
extern void char_out(unsigned char);
int op =0; //operation value +/-
int getNum() {
unsigned char myChar;
int myNum = 0;
int temp = 0;
while(1){
myChar = char_in();
if (myChar == 0x2B) { //user enters the + sign 0x2B = + in ASCII
op =1; //make operand true
break;
}
else if(myChar == 0x2D) { //user enters -
op=0; //make operand false
break;
}
else if(myChar == 0x3D) { //user enters =
break;
}
else if (myChar >= 0x30 && myChar <= 0x39) //if the character actually turns into an integer
{
temp = (int)(myChar - 0x30);
myNum = myNum * 10;
myNum = myNum + temp; //you read it as an integer and not as a character
}
char_out(myChar); //outputting the +/- to show
}
char_out(myChar);
return myNum;
}
int main (void) {
UART0Init();
while(1){
int answer = 0; //the output of the function
int output[5] = {0x30,0x30,0x30,0x30,0x30};
int firstVal = getNum(); //enter the first value
int secondVal = getNum(); //enter the second value
int r = 0; //remainder
int n = 4;
int m = 0;
int x = 0;
if (op == 1){answer = firstVal + secondVal;}
else {answer = firstVal - secondVal;}
while(n>=0){
r = answer % 10;
answer = answer / 10;
output[n] = r + 0x30;
n--;
}
while(x<5){
if (output[x] == 0x30){x++;}
else{
m = x;
break;}
}
while (m<5){
char_out(output[m]);
m++;
}
char_out(0x0A);
char_out(0x0D);
}
}
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started