目录
前言
一、功能描述
二、各模块代码
1.数码管相关代码
2.独立按键代码
3.I2C驱动代码
4.LED代码
5.主函数
三.功能展示
总结
最近准备蓝桥杯单片机比赛,差不多学完了省赛要考的各个模块。因此做了一套省赛模拟题,用来记录一下学习过程。功能应该差不多实现完了,大家仅供参考。第一次发文,不完善的地方大家多多担待。
1.SMG.c
#include "regx52.h"
code unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x8e,0xc8,0xc1,0xbf};//0-9,熄灭,F,N,U,-;
unsigned int DispBuff[8] = {10,10,10,10,10,10,10,10};
unsigned char dspcom=0;
extern unsigned char mainmode,submode;
extern unsigned short cnt1;
extern unsigned short T;
extern unsigned short V1,V2;
//锁存器选择
void Select_Y(unsigned char Channel)
{
switch(Channel)
{
case 4: P2 = (P2&0x1f)|0x80; break;
case 5: P2 = (P2&0x1f)|0xa0; break;
case 6: P2 = (P2&0x1f)|0xc0; break;
case 7: P2 = (P2&0x1f)|0xe0; break;
}
}
void SMG_Scan(void)
{
//消影
Select_Y(7);
P0 = 0xff;
//送位码
Select_Y(6);
P0 = 1<9999)
DispBuff[3] = cnt1/10000;
else DispBuff[3] = 10;
if(cnt1>999)
DispBuff[4] = (cnt1/1000)%10;
else DispBuff[4] = 10;
if(cnt1>99)
DispBuff[5] = (cnt1/100)%10;
else DispBuff[5] = 10;
if(cnt1>9)
DispBuff[6] = (cnt1/10)%10;
else DispBuff[6] = 10;
if(cnt1>0)
DispBuff[7] = cnt1%10;
}
//周期界面
else if(mainmode == 1)
{
DispBuff[0] = 12;
DispBuff[1] = 10;
DispBuff[2] = 10;
if(T>9999)
DispBuff[3] = T/10000;
else DispBuff[3] = 10;
if(T>999)
DispBuff[4] = (T/1000)%10;
else DispBuff[4] = 10;
if(T>99)
DispBuff[5] = (T/100)%10;
else DispBuff[5] = 10;
if(T>9)
DispBuff[6] = (T/10)%10;
else DispBuff[6] = 10;
if(T>0)
DispBuff[7] = T%10;
}
//电压界面
else if(mainmode == 2)
{
//通道1
if(submode == 0)
{
DispBuff[0] = 13;
DispBuff[1] = 14;
DispBuff[2] = 1;
DispBuff[3] = 10;
DispBuff[4] = 10;
DispBuff[5] = V1/100;
DispBuff[6] = V1/10%10;
DispBuff[7] = V1%10;
}
//通道3
else if(submode == 1)
{
DispBuff[0] = 13;
DispBuff[1] = 14;
DispBuff[2] = 3;
DispBuff[3] = 10;
DispBuff[4] = 10;
DispBuff[5] = V2/100;
DispBuff[6] = V2/10%10;
DispBuff[7] = V2%10;
}
}
}
key.c
#include "regx52.h"
#include "iic.h"
#include "SMG.h"
extern unsigned short V1,V2;
extern unsigned char Vflag,Tflag;
extern unsigned char keyflag,longkeyflag,shortkeyflag;
extern unsigned char mainmode,submode;
extern unsigned char LEDflag;
void delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
void modechange(void)
{
mainmode++;
if(mainmode>2) mainmode = 0;
}
void submodechange(void)
{
submode++;
if(submode>1) submode = 0;
}
void Key_Scan(void)
{
static unsigned char cnt = 0;
if(P3_3 == 0)
{
delay(20);
while(P3_3 == 0)
delay(20);
modechange();
}
if(P3_2 == 0)
{
delay(20);
while(P3_2 == 0)
delay(20);
submodechange();
}
if(P3_1 == 0)
{
delay(20);
while(P3_1 == 0)
{
delay(20);
Vflag = 1;
}
}
if(P3_0 == 0)
{
delay(20);
while(P3_0 == 0)
{
delay(20);
keyflag = 1;
if(longkeyflag == 1)
{
LEDflag = 1 - LEDflag ;
longkeyflag = 0;
cnt++;
if(cnt == 2)
{
LEDflag = 1 - LEDflag;
cnt = 0;
}
}
else if( shortkeyflag == 1)
{
shortkeyflag = 0;
Tflag = 1;
}
}
}
}
iic.c
#include "iic.h"
#include "regx52.h"
void IIC_Delay(unsigned char i)
{
while(i--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(10);
SDA = 0;
IIC_Delay(10);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(10);
SDA = 1;
}
//应答位控制
void IIC_Ack(unsigned char ackbit)
{
if(ackbit)
{
SDA = 0;
}
else
{
SDA = 1;
}
IIC_Delay(10);
SCL = 1;
IIC_Delay(10);
SCL = 0;
SDA = 1;
IIC_Delay(10);
}
//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
IIC_Delay(10);
SCL = 1;
IIC_Delay(10);
if(SDA)
{
SCL = 0;
IIC_Stop();
return 0;
}
else
{
SCL = 0;
return 1;
}
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
IIC_Delay(10);
SCL = 1;
byt <<= 1;
IIC_Delay(10);
SCL = 0;
}
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 1;
IIC_Delay(10);
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
IIC_Delay(10);
}
return da;
}
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
unsigned char Get_V(unsigned char ain)
{
unsigned char dat;
IIC_Start();
IIC_SendByte(0x90);//写
IIC_WaitAck();
IIC_SendByte(ain);
IIC_WaitAck();
IIC_Stop();
//读了丢舍弃一次
IIC_Start();
IIC_SendByte(0x91);//读
IIC_WaitAck();
//加延时把数据丢完不然要数据异常
Delay1ms();
IIC_RecByte();
IIC_Ack(0);
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);//读
IIC_WaitAck();
dat = IIC_RecByte();
IIC_Ack(0);
IIC_Stop();
return dat;
}
//读取电压
void Read_V(unsigned short *V1,unsigned short*V2)
{
*V1 = Get_V(1)*(5.0/255)*100;
*V2 = Get_V(3)*(5.0/255)*100;
}
void AT24C02_WriteByte(unsigned char address,unsigned char dat)
{
EA = 0;
IIC_Start();
IIC_SendByte(0Xa0);
IIC_WaitAck();
IIC_SendByte(address);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
EA = 1;
Delay1ms();
}
unsigned char AT24C02_ReadByte(unsigned address)
{
unsigned char dat;
EA = 0;
IIC_Start();
IIC_SendByte(0Xa0);
IIC_WaitAck();
IIC_SendByte(address);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0Xa1);
IIC_WaitAck();
dat = IIC_RecByte();
IIC_Ack(0);
IIC_Stop();
EA = 1;
return dat;
}
LED.c
#include
#include "SMG.h"
extern unsigned char VSET;
extern unsigned short V1,cnt1,FSET;
extern unsigned char LEDflag;
extern unsigned char mainmode;
void LED_Control(void)
{
if(LEDflag == 1)
{
Select_Y(4);
P0 = 0xff;
if(V1 > VSET*10)
P0_0 = 0;
else
P0_0 = 1;
if(cnt1>FSET)
P0_1 = 0;
else
P0_1 = 1;
if(mainmode == 0)
P0_2 = 0;
else P0_2 = 1;
if(mainmode == 1)
P0_3 = 0;
else P0_3 = 1;
if(mainmode == 2)
P0_4 = 0;
else P0_4 = 1;
}
else {
Select_Y(4);
P0 = 0xff;
}
}
main.c
#include
#include "key.h"
#include "SMG.h"
#include "IIC.h"
#include "LED.h"
unsigned char mainmode = 0,submode = 0;
unsigned short cnt = 0,cnt1 = 0;
unsigned short timecnt = 0;
unsigned short T = 0;
unsigned char timeflag1 = 0,timeflag2 = 0,timeflag3 = 0,timeflag4 = 0;
unsigned short V1,V2;
unsigned char VSET = 0;
unsigned short FSET;
unsigned char Vflag = 0,Tflag = 0;
unsigned short longkeycnt = 0;
unsigned char keyflag = 0,longkeyflag = 0, shortkeyflag = 0;
unsigned char LEDflag = 1;
void Init_Timer()
{
TH0 = 0Xff;
TL0 = 0xff;
TH1 = (65536-2000)/256;
TL1 = (65536-2000)%256;
TMOD = 0x16;
ET0 = 1;
ET1 = 1;
EA = 1;
TR0 = 1;
TR1 = 1;
}
void Init_System(void)
{
Select_Y(4);
P0 = 0XFF;
Select_Y(5);
P0 = 0X00;
}
void main(void)
{
Init_System();
Init_Timer();
SMG_DispUpdate();
while(1)
{
if(timeflag1 == 1)
{
timeflag1 = 0;
SMG_Scan();
SMG_DispUpdate();
Key_Scan();
LED_Control();
}
if(timeflag2 == 1)
{
timeflag2 = 0;
Read_V(&V1,&V2);
SMG_DispUpdate();
}
if(timeflag3 == 1)
{
timeflag3 = 0;
cnt1 = cnt;
cnt = 0;
timecnt = 0;
T = 1000000/cnt1;
SMG_DispUpdate();
}
if(timeflag4 == 1)
{
timeflag4 = 0;
VSET = AT24C02_ReadByte(0x01);
FSET = AT24C02_ReadByte(0x02);
FSET = (FSET<<8) | AT24C02_ReadByte(0x03);
}
if(Vflag == 1)
{
Vflag = 0;
AT24C02_WriteByte(0x01,V2/10);
}
if(Tflag == 1)
{
Tflag = 0;
AT24C02_WriteByte(0x02,cnt1/256);
AT24C02_WriteByte(0x03,cnt1%256);
}
}
}
void Timer0() interrupt 1
{
cnt++;
}
void Timer1() interrupt 3
{
TH1 = (65536-2000)/256;
TL1 = (65536-2000)%256;
timecnt++;
if(keyflag == 1)
{
keyflag = 0;
longkeycnt++;
if(longkeycnt>=50)
{
longkeycnt = 0;
longkeyflag = 1;
}
else
shortkeyflag = 1;
}
timeflag1 = 1;
if(timecnt == 5)
{
timeflag2 = 1;
timeflag4 = 1;
}
if(timecnt == 500)
{
timecnt = 0;
timeflag3 = 1;
}
}
这里因为全部功能展示的话,视频太大了因此就发几张图片来展示部分功能。(这里的第六位数码管是坏了的,所以显示有点问题,不过不影响功能)这里的LED1,LED2为什么一直亮着,是因为我的缓存电压和缓存频率默认是0。
1.频率界面
2.周期界面
3. 电压界面
4.LED灯禁用
第一次发文,不好的地方,希望大家多多见谅。总的来说这套题思路不难,就是在写代码会遇见各种各样的小问题,这个需要花时间解决,不过练多了就会很快。大家加油,有问题也希望大家给我指出来,一起学习。