单片机设计 按键顺序控制加减计数(1602 液晶显示) 程序
51单片机控制lcd1602实现计算器

//利用51单片机控制LCD1602,实现加减乘除运算#include<reg52.h>#define uint unsigned int#define uchar unsigned char#define DATE_IO P0//P0口并行传输数据(LCD1602的数据端接P0口)sbit RS=P1^0;//LCD1602寄存器选择端sbit E=P1^2; //使能信号端sbit RW=P1^1;//读写控制端sbit deng=P1^3;//结果sbit shuzi11=P3^2;//前面的数字加1(因为我的按键是与P3口相连的)sbit shuzi22=P3^7; //后面的数字加1sbit jia=P3^3;//加号sbit jian=P3^4;//减号sbit cheng=P3^5;//乘号sbit chu=P3^6;//除号uint countqian=0,counthou=0;//数值uchar qian,bai,shi,ge,a=0;uchar code table1[]="0123456789";uchar code table2[]="+-*/";//**********************延时函数***************************************** void delay_us(unsigned int n){if(n==0)return ;while(--n);}void delay_ms(uint i){unsigned char a,b;for (a=1;a<i;a++)for(b=1;b;b++);}void delay(uint z){uint x,y;for(x=110;x>0;x--)for(y=z;y>0;y--);}//***********************************************************************//*********************控制LCD1602的函数*******************************void write_command(uchar come)//写指令函数{RS=0;//选择指令寄存器E=1;//由高电平跳变成低电平时,液晶执行命令DATE_IO=come;delay_us(5);E=0;RS=1;}void write_date(uchar date)//写数据函数{RS=1;//选择数据寄存器E=1;//由高电平跳变成低电平时,液晶执行命令DATE_IO=date;delay_us(5);E=0;RS=0;}//***************************************************************************** ***//**************************液晶初始化函数(基本上就是这个模式)*******************void init()//液晶初始化函数{RW=0;//低电平时进行写操作(高电平时进行读操作)E=0;write_command(0x38);//设置LCD两行显示,一个数据由5*7点阵表示,数据由8跟线传输delay_ms(5);write_command(0x01);//清除屏幕显示delay_ms(5);write_command(0x06);//设定输入方式,增量不移位delay_ms(5);write_command(0x0c);//开整体显示,关光标,不闪烁delay_ms(5);}//***************************************************************************** *****void jiayiqian()//前边数字加1计数函数{if(shuzi11==0)//如果前面加1的按键按下{delay(50);//消除抖动countqian=countqian+1;}if(countqian==999)//记到999归0countqian=0;}void jiayihou()//后边数字加1计数函数{if(shuzi22==0)//如果后面加1的按键按下{delay(50);//消除抖动counthou=counthou+1;}if(counthou==999)//记到999归0counthou=0;}void fuhao()//+,-,*,/运算号{if(jia==0)//如果加号按下{while(!jia);//等待按键的释放write_date(table2[0]);//显示'+'a=1;//加号按下的标志}if(jian==0)//如果减号按下{while(!jian);//等待按键的释放write_date(table2[1]);//显示'-'a=2;//减号按下的标志}if(cheng==0)//如果乘号按下{while(!cheng);//等待按键的释放write_date(table2[2]);//显示'*'a=3; //乘号按下的标志}if(chu==0)////如果除号按下{while(!chu);//等待按键的释放write_date(table2[3]);//显示'/'a=4;//除号按下的标志}}void chaiqian()//将前边各位数字拆开函数{bai=countqian/100;//求百位数字shi=countqian%100/10;//求十位数字ge=countqian%10;//求各位数字}void chaihou()//将后边各位数字拆开函数{bai=counthou/100;//求百位数字shi=counthou%100/10;//求十位数字ge=counthou%10;//求各位数字}void chaijiejia()//将相加结果各位数字拆开函数{qian=(countqian+counthou)/1000;//求千位数字bai=(countqian+counthou)%1000/100;//求百位数字shi=(countqian+counthou)%100/10;//求十位数字ge=(countqian+counthou)%10;//求各位数字}void chaijiejian()//将相减结果各位数字拆开函数{qian=(countqian-counthou)/1000;//求千位数字bai=(countqian-counthou)%1000/100;//求百位数字shi=(countqian-counthou)%100/10;//求十位数字ge=(countqian-counthou)%10;//求各位数字}void chaijiecheng()//将相乘结果各位数字拆开函数{qian=(countqian*counthou)/1000;//求千位数字bai=(countqian*counthou)%1000/100;//求百位数字shi=(countqian*counthou)%100/10;//求十位数字ge=(countqian*counthou)%10;//求各位数字}void chaijiechu()//将相除结果各位数字拆开函数(只取了模值){qian=(countqian/counthou)/1000;//求千位数字bai=(countqian/counthou)%1000/100;//求百位数字shi=(countqian/counthou)%100/10;//求十位数字ge=(countqian/counthou)%10;//求各位数字}void xianshiqian()//显示前边数字{write_command(0x80);//设置显示地址为LCD第一行,一旦首地址确定,显示完第一个数字后,光标会自动加1右移write_date(table1[bai]);//第一位显示百位write_date(table1[shi]); //第二位显示十位write_date(table1[ge]); //第三位显示个位fuhao();//显示运算号delay(50);//改变数值可以修改数字滚动的速度}void xianshihou()//显示后边数字{write_command(0x80+4);//设置显示地址为LCD第一行,一旦首地址确定,显示完第一个数字后,光标会自动加1右移write_date(table1[bai]);//第一位显示百位write_date(table1[shi]); //第二位显示十位write_date(table1[ge]); //第三位显示个位//delay(50);//改变数值可以修改数字滚动的速度}void xianshijie()//显示结果{write_command(0xc0);//设置显示地址为LCD第二行,一旦首地址确定,显示完第一个数字后,光标会自动加1右移write_date(table1[qian]);//第一位显示千位write_date(table1[bai]);//第二位显示百位write_date(table1[shi]); //第三位显示十位write_date(table1[ge]); //第四位显示个位//delay(50);//改变数值可以修改数字滚动的速度}void main()//主函数{init();//调用液晶初始化函数while(1){jiayiqian();//调用前边数字加1计数函数chaiqian();//调用将前边数字各位数字拆开函数xianshiqian();//显示前边数字jiayihou();//调用后边数字加1计数函数chaihou();//调用将后边数字各位数字拆开函数xianshihou();//显示后边数字if(deng==0)//控制显示结果的按键按下{if(a==1)//计算的是加法{chaijiejia();//将结果的各位数字拆分开xianshijie(); //显示结果}if(a==2)//计算的是减法{chaijiejian(); //将结果的各位数字拆分开xianshijie();//显示结果}if(a==3)//计算的是乘法{chaijiecheng();//将结果的各位数字拆分开xianshijie(); //显示结果}if(a==4) //计算的是除法{chaijiechu();//将结果的各位数字拆分开xianshijie(); //显示结果}}}}。
C8051F350单片机1602液晶显示程序

#include <C8051F350.h>#include <stdio.h>#include <math.h>//-----------------------------------------------------------------------------// 16-bit SFR Definitions for 'F35x//-----------------------------------------------------------------------------sfr16 TMR2RL = 0xCA; // Timer2 reload valuesfr16 TMR2 = 0xCC; // Timer2 countersfr16 ADC0DEC = 0x9A; // ADC0 Decimation Ratio Register//sfr16 ADC0 = 0xbd;//-----------------------------------------------------------------------------// Global CONSTANTS//-----------------------------------------------------------------------------#define SYSCLK 24500000 // SYSCLK frequency in Hz#define MDCLK 2457600 // Modulator clock in Hz (ideal is// (2.4576 MHz)#define OWR 960 // Desired Output Word Rate in Hz ADC0输出字速率,最大960 #define BAUDRATE 115200 // Baud rate of UART in bps#define uchar unsigned char#define uint unsigned int#define DataPort P0sbit LCM_EN=P1^0;sbit LCM_RS=P1^1;unsigned char D1,D2,D3,D4,D5,D6,D7,D8;//sbit LED = P0^7;unsigned int k;//-----------------------------------------------------------------------------// Function PROTOTYPES//-----------------------------------------------------------------------------void Oscillator_Init (void);void Port_Init (void);void UART0_Init (void);void ADC0_Init(void);void delay(int i);void WriteCommandLCM(uchar CMD);void WriteDataLCM(uchar dataW);void InitLcd();void lcd_write_char(uchar x,uchar y,uchar dataW) ;//-----------------------------------------------------------------------------// MAIN Routine//-----------------------------------------------------------------------------void main (void){PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer// enable)Oscillator_Init(); // Initialize system clockPort_Init(); // Initialize Crossbar and GPIO// UART0_Init(); // Initialize UART0 for printf'sInitLcd();ADC0_Init(); // Initialize ADC0AD0INT = 0;ADC0MD = 0x83; // Start continuous conversions EA = 1; // Enable global interruptswhile (1) { // Spin forever}}//-----------------------------------------------------------------------------// Initialization Subroutines//-----------------------------------------------------------------------------void delay(int i) //大概0.43ms{int j,k;for(j=0;j<i;j++)for(k=0;k<2000;k++);}void lcd_write_char(uchar x,uchar y,uchar dataWord) //y是行,x是列,都是从0开始计数{unsigned char add;if(y==0)add=0x80+x;elseadd=0xc0+x;WriteCommandLCM(add);WriteDataLCM(dataWord);}void WriteCommandLCM(uchar CMD){//delay(2);LCM_EN=0;LCM_RS=0;DataPort&=0xf0;// delay(2);DataPort|=(CMD&0xf0)>>4; delay(5);LCM_EN=1;delay(10);LCM_EN=0;delay(10);//CMD=CMD>>4;DataPort&=0xf0;// delay(2);DataPort|=(CMD&0x0f); delay(10);LCM_EN=1;delay(10);LCM_EN=0;}void WriteDataLCM(uchar dataW) // delay(2);LCM_EN=0;LCM_RS=1;// delay(2);DataPort&=0xf0;// delay(2);DataPort|=(dataW&0xf0)>>4; delay(2);LCM_EN=1;delay(5);LCM_EN=0;delay(5);// dataW=dataW>>4;DataPort&=0xf0;// delay(2);DataPort|=(dataW&0x0f);delay(2);LCM_EN=1;delay(5);LCM_EN=0;}void InitLcd(){delay(2000);WriteCommandLCM(0x28); //4位数据总线//delay(5);WriteCommandLCM(0x01); //清屏WriteCommandLCM(0x0C); //显示开及光标设置// WriteCommandLCM(0x0f);// delay(200);}//----------------------------------------------------------------------------- // Oscillator_Init//----------------------------------------------------------------------------- //// Return Value : None// Parameters : None//// This routine initializes the system clock to use the internal 24.5MHz// oscillator as its clock source. Also enables missing clock detector reset.////-----------------------------------------------------------------------------void Oscillator_Init (void){OSCICN = 0x83; // Configure internal oscillator for 配置内部振荡器// its lowest frequency RSTSRC = 0x04; // Enable missing clock detector}//-----------------------------------------------------------------------------// Port_Init//-----------------------------------------------------------------------------//// Return Value : None// Parameters : None////ThisfunctioninitializestheGPIO and the Crossbar 初始化GPI0和交叉开关//// Pinout://// P0.4 - UART TX (digital, push-pull)// P0.5 - UART RX (digital, open-drain)//// AIN0.2 - ADC0 input////-----------------------------------------------------------------------------void Port_Init (void){// XBR0 = 0x01; // UART0 SelectedXBR1 = 0x40; // Enable crossbar and weak pull-ups P0MDOUT |= 0xDf; // TX, LEDs = Push-pullP1MDOUT |=0x03;}//-----------------------------------------------------------------------------// UART0_Init//-----------------------------------------------------------------------------//// Return Value : None// Parameters : None//// Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1.////-----------------------------------------------------------------------------/*void delay(unsigned int time){unsigned int i;while(--time){for(i=0;i<125;i++);}}*//*void UART0_Init (void){SCON0 = 0x10; // SCON0: 8-bit variable bit rate 串口控制寄存器// level of STOP bit is ignored// RX enabled// ninth bits are zeros// clear RI0 and TI0 bits if (SYSCLK/BAUDRATE/2/256 < 1) { TH1 = -(SYSCLK/BAUDRATE/2);CKCON |= 0x08; // T1M = 1; SCA1:0 = xx} else if (SYSCLK/BAUDRATE/2/256 < 4) {TH1 = -(SYSCLK/BAUDRATE/2/4);CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01CKCON |= 0x01;} else if (SYSCLK/BAUDRATE/2/256 < 12) {TH1 = -(SYSCLK/BAUDRATE/2/12);CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00} else if (SYSCLK/BAUDRATE/2/256 < 48) {TH1 = -(SYSCLK/BAUDRATE/2/48);CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10CKCON |= 0x02;} else {while (1); // Error. Unsupported baud rate }TL1 = TH1; // Init Timer1 定时器1是用来确定有相同的波特率TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreloadTMOD |= 0x20;TR1 = 1; // START Timer1TI0 = 1; // Indicate TX0 ready}*///-----------------------------------------------------------------------------// ADC0_Init//-----------------------------------------------------------------------------//// Return Value : None// Parameters : None//// Initialize the ADC to use the temperature sensor. (non-differential)////-----------------------------------------------------------------------------void ADC0_Init (void){REF0CN |= 0x03; // Enable internal VrefADC0CN = 0x00; // Gain = 1, Unipolar mode 最后三位PGA增益=1,ADC控制寄存器ADC0CF = 0x00; // Interrupts upon SINC3 filter output ADC0配置寄存器,位4选择哪一个滤波器转换结束后使AD0INT中断标志置1,// and uses internal VREF 位2是VREF源选择位ADC0CLK = (SYSCLK/MDCLK)-1; // Generate MDCLK for modulator. 调制器时钟分频系数,由最佳调制器时钟频率反求系数// Ideally MDCLK = 2.4576MHz// Program decimation rate for desired OWRADC0DEC = ((unsigned long) MDCLK / (unsigned long) OWR / // ADC0抽取比寄存器,确定ADC输出字速率,由输出字速率反求抽取比(unsigned long) 128) - 1;ADC0BUF = 0x00; // Turn off Input BuffersADC0MUX = 0x08; // Select AIN0.2 模拟多路选择控制寄存器ADC0MD = 0x81; // Start internal calibration ADC0控制寄存器,校准和转换选择while(AD0CALC != 1); // Wait until calibration is completeEIE1 |= 0x08; // Enable ADC0 Interrupts 转换结束中断允许ADC0MD = 0x80; // Enable the ADC0 (IDLE Mode)}//-----------------------------------------------------------------------------// Interrupt Service Routines//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------// ADC0_ISR//-----------------------------------------------------------------------------//// This ISR prints the result to the UART. The ISR is called after each ADC // conversion.////-----------------------------------------------------------------------------void ADC0_ISR (void) interrupt 10{unsigned long ADC_OutputVal;static double accumulator = 0;// unsigned long int i;static unsigned int measurements = 0;static unsigned int number=0;// static unsigned long average;static unsigned int flag = 1;unsigned int result=0;while(!AD0INT);AD0INT = 0;// InitLcd();ADC_OutputVal=0x00000000;ADC_OutputVal = ADC0H;ADC_OutputVal <<= 16;ADC_OutputVal += (long)ADC0L + ((long)ADC0M << 8); //ADC_OutputVal=ADC_OutputVal*0.9992+10126; accumulator += ADC_OutputVal;measurements++;if( measurements== 1){number++;if(number==1){result = accumulator / measurements;/*D1=result/10000000+0x30;D2=(result%10000000)/1000000+0x30;D3=(result%1000000)/100000+0x30;D4=(result%100000)/10000+0x30;D5=(result%10000)/1000+0x30;D6=(result%1000)/100+0x30;D7=(result%100)/10+0x30;D8=(result%10)+0x30;*/number=0;/*D1=1;D2=2;D3=3;D4=4;D5=5;D6=6;D7=7;D8=8;*//* HighData=result>>8; // 串口发送数据LowData=result; a[0]=HighData & 0X0F;a[1]=LowData;for(i=0;i<2;i++){SBUF0=a[i];while(TI0==0){};TI0=0;}*/lcd_write_char(0,0,'A'); lcd_write_char(1,0,'D'); lcd_write_char(2,0,'C'); lcd_write_char(3,0,'0'); lcd_write_char(4,0,':'); lcd_write_char(0,1,'A'); lcd_write_char(1,1,'A'); lcd_write_char(2,1,'1'); lcd_write_char(3,1,'2'); lcd_write_char(4,1,'3'); lcd_write_char(5,1,'4'); lcd_write_char(6,1,'5'); lcd_write_char(7,1,'6');lcd_write_char(8,1,'7');lcd_write_char(9,1,'8');lcd_write_char(10,1,'B');lcd_write_char(11,1,'B');delay(1000);if (flag==1){//WriteCommandLCM(0x01);InitLcd();flag=0;}}measurements = 0;accumulator=0;/* if(number==200) //采集的个数受到accumulator的限制{ average=accumulator/number;//average=average*0.9992+10126;a[0] =average>>24;a[1] =average>>16;a[2] =average>>8;a[3] =average;for(i=1;i<4;i++){SBUF0=a[i]; // 发送完成,产生中断,需要软件清零while(TI0==0){};TI0=0;}accumulator=0;number=0;}*/}}//----------------------------------------------------------------------------- // End Of File//-----------------------------------------------------------------------------。
基于51单片机1602液晶显示简易计算器设计..

#include<reg52.h>#include<math.h>#define uint unsigned int#define uchar unsigned char#define PI 3.141592sbit RS = P2^0;sbit RW = P2^1;sbit EN = P2^2;sbit led=P2^4;sbit speek=P3^7;uchar table0[]={"Welcome to use"};uchar table1[]={"made by Ms. Li"};uchar table2[]={"error"};uchar count;void main(void){uchar error=0,i,first=0,dot1,dot2,dot1_num,dot2_num,minus1,minus2;//错误标志、第一次清屏标记、小数点标记以及小数点个数负号标记、负号个数uchar Sin,Cos,Tan,ln;uchar Key_num,last_key_num; //键号uchar flag=0,equal_flag;double num1=0,num2=0,num=0,result=0,save_result; //运算符、等于符//第一个数、第二个数、计算结果uchar first_num=0,Ans=0,second_num=0; InitLcd();EA=1;ET0=1;TMOD=0X01;TH0=(65536-500)/256;TL0=(65536-500)%256;write_com(0x80+0x40+15);write_Dat('0');write_com(0x80);while(1){while(key_scan()==0xff);TR0=1;if(first==0){first=1;write_com(0x01);}Key_num=key_scan();switch(key_scan()){case 1:if(last_key_num!=Key_num){write_Dat('l');write_Dat('n');ln=1;}break;case 2:if(last_key_num!=Key_num){write_Dat('s');write_Dat('i');write_Dat('n');Sin=1;}break;case 3:if(last_key_num!=Key_num){write_Dat('c');write_Dat('o');write_Dat('s');Cos=1;}break;case 4:if(last_key_num!=Key_num){write_Dat('t');write_Dat('a');write_Dat('n');Tan=1;}break;case 5:if(last_key_num!=Key_num){write_Dat('^');flag=5;}break;case 6:write_Dat('7');num=7;break; case 7:write_Dat('8');num=8;break; case 8:write_Dat('9');num=9;break; case 9:if(last_key_num!=Key_num){write_Dat('+');flag=1;}break;case 10:if(last_key_num!=Key_num){write_Dat('T');flag=6;}break;case 11:write_Dat('4');num=4;break; case 12:write_Dat('5');num=5;break; case 13:write_Dat('6');num=6;break; case 14:if(last_key_num!=Key_num){write_Dat('-');flag=2;}break;case 15:if(last_key_num!=Key_num){if(equal_flag==1){write_com(0x01);write_com(0x80);write_Dat('A');write_Dat('n');write_Dat('s');write_Dat('=');save_result=result;}else{if(Key_num!=1&&Key_num!=2&&Key_num!=3&&Key_num!=4&&Key_num!=22&&Key_num!=23 &&Key_num!=25){write_Dat('A');write_Dat('n');write_Dat('s');if(flag==0){num1=save_result;first_num=1;}else{num2=save_result;second_num=1;}}}}break;case 16:write_Dat('1');num=1;break;case 17:write_Dat('2');num=2;break;case 18:write_Dat('3');num=3;break;case 19:if(last_key_num!=Key_num){write_Dat('*');flag=3;}break;case 21:write_Dat('0');num=0;break;case 22:if(last_key_num!=Key_num){if(flag==0){minus1++;if(minus1==1){write_Dat('-');}}else{minus2++;if(minus2==1){write_Dat('-');}}} break;case 23:if(last_key_num!=Key_num){if(flag==0){dot1++;if(dot1==1){write_Dat('.');}}else{dot2++;if(dot2==1){write_Dat('.');}}} break;case 24:if(last_key_num!=Key_num){write_Dat('/');flag=4;}break;case 25:if(last_key_num!=Key_num){write_Dat('=');equal_flag=1;}break;}if(Key_num!=1&&Key_num!=2&&Key_num!=3&&Key_num!=4&&Key_num!=15&&Key_num!=22 &&Key_num!=23&&Key_num!=25)// 第一个数{if(flag==0){num1=num1*10+num;num=0;if(dot1!=0){dot1_num++;}first_num=1;}if(flag!=0){num2=num2*10+num;num=0;if(dot2!=0){dot2_num++;}second_num=1;}}if(equal_flag==1&&first_num==1){if(dot1!=0){num1=num1/pow(10,dot1_num);dot1=0;}if(dot2!=0){num2=num2/pow(10,dot2_num);dot2=0;}if(minus1!=0){num1=num1*(-1);}if(minus2!=0){num2=num2*(-1);}if(second_num!=0){switch(flag){case 1:result=num1+num2;break;case 2:result=num1-num2;break;case 3:result=num1*num2;break;case 4:if(num2!=0){result=num1/num2;}else{write_com(0x80+0x40+10);for(i=0;i<5;i++){write_Dat(table2[i]);}error=1;} break;case 5: result=pow(num1,num2);break;case 6: result=pow(num1,1/num2);break;}}else if(second_num==0&&Sin==0&&Cos==0&&Tan==0&&ln==0) result=num1;else if(second_num==0&&(Sin==1||Cos==1||Tan==1||ln==1)) {if(Sin==1)result=sin(num1/180*PI)+0.005;if(Cos==1)result=cos(num1/180*PI)+0.005;if(Tan==1)result=tan(num1/180*PI)+0.005;if(ln==1){if(num1>0)result=log(num1)+0.005;else{write_com(0x80+0x40+10);for(i=0;i<5;i++){write_Dat(table2[i]);}error=1;}}}if(error!=1)display(result);}// 清零if(Key_num==20){num1=num2=result=0;flag=equal_flag=0;error=0;first=0;dot1_num=dot2_num=0;minus1=0;minus2=0;first_num=0,second_num=0;Sin=Cos=Tan=ln=0;write_com(0x01);write_com(0x80+0x40+15);write_Dat('0');}last_key_num=Key_num;while(key_scan()!=0xff);}}void time0() interrupt 1{TH0=(65536-600)/256;TL0=(65536-600)%256;count++;speek=!speek;if(count>50){TR0=0;count=0;}}void delay(uint x){uchar y;while(x--)for(y=0;y<120;y++);}void write_com(unsigned char c) {RS=0;RW=0;EN=1;delay(5);P0=c;EN=0;}void write_Dat(unsigned char c) {RS=1;RW=0;EN=1;delay(5);P0=c;EN=0;}void InitLcd(){write_com(0x38); //display modewrite_com(0x06); // write_com(0x0c); // write_com(0x01); // } 显示光标挪动地点显示开及光标设置显示清屏uchar key_scan(){uchar key_num=0xff;uint temp;P3=0x03;P1=0xe0;temp=(P3<<8)|P1;if((temp&0x03e0)!=0x03e0){delay(10);if((temp&0x03e0)!=0x03e0){// 第一行P3=0x03;P1=0xfe;temp=(P3<<8)|P1;switch(temp){case 0x03de:key_num=1; break;case 0x03be:key_num=2; break;case 0x037e:key_num=3; break;case 0x02fe:key_num=4; break;case 0x01fe:key_num=5; break;}//第二行P3=0x03;P1=0xfd;temp=(P3<<8)|P1;switch(temp){case 0x03dd:key_num=6; break;case 0x03bd:key_num=7; break;case 0x037d:key_num=8; break;case 0x02fd:key_num=9; break;case 0x01fd:key_num=10; break;}//第三行P3=0x03;P1=0xfb;temp=(P3<<8)|P1;switch(temp){case 0x03db:key_num=11; break;case 0x03bb:key_num=12; break;case 0x037b:key_num=13; break;case 0x02fb:key_num=14; break;case 0x01fb:key_num=15; break;}//第四行P3=0x03;P1=0xf7;temp=(P3<<8)|P1;switch(temp){case 0x03d7:key_num=16; break;case 0x03b7:key_num=17; break;case 0x0377:key_num=18; break;case 0x02f7:key_num=19; break;case 0x01f7:key_num=20; break;}P3=0x03;//第五行P1=0xef;temp=(P3<<8)|P1;switch(temp){case 0x03cf:key_num=21; break;case 0x03af:key_num=22; break;case 0x036f:key_num=23; break;case 0x02ef:key_num=24; break;case 0x01ef:key_num=25; break;}}}return key_num;}void display(double Data){uchar xs=0,fs=0,i;if(Data<0){fs=1;Data=Data*(-1);}if(Data>(long)Data){xs=1;}if(Data<10)//0~9{if(xs==1){Data=Data*100;write_com(0x80+0x40+11);if(fs==1)write_Dat('-');elsewrite_Dat(' ');write_Dat((long)Data/100+'0');write_Dat('.');write_Dat((long)Data/10%10+'0');write_Dat((long)Data%10+'0');}else if(xs==0){write_com(0x80+0x40+14);if(fs==1)write_Dat('-');elsewrite_Dat(' ');write_Dat((long)Data+'0');}}else if(Data<100)//10~99{if(xs==1){Data=Data*100;write_com(0x80+0x40+10);if(fs==1)write_Dat('-');elsewrite_Dat(' ');write_Dat((long)Data/1000+'0');write_Dat((long)Data/100%10+'0');write_Dat('.');write_Dat((long)Data/10%10+'0');write_Dat((long)Data%10+'0');}else if(xs==0){write_com(0x80+0x40+13);if(fs==1)write_Dat('-');elsewrite_Dat(' ');write_Dat((long)Data/10+'0');write_Dat((long)Data%10+'0');}}else if(Data<1000)//100~999 {if(xs==1){Data=Data*100;write_com(0x80+0x40+9);if(fs==1)write_Dat('-');elsewrite_Dat(' ');write_Dat((long)Data/10000+'0');write_Dat((long)Data/1000%10 +'0');write_Dat((long)Data/100%10+'0');write_Dat('.');write_Dat((long)Data/10%10+'0');write_Dat((long)Data%10+'0');}else if(xs==0){write_com(0x80+0x40+12);if(fs==1)write_Dat('-');elsewrite_Dat(' ');write_Dat((long)Data/100+'0');write_Dat((long)Data/10%10+'0');write_Dat((long)Data%10+'0');}}else if(Data<10000)//1000~9999 {if(xs==1){Data=Data*100;write_com(0x80+0x40+8);if(fs==1)write_Dat('-');elsewrite_Dat(' ');write_Dat((long)Data/100000+'0');write_Dat((long)Data/10000%10+'0');write_Dat((long)Data/1000%10 +'0');write_Dat((long)Data/100%10+'0');write_Dat('.');write_Dat((long)Data/10%10+'0');write_Dat((long)Data%10+'0');}else if(xs==0){write_com(0x80+0x40+11);if(fs==1)write_Dat('-');elsewrite_Dat(' ');write_Dat((long)Data/1000+'0');write_Dat((long)Data/100%10+'0');write_Dat((long)Data/10%10+'0');write_Dat((long)Data%10+'0');}}else if(Data<100000)//10000~99999 {if(xs==1){Data=Data*100;write_com(0x80+0x40+7);if(fs==1)write_Dat('-');elsewrite_Dat(' ');write_Dat((long)Data/1000000+'0');write_Dat((long)Data/100000%10+'0');write_Dat((long)Data/10000%10+'0');write_Dat((long)Data/1000%10 +'0');write_Dat((long)Data/100%10+'0');write_Dat('.');write_Dat((long)Data/10%10+'0');write_Dat((long)Data%10+'0');}else if(xs==0){write_com(0x80+0x40+10);if(fs==1)write_Dat('-');elsewrite_Dat(' ');write_Dat((long)Data/10000+'0');write_Dat((long)Data/1000%10+'0');write_Dat((long)Data/100%10+'0');write_Dat((long)Data/10%10+'0');write_Dat((long)Data%10+'0');}}else if(Data<1000000) //100000~999999{if(xs==1){Data=Data*100;write_com(0x80+0x40+7);if(fs==1)write_Dat('-');elsewrite_Dat(' ');write_Dat((long)Data/10000000+'0');write_Dat((long)Data/1000000%10+'0');write_Dat((long)Data/100000%10+'0');write_Dat((long)Data/10000%10+'0');write_Dat((long)Data/1000%10 +'0');write_Dat((long)Data/100%10+'0');write_Dat('.');write_Dat((long)Data/100000%10+'0');write_Dat((long)Data/100000%10+'0');write_Dat((long)Data/10000%10+'0');write_Dat((long)Data/1000%10 +'0');write_Dat((long)Data/100%10+'0');}else if(xs==0){write_com(0x80+0x40+9);if(fs==1)write_Dat('-');elsewrite_Dat(' ');write_Dat((long)Data/100000+'0');write_Dat((long)Data/10000%10+'0');write_Dat((long)Data/1000%10+'0');write_Dat((long)Data/100%10+'0');write_Dat((long)Data/10%10+'0');write_Dat((long)Data%10+'0');}}else{write_com(0x80+0x40+10);for(i=0;i<5;i++){write_Dat(table2[i]);}}}。
51单片机控制1602LCD显示程序

LCD显示电路#include<reg51.h>sbit RS=P3^7; //寄存器选择位,将RS位定义为P2.0引脚sbit RW=P3^6; //读写选择位,将RW位定义为P2.1引脚sbit E=P2^7; //使能信号位,将E位定义为P2.2引脚sbit BF=P0^7; //忙碌标志位,将BF位定义为P0.7引脚#define Lcd_Data P0#include <string.h>#include<intrins.h> //包含_nop_()函数定义的头文件unsigned char code string1[ ]={0x77,0x75,0x20,0x79,0x61,0x6E,0x67,0x20,0x79,0x61,0x6E,0x67,0x20,0x20,0x20,0x20}; //第一行显示的字符void Lcd_delay1ms() // 函数功能:延时1ms//注:不同单片机不同晶振需要对此函数进行修改{ unsigned char i,j;for(i=0;i<90;i++)for(j=0;j<33;j++);}void Lcd_delay(unsigned int n) // 函数功能:延时若干毫秒,入口参数:n{ unsigned int i;for(i=0;i<n;i++)Lcd_delay1ms();}/*****************************************************函数功能:判断液晶模块的忙碌状态返回值:result。
result=1,忙碌;result=0,不忙***************************************************/bit Lcd_BusyTest(void)bit result;RS=0; //根据规定,RS为低电平,RW为高电平时,可以读状态RW=1;E=1; //E=1,才允许读写_nop_(); //空操作_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间result=BF; //将忙碌标志电平赋给resultE=0;return result;}/*****************************************************函数功能:将模式设置指令或显示地址写入液晶模块入口参数:dictate***************************************************/void Lcd_WriteCom (unsigned char dictate){ while(Lcd_BusyTest()==1); //如果忙就等待RS=0; //根据规定,RS和R/W同时为低电平时,可以写入指令RW=0;E=0; //E置低电平(写指令时就是让E从0到1发生正跳变,所以应先置ぜ? _nop_();_nop_(); //空操作两个机器周期,给硬件反应时间Lcd_Data=dictate; //将数据送入P0口,即写入指令或地址_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=1; //E置高电平_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令}/*****************************************************函数功能:指定字符显示的实际地址x入口参数:注:此函数已经加上了0x80,故只需写上实际地址就行***************************************************/void Lcd_WriteAddress(unsigned char x){ Lcd_WriteCom(x|0x80); //显示位置的确定方法规定为80H+地址码x/*****************************************************函数功能:将数据(字符的标准ASCII码)写入液晶模块入口参数:y(为字符常量)***************************************************/void Lcd_WriteData(unsigned char y){while(Lcd_BusyTest()==1);RS=1; //RS为高电平,RW为低电平时,可以写入数据RW=0;E=0; //E置低电平(写指令时就是让E从0到1发生正跳变所以应先置ぜ?Lcd_Data=y; //将数据送入P0口,即将数据写入液晶模块_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=1; //E置高电平_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令}/*****************************************************函数功能:对LCD的显示模式进行初始化设置***************************************************/void Lcd_Int(void){Lcd_delay(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间Lcd_WriteCom(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口Lcd_delay(5); //延时5msLcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);设置模式次写9// Lcd_WriteCom(0x38);Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x0C); //显示模式设置:显示开,有光标,光标闪烁Lcd_delay(5);Lcd_WriteCom(0x06); //显示模式设置:光标右移,字符不移Lcd_delay(5);Lcd_WriteCom(0x01); //清屏幕指令,将以前的显示内容清零Lcd_delay(5); }void hanying_show(void){unsigned char Lcd_i;Lcd_WriteCom(0x01);//清显示:清屏幕指令Lcd_delay(2);Lcd_WriteAddress(0x00); // 设置显示位置为最左侧Lcd_delay(2);Lcd_i=0;while(string1[Lcd_i]!='\0') //'\0'是数组结束标志需先将字符存入{Lcd_WriteData(string1[Lcd_i]); // 显示字符Lcd_i++;Lcd_delay(4);}}void main(){Lcd_Int(); //1602初始化while(1){hanying_show();}}。
51单片机计算器1602显示程序

delay_jsq(5);
if(P2!=0xfb)
{
if(P2!=0xfb)
{
temp=P2&0xf0;
switch(temp)
{
case 0xe0:num=8;
break;
case 0xd0:num=9;
break;
case 0xb0:num=10;
break;
case 0x70:num=11;
case 0x70:num=7;
break;
}
}
while(P2!=0xfd);
if(j!=0)
{
write_lcd1602(0x01,0);
delay(1);
j=0;
}
if(num==4||num==5||num==6&&num!=7)//如果按下的是'4','5'或'6'
{
if(flag1==0)//没有按过符号键
break;
}
}
}
}
void main()
{
ini_lcd1602();
while(1)
{
keyscan_4_4();
}
}
write_lcd1602(0x06,0);
delay(1);
write_lcd1602(0x01,0);
delay(1);
num_1=0;
i=0;
j=0;
a=0; //第一个参与运算的数
b=0; //第二个参与运算的数
c=0;
flag1=0; //flag1表示是否有符号键按下,
fuhao=0; // fuhao表征按下的是哪个符号
单片机设计_按键顺序控制加减计数(1602_液晶显示)_程序

#include<reg51.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned int#define LCD_IO P2sbit KK1 = P3^2; //按键输入;sbit KK2 = P3^3; //按键输入;sbit LCD_RS = P3^5;sbit LCD_RW = P3^6;sbit LCD_EN = P3^7;uchar code LCD_line1[] = " The Counter";int idata mydata=0;/************************************************************** * 名称: Delay_1ms()* 功能: 延时子程序,延时时间为1ms * x* 输入: x (延时一毫秒的个数)* 输出: 无***************************************************************/ void Delay_1ms(uint x){uchar i, j;for(i = 0; i < x; i++) for(j = 0; j <= 148; j++);}/************************************************************** * 名称: lcd_bz( )* 功能: 测试忙碌子程序* 输入: 无* 输出: result***************************************************************/ bit lcd_bz(){bit result;LCD_RS = 0;LCD_RW = 0;LCD_EN = 0;_nop_();_nop_();_nop_();_nop_();result=(bit)(P3&0x80);LCD_EN = 0;return result;}/*************************************************************** 名称: W_LCD_Com( )* 功能: 写指令子程序* 输入: com* 输出: 无***************************************************************/void W_LCD_Com(uchar com){while(lcd_bz());LCD_RS = 0; LCD_RW=0; LCD_EN = 0; // LCD_RS和R/W同时为低电平时,可以写入指令LCD_IO = com; Delay_1ms(5); //下面用EN输入一个高脉冲LCD_EN = 1; Delay_1ms(5); LCD_EN = 0;}/*************************************************************** 名称: W_LCD_Dat( )* 功能: 写数据子程序* 输入: dat* 输出: 无***************************************************************/void W_LCD_Dat(uchar dat){while(lcd_bz());LCD_RS = 1; LCD_RW=0;LCD_EN = 0; // LCD_RS为高,LCD_RW为低时,可以写入数据LCD_IO = dat; Delay_1ms(5); //下面用EN输入一个高脉冲LCD_EN = 1; Delay_1ms(5); LCD_EN = 0;}/*************************************************************** 名称: W_LCD_STR( )* 功能: 写字符串子程序* 输入: *s* 输出: 无***************************************************************/void W_LCD_STR(uchar *s){while(*s > 0) {W_LCD_Dat(*s); s++;}}/*************************************************************** 名称: LCD_cursor( )* 功能: 设置光标位置子程序* 输入: pos* 输出: 无***************************************************************/void LCD_cursor(uchar pos) //LCD光标定位到处{W_LCD_Com(pos+0x80); //第一行地址是0x80}/*************************************************************** 名称: initial( )* 功能: 初始化子程序* 输入: 无* 输出: 无* 指令:#define LCD_AC_AUTO_INCREMENT 0x06 //数据读、写操作后,AC自动增一#define LCD_DISPLAY_ON 0x0C //显示开#define LCD_DISPLAY_DOUBLE_LINE 0x38 //两行显示***************************************************************/void initial(){W_LCD_Com(0x06|0x04);W_LCD_Com(0x0c|0x08);W_LCD_Com(0x38);W_LCD_STR(LCD_line1);}/*************************************************************** 名称: Main()* 功能: 主函数***************************************************************/void main(){bit flag;uchar temp;uchar pos;Delay_1ms(10) ;initial();while(1){pos=0x4f;if(mydata>255)mydata=0;else if(mydata<0)mydata=255;if(mydata>127) //把mydata当做-128~127的有符号数来显示{flag=1;temp=256-mydata;}else {temp=mydata;flag=0;}LCD_cursor(pos);W_LCD_Dat((temp%10)+'0');pos--;//光标左移(其实光标不显示,只是为了输出高位)Delay_1ms(10);if(temp/100 || temp/10){LCD_cursor(pos);W_LCD_Dat((temp/10)%10+'0');pos--;}Delay_1ms(10);if(temp/100){LCD_cursor(pos);W_LCD_Dat((temp/100)%10+'0');pos--;}if(flag){LCD_cursor(pos);W_LCD_Dat('-');//负号}else{ LCD_cursor(pos);W_LCD_Dat(' ');//清除负号(空格代替)}if(!KK1){while(KK2);while(!KK2);mydata++;}else if(!KK2){while(KK1);while(!KK1);mydata--;}} }。
51单片机控制基于1602液晶显示 电子时钟【带闹铃和整点报时】

write_date(week6[num]);
delay1();
}
};
break;
}
}
void display() //显示时间子程序
{
write_week(week);
write_ymd(3,year);
write_ymd(6,months);
write_ymd(9,day);
write_sfm(0,shi);
write_sfm(3,fen);
write_sfm(6,miao);
}
void display_1() //显示闹钟子程序
{
write_week(week_1);
write_ymd(3,year1);
write_ymd(6,months1);
write_ymd(9,day1);
write_sfm(0,shi1);
write_com(0x80+add);
write_date(0x30+sh);
write_date(0x30+ge);
}
void write_week(uchar add) //周几显示
{
switch(add)
{
case 0:{
write_com(0x80+12);//设置数据起始地址
for(num=0;num<3;num++)
{
write_date(week3[num]);
delay1();
}
};
break;
case 4:{
write_com(0x80+12);//设置数据起始地址
for(num=0;num<3;num++)
DS18B20万年历温度时间按键控制1602显示51单片机程序

uint year=2015;
uchar month=2;
uchar day=27,daytemp;
uchar weekdayflag=5;
char H=12;
char M=0;
char S=0;
uchar displaybuf[9];
uchar code cdis1[20]= {"0123456789:.C- "};
sbit LCD_RS = P2^0; //LCD1602数据/命令选择端
sbit LCD_RW = P2^1; //LCD1602读/写选择端
sbit LCD_EN = P2^2; //LCD1602使能端
sbit DQ=P3^3; //DS18B20信号端
delayNOP();
}
//液晶初始化
void lcd_init() //1602液晶初始化函数
{
delay(5);
write_control(0x38); //16*2显示,5*7点阵,8位数据
**********************************************************/
void delayNOP()
{
_nop_(); //一个机器周期1us延时
_nop_();
_nop_();
_nop_();
_nop_();
delayNOP(); //5us延时
result = (bit)(P0&0x80); //确保STA7为0,说明为“闲”状态,为1位“忙”操作;(bit)(P0&0x80)为强制类型转换
LCD_EN = 0; //读取数据结束之后,复位执行使能操作
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define LCD_IO P2
sbit KK1 = P3^2; //按键输入;
sbit KK2 = P3^3; //按键输入;
sbit LCD_RS = P3^5;
sbit LCD_RW = P3^6;
sbit LCD_EN = P3^7;
uchar code LCD_line1[] = " The Counter";
int idata mydata=0;
/************************************************************** * 名称: Delay_1ms()
* 功能: 延时子程序,延时时间为1ms * x
* 输入: x (延时一毫秒的个数)
* 输出: 无
***************************************************************/ void Delay_1ms(uint x)
{
uchar i, j;
for(i = 0; i < x; i++) for(j = 0; j <= 148; j++);
}
/************************************************************** * 名称: lcd_bz( )
* 功能: 测试忙碌子程序
* 输入: 无
* 输出: result
***************************************************************/ bit lcd_bz()
{
bit result;
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
_nop_();
_nop_();
result=(bit)(P3&0x80);
LCD_EN = 0;
return result;
}
/**************************************************************
* 名称: W_LCD_Com( )
* 功能: 写指令子程序
* 输入: com
* 输出: 无
***************************************************************/
void W_LCD_Com(uchar com)
{
while(lcd_bz());
LCD_RS = 0; LCD_RW=0; LCD_EN = 0; // LCD_RS和R/W同时为低电平时,可以写入指令
LCD_IO = com; Delay_1ms(5); //下面用EN输入一个高脉冲
LCD_EN = 1; Delay_1ms(5); LCD_EN = 0;
}
/**************************************************************
* 名称: W_LCD_Dat( )
* 功能: 写数据子程序
* 输入: dat
* 输出: 无
***************************************************************/
void W_LCD_Dat(uchar dat)
{
while(lcd_bz());
LCD_RS = 1; LCD_RW=0;LCD_EN = 0; // LCD_RS为高,LCD_RW为低时,可以写入数据LCD_IO = dat; Delay_1ms(5); //下面用EN输入一个高脉冲
LCD_EN = 1; Delay_1ms(5); LCD_EN = 0;
}
/**************************************************************
* 名称: W_LCD_STR( )
* 功能: 写字符串子程序
* 输入: *s
* 输出: 无
***************************************************************/
void W_LCD_STR(uchar *s)
{
while(*s > 0) {W_LCD_Dat(*s); s++;}
}
/**************************************************************
* 名称: LCD_cursor( )
* 功能: 设置光标位置子程序
* 输入: pos
* 输出: 无
***************************************************************/
void LCD_cursor(uchar pos) //LCD光标定位到处{
W_LCD_Com(pos+0x80); //第一行地址是0x80
}
/**************************************************************
* 名称: initial( )
* 功能: 初始化子程序
* 输入: 无
* 输出: 无
* 指令:#define LCD_AC_AUTO_INCREMENT 0x06 //数据读、写操作后,AC自动增一#define LCD_DISPLAY_ON 0x0C //显示开
#define LCD_DISPLAY_DOUBLE_LINE 0x38 //两行显示
***************************************************************/
void initial()
{
W_LCD_Com(0x06|0x04);
W_LCD_Com(0x0c|0x08);
W_LCD_Com(0x38);
W_LCD_STR(LCD_line1);
}
/**************************************************************
* 名称: Main()
* 功能: 主函数
***************************************************************/
void main()
{
bit flag;
uchar temp;
uchar pos;
Delay_1ms(10) ;
initial();
while(1){
pos=0x4f;
if(mydata>255)
mydata=0;
else if(mydata<0)
mydata=255;
if(mydata>127) //把mydata当做-128~127的有符号数来显示
{
flag=1;
temp=256-mydata;
}
else {temp=mydata;flag=0;}
LCD_cursor(pos);
W_LCD_Dat((temp%10)+'0');
pos--;//光标左移(其实光标不显示,只是为了输出高位)Delay_1ms(10);
if(temp/100 || temp/10)
{
LCD_cursor(pos);
W_LCD_Dat((temp/10)%10+'0');
pos--;
}
Delay_1ms(10);
if(temp/100)
{
LCD_cursor(pos);
W_LCD_Dat((temp/100)%10+'0');
pos--;
}
if(flag)
{
LCD_cursor(pos);
W_LCD_Dat('-');//负号
}
else
{ LCD_cursor(pos);
W_LCD_Dat(' ');//清除负号(空格代替)
}
if(!KK1)
{
while(KK2);
while(!KK2);
mydata++;
}
else if(!KK2)
{
while(KK1);
while(!KK1);
mydata--;
}
}
}。