本程序借鉴了小蜜蜂老师的代码风格。
记录下自己学习过程中的代码。
依旧是和大白话一样简单繁琐的代码。
这一届感觉难度挺大,一开始题目都看不太懂,后续也有不少小bug,不过最后只有pwm处理的不太好,亮度低的时候会闪,其余的问题不大。
main.c
#include "reg52.h"
#include "iic.h"
unsigned char code SMG_NoDot[18]={0xc0,0xf9,
0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
void Delay(unsigned int t)
{
while(t--);
}
void HC573(unsigned char a,unsigned char b)
{
P0=b;
switch(a)
{
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;
case 0:
P2=(P2&0x1f)|0x00;
break;
}
P2=(P2&0x1f)|0x00;
}
void DisplaySMG(unsigned char pos,unsigned char dat)
{
HC573(6,(0x01<<pos));
HC573(7,dat);
Delay(500);
HC573(6,0xff);
HC573(7,0xff);
}
char mode=1; //led运行模式
unsigned int time[4]; //数组存放四个间隔
unsigned char lignt=0; //亮度
unsigned char smg_mode=0; //数码管显示
unsigned char n1=0; //设置选择位
unsigned char smg=1; //数码管闪烁
void Display()
{
if(smg_mode==0) //设置界面
{
if(n1==0) //初始化熄灭
{
DisplaySMG(6,0xff);
DisplaySMG(7,0xff);
}
else if(n1==1) //选中运行模式
{
if(smg) //闪烁
{
DisplaySMG(0,SMG_NoDot[16]);
DisplaySMG(1,SMG_NoDot[mode]);
DisplaySMG(2,SMG_NoDot[16]);
}
else
{
DisplaySMG(0,0xff);
DisplaySMG(1,0xff);
DisplaySMG(2,0xff);
}
if(time[mode-1]>999)
DisplaySMG(4,SMG_NoDot[time[mode-1]/1000]);
DisplaySMG(5,SMG_NoDot[time[mode-1]/100%10]);
DisplaySMG(6,SMG_NoDot[time[mode-1]/10%10]);
DisplaySMG(7,SMG_NoDot[time[mode-1]%10]);
}
else if(n1==2) //选中流转间隔
{
DisplaySMG(0,SMG_NoDot[16]);
DisplaySMG(1,SMG_NoDot[mode]);
DisplaySMG(2,SMG_NoDot[16]);
if(smg)
{
if(time[mode-1]>999)
DisplaySMG(4,SMG_NoDot[time[mode-1]/1000]);
DisplaySMG(5,SMG_NoDot[time[mode-1]/100%10]);
DisplaySMG(6,SMG_NoDot[time[mode-1]/10%10]);
DisplaySMG(7,SMG_NoDot[time[mode-1]%10]);
}
else
{
DisplaySMG(4,0xff);
DisplaySMG(5,0xff);
DisplaySMG(6,0xff);
DisplaySMG(7,0xff);
}
}
}
else //亮度等级显示
{
DisplaySMG(6,SMG_NoDot[16]);
DisplaySMG(7,SMG_NoDot[lignt]);
}
}
void Write1(unsigned char addr,unsigned char dat) //24C02写入
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
unsigned char Read1(unsigned char addr) 24C02读取
{
unsigned char tem;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
tem=IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return tem;
}
unsigned char Read2() //RB2电压采样
{
unsigned char tem;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x03);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
tem=IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return tem;
}
void InitT()
{
TMOD=0x11;
TH0=(65535-1000)/256;
TL0=(65535-1000)%256;
TH1=(65535-1000)/256;
TL1=(65535-1000)%256;
ET0=1;
EA=1;
TR0=1;
ET1=1;
}
unsigned char pwm_t=0,pwm=0; //计时,占空比
unsigned int adc=0; //采样电压
unsigned char pwm_mode=0;
unsigned int smg_t=0;
void Service0() interrupt 1
{
TH0=(65535-1000)/256;
TL0=(65535-1000)%256;
pwm_t++;
if(pwm_t<=pwm)
pwm_mode=0;
else if(pwm_t<=20)
pwm_mode=1;
else
pwm_t=0;
if(n1)
{
smg_t++;
if(smg_t==800) //0.8s
{
smg=!smg;
smg_t=0;
}
}
}
unsigned int led_t=0,led_s=1; //计时,led状态
unsigned char led_start=0; //led启动
unsigned char led_mode=1;
void Service1() interrupt 3
{
TH1=(65535-1000)/256;
TL1=(65535-1000)%256;
if(led_start==1)
{
led_t++;
if(led_t==time[led_mode-1])
{
led_s++;
if(led_s>24)
led_s=1;
led_t=0;
}
}
}
unsigned char led=0xff;
void LED_Run() //led运行
{
if(led_start==1)
{
if(pwm_mode==0)
{
if((led_s>=1)&&(led_s<=8))
{
led_mode=1;
led=~(0x01<<(led_s-1));
}
else if((led_s>=9)&&(led_s<=16))
{
led_mode=2;
led=~(0x80>>(led_s-9));
}
else if((led_s>=17)&&(led_s<=20))
{
led_mode=3;
switch(led_s)
{
case 17:
led=0x7e;
break;
case 18:
led=0xbd;
break;
case 19:
led=0xdb;
break;
case 20:
led=0xe7;
break;
}
}
else if((led_s>=21)&&(led_s<=24))
{
led_mode=4;
switch(led_s)
{
case 21:
led=0xe7;
break;
case 22:
led=0xdb;
break;
case 23:
led=0xbd;
break;
case 24:
led=0x7e;
break;
}
}
}
else
led=0xff;
HC573(4,led);
}
}
void LED_Lignt() //亮度
{
adc=Read2()*(5.0/255)*100;
if((adc>0)&&(adc<=125))
{
lignt=1;
pwm=5;
}
else if((adc>125)&&(adc<=250))
{
lignt=2;
pwm=10;
}
else if((adc>250)&&(adc<=375))
{
lignt=3;
pwm=15;
}
else if((adc>375)&&(adc<=500))
{
lignt=4;
pwm=20;
}
}
sbit S4=P3^3;
sbit S5=P3^2;
sbit S6=P3^1;
sbit S7=P3^0;
void Scan()
{
if(S4==0)
{
Delay(100);
if(S4==0)
{
if(n1==0)
{
smg_mode=1;
}
else if(n1==1)
{
mode--;
if(mode<1)
mode=4;
}
else if(n1==2)
{
time[mode-1]-=100;
if(time[mode-1]<400)
time[mode-1]=1200;
}
while(S4==0)
{
LED_Lignt();
Display();
LED_Run();
}
smg_mode=0;
}
}
if(S5==0)
{
Delay(100);
if(S5==0)
{
if(n1==1)
{
mode++;
if(mode>4)
mode=1;
}
else if(n1==2)
{
time[mode-1]+=100;
if(time[mode-1]>1200)
time[mode-1]=400;
}
while(S5==0)
Display();
}
}
if(S6==0)
{
Delay(100);
if(S6==0)
{
n1++;
if(n1==3)
{
n1=0;
switch(mode) //将改变后的间隔写入地址
{
case 1: Write1(0x00,time[0]/10); break;
case 2: Write1(0x01,time[1]/10); break;
case 3: Write1(0x02,time[2]/10); break;
case 4: Write1(0x03,time[3]/10); break;
}
}
while(S6==0)
Display();
}
}
if(S7==0)
{
Delay(100);
if(S7==0)
{
led_start=1;
if(TR1==0)
TR1=1;
else
TR1=0;
while(S7==0)
{
Display();
LED_Run();
}
}
}
}
void Init()
{
HC573(4,0xff);
HC573(5,0x00);
HC573(6,0xff);
HC573(7,0xff);
InitT();
if(((Read1(0x00)*10)<400)||((Read1(0x00)*10)>1200)) //边界控制
time[0]=400;
else
time[0]=Read1(0x00)*10; //每次上电自动载入
if(((Read1(0x01)*10)<400)||((Read1(0x01)*10)>1200))
time[1]=400;
else
time[1]=Read1(0x01)*10;
if(((Read1(0x02)*10)<400)||((Read1(0x02)*10)>1200))
time[2]=400;
else
time[2]=Read1(0x02)*10;
if(((Read1(0x03)*10)<400)||((Read1(0x03)*10)>1200))
time[3]=400;
else
time[3]=Read1(0x03)*10;
}
void main()
{
Init();
while(1)
{
LED_Run();
LED_Lignt();
Scan();
Display();
}
}
iic.c
#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;
}
iic.h
#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