首先根据系统程序框图来提前调试好各模块部分的功能。比如按键,数码管,PCF8591,AT24C02。
调试完成之后,可以进一步往下看题目。
这一部分主要讲解一些功能和要求,看一遍注意一下就行。
然后看数码管显示界面设计。
uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff,0xbf,0x8c,0xc1,0xc8};//p u n
uchar SMG[8]={20,20,20,20,20,20,20,20};//初始显示20,全息数码管
uchar SMG_mode=0;//控制数码管模式
uint move=0;//pcf8591的滑动变阻器读取值
int Vp=300; //定义电压参数
int count=13; //定义计数值
void main(void)
{
init();
while(1)
{
move=IIC_read(PCF8591_address,Move_address);//读取滑动变阻器
move=1.9607*move;//move *(5 /255 *100) 将0-255转换到0-500,便于显示
if(SMG_mode==0) //数据界面
{
SMG[0]=23;SMG[1]=SMG[2]=SMG[3]=SMG[4]=20;
SMG[5]=move/100+10;SMG[6]=move%100/10;SMG[7]=move%10;
}
else if(SMG_mode==1) //参数界面
{
SMG[0]=22;SMG[1]=SMG[2]=SMG[3]=SMG[4]=20;
SMG[5]=Vp/100+10;SMG[6]=Vp%100/10;SMG[7]=Vp%10;
}
else if(SMG_mode==2) //计数界面
{
SMG[0]=24;SMG[1]=SMG[2]=SMG[3]=SMG[4]=20; ///不同count对应的数码管显示不同
if(count<10){SMG[5]=20;SMG[6]=20;SMG[7]=count;}
else if(count<100){SMG[5]=20;SMG[6]=count/10;SMG[7]=count%10;}
else if(count<1000){SMG[5]=count/100;SMG[6]=count%100/10;SMG[7]=count%10;}
}
SMG_output();
Jkey_scan();
}
}
然后看按键功能,可以发现是矩阵按键的右下角一部分。
按照相关进行设置即可,需要注意一下按键功能设计要求。
void Jkey_scan(void)
{
unsigned char i,key;
for(i=0x80;i>8;i >>=1)
{
if(i==0x80){P44=0;P42=1;P3=~i;}
else if(i==0x40){P44=1;P42=0;P3=~i;}
else {P44=1;P42=1;P3=~i;}
if(i==0x80){key=P3;key&=0x7f;}
else if(i==0x40){key=P3;key&=0xbf;}
else {key=P3;}
if((key&0x0f)!=0x0f)
{
Delay5ms();
if((key&0x0f)!=0x0f)
{
switch(key)
{
case 0xdb: //S13
if(SMG_mode==2) count=0; //计数界面有效,计数值清零
break;
case 0xd7: //S12
if(SMG_mode==0)SMG_mode=1; //模式切换
else if(SMG_mode==1){SMG_mode=2;IIC_write(AT24C02_address,0,Vp/10);}//模式切换,保存计数值
else if(SMG_mode==2)SMG_mode=0; //模式切换
break;
case 0xeb: //S17
if(SMG_mode==1) Vp-=50; //参数界面按下减5
if(Vp<0)Vp=500; //限幅设置
break;
case 0xe7: //S16
if(SMG_mode==1) Vp+=50;//参数界面按下加5
if(Vp>500)Vp=0; //限幅设置
break;
}
}
while((key&0x0f)!=0x0f)
{
key=P3;SMG_output(); //按下按键不影响数码管显示
}
}
}
}
uchar led=0xff;//led变量
bit L1_enable=0;//L1使能
char L3_enable=0; //L3使能
if(move<Vp) L1_enable=1; //当move小于vp开始计时
else {L1_enable=0;led |=0x01;} //L1熄灭
if(count%2!=0) led &=0xfd; //L2点亮//计数值为奇数
else led |=0x02; //L2熄灭
if(L3_enable>=3) led &=0xfb; //L3点亮//无效按键三次
else led |=0x04; //L3熄灭
P2=0X80;P0=led;//点亮
//通过1ms定时器判断5s
uint t=0;
void time0() interrupt 1
{
if(L1_enable==1)
{
t++;
if(t>=5000) //5s
{
t=0;
led &=0xfe; //超过就点亮
}
}
}
if(move>Vp) state=1; //高于时标志位置一
if((state==1)&&(move<Vp)) {count++;state=0;}//低于时标志位置0,计数++
#include
#include"intrins.h"
#include "iic.h"
#define uchar unsigned char
#define uint unsigned int
#define PCF8591_address 0x90
#define Move_address 0x03
#define AT24C02_address 0xA0
void SMG_output(void);
void init(void);
void Delay1ms(void);
void Timer0Init(void);
void Jkey_scan(void);
void Delay5ms(void);
uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff,0xbf,0x8c,0xc1,0xc8};//p u n
uchar SMG[8]={20,20,20,20,20,20,20,20};//初始显示20,全息数码管
uchar SMG_mode=0;//控制数码管模式
uint move=0;//pcf8591的滑动变阻器读取值
int Vp=0; //定义电压参数
int count=0; //定义计数值
uchar led=0xff;//led变量
bit L1_enable=0;//L1使能
char L3_enable=0; //L3使能
bit state=0;//判断计数值标志位
void main(void)
{
init(); //初始化开发板
Timer0Init();//定时器初始化
Vp=IIC_read(AT24C02_address,0);//读取eeprom
Vp *=10;//变为100
while(1)
{
if(move>Vp) state=1; //高于时标志位置一
if((state==1)&&(move<Vp)) {count++;state=0;}//低于时标志位置0,计数++
move=IIC_read(PCF8591_address,Move_address);//读取滑动变阻器
move=1.9607*move;//move *(5 /255 *100) 将0-255转换到0-500,便于显示
if(SMG_mode==0) //数据界面
{
SMG[0]=23;SMG[1]=SMG[2]=SMG[3]=SMG[4]=20;
SMG[5]=move/100+10;SMG[6]=move%100/10;SMG[7]=move%10;
}
else if(SMG_mode==1) //参数界面
{
SMG[0]=22;SMG[1]=SMG[2]=SMG[3]=SMG[4]=20;
SMG[5]=Vp/100+10;SMG[6]=Vp%100/10;SMG[7]=Vp%10;
}
else if(SMG_mode==2) //计数界面
{
SMG[0]=24;SMG[1]=SMG[2]=SMG[3]=SMG[4]=20; ///不同count对应的数码管显示不同
if(count<10){SMG[5]=20;SMG[6]=20;SMG[7]=count;}
else if(count<100){SMG[5]=20;SMG[6]=count/10;SMG[7]=count%10;}
else if(count<1000){SMG[5]=count/100;SMG[6]=count%100/10;SMG[7]=count%10;}
}
if(move<Vp) L1_enable=1; //当move小于vp开始计时
else {L1_enable=0;led |=0x01;} //L1熄灭
if(count%2!=0) led &=0xfd; //L2点亮//计数值为奇数
else led |=0x02; //L2熄灭
if(L3_enable>=3) led &=0xfb; //L3点亮//无效按键三次
else led |=0x04; //L3熄灭
P2=0X80;P0=led; //点亮
SMG_output();
Jkey_scan();
}
}
//通过1ms定时器判断5s
uint t=0;
void time0() interrupt 1
{
if(L1_enable==1)
{
t++;
if(t>=5000) //5s
{
t=0;
led &=0xfe; //超过就点亮
}
}
}
void Jkey_scan(void)
{
unsigned char i,key;
for(i=0x80;i>8;i >>=1)
{
if(i==0x80){P44=0;P42=1;P3=~i;}
else if(i==0x40){P44=1;P42=0;P3=~i;}
else {P44=1;P42=1;P3=~i;}
if(i==0x80){key=P3;key&=0x7f;}
else if(i==0x40){key=P3;key&=0xbf;}
else {key=P3;}
if((key&0x0f)!=0x0f)
{
Delay5ms();
if((key&0x0f)!=0x0f)
{
switch(key)
{
case 0xdb: //S13
L3_enable=0; //正确操作
if(SMG_mode==2) count=0; //计数界面有效,计数值清零
break;
case 0xd7: //S12
L3_enable=0; //正确操作
if(SMG_mode==0)SMG_mode=1; //模式切换
else if(SMG_mode==1){SMG_mode=2;IIC_write(AT24C02_address,0,Vp/10);}//模式切换,保存计数值
else if(SMG_mode==2)SMG_mode=0; //模式切换
break;
case 0xeb: //S17
L3_enable=0; //正确操作
if(SMG_mode==1) Vp-=50; //参数界面按下减5
if(Vp<0)Vp=500; //限幅设置
break;
case 0xe7: //S16
L3_enable=0; //正确操作
if(SMG_mode==1) Vp+=50;//参数界面按下加5
if(Vp>500)Vp=0; //限幅设置
break;
default:
L3_enable++; //其他按键错误加1
break;
}
}
while((key&0x0f)!=0x0f)
{
key=P3;SMG_output(); //按下按键不影响数码管显示
}
}
}
}
void SMG_output(void)
{
uchar i;
for(i=0;i<8;i++)
{
P2=(P2&0X1F)|0Xc0;
P0=(1<<i);
P2=(P2&0X1F)|0Xe0;
P0=tab[SMG[i]];
Delay1ms();
}
P2=(P2&0X1F)|0Xc0;
P0=0Xff;
P2=(P2&0X1F)|0Xe0;
P0=0Xff;
}
void Timer0Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;ET0=1;
}
void init(void)
{
P2=(P2&0X1F)|0XA0;
P0=0X00;
P2=(P2&0X1F)|0X80;
P0=0Xff;
P2=(P2&0X1F)|0Xc0;
P0=0Xff;
P2=(P2&0X1F)|0Xe0;
P0=0Xff;
}
void Delay5ms() //@11.0592MHz
{
unsigned char i, j;
i = 54;
j = 199;
do
{
while (--j);
} while (--i);
}
void Delay1ms(void) //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
#include
#include "iic.h"
#define DELAY_TIME 40
void IIC_write(uchar hw_address,uchar reg_address,uchar num)
{
IIC_Start();
IIC_SendByte(hw_address&0xfe);
IIC_WaitAck();
IIC_SendByte(reg_address);
IIC_WaitAck();
IIC_SendByte(num);
IIC_WaitAck();
IIC_Stop();
}
uchar IIC_read(uchar hw_address,uchar reg_address)
{
uchar num;
IIC_Start();
IIC_SendByte(hw_address&0xfe);
IIC_WaitAck();
IIC_SendByte(reg_address);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(hw_address|0x01);
IIC_WaitAck();
num=IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
return num;
}
//
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit;
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
#ifndef _IIC_H
#define _IIC_H
#include "stc15f2k60s2.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
sbit SDA = P2^1;
sbit SCL = P2^0;
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
void IIC_write(uchar hw_address,uchar reg_address,uchar num);
uchar IIC_read(uchar hw_address,uchar reg_address);
#endif
工程文件有注释