蓝桥杯单片机第九届省赛

本程序借鉴了小蜜蜂老师的代码风格。

记录下自己学习过程中的代码。

依旧是和大白话一样简单繁琐的代码。

这一届感觉难度挺大,一开始题目都看不太懂,后续也有不少小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

  • 17
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值