欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

msp430实现串口计算器

程序员文章站 2022-06-09 19:36:35
...

工程下载链接:

本次实验实现了基于串口通信的表达式解析与计算功能,如下图所示,向单片机输入表达式:9*9*8 +9/3*6-3*8 * (1 * 5+4 * (2-2)+5)/(3-1 * 9)=;(空格会自动忽略); 返回计算结果:706,等等。msp430实现串口计算器
msp430实现串口计算器msp430实现串口计算器
msp430实现串口计算器
实验配置了一个波特率为115200的串口UART,在接受缓存满和发送缓存空的时候都会产生中断。在接受中断中调用oneCharProcess(revChar_temp);处理接受字符,在发送中断中发送待发送字符串。

中断服务程序如下:

/* ======== USCI A0/B0 TX Interrupt Handler Generation ======== */
#pragma vector = USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void){
    switch(__even_in_range(UCA1IV,4)){//user guide:36.4.14 UCAxIV Register
        case 0:break;
        case 2://接受数据
            revChar_temp = UCA1RXBUF;
            oneCharProcess(revChar_temp);
            break;                   //vector 2 : RXIFG
        case 4://发送数据
            if(sendstr[str_index] != '\0'){
                UCA1TXBUF = sendstr[str_index++];
            }else{
                str_index = 0;
            }
            break;                    //vector 4 : TXIFG
        default: break;
    }
}

在这里我们将用到如下变量作为表达式计算的中间变量缓存,这个和计算的算法相关,使用了两个栈,一个存储运算数,一个存储运算符:

int num[20] = {0};//运算数栈
int num_index = -1;//运算数栈栈顶指针
u8 sp[20] = {0};//运算符栈
int sp_index = -1;//运算符栈栈顶指针

在这个程序中我们封装了如下函数:

//使用的函数声明

//运算符优先级:数值越小优先级越高
u8 getPriority(u8 oneChar);

//中断处理函数,一次处理一个字符
void oneCharProcess(u8 oneChar);

/*
 * 字符解析函数
 * 说明:若输入字符0~9,返回数字0~9,其他返回-1
 * 返回值:
 *       0~9:数字字符解析为数字
 *       -1:四则运算符和括号和=
 *       -2:其他
 */
int analysis_char(u8 oneChar0);

/*
 * 发送最终结果
 * 参数:num 最终结果数字
 */
void sendResult(int num);

//b char0 a = ?
int calculate(char char0, int a, int b);

在我们看中断处理函数之前,我们先要简要讲解一下算法:

除了括号和等号之外,四则运算符本质上都是二元运算符,换言之运算数的数目是固定的,顺序也是固定的。因此我们使用两个栈,一个存储运算数,一个存储运算符。那么一个运算符必然代表着两个运算数,所以运算符堆栈里面的元素个数代表了运算数的读写次数。而由于栈先进后出,因此确保了二元运算数的顺序。

现在描述算法如下:

首先设置运算符优先级如下:
( > * > / > - > + > ) > =
计算时,
1 从左往右扫描表达式,
  • 如果SP栈空,则遇到运算符即入栈,此时如果NUM栈空,则在NUM栈补零入栈;
  • 如果遇到(,(入SP栈; 如果遇到数字即入NUM栈;
  • 如果遇到当前运算符优先级高于SP栈顶运算符,则运算符入SP栈;
  • 如果遇到当前运算符优先级低于或等于SP栈顶运算符,且SP栈顶运算符不是(。则依次弹出一个SP栈顶元素,并弹出两个NUM栈元素进行二元运算,将结果再入NUM栈。重复此过程直到运算符的优先级大于SP栈顶运算符优先级;
  • 如果遇到),则依次弹出一个SP栈顶元素,并弹出两个NUM栈元素进行二元运算,将结果再入NUM栈。重复此过程直到遇到(。然后弹出(,将其丢弃。
2 扫描结束后,即遇到=,则循环弹出依次弹出一个SP栈顶元素,并弹出两个NUM栈元素进行二元运算,将结果再入NUM栈。重复此过程直到SP栈空,此时弹出NUM栈顶元素即为最终结果。

具体代码如下:

//中断处理函数,一次处理一个字符
void oneCharProcess(u8 oneChar){
    int analysisChar = analysis_char(oneChar);//遇到操作数时,将其压入num
    if(analysisChar != -1 && analysisChar != -2){
        num_push(analysisChar);
    }else if(analysisChar == -1){
        if(oneChar=='='){//所有SP出栈,最后的计算结果在num栈中
            char temp1 = sp_pop();
            while(temp1 != 0){
                num_push(calculate(temp1, num_pop(), num_pop()));
                temp1 = sp_pop();
            }
            sendResult(num_pop());
        }else if((sp_index==-1) && (num_index==-1) && (oneChar == '-')){//第一个运算数是负数情况
            sp_push(oneChar);
            num_push(0);
        }else if((sp_index==-1) || (oneChar=='(') || (getPriority(oneChar)<getPriority(sp[sp_index]))){//三种情况下直接入SP栈①SP为空②运算符为‘(’③运算符优先级比SP栈顶运算符的高;
            sp_push(oneChar);
        }else if(oneChar==')'){//如果右括号“)”,则依次弹出SP栈顶的运算符,并压入num,直到遇到左括号为止,此时将这一对括号丢弃;
            char temp1 = sp_pop();
            while(temp1!='('){
                num_push(calculate(temp1, num_pop(), num_pop()));
                temp1 = sp_pop();//最后一次丢弃(
            }
        }else if((getPriority(oneChar)>=getPriority(sp[sp_index])) && (sp[sp_index]!='(')){//若运算符优先级小于或等于SP栈顶运算符的优先级,且栈顶运算符不是(,则依次弹出SP栈顶元素,直到运算符的优先级大于SP栈顶运算符优先级;
            while((getPriority(oneChar)>=getPriority(sp[sp_index])) && (sp[sp_index]!='(')){
                num_push(calculate(sp[sp_index], num_pop(), num_pop()));
                sp_pop();//移出使用过的运算符
            }
            sp_push(oneChar);
        }else{
            sp_push(oneChar);
        }
    }
}
相关标签: tiva、msp430