蓝桥杯学习笔记 单片机CT107D 第十三届国赛

碎碎念:这一届的难点我觉得在于PWM输出与其他模块之间的冲突,同时如果不使用PCA的话还有定时器之间的冲突的问题。我最开始做的时候并没有在意这些细节上的问题,然后出了许多问题,比如LED和数码管乱闪,IIC时序异常等,现在虽然解决了一部分,但还是有一些瑕疵。

一.题目要求:

自己的一些见解:

关于NE555:

        在测量频率的时候,我发现数码管显示的频率与频率计测出的频率误差较大,排查之后发现问题处在PCA上,因为我时在定时器中调用了超声波,但超声波SendWave的时候会有12*2*8的延时,这段延时对频率测量的影响还是蛮大的,所以我这里新开了一个定时器2用于频率测量.

关于PWM:

        PWM实现的时候,出现LED,数码管乱闪的问题,我初步推测是应为PWM中断的频率太高( 100us),导致P0口的值非常复杂,而且一开始的时候, 我是每进一次中断都会给P0口赋值,加重了P0口值的混乱。只有我便采取了几种措施.一是提高定时器的计数周期(100us改到200us),之后不再是每进一次中断对P0口赋值一次,而是在占空比处和计数值为10的时候分别赋值,第三便是在进中断的时候先存好P0口的值,中断结束后将P0原先的值赋值回去.

void Timer1_Service() interrupt 3
{
	unsigned char temp;
	count_times++;
	PWM_times++;
	temp=P0;
	if(count_times==5000)
	{
		dat_F=count_F;
		count_F=0;
		count_times=0;
	}
	if(LED_Flag==1)
	{
		if(count_times%500==0)
		{
			Flash_Flag=~Flash_Flag;
			if(Flash_Flag==1)
			{
				if(SMG_Mode==1)
				{
					LED_Mode=(LED_Mode|0x07)&0xfe;
					SelectHC573(4,LED_Mode);
				}
				else if(SMG_Mode==2)
				{
					LED_Mode=(LED_Mode|0x07)&0xfd;
					SelectHC573(4,LED_Mode);
				}
				else if(SMG_Mode==3)
				{
					LED_Mode=(LED_Mode|0x07)&0xfb;
					SelectHC573(4,LED_Mode);
				}
			}
		else if(Flash_Flag==0)
			{
				LED_Mode|=0x07;
				SelectHC573(4,LED_Mode);
			}
		}
	}
	if(PWM_times==5)
	{
		jdq_Mode|=0x20;		
		PWM_times=0;
	}
	if(PWM_times==Duty)
	{
		jdq_Mode&=0xdf;
	}
	SelectHC573(5,jdq_Mode);
	P0=temp;
}

第二便是PWM影响IIC时序问题,之前采用的是在iic中直接关闭总中断的方式,当时表面上没有什么问题,但拿频率计测量发现,pwm的频率降为800khz左右,不符合要求,之后我看题目要求中对ADC没有时间上的要求,所以将ADC刷新的时间延迟,放在定时器中没-.5s调用一次,整体观感和性能还是不错的,但数码管还有偶尔会闪烁.

关于掉电不丢失:

掉电不丢失有一个点就是是否第一次上电,我的解决方法是在一个内存地址内写入一个标志位(随便写,我这里采用的是0xac),上电的时候先读取标志位,如果读取到了说明不是第一次,之间读取即可,如果读取到的数据不对,则对存放内容的地址空间写入0 

二.代码部分:
main.c
#include <STC15F2K60S2.H>
#include "intrins.h"
#include "iic.h"
sbit S4=P3^3;
sbit S5=P3^2;
sbit S6=P3^1;
sbit S7=P3^0;
sbit TX=P1^0;
code unsigned char SMG_Nodot[] =
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
code unsigned char SMG_Dot[] =
{0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
unsigned char SMG_Mode=1;
unsigned char show_Mode=1;
unsigned int dat_F;
unsigned int count_F;
unsigned char shidu;
unsigned char PCA_times;
unsigned char Distance;
unsigned char param_Mode=1;
unsigned char fre_param=90;
unsigned char shidu_param=40;
unsigned char Dis_param=6;
unsigned int count_times;
unsigned char ADC_Value;
unsigned char DAC_Value;
bit PCA_Flag;
unsigned int times;
unsigned char jdq_Mode=0x00;
unsigned char LED_Mode=0xff;
bit LED_Flag;
bit Flash_Flag;
unsigned char Duty;
unsigned char PWM_times;
unsigned char chufa_times;
bit chufa_Flag=0;
unsigned int Key_times;
bit Key_Flag=0;
void Delay_SMG(unsigned int t)
{
	while(t--);
}
void Delay12us()		//@12.000MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 33;
	while (--i);
}

void SelectHC573(unsigned char channel,unsigned char dat)
{
	P2=(P2&0x1f)|0x00;
	P0=dat;
	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;
		case 0:
			P2=(P2&0x1f)|0x00;
		break;
	}
	P2=(P2&0x1f)|0x00;
}
void Display_SMG(unsigned char pos,unsigned char dat)
{
	SelectHC573(6,0x01<<(pos-1));
	SelectHC573(7,dat);
	Delay_SMG(500);
	SelectHC573(6,0x01<<(pos-1));
	SelectHC573(7,0xff);
}
void Display_Dynamic()
{
	if(SMG_Mode==1)
	{
		Display_SMG(1,SMG_Nodot[15]);
		Display_SMG(2,SMG_Nodot[chufa_times/10]);
		Display_SMG(3,SMG_Nodot[chufa_times%10]);
		if(show_Mode==1)
		{
			if(dat_F>9999)
			{
				Display_SMG(4,SMG_Nodot[dat_F/10000]);
			}
			if(dat_F>999)
			{
				Display_SMG(5,SMG_Nodot[dat_F%10000/1000]);
			}
			if(dat_F>99)
			{
				Display_SMG(6,SMG_Nodot[dat_F%1000/100]);
			}
			if(dat_F>9)
			{
				Display_SMG(7,SMG_Nodot[dat_F%100/10]);
			}
			Display_SMG(8,SMG_Nodot[dat_F%10]);
		}
		if(show_Mode==2)
		{
			if(dat_F>9999)
			{
				Display_SMG(6,SMG_Nodot[dat_F/10000]);
			}
			Display_SMG(7,SMG_Dot[dat_F%10000/1000]);
			Display_SMG(8,SMG_Nodot[dat_F%1000/100]);
		}
	}
	if(SMG_Mode==2)
	{
		Display_SMG(1,0x89);
		Display_SMG(7,SMG_Nodot[shidu/10]);
		Display_SMG(8,SMG_Nodot[shidu%10]);
	}
	if(SMG_Mode==3)
	{
		Display_SMG(1,SMG_Nodot[10]);
		if(show_Mode==1)
		{
			if(Distance>99)
			{
				Display_SMG(6,SMG_Nodot[Distance/100]);
			}
			if(Distance>9)
			{
				Display_SMG(7,SMG_Nodot[Distance%100/10]);
			}
			Display_SMG(8,SMG_Nodot[Distance%10]);
		}
		if(show_Mode==2)
		{
			Display_SMG(6,SMG_Dot[Distance/100]);
			Display_SMG(7,SMG_Nodot[Distance%100/10]);
			Display_SMG(8,SMG_Nodot[Distance%10]);
		}
	}
	if(SMG_Mode==4)
	{
		Display_SMG(1,0x8c);
		Display_SMG(2,SMG_Nodot[param_Mode]);
		if(param_Mode==1)
		{
			if(fre_param>99)
			{
				Display_SMG(6,SMG_Nodot[fre_param/100]);
			}
			Display_SMG(7,SMG_Dot[fre_param%100/10]);
			Display_SMG(8,SMG_Nodot[fre_param%10]);
		}
		if(param_Mode==2)
		{
			Display_SMG(7,SMG_Nodot[shidu_param/10]);
			Display_SMG(8,SMG_Nodot[shidu_param%10]);
		}
		if(param_Mode==3)
		{
			Display_SMG(7,SMG_Dot[Dis_param/10]);
			Display_SMG(8,SMG_Nodot[Dis_param%10]);
		}
	}
}
void Timer1Init(void)		//200us@12.000MHz
{
	AUXR &= 0xBF;		
	TMOD = 0x06;		
	TL1 = 0x38;		
	TH1 = 0xFF;		
	TF1 = 0;		
	TR1 = 1;		
	EA=1;
	ET1=1;
}
void Timer2Init(void)		//1ms@12.000MHz
{
	AUXR &= 0xFB;		
	T2L = 0x18;		
	T2H = 0xFC;		
	AUXR |= 0x10;		
	IE2=0x04;
}

void Timer0_Init()
{
	TH0=0xff;
	TL0=0xff;
	TR0=1;
	ET0=1;
}
void Timer0_Service() interrupt 1
{
	count_F++;
}
void PCA_Init()
{
	CMOD=0x01;
	CCON=0x00;
	CCAPM0=0x11;
}
void Send_Wave()
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		TX=0;
		Delay12us();
		TX=1;
		Delay12us();
	}
}
void Measure_Distance()
{
	CH=CL=0;
	Send_Wave();
	CR=1;
	if(PCA_Flag==0)
	{
		Distance=255;
	}
	if(PCA_Flag==1)
	{
		Distance=times*0.017;
	}
}
void PCA_Service() interrupt 7
{
	CR=0;
	if(CCF0==1)
	{
		CCF0=0;
		PCA_Flag=1;
		times=(CCAP0H<<8)|CCAP0L;
	}
	if(CF==1)
	{
		CF=0;
		PCA_Flag=0;
	}
}
void Timer1_Service() interrupt 3
{
	unsigned char temp;
	count_times++;
	PWM_times++;
	temp=P0;
	if(count_times==5000)
	{
		dat_F=count_F;
		count_F=0;
		count_times=0;
	}
	if(LED_Flag==1)
	{
		if(count_times%500==0)
		{
			Flash_Flag=~Flash_Flag;
			if(Flash_Flag==1)
			{
				if(SMG_Mode==1)
				{
					LED_Mode=(LED_Mode|0x07)&0xfe;
					SelectHC573(4,LED_Mode);
				}
				else if(SMG_Mode==2)
				{
					LED_Mode=(LED_Mode|0x07)&0xfd;
					SelectHC573(4,LED_Mode);
				}
				else if(SMG_Mode==3)
				{
					LED_Mode=(LED_Mode|0x07)&0xfb;
					SelectHC573(4,LED_Mode);
				}
			}
		else if(Flash_Flag==0)
			{
				LED_Mode|=0x07;
				SelectHC573(4,LED_Mode);
			}
		}
	}
	if(PWM_times==5)
	{
		jdq_Mode|=0x20;		
		PWM_times=0;
	}
	if(PWM_times==Duty)
	{
		jdq_Mode&=0xdf;
	}
	SelectHC573(5,jdq_Mode);
	P0=temp;
}
void Timer2_Service() interrupt 12
{
	PCA_times++;
	if(PCA_times==125)
	{
		PCA_times=0;
		Measure_Distance();
	}
	if(Key_Flag==1)
	{
		Key_times++;
	}
}
void ADC_Read()
{
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x43);
	I2CWaitAck();
	I2CStop();
	EA=0;
	I2CStart();	
	I2CSendByte(0x91);
	I2CWaitAck();
	ADC_Value=I2CReceiveByte();
	EA=1;
	I2CSendAck(1);
	I2CStop();
	shidu=ADC_Value/255.0*99;
	
}
void DAC_Caculate()
{
	float k;
	k=204.0/(80-shidu_param);
	if(shidu>80)
	{
		DAC_Value=255;
	}
	if(shidu<shidu_param)
	{
		DAC_Value=51;
	}
	if(shidu<80&&shidu>shidu_param)
	{
		DAC_Value=k*(shidu-shidu_param)+51;
	}
}
void DAC_Write()
{
	DAC_Caculate();
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x43);
	I2CWaitAck();
	I2CSendByte(DAC_Value);
	I2CWaitAck();
	I2CStop();
}
unsigned char AT24C02_Read(unsigned char address)
{
	unsigned char temp;
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(address);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	temp=I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	return temp;
}
void AT24C02_Write(unsigned char dat)
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(0x00);
	I2CWaitAck();
	I2CSendByte(dat);
	I2CWaitAck();
	I2CSendByte(0xac);
	I2CWaitAck();
	I2CStop();
}
void Scan_Key()
{
	if(S4==0)
	{
		Delay_SMG(500);
		if(S4==0)
		{
			switch(SMG_Mode)
			{
				case 1:
					SMG_Mode=2;
				break;
				case 2:
					SMG_Mode=3;
					show_Mode=1;
				break;
				case 3:
					SMG_Mode=4;
					param_Mode=1;
				break;
				case 4:
					SMG_Mode=1;
					show_Mode=1;
				break;
			}
		}
		while(S4==0)
		{
			Display_Dynamic();
			ADC_Read();
		}
	}
	if(S5==0)
	{
		Delay_SMG(500);
		if(S5==0)
		{
			if(SMG_Mode==4)
			{
				switch(param_Mode)
				{
					case 1:
						param_Mode=2;
					break;
					case 2:
						param_Mode=3;
					break;
					case 3:
						param_Mode=1;
					break;
				}
			}
		}
		while(S5==0)
		{
			Display_Dynamic();
			ADC_Read();
		}
	}
	if(S6==0)
	{
		Delay_SMG(500);
		if(S6==0)
		{
			if(SMG_Mode==3)
			{
				switch(show_Mode)
				{
					case 1:
						show_Mode=2;
					break;
					case 2:
						show_Mode=1;
					break;
				}
			}
			if(SMG_Mode==4)
			{
				if(param_Mode==1)
				{
					fre_param+=5;
					if(fre_param>120)
					{
						fre_param=10;
					}
				}
				if(param_Mode==2)
				{
					shidu_param+=10;
					if(shidu_param>60)
					{
						shidu_param=10;
					}
				}
				if(param_Mode==3)
				{
					Dis_param+=1;
					if(Dis_param>12)
					{
						Dis_param=1;
					}
				}
			}
		}
		while(S6==0)
		{
			Display_Dynamic();
			ADC_Read();
		}
	}
	if(S7==0)
	{
		Delay_SMG(500);
		if(S7==0)
		{
			while(S7==0)
			{
				Key_Flag=1;
				Display_Dynamic();
				ADC_Read();
			}
			Key_Flag=0;
			if(Key_times>1000)
			{
				if(SMG_Mode==2)
				{
					chufa_times=0;
					AT24C02_Write(chufa_times);
				}
			}
			if(Key_times<=1000)
			{
				if(SMG_Mode==1)
				{
					switch(show_Mode)
					{
						case 1:
							show_Mode=2;
						break;
						case 2:
							show_Mode=1;
						break;
					}
				}
				if(SMG_Mode==4)
				{
					if(param_Mode==1)
					{
						fre_param-=5;
						if(fre_param<10)
						{
							fre_param=120;
						}
					}
					if(param_Mode==2)
					{
						shidu_param-=10;
						if(shidu_param<10)
						{
							shidu_param=60;
						}
					}
					if(param_Mode==3)
					{
						Dis_param-=1;
						if(Dis_param<1)
						{
							Dis_param=12;
						}
					}
				}
			}
			Key_times=0;
		}
	}
}
void PWM_Config()
{
	if(dat_F>fre_param*100)
	{
		Duty=4;
	}
	if(dat_F<fre_param*100)
	{
		Duty=1;
	}
}
void jdq_Control()
{
	if(Distance>Dis_param*10)
	{
		jdq_Mode|=0x10;
		SelectHC573(5,jdq_Mode);
		if(chufa_Flag==1)
		{
			chufa_Flag=0;
			chufa_times++;
			AT24C02_Write(chufa_times);
		}
	}
	if(Distance<Dis_param*10)
	{
		jdq_Mode&=0xef;
		SelectHC573(5,jdq_Mode);
		chufa_Flag=1;
	}
}
void LED_control()
{
	if(SMG_Mode==1||SMG_Mode==2||SMG_Mode==3)
	{
		LED_Flag=1;
	}
	if(SMG_Mode==4)
	{
		LED_Flag=0;
		LED_Mode|=0x07;
	}
	if(dat_F>fre_param)
	{
		LED_Mode&=0xf7;
		SelectHC573(4,LED_Mode);
	}
	if(dat_F<fre_param)
	{
		LED_Mode|=0x08;
		SelectHC573(4,LED_Mode);
	}
	if(shidu>shidu_param)
	{
		LED_Mode&=0xef;
		SelectHC573(4,LED_Mode);
	}
	if(shidu<shidu_param)
	{
		LED_Mode|=0x10;
		SelectHC573(4,LED_Mode);
	}
	if(Distance>Dis_param*10)
	{
		LED_Mode&=0xdf;
		SelectHC573(4,LED_Mode);
	}
	if(Distance<Dis_param*10)
	{
		LED_Mode|=0x20;
		SelectHC573(4,LED_Mode);
	}
}
void Sys_Init()
{
	SelectHC573(4,0xff);
	SelectHC573(5,0x00);
	Timer1Init();
	EA=0;
	Timer0_Init();
	Timer2Init();
	PCA_Init();
	if(AT24C02_Read(0x01)!=0xac)
	{
		AT24C02_Write(0);
	}
	if(AT24C02_Read(0x01)==0xac)
	{
		chufa_times=AT24C02_Read(0x00);
	}
	EA=1;
}
void main()
{
	Sys_Init();
	while(1)
	{
		Display_Dynamic();
		Scan_Key();
		ADC_Read();
		DAC_Write();
		jdq_Control();
		PWM_Config();
		LED_control();
	}
}
 iic.h
/*	#   I2C代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <STC15F2K60S2.H>
#include "intrins.h"
sbit scl=P2^0;
sbit sda=P2^1;
#define DELAY_TIME	10
//
static void I2C_Delay(unsigned char n)
{
    do
    {
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();		
    }
    while(n--);      	
}

//
void I2CStart(void)
{
    sda = 1;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 0;
	I2C_Delay(DELAY_TIME);
    scl = 0;    
}

//
void I2CStop(void)
{
    sda = 0;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 1;
	I2C_Delay(DELAY_TIME);
}

//
void I2CSendByte(unsigned char byt)
{
    unsigned char i;
	
    for(i=0; i<8; i++){
        scl = 0;
		I2C_Delay(DELAY_TIME);
        if(byt & 0x80){
            sda = 1;
        }
        else{
            sda = 0;
        }
		I2C_Delay(DELAY_TIME);
        scl = 1;
        byt <<= 1;
		I2C_Delay(DELAY_TIME);
    }
	
    scl = 0;  
}

//
unsigned char I2CReceiveByte(void)
{
	unsigned char da;
	unsigned char i;
	for(i=0;i<8;i++){   
		scl = 1;
		I2C_Delay(DELAY_TIME);
		da <<= 1;
		if(sda) 
			da |= 0x01;
		scl = 0;
		I2C_Delay(DELAY_TIME);
	}
	return da;    
}

//
unsigned char I2CWaitAck(void)
{
	unsigned char ackbit;
	
    scl = 1;
	I2C_Delay(DELAY_TIME);
    ackbit = sda; 
    scl = 0;
	I2C_Delay(DELAY_TIME);
	
	return ackbit;
}

//
void I2CSendAck(unsigned char ackbit)
{
    scl = 0;
    sda = ackbit; 
	I2C_Delay(DELAY_TIME);
    scl = 1;
	I2C_Delay(DELAY_TIME);
    scl = 0; 
	sda = 1;
	I2C_Delay(DELAY_TIME);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值