找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3691|回复: 2
打印 上一主题 下一主题
收起左侧

51单片机计算器的制作

[复制链接]
跳转到指定楼层
楼主


  1. #include <reg51.h>

  2. #include <math.h>

  3. #define uchar unsigned char

  4. #define uint unsigned int

  5. //---------定义引脚--------------------

  6. bit clr=0;

  7. bit ok=0;

  8. bit xiaoshu=0;

  9. bit jiego=0;

  10. bit first_1=1;

  11. bit first_2=1;

  12. sbit dout = P3^2;

  13. sbit load = P2^0;

  14. sbit din = P2^1;

  15. sbit dclk = P2^2;

  16. sbit beer=P0^1;

  17. sbit LCD1602_RS=P2^3;

  18. sbit LCD1602_RW=P2^4;

  19. sbit LCD1602_E=P2^5;

  20. //---------定义变量--------------------

  21. uchar ch451_key=0xff;

  22. uchar yun_sign;

  23. uchar xiabiao=0;

  24. uchar tab[32];

  25. uchar tab1[]={"welcome to use!"};

  26. uchar tab2[]={" make by JunRu!"};

  27. uchar tab3[]={"ERR0R"};

  28. float opr_1=0,opr_temp=0,end=0,a;

  29. //---------声明函数--------------------

  30. void ch451_init(void); //CH451初始化

  31. void ch451_write(uint command);//写命令或数据到ch451

  32. uchar ch451_read(void); //读按键值

  33. uchar get_char(void);

  34. void LCD_init(void);//初始化;

  35. void delay(unsigned int k);//延时程序

  36. void LCD_inter_command(unsigned char command);//写入控制字

  37. void LCD_inter_dat(unsigned char dat);//写入要显示的数据

  38. void set_xy(unsigned char x,unsigned char y);//找地址

  39. void write(unsigned char date);//写入字符

  40. void lcdbusy();//查忙时

  41. void display(void);

  42. void spec(void);

  43. void get_end(void);

  44. void hun_he(uchar n);

  45. //-------- 主函数----------------------

  46. void main()

  47. {

  48. uchar i;

  49. LCD_init();//LCD初始化;

  50. ch451_init();//CH451初始化

  51. EA = 1;//打开中断

  52. LCD_inter_command(0x01);//清屏

  53. for(i=0;i<=14;i++)

  54. {

  55. LCD_inter_dat(tab1[i]);

  56. beer=0;

  57. delay(4000);//延时

  58. beer=1;

  59. }

  60. LCD_inter_command(0xc0);//从第二行开始显示

  61. for(i=0;i<=14;i++)

  62. {

  63. LCD_inter_dat(tab2[i]);

  64. beer=0;

  65. delay(4000);//延时

  66. beer=1;

  67. }

  68. delay(0xffff);

  69. delay(0xffff);

  70. LCD_inter_command(0x01);

  71. while(1)

  72. {

  73. if(ok)

  74. {

  75. display();

  76. ok=0;clr=1;

  77. }

  78. }

  79. }

  80. //----------子函数--------------------

  81. void hun_he(uchar n)

  82. {int j;

  83. switch(n)

  84. {

  85. case '+':opr_temp=opr_temp+opr_1;break;

  86. case '-':opr_temp=opr_temp-opr_1;break;

  87. case '*':opr_temp=opr_temp*opr_1;break;

  88. case '/':

  89. {

  90. if(a==0)//减数为零显错

  91. { LCD_inter_command(0xc0);

  92. for(j=0;j<=4;j++)

  93. {

  94. LCD_inter_dat(tab3[j]);

  95. beer=0;

  96. delay(4000);//延时

  97. beer=1;

  98. }

  99. }

  100. else

  101. {opr_temp=opr_temp/opr_1;}

  102. break;

  103. }

  104. default:break;}

  105. }

  106. void ch451_init(void)//CH451初始化

  107. {

  108. EX0 = 1;

  109. din = 0;

  110. din = 1;

  111. ch451_write(0x403); //开显示

  112. ch451_write(0x580); //BCD译码方式

  113. }

  114. void ch451_write(uint command)//写命令或数据到ch451

  115. { uchar i;

  116. EX0 = 0;

  117. load = 0;

  118. for(i=0;i<12;i++)

  119. {

  120. din = command&1;

  121. dclk = 0;

  122. command>>=1;

  123. dclk = 1;

  124. }

  125. load = 1;

  126. EX0 = 1;

  127. }

  128. uchar ch451_read(void)//读

  129. 按键值

  130. { uchar key=0x07;

  131. uchar i;

  132. EX0=0;

  133. load = 0;

  134. for(i=0;i<4;i++) //将0111读入

  135. {

  136. din = key &1;

  137. dclk = 0;

  138. key>>=1;

  139. dclk =1;

  140. }

  141. load = 1;

  142. key = 0;

  143. for(i=0;i<7;i++) //从CH451读出按键值

  144. {

  145. key<<=1;

  146. key|= dout;

  147. dclk =0;

  148. dclk =1;

  149. }

  150. EX0 =1;

  151. return key;

  152. }

  153. void EX0_ISR(void)interrupt 0 //中断程序

  154. {

  155. uchar temp;

  156. ch451_key=ch451_read(); //将读出的按键值赋给变量

  157. spec();

  158. if(clr) {LCD_inter_command(0x01);clr=0;}

  159. temp=get_char();

  160. if(temp){tab[xiabiao++]=temp; LCD_inter_dat(temp);}

  161. if(xiabiao>=16)LCD_inter_command(0xc0);//若大于16,则从第2行开始显示

  162. if(ok) get_end();

  163. beer=0;

  164. delay(3000);

  165. beer=1;

  166. }

  167. uchar get_char(void)

  168. {

  169. uchar dis=0;

  170. uint temp=0,temp1=0;

  171. switch(ch451_key)

  172. {

  173. case 0x40:dis='1';break;

  174. case 0x41:dis='2';break;

  175. case 0x42:dis='3';break;

  176. case 0x48:dis='4';break;

  177. case 0x49:dis='5';break;

  178. case 0x4A:dis='6';break;

  179. case 0x50:dis='7';break;

  180. case 0x51:dis='8';break;

  181. case 0x52:dis='9';break;

  182. case 0x58:dis='0';break;

  183. case 0x43:dis='+';break;

  184. case 0x4B:dis='-';break;

  185. case 0x53:dis='x';break;

  186. case 0x5B:dis='/';break;

  187. case 0x44:dis='!';break;

  188. case 0x5A:dis='=';

  189. ok=1; //遇到“=”,开始运算

  190. break;

  191. case 0x59:dis='.';break; //小数点

  192. case 0x5C: //删除键

  193. LCD_inter_command(0x01);

  194. xiabiao=0;

  195. break;

  196. default: break;

  197. }

  198. return dis;

  199. }

  200. void spec(void) //特殊功能键

  201. {

  202. switch(ch451_key)

  203. {

  204. case 0x4C:LCD_inter_command(0x10);{if(xiabiao>0)xiabiao-=1;}break; //左移

  205. case 0x54:LCD_inter_command(0x14);{xiabiao+=1;}break; //右移

  206. default:break;

  207. }

  208. }

  209. void delay(unsigned int k)//延时程序

  210. {

  211. while (k--);

  212. }

  213. void LCD_inter_command(unsigned char command)//写入控制字

  214. {

  215. delay(5000);

  216. LCD1602_RS=0;

  217. LCD1602_RW=0;

  218. LCD1602_E=1;

  219. P1=command;

  220. LCD1602_E=0;

  221. lcdbusy();

  222. }

  223. void LCD_init(void)//初始化;

  224. {delay(5000);

  225. LCD_inter_command(0x01);//清屏

  226. delay(5000);

  227. LCD_inter_command(0x38);//设置为8位的数据接口,两行显示,5、7点字符

  228. delay(5000);

  229. LCD_inter_command(0x0E);//显示打开,光标开并闪烁

  230. delay(5000);

  231. }

  232. void LCD_inter_dat(unsigned char dat)//写入要显示的数据

  233. {

  234. delay(5000);

  235. LCD1602_RS=1;

  236. LCD1602_RW=0;

  237. LCD1602_E=1;

  238. P1=dat;

  239. LCD1602_E=0;

  240. lcdbusy();

  241. }

  242. void lcdbusy()//查忙

  243. {

  244. P1=0xFF;

  245. LCD1602_RS=0;

  246. LCD1602_RW=1;

  247. LCD1602_E=1;

  248. while((P1&0x80)==1);

  249. }

  250. void display(void) //转化在LCD上显示计算结果

  251. {

  252. int temp=end; //浮点数

  253. int i;

  254. uint xiao_temp;

  255. uint xx; //浮点数的整数部分

  256. if (end>-32769&&end<32768)

  257. {

  258. xx=fabs(end);

  259. xiao_temp=(fabs(end)-xx)*1000;//取出浮点数的小数部分

  260. LCD_inter_command(0xc0);

  261. if(end<0) LCD_inter_dat('-'

  262. );beer=0;delay(4000); beer=1;//判断是否为负数,若是则显示负号

  263. if(xx>9999) LCD_inter_dat((xx/10000)%10+'0'); beer=0;delay(4000);beer=1;

  264. if(xx>999) LCD_inter_dat((xx/1000)%10+'0');beer=0;delay(4000);beer=1; //在LCD上显示千位的数

  265. if(xx>99)LCD_inter_dat((xx/100)%10+'0'); beer=0;delay(4000);beer=1;//百位

  266. if(xx>9)LCD_inter_dat((xx/10)%10+'0');beer=0;delay(4000); beer=1;//十位

  267. LCD_inter_dat(xx%10+'0');beer=0;delay(4000); beer=1;//个位

  268. if(xiao_temp!=0) //显示小数部分

  269. {

  270. LCD_inter_dat('.');beer=0;delay(4000);beer=1;

  271. LCD_inter_dat((xiao_temp/100)%10+'0');beer=0;delay(4000);beer=1;

  272. LCD_inter_dat((xiao_temp/10)%10+'0');beer=0;delay(4000);beer=1;

  273. LCD_inter_dat(xiao_temp%10+'0');beer=0;delay(4000);beer=1;

  274. }

  275. }

  276. else {LCD_inter_command(0xc0);//从第二行开始显示

  277. for(i=0;i<=4;i++)

  278. { LCD_inter_dat(tab3[i]);

  279. beer=0;

  280. delay(4000);//延时

  281. beer=1;

  282. }

  283. }

  284. }

  285. void get_end(void)//计算子程序

  286. { float xiaoshu=1;

  287. uchar fu_flag=0;

  288. uchar xiao_flag=0;

  289. uchar lianji_sign;

  290. uchar i=0;

  291. uchar j;

  292. uchar n;//正负标记符

  293. while(i<=xiabiao)

  294. {

  295. while(tab[i]<=0x39&&tab[i]>=0x30)

  296. {

  297. n=0;

  298. opr_1*=10;

  299. opr_1+=tab[i++]-0x30;

  300. n='+';

  301. }

  302. switch(tab[i])

  303. {

  304. case '.': xiao_flag=1;break;//遇到小数点跳到“if(xiao_flag)”里

  305. case '!': fu_flag=1;break;

  306. case '+': xiaoshu=1;yun_sign='+';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);opr_1=0;lianji_sign='+'; break;

  307. case '-': xiaoshu=1;yun_sign='-';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);opr_1=0;lianji_sign='-'; break;

  308. case 'x': xiaoshu=1;yun_sign='x';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);opr_1=0;lianji_sign='*';break;

  309. case '/': xiaoshu=1;yun_sign='/';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);a=opr_1;opr_1=0;lianji_sign='/';break;

  310. case '=':

  311. switch(yun_sign)//进行运算

  312. {

  313. case '+':end=opr_temp+opr_1;break;

  314. case '-':end=opr_temp-opr_1;break;

  315. case 'x':end=opr_temp*opr_1;break;

  316. case '/':{

  317. if(a==0)//减数为零显错

  318. { LCD_inter_command(0xc0);

  319. for(j=0;j<=4;j++)

  320. {

  321. LCD_inter_dat(tab3[j]);

  322. beer=0;

  323. delay(4000);//延时

  324. beer=1;

  325. }

  326. }

  327. else

  328. {end=opr_temp/opr_1;}

  329. break;

  330. }

  331. default:break;

  332. }

  333. ok=1;//开始进行显示,标志位置1

  334. xiabiao=0;//小数的标志位清零

  335. break;

  336. default:break;

  337. }

  338. i++;

  339. if(xiao_flag)//表示小数

  340. {

  341. while(tab[i]<=0x39&&tab[i]>=0x30)

  342. {

  343. xiaoshu*=0.1;

  344. switch(n)

  345. {

  346. case '+': opr_1=opr_1+(tab[i++]-0x30)*xiaoshu;break;

  347. case '-': opr_1=opr_1-(tab[i++]-0x30)*xiaosh

  348. u; break ;

  349. default:break; }

  350. xiao_flag=0;

  351. }

  352. }

  353. if(fu_flag)

  354. {

  355. while(tab[i]<=0x39&&tab[i]>=0x30)

  356. {

  357. n=0;

  358. opr_1=-opr_1*10;

  359. opr_1=-(opr_1+(tab[i++]-0x30));

  360. n='-';

  361. fu_flag=0;

  362. }

  363. }

  364. }

  365. opr_1=0;

  366. opr_temp=0;

  367. xiabiao=0;

  368. xiaoshu=1;

  369. }
复制代码
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:82765 发表于 2017-3-17 14:50 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

板凳
ID:130231 发表于 2017-3-17 15:02 | 只看该作者
不错哦
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表