资讯详情

蓝桥杯单片机------第十一届省赛第一场

题目要求

考察模块

分析

1、注意点

2、题目分析

3、LED功能实现

实现程序代码

1、主函数

iic.c

iic.h


题目要求

考察模块

  • 三大金刚:LED,数字管,按钮(矩阵键盘)。
  • ADC。---IIC
  • EEPROM。-----IIC

分析

1、注意点

首先要注意题目要求12MHZ,以及按键KBD模式,J13为IO使用模式stc--isp生成定时器时,必须选择12MHZ,以前用过11.0592MHZ的。

读取的通道值是Rb2的,地址为0x03,EEPROM存数地址为0,读取的电压范围为0-5.0V

初始状态很重要

2、题目分析

通过变量值的变化,可以设置一个变量来实现界面显示。这里有一个xd我觉得自己写的很好。可以借鉴

实现计数值加1条件:

从图可以看出,当Van在减少的部分下,减少等于Vp时,计数值加1。Van3值等于参数值Vp值加1。一定要注意。

解决方法:

我们可以比较两者的状态大小。

 static uchar dat;  switch(dat)   //计数值加1  {   case 0:   if(V_Value>V_Value_P)   {     dat=1;   }   break;    case 1:   if(V_Value<V_Value_P)   {     N  ;     dat=0;   }   break;  }  V_Value:Van3的值。 V_Value_P:Vp的值。

3、LED功能实现

其实LED很恶心

但还是可以解决的,一个学长的方法:用一个数来存储某个小灯的状态值,通过这个值来控制led灯的亮灭。比如:L1亮灭

void Led_Set()			 //小灯
{
    P2 = 0x80;
    P0 = ~LED;
    P2 = 0;
}


void Time1()interrupt 3
{
   static uint LED_count;
   if(V_Value<V_Value_P)
   {
   		LED_count++;
   	  if(LED_count==5000)
	  {
	   	LED|=1;		  //L1亮
	  }
   }
   else
   {
   	 LED_count=0;
   	 LED&=~1;		  //L1灭
   }
}

        其他的小灯也用同种方法,你可以看最后主程序中的其他几个小灯的实现方法,和这个一模一样。不直接给小灯赋值的原因是,单独一个小灯可能没啥问题,但是几个小灯一起的时候,你就会发现问题很大。各种奇葩问题都有。本人之前就是直接赋值写的,最后小灯部分没完成。采用这个方法,觉得很nice,真的!

程序代码实现

1、主函数

#include<stc15f2k60s2.h>
#include"iic.h"
#define uchar unsigned char
#define uint unsigned int

sbit buzzer =P0^6;		//蜂鸣器
sbit relay =P0^4;	   //继电器
/*************  本地常量声明    **************/
uchar code t_display[]={                       //标准字库
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

uchar code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //位码
uchar smg_table[]={16,16,16,16,16,16,16,16};
uchar keypress,ReadData,Trg,Cont;
bit key_flag;  //按键标志
uchar mode=0;//0为数据界面,1参数界面,2为计数界面
uint V_Value;
int V_Value_P=0;		   //ADC转换值和vp值
uint N=0;			  //计数值
uchar LED;			//LED变化
uchar key_num;	  //无效按键计数

void Init_close()	 //关闭外设
{
	P2=0xa0; buzzer = 0; relay=0;P2=0x00;
	P2=0x80;P0=0xff;P2=0x00;
}

void Led_Set()			 //小灯
{
    P2 = 0x80;
    P0 = ~LED;
    P2 = 0;
}
void Timer0Init(void)		//1毫秒@12.000MHz
{
	EA=1;ET0=1;
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x20;		//设置定时初值
	TH0 = 0xD1;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}
void Timer1Init(void)		//1毫秒@12.000MHz
{
	EA=1;ET1=1;
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x20;		//设置定时初值
	TH1 = 0xD1;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
}

void Time0()interrupt 1
{
	static uint smg_count,key_count,i;
	if(++smg_count>=2)
	{
	   smg_count=0;
	   P2=0xe0;P0=0xff;P2=0x00;
	   P2=0xc0;P0=T_COM[i];P2=0x00;
	   P2=0xe0;P0=~t_display[smg_table[i]];P2=0x00;
	   i++;
	   if(i>=8)i=0;
	}
	if(++key_count>=10)
	{
	  key_count=0;
	  key_flag=1;
	}
}
void Time1()interrupt 3
{
   static uint LED_count;
   if(V_Value<V_Value_P)
   {
   		LED_count++;
   	  if(LED_count==5000)
	  {
	   	LED|=1;		  //L1亮
	  }
   }
   else
   {
   	 LED_count=0;
   	 LED&=~1;		  //L1灭
   }
}

void N_num()
{
	static uchar dat;
	switch(dat)			//计数值加1
	{
		case 0:
		if(V_Value>V_Value_P)
		{
		  dat=1;
		}
		break;

		case 1:
		if(V_Value<V_Value_P)
		{
		  N++;
		  dat=0;
		}
		break;
	}
	if(N%2==1)		//N为奇数
	{
	   LED |= 2; //L2点亮
	}
	else {
	 LED &=~2; //L2灭
	}
}
void ReadKey()
{
  P3=0xf0;
  P42=P44=1;
  P36=P42;
  P37=P44;
  keypress=P3;

  P3=0x0f;
  P42=P44=0;

  ReadData=(keypress|P3)^0xff;
  Trg=ReadData&(ReadData^Cont);
  Cont =ReadData;
}

void dis_key()
{
  if(key_flag)
  {
  	key_flag=0;
	ReadKey();
	switch(Trg)
	{
	   case 0x28:		 //s12
		   mode++;
		if(mode>=3)mode=0;
			key_num=0;
	   break;
	   case 0x24:		 //s13
		  if(mode==2) {
		  	 key_num=0;
		  		N=0;			//N计数界面下清0
			}
		else{
		  key_num++;
		}
	   break;
	   case 0x18:		 //s16
		   if(mode==1)
		   {
		   	 key_num=0;
		   	  V_Value_P+=50;
			  if(V_Value_P==550)V_Value_P=0;
		   }
		   else{
		  key_num++;
		}
	   break;
	   case 0x14:		   //s17
		   if(mode==1)
		   {
		   	 key_num=0;
		   	  V_Value_P-=50;
			  if(V_Value_P<0)V_Value_P=500;
		   }
		   else{
		  key_num++;
		}
	   break;
	}
	  //无效按键
		if(key_num>=3)
		{
		 LED |= 4; //L3点亮	
		}
		else{
		  LED &=~4; //L3灭
		}
  }
}
void main()
{
	Init_close();//关闭外设
	Timer0Init();
	Timer1Init();
	Write_Adc(0x03);		//rb2
	V_Value_P=Read_Eeprom(0x00)*10;
	while(1)
	{
		Led_Set();
		EA=0;
		V_Value=Read_Adc(0x03)*500.0/255;		   //读取rb2通道值
		EA=1;
		if(mode==2){
		   EA=0;
		   Write_Eeprom(0x00,V_Value_P/10);				 //存Vp参数值
		   EA=1;
		}
		switch(mode)		//界面显示
		{
		  case 0:
		   	  smg_table[0]=25;
			  smg_table[1]=16;
			  smg_table[2]=16;
			  smg_table[3]=16;
			  smg_table[4]=16;
			  smg_table[5]=V_Value/100+32;
			  smg_table[6]=V_Value/10%10;
			  smg_table[7]=V_Value%10;
		  break;
		  case 1:
			  smg_table[0]=24;
			  smg_table[1]=16;
			  smg_table[2]=16;
			  smg_table[3]=16;
			  smg_table[4]=16;
			  smg_table[5]=V_Value_P/100+32;
			  smg_table[6]=V_Value_P/10%10;
			  smg_table[7]=V_Value_P%10;
		  break;
		  case 2:
			  smg_table[0]=22;
			  smg_table[1]=16;
			  smg_table[2]=16;
			  smg_table[3]=16;
			  smg_table[4]=(N/1000==0)?16:N/1000;
			  smg_table[5]=(N/100%10==0)?16:N/100%10;
			  smg_table[6]=(N/10%10==0)?16:N/10%10;
			  smg_table[7]=N%10;
		  break;
		}	
		dis_key();		 //按键功能
		N_num();		 //计数加1
	}
}

2、IIC

        iic.c

/*
  程序说明: 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);
}

//等待应答
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;    
}

//ADC
void Write_Adc(unsigned char add)
{
   IIC_Start();
   IIC_SendByte(0x90);
   IIC_WaitAck();
   IIC_SendByte(add);
   IIC_WaitAck();
   IIC_Stop();
}

unsigned char Read_Adc(unsigned char add)
{
	unsigned char temp;
   IIC_Start();
   IIC_SendByte(0x90);
   IIC_WaitAck();
   IIC_SendByte(add);
   IIC_WaitAck();

   IIC_Start();
   IIC_SendByte(0x91);
   IIC_WaitAck();
  temp=IIC_RecByte();
   IIC_WaitAck();
   IIC_Stop();

   return temp;
}

//EEPROM
void Write_Eeprom(unsigned char add,unsigned char dat)
{
   IIC_Start();
   IIC_SendByte(0xa0);
   IIC_WaitAck();
   IIC_SendByte(add);
   IIC_WaitAck();
   IIC_SendByte(dat);
   IIC_WaitAck();
   IIC_Stop();
}

unsigned char Read_Eeprom(unsigned char add)
{
	unsigned char temp;
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	temp=IIC_RecByte();
	IIC_WaitAck();
	IIC_Stop();

   return temp;
}

        iic.h

#ifndef _IIC_H
#define _IIC_H

void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 

//ADC
void Write_Adc(unsigned char add);
unsigned char Read_Adc(unsigned char add);

//EEPROM
void Write_Eeprom(unsigned char add,unsigned char dat);
unsigned char Read_Eeprom(unsigned char add);
#endif								 

标签: 7d计数继电器1e计数继电器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台