一个基于AVR单片机的计算器程序Word下载.docx

上传人:b****3 文档编号:18482582 上传时间:2022-12-17 格式:DOCX 页数:16 大小:19.44KB
下载 相关 举报
一个基于AVR单片机的计算器程序Word下载.docx_第1页
第1页 / 共16页
一个基于AVR单片机的计算器程序Word下载.docx_第2页
第2页 / 共16页
一个基于AVR单片机的计算器程序Word下载.docx_第3页
第3页 / 共16页
一个基于AVR单片机的计算器程序Word下载.docx_第4页
第4页 / 共16页
一个基于AVR单片机的计算器程序Word下载.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

一个基于AVR单片机的计算器程序Word下载.docx

《一个基于AVR单片机的计算器程序Word下载.docx》由会员分享,可在线阅读,更多相关《一个基于AVR单片机的计算器程序Word下载.docx(16页珍藏版)》请在冰豆网上搜索。

一个基于AVR单片机的计算器程序Word下载.docx

ucharfuhao;

//符号标志

uchardeflag1;

//小数点标志

uchardeflag2;

ucharoverflag;

//数值溢出标志

ucharallowflag=1;

//符号允许标志,用于禁止连续两个符号的输出

ucharnegative;

//负数标志,当是负数要作相应的处理

longtemp3,temp4;

//计算的数值得数用其中一个变量存储即可,不用再浪费内存开辟其他变量

floattemp1,temp2;

constunsignedcharkey_table[16]=

{

7,8,9,10,

4,5,6,11,

1,2,3,12,

50,0,21,13

};

//键盘编码可根据具体情况而设定

voidport_init();

//端口初始化

voiddevice_init();

//夜晶初始化

voidtime_init();

//定时器初始化

voidwright_com(ucharcom);

//夜晶写指令函数

voidwright_data(uchardate);

//夜晶写数据函数

voidlcd_handle(uchartemp);

//夜晶显示处理,该显示什么,不该显示什么

ucharkeyscan();

//键盘扫描

voidjudgechar(uchart);

//判断字符为符号还是数字

voiddecimal(ucharde);

//判断是不是小数点,只能出现两个小数点,且不能连续出现

voidreset();

//复位函数

voidcalculate(void);

//对数值进行计算

voidresult(longvalue);

//显示结果

voidflow_clew();

//溢出提示函数

intmain()

{

port_init();

device_init();

time_init();

//初始化

while

(1)

{

flow_clew();

//溢出提示函数,一旦扫描到出错就会显示错误

}

}

/***********中断服务程序***********/

volatileunsignedinti;

//中断服务程序中要使用全局变量,且要加volatile

SIGNAL(SIG_OVERFLOW0)

TCNT0=205;

//重装初值

i=keyscan();

//返回键盘扫描值

if(i!

=No_key)//确认有按键按下

if(i==50)

{

wright_com(0x01);

//清显示

_delay_ms(10);

//延时等待清屏指令完成

wright_com(0x80);

wright_data('

0'

);

//重新显示0

reset();

flag=1;

//标志起动

if(i<

50&

&

flag)//条件为已经启动而且输入的是有效字符

{

judgechar(i);

//判断是不是操作符,要是则要作相应的处理

decimal(i);

//判断是不是小数点输入,要是则要作相应的处理

lcd_handle(i);

//对输入的数据进行合理存储并加以显示

}

if(i==21)//按下了等号键

wright_data('

='

//显示等号

calculate();

//计算数值

result(temp1);

//拆分数值后显示结果

/*******定时器初始化*********/

voidtime_init()

TCNT0=205;

//初值255-205=5050微秒

TIMSK|=(1<

TOIE0);

sei();

//开启总中断

TCCR0|=(1<

CS01);

//8分频8M/8=1M

/****端口初始化****/

voidport_init()

DI=0xff;

DDRA|=BIT(0);

DDRA|=BIT

(1);

//输出状态

lone_key_ddr&

=~BIT(0);

lone_key_port|=BIT(0);

//独立键盘接口设置为输入,并打开上拉电阻

DDRD=0;

//全部设为输入,有个上拉电阻,可以输入高电平

DDRB=0xff;

/*******夜晶初始化********/

voiddevice_init()

en_0;

//使能端拉低

wright_com(0x38);

//初始化格式

wright_com(0x0c);

//0x0e打开光标0x0c不显示光标0x0e光标不闪,0x0f光标闪

wright_com(0x01);

wright_com(0x80);

for(i=0;

i<

17;

i++)

wright_data(table1[i]);

_delay_ms(20);

/******夜晶写入指令的函数***********/

voidwright_com(ucharcom)

rs_0;

//低电平时写指令

DI=com;

_delay_ms

(1);

en_1;

/******夜晶写入数据的函数**********/

voidwright_data(uchardata)

rs_1;

//高电平时写数据

DI=data;

/**********4x4矩阵键盘及一个独立键盘的扫描函数*********/

ucharkeyscan(void)

unsignedchartemp,temp1,key,row,column;

key_ddr=0x0f;

//高四位输入列线/低四位输出到行线

key_port=0xf0;

//高四位打开上拉电阻/低四位输出低电平上拉电阻会把电平拉高

if(lone_key_pin==0)

_delay_ms(5);

//延时消抖

_delay_ms(90);

//等待松手

return(31);

}

if((key_pin&

0xF0)!

=0xF0)//作初检查有否键按下,没有,就返回如果列线不全为1,可能有键按下

_delay_ms(5);

//延时去抖动

=0xF0)//确认有按键按下

_delay_ms(1000);

//延时等待松手

for(row=0,key_port=0b11111110;

row<

4;

row++)

for(column=0,temp=0b11101111;

column<

column++)//设置列线初始值1110

0xF0)==(temp&

0xF0))//输入列线,查看这列有否键按下

key=4*row+column;

//键编码=4*行输入值+列扫描值

key=key_table[key];

//键盘编码转换键值

return(key);

temp<

=1;

//列线左移1位

key_port=((key_port<

1)|0x01);

//行线扫描值左移1位,扫描下一行

return(No_key);

/****对键盘扫描返回值进行判断是不是为符号*******/

voidjudgechar(uchart)//用带参数的函数可以减少键盘扫描次数

if(t>

9&

t<

14&

allowflag)//符号范围

fuhao=1;

//标志为符号,为后面的程序作决断算完后再将其清零

allowflag=0;

//禁止下一个符号的输入,只能输入一个符号

if(t==10)//输入的是减号

/'

}

if(t==11)//输入的是减号

*'

if(t==12)//输入的是减号

-'

if(t==13)//输入的是减号

+'

sym=t;

//把符号的编号保存下来,方便以后调用

/*****夜晶显示处理,该显示什么,不该显示什么*****/

voidlcd_handle(uchartemp)//用带参数的函数可以减少键盘扫描次数

if(temp>

=0&

temp<

10)//以下处理仅对数字有效

if(fuhao)//表示已经写了符号了,提示是输入第二个数了

if(deflag2)//判断为小数部分

{

if(dd<

=3)

{

wright_data('

+temp);

//输入一个数就显示一个数

b1[++dd]=temp;

//保存小数点后面的数字

}

else

overflag=1;

}

else//整数部分

if(bb<

=5)//条件为位数还不足六位

b[++bb]=temp;

//输入的是第二个数保存的是整数部分

else

overflag=1;

//数值溢出

else//输入的是第一个数

if(deflag1)//判断为小数部分

if(cc<

a1[++cc]=temp;

if(aa<

if(aa==0)

{

wright_com(0x80);

//从每个位置起写

}

a[++aa]=temp;

//保存的是整数部分

/*********重新初始化的函数*********/

voidreset()//按下复位键后变量要全部变到初始状态

uchark;

for(k=1;

k<

7;

k++)

a[k]=0;

b[k]=0;

overflag=0;

//溢出标志复位

flag=0;

//启动标志复位

allowflag=1;

//符号允许标志置位

fuhao=0;

//符号已使用标志复位

aa=0;

bb=0;

//元素个数清零

sym=0;

//符号的编码置0;

/***********对数值进行计算,a[],b[]存储的是数,sym操作符编号***********/

voidcalculate(void)

switch(aa)//根据位数代入对应的公式

case1:

temp1=a[aa];

break;

case2:

temp1=a[2]+a[1]*10;

case3:

temp1=a[3]+a[2]*10+a[1]*100;

case4:

temp1=a[4]+a[3]*10+a[2]*100+a[1]*1000;

case5:

temp1=a[5]+a[4]*10+a[3]*100+a[2]*1000+a[1]*10000;

case6:

temp1=a[6]+a[5]*10+a[4]*100+a[3]*1000+a[2]*10000+a[1]*100000;

switch(bb)//根据位数代入对应的公式

temp2=b[bb];

temp2=b[2]+b[1]*10;

temp2=b[3]+b[2]*10+b[1]*100;

temp2=b[4]+b[3]*10+b[2]*100+b[1]*1000;

temp2=b[5]+b[4]*10+b[3]*100+b[2]*1000+b[1]*10000;

temp2=b[6]+b[5]*10+b[4]*100+b[3]*1000+b[2]*10000+b[1]*100000;

temp3=a1[1]*1000+a1[2]*100+a1[3]*10+a1[4];

temp4=b1[1]*1000+b1[2]*100+b1[3]*10+b1[4];

//小数部分放大10000倍

temp1=temp1+temp3/10000.0;

temp2=temp2+temp4/10000.0;

//整数与小数的结合

switch(sym)//判断输入的是哪个操作符并作相应的计算

case10:

temp1=temp1/temp2;

case11:

temp1=temp1*temp2;

case12:

temp1=temp1-temp2;

case13:

temp1=temp1+temp2;

if(temp1>

999999.9999)//数据溢出要作处理

overflag=1;

temp1*=10000;

//变成整数处理,方便

if(temp1<

0)

temp1=-temp1;

//变负为正

negative=1;

//负数标志

/*****把结果数值拆分显示*********/

voidresult(longvalue)

ucharwe[10];

ucharj;

we[10]=value/1000000000;

we[9]=value/100000000%10;

we[8]=value/10000000%10;

we[7]=value/1000000%10;

we[6]=value/100000%10;

we[5]=value/10000%10;

we[4]=value/1000%10;

we[3]=value/100%10;

we[2]=value/10%10;

we[1]=value%10;

if(negative)

wright_data('

//要是得到的结果是个负数得先输入个负号

for(k=10;

k>

5;

k--)//只能十位以上的数字进行检测,个位的不管是不是零都要显示

if(we[k]!

=0)

//确定第一个非零数字,只显示有效数字

}

for(j=k;

j>

0;

j--)//从第一个非零数字开始显示

if(j==4)

.'

//小数部分前面要加个小数点

+we[j]);

_delay_ms

(2);

/**********溢出提示函数*******************/

voidflow_clew()

ucharnum;

if(overflag)

wright_com(0x80+0x40+5);

for(num=0;

num<

6;

num++)

wright_data(table2[num]);

_delay_ms

(2);

/***********判断是不是小数点**************/

voiddecimal(ucharde)

if(de==31)

if(fuhao==0&

deflag1==0)//条件为正在输入的是第一个数且此数之前还没有小数点出现

//显示小数点

deflag1=1;

//不能再有下一个小数点了,置位可以防止有第二个小数点

if(fuhao&

deflag2==0)//条件为正在输入的是第一个数且此数之前还没有小数点出现

deflag2=1;

//不能再有下一个小数点了,置位可以防止有第二个小数点

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1