参考佬中佬,但不搬运 !!!
#include <STC15F2K60S2.H>
#include <IIC.H>
sbit s7=P3^0;
sbit s6=P3^1;
sbit s5=P3^2;
sbit s4=P3^3;
#define u8 unsigned char
#define u16 unsigned int
u8 smg[8]={11,11,11,11,11,11,11,11};//初始显示10,全息数码管
u8 tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};
u8 LED1[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //模式1
u8 LED2[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //模式2
u8 LED3[4]={0x7e,0xbd,0xdb,0xe7}; //模式3
u8 LED4[4]={0xe7,0xdb,0xbd,0x7e}; //模式4
u16 smg_t;
u16 led_t;
u16 gap;
u8 num;
u8 smg_flag;
u8 smg_mode;
u8 led=0xff;
u8 led_mode;
u8 led_flag;
u8 pwm_duty;
u8 pwm_t;
u8 s6_sta;
u8 s7_flag;
u8 key_flag;
//============================初始化函数================================
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
void Delay5ms() //@11.0592MHz
{
unsigned char i, j;
i = 54;
j = 199;
do
{
while (--j);
} while (--i);
}
void Timer1Init(void) //1毫秒@12.000MHz led流转
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初值
TH1 = 0xFC; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
EA=1;ET1=1;
}
void Timer0Init(void) //8毫秒@12.000MHz 扫描按键
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x60; //设置定时初值
TH0 = 0xF0; //设置定时初值
TF0 = 0; //清除TF0标志
TR0=1;//定时器0开始计时
EA=1;ET0=1;
}
void Initsystem()
{
P2=(P2&0x1f)|0x80;
P0=0xff;
P2=(P2&0x1f)|0xa0;
P0=0x00;
P2=(P2&0x1f)|0xc0;
P0=0xff;
P2=(P2&0x1f)|0xe0;
P0=0xff;
}
//============================led流转================================
void setled()
{
switch(led_mode)
{
case 1:if(num>=8)num=0;led=LED1[num];break;//led1
case 2:if(num>=8)num=0;led=LED2[num];break;//led2
case 3:if(num>=4)num=0;led=LED3[num];break;//led3
case 4:if(num>=4)num=0;led=LED4[num];break;//led4
}
}
void Timer1Service() interrupt 3
{
if(smg_mode==0)
{
if(s7_flag)
{
led_t++;
//控制流转间隔
if(led_t>=gap){
led_t=0;
if(led_flag) led_flag=0;
else{num++; led_flag=1;}
}
if(led_flag) {
//控制亮度
pwm_t++;
if(pwm_t==pwm_duty)
led=0xff;
if(pwm_t==5)
{ pwm_t=0;
setled();
}
}
else led=0xff;
}
else led=0xff;
}
else//数码管0.8s闪烁
{
led=0xff;
smg_t++;
if(smg_t>=800)
{
smg_t=0; smg_flag=~smg_flag;
}
}
}
//============================PWm_duty调节================================
u8 PCF8591NUM()
{
u8 Val;
EA = 0;
IIC_Start(); //IIC启动
IIC_SendByte(0x90); //IIC选择地址,并发送写指令
IIC_WaitAck(); //等待IIC应答
IIC_SendByte(0x03); //选择模拟量输入通道
IIC_WaitAck();
IIC_Stop(); //IIC停止,接下来开始读取数据
IIC_Start(); //IIC启动
IIC_SendByte(0x91); //IIC选择地址,并发送读指令
IIC_WaitAck(); //IIC等待应答
Val = IIC_RecByte(); //接收PCF8591数据
IIC_SendAck(1); //发送应答位
IIC_Stop();
EA = 1;
if(Val>=0&&Val<50)
Val = 1;
else if(Val>=50&&Val<100)
Val = 2;
else if(Val>=100&&Val<150)
Val = 3;
else if(Val>=150&&Val<256)
Val = 4;
/*根据所得ad值返回四种不同的数据给PWM*/
return Val;
}
//============================数据保存================================
void eeprom_weite(u8 addr ,u8 val)
{
IIC_Start(); //IIC启动
IIC_SendByte(0xA0); //IIC选择地址,并发送写指令
IIC_WaitAck(); //等待IIC应答
IIC_SendByte(addr); //选择模拟量输入通道
IIC_WaitAck();
IIC_SendByte(val);
IIC_WaitAck();
IIC_Stop(); //IIC停止,接下来开始读取数据
}
u8 eeprom_read(u8 addr)
{
u8 Val;
EA = 0;
IIC_Start(); //IIC启动
IIC_SendByte(0xA0); //IIC选择地址,并发送写指令
IIC_WaitAck(); //等待IIC应答
IIC_SendByte(addr); //选择模拟量输入通道
IIC_WaitAck();
IIC_Start(); //IIC启动
IIC_SendByte(0xA1); //IIC选择地址,并发送读指令
IIC_WaitAck(); //IIC等待应答
Val = IIC_RecByte(); //接收PCF8591数据
IIC_SendAck(1); //发送应答位
IIC_Stop();
EA=1;
return Val;
}
//============================显示数码管================================
void setgap() //流转间隔数据
{
if(gap>999)
{
smg[4]=gap/1000;
smg[5]=gap/100%10;
}
else
{
smg[4]=11;
smg[5]=gap/100;
}
smg[6]=gap/10%10;
smg[7]=gap%10;
}
void setsmg() //显示界面
{
switch(smg_mode)
{
case 0 : smg[0]= smg[1]=smg[2]= smg[3]=smg[4]= smg[5]=smg[6]= smg[7]=11;
break;
case 1 : smg[0]= smg[2]=10; smg[3]=11, setgap();
if(smg_flag) { smg[1]=led_mode; }
else smg[1]=11;
break;
case 2 : smg[0]= smg[2]=10; smg[3]=11; smg[1]=led_mode;
if(smg_flag) setgap();
else { smg[4]= smg[5]=smg[6]= smg[7]=11;}
break;
}
}
void outputsmg() //数码管输出
{
u8 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 Timeber0service() interrupt 1
{
key_flag=1;
}
void scankey()
{
if(key_flag)
{
key_flag=0;
if(s7==0)
{
while(s7==0);
s7_flag=~s7_flag;
}
else if(s6==0)
{
switch(s6_sta)
{
case 0: smg_mode=1; s6_sta=1; break;
case 1: smg_mode=2; s6_sta=2; break;
case 2: smg_mode=0;TR0=0; eeprom_weite(0x00,led_mode); Delay5ms(); eeprom_weite(0x01,gap/10); TR0=1; s6_sta=0;break;
}
while(s6==0){outputsmg();}
}
else if(s5==0)
{
while(s5==0){outputsmg();}
switch(smg_mode)
{
case 1: if(led_mode>=4) led_mode=1;else led_mode+=1; break;
case 2: if(gap>=1200) gap=100;else gap+=100; break;
}
}
else if(s4==0)
{
while(s4==0){outputsmg();}
switch(smg_mode)
{
case 1: if(led_mode<=1) led_mode=1; else led_mode-=1; break;
case 2: if(gap<=100) gap=100; else gap-=100; break;
}
}
}
}
//============================main函数================================
void main()
{
Timer1Init();
Timer0Init();
Initsystem();
led_mode=eeprom_read(0x00); //上电数据读取
gap=eeprom_read(0x01);
gap*=10;
while(1)
{
scankey();
if(smg_mode) //数码管没有熄灭
{
setsmg();
outputsmg();
}
else //数码管熄灭
{
while(s4==0) //长按S4
{
led=0xff; P2=0x80;
smg[0]= smg[1]=smg[2]= smg[3]=smg[4]= smg[5]=11;
smg[6]=10; smg[7]= pwm_duty;
outputsmg();
}
}
pwm_duty=PCF8591NUM(); //读取Pwm_duty
P2=0x80; P0=led; //输出led值
}
}
驱动程序
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include "reg52.h"
#include "intrins.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
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; // 0:应答,1:非应答
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;
}
//通过I2C总线发送数据
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;
}
//从I2C总线上接收数据
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_
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);
#endif