可以用语音来实现加减乘除之类计算 并显示到1602上面
单片机源程序如下:
- /*
- 接盘按键说明:
- --------------------------------------------------
- | 1 | 2 | 3 | + |
- - - - - - - - - - - - - -
- | 4 | 5 | 6 | - |
- - - - - - - - - - - - - -
- | 7 | 8 | 9 | * |
- - - - - - - - - - - - - -
- | C | 0 | = | / |
- --------------------------------------------------*/
- #include<reg51.h>
- #define uint unsigned int
- #define uchar unsigned char
- #define XTAL 12000000 //CPU晶振频率
- #define baudrate 9600 //通信波特率
- //--------LCD1602-------------------
- //P00-07==== D0-7
- sbit rs=P1^5; //指令or数据 2.6
- sbit wela=P1^4; //读or写 2.5
- sbit lcden=P1^6; //使能信号 2.7
- sbit feng=P1^0; //蜂鸣器
- //--------LCD1602-------------------
- //--------KEY-----------------------
- //P1口
- //--------KEY-----------------------
- uchar code table[]= " ";
- unsigned char data_a,data_b; //计算结果
- unsigned char data_c;
- unsigned char num1; //第一个数
- unsigned char num2; //第二个数
- unsigned char count; //一个起识别作用的变量
- unsigned char yusuanfu; //加减乘除等运算符
- uchar dispaly[10]; //显示缓冲
- //************************************************************************/
- // 描述: 延时t us函数
- //************************************************************************/
- void LCD_Delay_us(unsigned int t)
- {
- while(t--); //t=0,退出
- }
- //************************************************************************/
- // 描述: 延时t ms函数
- //************************************************************************/
- void LCD_Delay_ms(unsigned int t)
- {
- unsigned int i,j;
- for(i=0;i<t;i++) //执行t次循环
- for(j=0;j<113;j++) //执行113次循环
- ;
- }
- //************************************************************************/
- // 描述: 1602液晶写指令
- //************************************************************************/
- void write_com(uchar com) //1602液晶写指令
- {
- rs=0; //写指令
- lcden=0; //使能1602
- P2=com; //写入指令com
- LCD_Delay_ms(1); //延时1ms
- lcden=1; //使能1602
- LCD_Delay_ms(2); //延时2ms
- lcden=0; //使能1602
- }
- //************************************************************************/
- // 描述:1602液晶写数据
- //************************************************************************/
- void write_date(uchar date) //1602液晶写数据
- {
- rs=1; //写数据
- lcden=0; //使能1602
- P2=date; //写入数据date
- LCD_Delay_ms(1); //延时1ms
- lcden=1; //使能1602
- LCD_Delay_ms(2); //延时2ms
- lcden=0; //使能1602
- }
- //************************************************************************/
- // 描述:指定x,y写入字符函数
- //************************************************************************/
- void W_lcd(unsigned char x,unsigned char y,unsigned char Data)
- {
- if (y == 0){write_com(0x80 + x);} //第一行
- else{write_com(0xc0 + x);} //第二行
- write_date( Data); //写入数据
- }
- //指定x,y写入字符串函数
- void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
- {
- if (y == 0){write_com(0x80 + x);} //第一行
- else{write_com(0xC0 + x);} //第二行
- while (*s) //
- {write_date( *s); s++;} //写入数据
- }
- //************************************************************************/
- // 描述:初始化液晶,及画面初始化
- //************************************************************************/
- void init_lcd(void) //初始化液晶,及画面初始化
- {
- wela=0; //写液晶
- lcden=0; //使能1602
- write_com(0x38); //8 位总线,双行显示,5X7 的点阵字符
- LCD_Delay_us(100); //延时100us
- write_com(0x0c); //开显示,无光标,光标不闪烁
- write_com(0x06); //光标右移动
- write_com(0x01); //清屏
- write_com(0x80); //DDRAM 地址归0
- }
- //************************************************************************/
- // 描述: 反转法键盘扫描
- //************************************************************************/
- short keycheckdown() /* 反转法键盘扫描 */
- {
- short temp1,temp2,temp,a=0xff;
- P1=0xf0; /* 输入行值(或列值) */
- LCD_Delay_ms(20); /* 延时 */
- temp1=P1; /* 读列值(或行值) */
- P1=0xff;
- LCD_Delay_ms(20); /* 延时 */
- P1=0x0f; /* 输入列值(或行值) */
- LCD_Delay_ms(20); /* 延时 */
- temp2=P1; /* 读行值(或列值) */
- P1=0xff;
- temp=(temp1&0xf0)|(temp2&0xf); /* 将两次读入数据组合 */
- switch(temp) /* 通过读入数据组合判断按键位置 */
- {
- case 0x77 :a=0x0d;break; // 按键/ 77
- case 0xb7 :a=0x0e; break;// 按键= 7b
- case 0xd7 :a=0; break;// 按键0 7d
- case 0xe7 :a=0x0f; break;// 按键CE 7e
- case 0x7b :a=0x0c;break;// 按键* b7
- case 0xbb :a=0x9;break; // 按键9 bb
- case 0xdb :a=0x8;break; // 按键8 bd
- case 0xeb :a=0x7;break; // 按键7 be
- case 0x7d :a=0x0b;break;// 按键- d7
- case 0xbd :a=0x6;break; // 按键6 db
- case 0xdd :a=0x5;break; // 按键5 dd
- case 0xed :a=0x4;break; // 按键4 de
-
- case 0x7e :a=0x0a; break;// 按键+ e7
- case 0xbe :a=3;break;// 按键3 eb
- case 0xde :a=2;break;// 按键2 ed
- case 0xee :a=1;break;// 按键1 ee
- default :a=0xff;
- }
- return a; /* 返回按键值 */
- }
- void display_a() //显示运算结果
- {
- dispaly[3]=data_a%10000/1000; //千
- dispaly[2]=data_a%1000/100; //百
- dispaly[1]=data_a%100/10; //十
- dispaly[0]=data_a%10; //个
- write_com(0x80+7); //显示运算结果在7的位置上
- if(data_a>999){ write_date('0'+dispaly[3]);} //显示千位
- if(data_a>99){ write_date('0'+dispaly[2]);} //显示百位
- if(data_a>9){ write_date('0'+dispaly[1]);} //显示十位
- write_date('0'+dispaly[0]); //显示个位
- }
- void display_num1() //显示数据a
- {
- dispaly[3]=num1%10000/1000; //千
- dispaly[2]=num1%1000/100; //百
- dispaly[1]=num1%100/10; //十
- dispaly[0]=num1%10; //个
- write_com(0x80+0); //显示第一个数在0的位置上
- if(num1>999){ write_date('0'+dispaly[3]);} //显示千位
- if(num1>99){ write_date('0'+dispaly[2]);} //显示百位
- if(num1>9){ write_date('0'+dispaly[1]);} //显示十位
- write_date('0'+dispaly[0]); //显示个位
- }
- void display_yusuanfu() //显示运算符
- {
- switch(yusuanfu)
- {
- case 219: write_com(0x80+1); write_date('+'); break; //写屏“+? 在1的位置上
- case 221: write_com(0x80+1); write_date('-'); break; //写屏“-” 在1的位置上
- case 136: write_com(0x80+1); write_date('*'); break; //写屏“*” 在1的位置上
- case 223: write_com(0x80+1); write_date('/'); break; //写屏“/” 在1的位置上
- }
- }
- void display_num2() //显示第二个数
- {
- dispaly[3]=num2%10000/1000; //千
- dispaly[2]=num2%1000/100; //百
- dispaly[1]=num2%100/10; //十
- dispaly[0]=num2%10; //个
- write_com(0x80+2); //显示第二个数在2的位置上
- if(num1>999){ write_date('0'+dispaly[3]);} //显示千位
- if(num1>99){ write_date('0'+dispaly[2]);} //显示百位
- if(num1>9){ write_date('0'+dispaly[1]);} //显示十位
- write_date('0'+dispaly[0]); //显示个位
- }
-
- void display_c(x) //此函数在此工程中没有用到,仅提供一个思路
- {
- if(data_c<100000000&&data_c>-1)//溢出时显示错误
- {
- dispaly[8]=data_c%1000000000/100000000; //万万
- dispaly[7]=data_c%100000000/10000000; //千万
- dispaly[6]=data_c%10000000/1000000; //百万
- dispaly[5]=data_c%1000000/100000; //十万
- dispaly[4]=data_c%100000/10000; //万
- dispaly[3]=data_c%10000/1000; //千
- dispaly[2]=data_c%1000/100; //百
- dispaly[1]=data_c%100/10; //十
- dispaly[0]=data_c%10; //个
- write_com(0x80+6+0x40); //第一行
- if(x==4)
- {
- if(data_c>99999999) { write_date('0'+dispaly[8]);} //显示万万
- if(data_c>9999999) { write_date('0'+dispaly[7]);} //千万
- if(data_c>999999) { write_date('0'+dispaly[6]);} //百万
- if(data_c>99999) { write_date('0'+dispaly[5]);} //十万
- if(data_b!=0) {
- write_date('0'+dispaly[4]); //万
- write_date('.');
- write_date('0'+dispaly[3]); //千
- write_date('0'+dispaly[2]); //百
- write_date('0'+dispaly[1]); //十
- write_date('0'+dispaly[0]); //个
- }
- }
- else{
- if(data_c>99999999) { write_date('0'+dispaly[8]);} //显示万万
- if(data_c>9999999) { write_date('0'+dispaly[7]);} //千万
- if(data_c>999999) { write_date('0'+dispaly[6]);} //百万
- if(data_c>99999) { write_date('0'+dispaly[5]);} //十万
- if(data_c>9999) { write_date('0'+dispaly[4]);} //万
- if(data_c>999) { write_date('0'+dispaly[3]);} //千
- if(data_c>99) { write_date('0'+dispaly[2]);} //百
- if(data_c>9) { write_date('0'+dispaly[1]);} //十
- write_date('0'+dispaly[0]); //个
- }
- }
- else //溢出时显示错误
- {
- write_com(0x80+11+0x40); //第一行
- write_date('E'); //显示 E
- write_date('r'); //显示R
- write_date('r'); //显示R
- write_date('o'); //显示O
- write_date('r'); //显示E
- }
- }
- //加减乘除运算
- void eql(uchar x) //此函数在此工程中没有用到 提供一个思路
- {
- switch(x) /*功能键选择*/
- {
- case 1:data_c=data_a+data_b;break; //加 /* + S=1 */ /* 数值转换函数 */
- case 2:if(data_a>=data_b){data_c=data_a-data_b;} /* - S=2 *///减
- else{data_c=data_b-data_a;W_lcd(5,1,'-');} //负数符号
- break;
- case 3:data_c=(data_a*data_b);break; /* * S=3 *///乘
- case 4:if(data_b==0){LCD_Write_String(0,1,"Error ! ");}else{data_c=(data_a*10000)/data_b;}break; /* / S=4 *///除//溢出时显示错误
- case 0:break;
- }
- }
- void UART_Init(void) // 串口初始化
- {
- SCON = 0x50;
- TMOD = 0x20;
- TH1 = 0xfd;
- TL1 = 0xfd;
- EA = 1;
- ES = 1;
- TR1 = 1;
- }
- void INT_UartRcv(void) interrupt 4 //串口中断函数
- {
- unsigned char Rcv = 0;
- if(RI)
- {
- RI = 0;
- Rcv = SBUF; //串口读数据
- if((Rcv>9||Rcv<0)&&(count==1)) //count=1,表明输入的是运算符
- {
- yusuanfu = Rcv; //将读回的数据存入yunsuanfu这个变量
- switch(yusuanfu) //判断读回的运算符,并将他们显示在屏上1的位置
- {
- case 75 : write_com(0x80+1); write_date('+'); LCD_Delay_ms(1000); break;
- case 77 : write_com(0x80+1); write_date('-'); break;
- case 248 : write_com(0x80+1); write_date('*'); break;
- case 79 : write_com(0x80+1); write_date('/'); break;
- }
- count++;
- }
- else if(count==2) //count=2表明第二个数据来了
- {
- num2= Rcv-2;
- display_num2();
- count++;
- }
-
- else if(count==3) //count=3表明该计算结果了
- {
- switch(yusuanfu) //判断运算符是哪个,并执行相应的计算
- {
- case 75: data_a = num1 +num2-110; break; //检测到”+“号,让两个数据相加
- case 77: data_a = num1 -num2-146; break; //检测到”-“号,让两个数据相减
- case 248: data_a = ((num2-110) *num1); break; //检测到”x“号,让两个数据相乘
- case 79: data_a = num1 /(num2-110); break; //检测到”/“号,让两个数据相除
- }
- display_a(); //显示运算结果
- LCD_Delay_ms(1000); //延时,让显示的结果延时一下
- count=0; //计算完一遍,让变量清0
- LCD_Write_String(0,0,table);LCD_Write_String(0,1,table);W_lcd(0,0,'0'); //清屏,让屏显示0,表示已准备好计算下一次
- }
- else if (count==0) //count=0,表示一次计算刚刚开始
- {
- num1 = Rcv-112; // 第一个数据发回来的码值减去112就是想要得到的数据
- display_num1(); // 显示第一个数
- count++; //变量加1
- feng=1; //蜂鸣器响一下,此语句是调试阶段用到的
- LCD_Delay_ms(1000);
- feng=0; //关掉蜂鸣器
- }
- }
- }
- void main()
- {
- UART_Init(); //串口初始化
- init_lcd(); //1602液晶初始化
- while(1) //什么也不做,等待执行中断函数
- {
- ;
- }
- }
复制代码
所有资料51hei提供下载:
1-计算器程序.rar
(51.11 KB, 下载次数: 10)
|