void menushow(unsigned char menu9)
{
switch(menu9)
{
case 8:
{//6-7-8-9-
displaydata[7]=6;
displaydata[6]=14;
displaydata[5]=7;
displaydata[4]=14;
displaydata[3]=8;
displaydata[2]=14;
displaydata[1]=9;
displaydata[0]=14;
setLCDsegment();
}
break;
case 1:
{//1-
displaydata[7]=1;
displaydata[6]=14;
displaydata[5]=16;
displaydata[4]=16;
displaydata[3]=16;
displaydata[2]=16;
displaydata[1]=16;
displaydata[0]=16;
setLCDsegment();
}
break;
case 2:
{//2-
displaydata[7]=2;
displaydata[6]=14;
displaydata[5]=16;
displaydata[4]=16;
displaydata[3]=16;
displaydata[2]=16;
displaydata[1]=16;
displaydata[0]=16;
setLCDsegment();
}
break;
case 3:
{//3-
displaydata[7]=3;
displaydata[6]=14;
displaydata[5]=16;
displaydata[4]=16;
displaydata[3]=16;
displaydata[2]=16;
displaydata[1]=16;
displaydata[0]=16;
setLCDsegment();
}
break;
}
}
void delay(unsigned char i)
{
int r;
for(;i>0;i--) /**/
for(r=1500;r>0;r--)
{;}
}
//*********************************************************
// 定时中断初始化(OPTION_REG)
//*********************************************************
void tmint(void)
{
T0CS=0; //时钟源为内部指令周期
PSA=0; //分频器分配给TMR0
//
PS2=1; //TMR0的分频比为1:256
PS1=1;
PS0=1;
//
GIE=1; //允许总中断
TMR0IE=1; //允许定时器0溢出中断
TMR0IF=0; //清楚定时器0中断标志
TMR0=0Xd8; //预置初值 T=(256-0xd8)x256=4000uS
}
void keyboradscan(void)
{
unsigned char key_a=200,key_i=0;
unsigned char temp;
//while(key_a--); //先消抖;
unsigned char result;
PORTC=0X7F; ////C7输出低电平,其他三位输出高电平 C7是列线
asm("nop"); //插入一定延时,确保电平稳定
result=PORTC; //读回C口高4位结果
result=result&0x0f; //清除高4位 因为我的布线 高四位是列线 低四位是行线
if(result!=0x0f) //判断低4位是否为全1(全1代表没按键按下)
{
result=result|0x70; //否,加上高4位0x70,做为按键扫描的结果
switch(result)
{
case 0x77: keys=64;while((PORTC&0x0f)!=0x0f);break;//ent
}
}
else //是,改变高4位输出,重新判断是否有按键按下
{
PORTC=0Xbf; //C6输出低电平,其他三位输出高电平 C6是列
asm("nop"); //插入一定延时,确保电平稳定
result=PORTC; //读回C口结果
result=result&0x0f; //清除高4位
if(result!=0x0f) //判断低4位是否为全1(全1代表没按键按下)
{
result=result|0xb0; //否,加上高4位0xb,做为按键扫描的结果
switch(result)
{
case 0xb7: keys=16;
while((PORTC&0x0f)!=0x0f);break;//set
case 0xbe:
if(tyle==0)
{
keys=6;
}
else {displaydata[7-(j+2)]=6;setLCDsegment(); l_tmpdate1[j]=6;j++;}while((PORTC&0x0f)!=0x0f);break;
case 0xbd: keys=3;displaydata[7-j]=3;j++;setLCDsegment();while((PORTC&0x0f)!=0x0f);break;//3
case 0xbb: keys=9;displaydata[7-j]=9;j++;setLCDsegment();while((PORTC&0x0f)!=0x0f);break;//9
}
}
else //是,改变高4位输出,重新扫描
{
PORTC=0Xdf; //C5输出低电平,其他三位输出高电平
asm("nop"); //插入一定延时,确保电平稳定
result=PORTC; //读回C口高4位结果
result=result&0x0f; //清除高4位
if(result!=0x0f) //判断低4位是否为全1(全1代表没按键按下)
{
result=result|0xd0; //否,加上高4位0x0d,做为按键扫描的结果
switch(result)
{
case 0xde: keys=1;displaydata[7-j]=1;j++;setLCDsegment();while((PORTC&0x0f)!=0x0f);break;//1
case 0xdd: keys=2;displaydata[7-j]=2;j++;setLCDsegment();while((PORTC&0x0f)!=0x0f);break;
//2
case 0xdb: keys=4;displaydata[7-j]=4;j++;setLCDsegment();while((PORTC&0x0f)!=0x0f);break;//4
case 0xd7: keys=5;displaydata[7-j]=5;j++;setLCDsegment(); l_tmpdate1[j]=5;while((PORTC&0x0f)!=0x0f);break;//5
}
}
else //是,改变高4位的输出,重新扫描
{
PORTC=0Xef; //C4输出低电平,其他三位输出高电平
asm("nop"); //插入一定延时,确保电平稳定
result=PORTC; //读回C口高4位结果
result=result&0x0f;//清除高4位
if(result!=0x0f) //判断低四位是否为全1(全1代表没有按键按下)
{
result=result|0xe0;//否,加上高4位0x0e,做为按键扫描的结果
switch(result)
{
case 0xe7: keys=32;
j--;
setLCDsegment();
while((PORTC&0x0f)!=0x0f);break;//del
case 0xeb:
keys=99;while((PORTC&0x0f)!=0x0f);break;//0 调试用于观察键值保存数组
case 0xee: keys=7;displaydata[7-j]=7;j++;setLCDsegment();while((PORTC&0x0f)!=0x0f);break;//7
case 0xed: keys=8;displaydata[7-j]=8;j++;setLCDsegment();while((PORTC&0x0f)!=0x0f);break;//8
}
}
else //是,全部按键扫描结束,没有按键按下,置无按键按下标志位
{
result=0xff; //扫描结果为0xff,做为没有按键按下的标志
}
}
}
}
result;
}
//*********************************************************
void interrupt dealtime() //中断入口,该中断完成数码管的动态扫描
{ //每中断一次的时间为4毫秒
unsigned char i,n;
if(TMR0IF==1&&TMR0IE==1)
{
//判断TMR1中断 T1中断
//TMR0IE=0;//禁止溢出中断,防止干扰
TMR0IF=0; // 清除TMR1中断标志,每次中断溢出需要软件将TMR1IF清零
keyboradscan();
TMR0 = 0Xd8;
}
PORTC=0; //为下一次按键做准备;
TMR0IF=0;
GIE=1; //开中断
}
void LCDinit()
{
LCDCON = 0b11001011; //LCD on, WERR off, SLPEN on 31Khz, 1/4 multiplex//
LCDPS = 0b00110010; //type a waveform, 1/3 BIAS, 1:3 prescaler LCD的相位寄存器 ,
LCDREF = 0b10000110; //
LCDCST = 0b00000000; //maximum contrast LCD对比度控制寄存器 最大
LCDSE0 = 0b10110001; //segment SEG 0 4 5 7
LCDSE1 = 0b11110000; //segment 12~15 enable
LCDSE2 = 0b11111111;//segment 16~23 enable
LCDDATA0=0;
LCDDATA1=0;
LCDDATA2=0;
LCDDATA3=0;
LCDDATA4=0;
LCDDATA5=0;
LCDDATA6=0;
LCDDATA7=0;
LCDDATA8=0;
LCDDATA9=0;
LCDDATA10=0;
LCDDATA11=0;
LCDRL = 0b11110100; //low power mode, A type waveform:4clock for A and 12 clock for B, B type waveform:4 clock for A and 28 clock for B
LCDIF = 0;
LCDIE = 0; //interrupt disabled
LCDEN = 1; //LCD on
}
void port_init()
{
OSCCON = 0b01101010;//内部4M晶振运行 方便定时器0
//ADCON1=0X07;
//SWDTEN=1; //WDT看门狗由SWDTEN这位控制,使能WDT
ANSELA=0;//设置A口为普通数字口,必须先把ANESELA设为数字IO 这样才能使用输出输入功能
ANSELB=0;////B口也设置成数字IO口
ANSELE=0;//E口也设置成数字IO口
TRISA=0B11000000;//RA6 7做晶振输入 ,0-5做为数码管控制输出
TRISB=0b00000000;
TRISC = 0x0F; //键盘的列设为输出,行设为输入,RC7 C6 C5 C4 输出 ,C0 C1 C2 C3输入
TRISD = 0x00; //数码管控制 设为输出
TRISE = 0B00001000; //RE3始终为输入 RE0 1 2为数码管输出
}
unsigned char setLCDsegment(void){
const unsigned char Arabic[17]={
0xFA,0x60,0xD6,0xF4,0x6C,0xBC,0xBE,0xE0,
0xFE,0xFC,0xEE,0x3E,0x9A,0x76,0x04,0xce,0x00
}; //0123456789abcdef 0xce是P 0x04是- //0123456789abcdef
unsigned char data0=0,data1=0,data2=0,data3=0,data4=0,data5=0,data6=0,data7=0,data8=0,data9=0,data10=0; //LCDDATAx暂存
unsigned char num;
unsigned char data11=0;
if(displaydata[0]<17){//轮流扫描8个数码管
num=Arabic[displaydata[0]];
data1|=(num&0x80)>>1;
data4|=(num&0x40);
data7|=(num&0x20)<<1;
data10|=(num&0x10)<<2;
data1|=(num&0x08)<<4;
data4|=(num&0x04)<<5;
data7|=(num&0x02)<<6;
}else{
return 0;
}
/***********************
第二个数
17 18
seg 12 13
************************/
if(displaydata[1]<17){
num=Arabic[displaydata[1]];
data1|=(num&0x80)>>3;
data4|=(num&0x40)>>2;
data7|=(num&0x20)>>1;
data10|=(num&0x10);
data1|=(num&0x08)<<2;
data4|=(num&0x04)<<3;
data7|=(num&0x02)<<4;
}else{
return 0;
}
/**
第三个数
15 16
seg21 22
*/
if(displaydata[2]<17){
num=Arabic[displaydata[2]];
data2|=(num&0x80)>>2;
data5|=(num&0x40)>>1;
data8|=(num&0x20);
data11|=(num&0x10)<<1;
data2|=(num&0x08)<<3;
data5|=(num&0x04)<<4;
data8|=(num&0x02)<<5;
}else{
return 0;
}
/**********************
第四个数
13 14
seg 16 20
***********************/
if(displaydata[3]<17){
num=Arabic[displaydata[3]];
data2|=(num&0x80)>>7;
data5|=(num&0x40)>>6;
data8|=(num&0x20)>>5;
data11|=(num&0x10)>>4;
data2|=(num&0x08)<<1;
data5|=(num&0x04)<<2;
data8|=(num&0x02)<<3;
}else{
return 0;
}
/*********************
第5个数
13 14
seg 16 20
**********************/
if(displaydata[4]<17){
num=Arabic[displaydata[4]];
data2|=(num&0x80);
data5|=(num&0x40)<<1;
data8|=(num&0x20)<<2;
data11|=(num&0x10)<<3;
data0|=(num&0x08)<<4;
data3|=(num&0x04)<<5;
data6|=(num&0x02)<<6;
}else{
return 0;
}
/**********************
第六个数
9 10
SEG4 5
*************************/
if(displaydata[5]<17){
num=Arabic[displaydata[5]];
data0|=(num&0x80)>>3;
data3|=(num&0x40)>>2;
data6|=(num&0x20)>>1;
data9|=(num&0x10);
data0|=(num&0x08)<<2;
data3|=(num&0x04)<<3;
data6|=(num&0x02)<<4;
}else{
return 0;
}
/**********************
第7个数
7 8
SEG19 18
*************************/
if(displaydata[6]<17){
num=Arabic[displaydata[6]];
data2|=(num&0x80)>>4;
data5|=(num&0x40)>>3;
data8|=(num&0x20)>>2;
data11|=(num&0x10)>>1;
data2|=(num&0x08)>>1;
data5|=(num&0x04);
data8|=(num&0x02)<<1;
}else{
return 0;
}
/***********************
第二个数
17 18
seg 12 13
************************/
if(displaydata[7]<17){
num=Arabic[displaydata[7]];
data0|=(num&0x80)>>7;
data3|=(num&0x40)>>6;
data6|=(num&0x20)>>5;
data9|=(num&0x10)>>4;
data2|=(num&0x08)>>2;
data5|=(num&0x04)>>1;
data8|=(num&0x02);
}else{
return 0;
}
/***********************
显示开机令
20
SEG15
************************/
data10|=0x01<<7;
data10|=0x01<<5;
data11|=0x01<<6;
if(keys == 32 )//清除标志
{
switch(7-j)
{
case 7://第8个数码管清零
displaydata[7]=16;
num=Arabic[displaydata[7]];
data2|=(num&0x80)>>4;
data5|=(num&0x40)>>3;
data8|=(num&0x20)>>2;
data11|=(num&0x10)>>1;
data2|=(num&0x08)>>1;
data5|=(num&0x04);
data8|=(num&0x02)<<1;
break;
//break;
case 6://第7个数码管
displaydata[6]=16;
num=Arabic[displaydata[6]];
data2|=(num&0x80)>>4;
data5|=(num&0x40)>>3;
data8|=(num&0x20)>>2;
data11|=(num&0x10)>>1;
data2|=(num&0x08)>>1;
data5|=(num&0x04);
data8|=(num&0x02)<<1;
break;
case 5://第6个数码管
displaydata[5]=16;
num=Arabic[displaydata[5]];
data0|=(num&0x80)>>3;
data3|=(num&0x40)>>2;
data6|=(num&0x20)>>1;
data9|=(num&0x10);
data0|=(num&0x08)<<2;
data3|=(num&0x04)<<3;
data6|=(num&0x02)<<4;
break;
case 4://第5个数码管
displaydata[4]=16;
num=Arabic[displaydata[4]];
data2|=(num&0x80);
data5|=(num&0x40)<<1;
data8|=(num&0x20)<<2;
data11|=(num&0x10)<<3;
data0|=(num&0x08)<<4;
data3|=(num&0x04)<<5;
data6|=(num&0x02)<<6;
break;
case 3://第4个数码管
displaydata[3]=16;
num=Arabic[displaydata[3]];
data2|=(num&0x80)>>7;
data5|=(num&0x40)>>6;
data8|=(num&0x20)>>5;
data11|=(num&0x10)>>4;
data2|=(num&0x08)<<1;
data5|=(num&0x04)<<2;
data8|=(num&0x02)<<3;
break;
case 2://第3个数码管
displaydata[2]=16;
num=Arabic[displaydata[2]];
data2|=(num&0x80)>>2;
data5|=(num&0x40)>>1;
data8|=(num&0x20);
data11|=(num&0x10)<<1;
data2|=(num&0x08)<<3;
data5|=(num&0x04)<<4;
data8|=(num&0x02)<<5;
break;
case 1://第2个数码管
displaydata[1]=16;
num=Arabic[displaydata[1]];
data1|=(num&0x80)>>3;
data4|=(num&0x40)>>2;
data7|=(num&0x20)>>1;
data10|=(num&0x10);
data1|=(num&0x08)<<2;
data4|=(num&0x04)<<3;
data7|=(num&0x02)<<4;
break;
case 0://第1个数码管
displaydata[0]=16;
num=Arabic[displaydata[0]];
data1|=(num&0x80)>>1;
data4|=(num&0x40);
data7|=(num&0x20)<<1;
data10|=(num&0x10)<<2;
data1|=(num&0x08)<<4;
data4|=(num&0x04)<<5;
data7|=(num&0x02)<<6;
break;
default:
break;
}
}
LCDDATA0=data0;
LCDDATA1=data1;
LCDDATA2=data2;
LCDDATA3=data3;
LCDDATA4=data4;
LCDDATA5=data5;
LCDDATA6=data6;
LCDDATA7=data7;
LCDDATA8=data8;
LCDDATA9=data9;
LCDDATA10=data10;
LCDDATA11=data11;//LCDDATA等于就是输出到段码的值
return 1;
}
unsigned char EEpromRead(unsigned char address)
{
EEADRL = address;//向低位直接写入要读的地址
/*
以下是读E2PROM必须要有的三个步骤
*/
CFGS = 0;
EEPGD = 0;
RD = 1;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
return EEDATL;
}
void EEpromWrite(unsigned char address,unsigned char data)
{
unsigned char tmp;
unsigned char flag;
unsigned char i;
flag=0;
// for(i=0;i<0xff;i++){
EEADRL = address;//存放要读写的地址
EEDATL = data; //EEDATL存放要读写的8位数据
CFGS = 0; //访问数据存储器 或者程序存储器
EEPGD = 0; //0是访问数据存储器 1是访问程序存储器
GIE=0;
tmp = INTCON;
INTCON = 0;
WREN = 1; //允许执行写操作
EECON2 = 0x55; //数据EEPROM 解锁模式位 为了解锁写操作 必须先写0X55 再写0XAA
EECON2 = 0xAA;
WR = 1; //写完后才能将WR置位
while(!EEIF);//ziji
GIE=1;
EEIF=0;//ziji
asm("nop");
asm("nop");
WREN = 0; //写完后软件清零
INTCON = tmp;
//}
} |