ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

msp430实现串口计算器

2021-06-08 16:02:19  阅读:202  来源: 互联网

标签:index SP 串口 sp 栈顶 运算符 num 计算器 msp430


工程下载链接:https://download.csdn.net/download/qq_45467083/12100424

本次实验实现了基于串口通信的表达式解析与计算功能,如下图所示,向单片机输入表达式:9*9*8 +9/3*6-3*8 * (1 * 5+4 * (2-2)+5)/(3-1 * 9)=;(空格会自动忽略); 返回计算结果:706,等等。在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
实验配置了一个波特率为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);
        }
    }
}


· 关注公众号【技术斋】,发现更多精彩!

标签:index,SP,串口,sp,栈顶,运算符,num,计算器,msp430
来源: https://blog.51cto.com/u_15262460/2883012

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有