主要涉及IIC通信中的 EEPROM和PCF8951。注意将驱动中的延时扩大8-12倍。在写本届赛题时字节超过2K,需要对软件进行破解,参考上篇
#include
#include "iic.h"
#define uchar unsigned char
#define uint unsigned int
uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0xc6};
uchar yi,er,san,si,wu,liu,qi,ba;
uchar led_start=0;
uchar mode=1;//模式编号
uchar set=0;//s6设置
uint jiange=400;//流转间隔
uint LED_tt=0,set_tt=0,AD_tt=0;//0.8秒闪烁
uint RB2=0;//AD转换
uchar flag4=0;//s4长按标志
uchar LED_n=0;
uchar Light=0,LED_T=0;
void allinit();
void Delay1ms(uint ms);
void display1(uchar yi,uchar er);
void display2(uchar san,uchar si);
void display3(uchar wu,uchar liu);
void display4(uchar qi,uchar ba);
void keyscan();
void Timer0Init(void);
void main()
{
allinit();
Timer0Init();
mode=EEPROM_Read(0x10);
Delay1ms(5);
jiange=EEPROM_Read(0x20)*100;
Delay1ms(5);
yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=11;
while(1)
{
// RB2=AD_Read(0x03);
if((set==0)&&(flag4==1))
{
if(RB2<64){yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=10;ba=1;}
else if((RB2>=64)&&(RB2<128)){yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=10;ba=2;}
else if((RB2>=128)&&(RB2<192)){yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=10;ba=3;}
else if((RB2>=192)&&(RB2<255)){yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=10;ba=4;}
}
else if(set==0)
{
yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=11;
}
keyscan();
display1(yi,er);
display2(san,si);
display3(wu,liu);
display4(qi,ba);
}
}
void keyscan()
{
if(P30==0)//s7
{
Delay1ms(5);
if(P30==0)
{
if(led_start==0)
led_start=1;
else if(led_start==1)
led_start=0;
}
while(!P30);
}
else if(P31==0)//s6
{
Delay1ms(5);
if(P31==0)
{
if(set==0)
{
set=1;set_tt=0;
if(jiange>=1000)
{
yi=10;er=mode;san=10;si=11;wu=jiange/1000;liu=jiange%1000/100;qi=jiange%100/10;ba=jiange%10;
}
else
{
yi=10;er=mode;san=10;si=11;wu=11;liu=jiange/100;qi=jiange%100/10;ba=jiange%10;
}
}
else if(set==1)
{
set=2;set_tt=0;
if(jiange>=1000)
{
yi=10;er=mode;san=10;si=11;wu=jiange/1000;liu=jiange%1000/100;qi=jiange%100/10;ba=jiange%10;
}
else
{
yi=10;er=mode;san=10;si=11;wu=11;liu=jiange/100;qi=jiange%100/10;ba=jiange%10;
}
}
else if(set==2)
{
set=0;set_tt=0;
yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=11;
EEPROM_Write(mode,0x10);
Delay1ms(5);
EEPROM_Write(jiange/100,0x20);
Delay1ms(5);
}
}
while(!P31);
}
else if(P32==0)//s5
{
Delay1ms(5);
if(P32==0)
{
if(set==1)
{
mode+=1;
if(mode>4)
{
mode=4;
}
}
else if(set==2)
{
jiange+=100;
if(jiange>1200)
{
jiange=1200;
}
}
}
while(!P32);
}
else if(P33==0)//s4
{
Delay1ms(5);
if(P33==0)
{
flag4=1;
}
}
if((flag4==1)&&(P33==1))
{
flag4=0;
if(set==1)
{
mode-=1;
if(mode<1)
{
mode=1;
}
}
else if(set==2)
{
jiange-=100;
if(jiange<400)
{
jiange=400;
}
}
}
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初值
TH0 = 0xD1; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;
ET0=1;
}
void Timer0() interrupt 1
{
set_tt++;
LED_tt++;
AD_tt++;
if((LED_tt==1)&&(led_start==1))//每1ms扫描一次模式
{
if(mode==1)
{
P2=0X00;P0=0XFF;P2=0X80;P0=~(0X01<>LED_n);P2=0X00;
}
else if(mode==3)
{
P2=0X00;P0=0XFF;P2=0X80;
if(LED_n==0)P0=0X7E;
else if(LED_n==1)P0=0XBD;
else if(LED_n==2)P0=0XDB;
else if(LED_n==3)P0=0XE7;
P2=0X00;
}
else if(mode==4)
{
P2=0X00;P0=0XFF;P2=0X80;
if(LED_n==0)P0=0XE7;
else if(LED_n==1)P0=0XDB;
else if(LED_n==2)P0=0XBD;
else if(LED_n==3)P0=0X7E;
P2=0X00;
}
}
else if(LED_tt==Light)//PWM控制 每一次循环20ms mode1 LED_tt=1亮 2-20熄灭 占空比5%
// mode2 LED_tt=1-4亮 占空比20%
// mode3 1-9占空比45% mode4 1-19 占空比95%
{
P2=0X00;P0=0XFF;P2=0X80;P0=0XFF;P2=0X00;
}
else if(LED_tt==20)//每20ms计时一次 LED_T +1
{
LED_tt=0;LED_T++;
if((LED_T*20)>=jiange)//到了对应时间间隔之后 重新计时
{
LED_T=0;
if(mode==1){LED_n++;if(LED_n>=8)LED_n=0;}
else if(mode==2){LED_n++;if(LED_n>=8)LED_n=0;}
else if(mode==3){LED_n++;if(LED_n>=4)LED_n=0;}
else if(mode==4){LED_n++;if(LED_n>=4)LED_n=0;}
}
}
if(AD_tt==200)//每200ms读取一次RB2值
{
AD_tt=0;
RB2=AD_Read(0x03);
if(RB2<64)Light=2;
else if((RB2>=64)&&(RB2<128))Light=5;
else if((RB2>=128)&&(RB2<192))Light=10;
else if((RB2>=192)&&(RB2<256))Light=19;
}
if(set_tt==800)
{
if(set==1)
{
if(jiange>=1000)
{
yi=11;er=11;san=11;si=11;wu=jiange/1000;liu=jiange%1000/100;qi=jiange%100/10;ba=jiange%10;
}
else
{
yi=11;er=11;san=11;si=11;wu=11;liu=jiange/100;qi=jiange%100/10;ba=jiange%10;
}
}
else if(set==2)
{
if(jiange>=1000)
{
yi=10;er=mode;san=10;si=11;wu=11;liu=11;qi=11;ba=11;
}
else
{
yi=10;er=mode;san=10;si=11;wu=11;liu=11;qi=11;ba=11;
}
}
}
if(set_tt==1600)
{
set_tt=0;
if(set==1)
{
if(jiange>=1000)
{
yi=10;er=mode;san=10;si=11;wu=jiange/1000;liu=jiange%1000/100;qi=jiange%100/10;ba=jiange%10;
}
else
{
yi=10;er=mode;san=10;si=11;wu=11;liu=jiange/100;qi=jiange%100/10;ba=jiange%10;
}
}
else if(set==2)
{
if(jiange>=1000)
{
yi=10;er=mode;san=10;si=11;wu=jiange/1000;liu=jiange%1000/100;qi=jiange%100/10;ba=jiange%10;
}
else
{
yi=10;er=mode;san=10;si=11;wu=11;liu=jiange/100;qi=jiange%100/10;ba=jiange%10;
}
}
}
}
void allinit()
{
P2=0X80;
P0=0XFF;
P2=0XC0;
P0=0XFF;
P2=0XE0;
P0=0XFF;
P2=0XA0;
P0=0X00;
}
void Delay1ms(uint ms) //@12.000MHz
{
uint k;
unsigned char i, j;
for(k=ms;k>0;k--)
{
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
void display1(uchar yi,uchar er)
{
P2=0XC0;
P0=0X01;
P2=0XE0;
P0=tab[yi];
Delay1ms(1);
P2=0XC0;
P0=0X02;
P2=0XE0;
P0=tab[er];
Delay1ms(1);
}
void display2(uchar san,uchar si)
{
P2=0XC0;
P0=0X04;
P2=0XE0;
P0=tab[san];
Delay1ms(1);
P2=0XC0;
P0=0X08;
P2=0XE0;
P0=tab[si];
Delay1ms(1);
}
void display3(uchar wu,uchar liu)
{
P2=0XC0;
P0=0X10;
P2=0XE0;
P0=tab[wu];
Delay1ms(1);
P2=0XC0;
P0=0X20;
P2=0XE0;
P0=tab[liu];
Delay1ms(1);
}
void display4(uchar qi,uchar ba)
{
P2=0XC0;
P0=0X40;
P2=0XE0;
P0=tab[qi];
Delay1ms(1);
P2=0XC0;
P0=0X80;
P2=0XE0;
P0=tab[ba];
Delay1ms(1);
P2=0XC0;
P0=0XFF;
P2=0XE0;
P0=0XFF;//关闭所有数码管使其亮度一致
}
驱动参考
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include
#include "intrins.h"
#include "iic.h"
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop;
SDA = 1;
}
////应答位控制
//void IIC_Ack(bit ackbit)
//{
// if(ackbit)
// {
// SDA = 0;
// }
// else
// {
// SDA = 1;
// }
// somenop;
// SCL = 1;
// somenop;
// SCL = 0;
// SDA = 1;
// somenop;
//}
//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
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;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 1;
somenop;
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
somenop;
}
return da;
}
//AD转换
unsigned char AD_Read(unsigned char add)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);//采集AD信息的地址
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Stop();
return temp;
}
//EEPROM读
unsigned char EEPROM_Read(unsigned char add)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Stop();
return temp;
}
//EEPROM写
void EEPROM_Write(unsigned char dat,unsigned char add)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
#ifndef _IIC_H
#define _IIC_H
//函数声明
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Ack(bit ackbit);
void IIC_SendByte(unsigned char byt);
bit IIC_WaitAck(void);
unsigned char IIC_RecByte(void);
//添加
//AD转换
unsigned char AD_Read(unsigned char add);
//EEPROM读
unsigned char EEPROM_Read(unsigned char add);
//EEPROM写
void EEPROM_Write(unsigned char dat,unsigned char add);
#endif