第十二届蓝桥杯单片机省赛第二场 手撸程序

#include <STC15F2K60S2.H>
#include <IIC.H>
/*变量很可怕,请蒙住眼睛....观看顺序 
数码管显示-----外设参数获取 (频率、电压等)-----外设参数的处理------按键----LED*/
sbit S4=P3^3;
sbit S5=P3^2;
sbit S6=P3^1;
sbit S7=P3^0;
sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit L4 = P0^3;
sbit L5 = P0^4;
unsigned int SMG_cylc;
unsigned int SMG_freq;
unsigned int SMG_vlot;
float adc_vlot;
unsigned int  count_f;
unsigned int  dat_f;
unsigned char count_t;
unsigned char key_t;
unsigned char key_SMG=0;
unsigned char F_SMG=1;
unsigned int old_freq;
unsigned int old_vlot;
bit key_vlot=0;
bit key_freq=0;
bit key_adc=1;
bit led_flag=1;
bit S7_flag;
unsigned char code Nodat[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char code Isdat[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};

void SelectHC573(unsigned char n)
{
	switch(n)
{
	case 0 : P2=(P2 &0x1f) |0x00; break;
	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;
}
}
// ==================定什么时,计什么数==============//
void Timber0init() //定时器0计数,每中断一次记一次数
{
	TMOD=0x06;
	TH0=0xff; 
	TH0=0xff;
	EA=1;ET0=1; TR0=1;
}
void Timber1init() //定时器1定时,每中断一次50ms  中断20次就是1秒,1秒计多少次数,就是频率
{ 
	AUXR &= 0xBF;		
	TMOD &= 0x0F;		
	TL1 = 0xB0;		
	TH1 = 0x3C;		
	TF1 = 0;		
	TR1 = 1;		
	EA=1;ET1=1;  
}

// ==================怎么选择的==============//
void Delay2ms()		//@12.000MH数码管专用延时
{
	unsigned char i, j;
	i = 24;
	j = 85;
	do
	{
		while (--j);
	} while (--i);
}
void Output_P0(unsigned char channel,unsigned char value)
{ 
	SelectHC573(channel);
	P0=value;
	SelectHC573(0);
}

void SMG_Bit(unsigned char pos,unsigned char value)
{
	Output_P0(6,0x01<<pos);
	Output_P0(7,value);
	Delay2ms();
	Output_P0(6,0x01<<pos);
	Output_P0(7,0xff);
}
void SMG_ALL(unsigned char value)
{
	Output_P0(6,0xff);
	Output_P0(7,value);
}
//========================显示数码管=================
/* 数码模块  F_SMG即数码管界面标志位,1=频率界面,2=周期界面,3=电压界面*/
/*  SMG_Bit(0,0x8e); 选择数码管第0位,然后给P0赋值   怎么选择的往上翻翻*/
void DispalySMG()
{
	switch(F_SMG)
	{
	 case 1:
	 SMG_Bit(0,0x8e);  
	 SMG_Bit(1,0xff);
	 SMG_Bit(2,0xff);
   if(SMG_freq>9999)
	 SMG_Bit(3,Nodat[ SMG_freq/10000]);  
	 if(SMG_freq>999)
	 SMG_Bit(4,Nodat[(SMG_freq/1000)%10]);
	 if(SMG_freq>99)
	 SMG_Bit(5,Nodat[(SMG_freq/100)%10]);
	 if(SMG_freq>9)
	 SMG_Bit(6,Nodat[(SMG_freq/10)%10]);
	 SMG_Bit(7,Nodat[SMG_freq%10]);
	 SMG_ALL(0xff); //关闭所有数码管的显示
	 break;
//SMG_freaq 频率 SMG_syclc 周期 SMG_vlot电压  参数值都按整数处理,参数管理会提及
	 case 2:
	 SMG_Bit(0,0xc8);
	 SMG_Bit(1,0xff);
	 SMG_Bit(2,0xff);
   if(SMG_cylc>9999)
	 SMG_Bit(3,Nodat[ SMG_cylc/10000]);
	 if(SMG_cylc>999)
	 SMG_Bit(4,Nodat[(SMG_cylc/1000)%10]);
	 if(SMG_cylc>99)
	 SMG_Bit(5,Nodat[(SMG_cylc/100)%10]);
	 if(SMG_cylc>9)
	 SMG_Bit(6,Nodat[(SMG_cylc/10)%10]);
	 SMG_Bit(7,Nodat[SMG_cylc%10]);
	 SMG_ALL(0xff);
	 break;
	 case 3:

	 SMG_Bit(0,0xc1);
	 SMG_Bit(1,0xbf);
	 if(key_adc)
	 SMG_Bit(2,Nodat[1]);
	 else
	 SMG_Bit(2,Nodat[3]);
	 SMG_Bit(3,0xff);
	 SMG_Bit(4,0xff);
	 SMG_Bit(5,Isdat[SMG_vlot/100]);
	 SMG_Bit(6,Nodat[(SMG_vlot/10)%10]);
	 SMG_Bit(7,Nodat[SMG_vlot%10]);
	 SMG_ALL(0xff);
	 break;

 }
}
//========================参数获取=================
unsigned char Read_adc(unsigned char addr) // pcf8591 addr=0x01 是光敏电压数据  addr=0x03 是电阻电压数据
{
	unsigned char medium;
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	
	IIC_SendByte(addr);
	IIC_WaitAck();
	IIC_Stop();
	
	DispalySMG();
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	medium=IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	return medium; //返回的最大值255
}
//=====555定时器 定时器0计数,定时器1定时   定什么时,计什么数 ????往上翻翻
void Timber0Service() interrupt 1
{
	count_f++;
}
void Timber1Service() interrupt 3
{
	count_t++;
	if(count_t==20) 
	{
		count_t=0;
		dat_f=count_f;
		count_f=0;
	}
	if(S7_flag)
	{
		key_t+=1;
	}
}
//========================参数处理=================
void Date_mange()
{

       SMG_freq=dat_f; //频率参数不处理
       SMG_cylc=1000000/dat_f;  //周期参数   微妙等于多少秒 10的6次方    T=(1/f)*1000000 HZ/us

		     if(key_adc)
	       adc_vlot=(Read_adc(0x03)*5.0)/255; //S7按下改变addr
		     else
		     adc_vlot=(Read_adc(0x01)*5.0)/255; 
				 
	       SMG_vlot=adc_vlot*100; //电压参数最大5.00 扩大100倍变成整数
}
//========================按键=================
void ScanKey()
{
if(S4==0) //界面切换
	{ DispalySMG();
	 if(S4==0)
	 {
    switch(key_SMG)
		{
			case 0 :F_SMG=1;key_SMG=1; break;
			case 1 :F_SMG=2;key_SMG=2; break;
			case 2 :F_SMG=3;key_SMG=0; break;
		}
	 }
	 while(S4==0)
	 DispalySMG();
  }
if(S5==0) //输出光敏还是电阻电压
	{ DispalySMG();
	 if(S5==0)
	 {
		key_adc= !key_adc;
	 }
	 while(S5==0)
	 DispalySMG();
  }
if(S6==0) //保存当前电压
	{ DispalySMG();
	 if(S6==0)
	 {
   old_vlot=SMG_vlot;
	 }
	 while(S6==0)
	 DispalySMG();
  }
if(S7==0)
	{ 
	 DispalySMG();
	 if(S7==0)
	 {
			S7_flag = 1;    //S7 按下了
      while(!S7)      //S7一直没松手
			DispalySMG();  
      S7_flag=0;      //欧耶终于松手
		 if(key_t>20)			 //你松手超过一秒了???
		 led_flag= !led_flag;//长按 LED_flag 标志位改变 0 or 1
		 else
		 old_freq=SMG_freq;;//短按 保存当前频率
		 key_t=0;          //退出 按键定时清0
	 }		  
}
}

void led()
{
	if (led_flag)//led_flag为1 此时正常点亮
	{
		if (SMG_vlot>old_vlot)//现在的电压和保存的电压比较大小
		{
			P2 = (P2 & 0x1f) | 0x80;
			L1 = 0;
		}
		if (SMG_freq>old_freq) //现在的频率和保存的频率比较大小
		{
			P2 = (P2 & 0x1f) | 0x80;
			L2 = 0;
		}
		if (F_SMG==1) //频率界面
		{
			P2 = (P2 & 0x1f) | 0x80;
			L3 = 0;
		}
		else if (F_SMG==2) //周期界面
		{
			P2 = (P2 & 0x1f) | 0x80;
			L4 = 0;
		}
		else if (F_SMG==3) //电压界面
		{
			P2 = (P2 & 0x1f) | 0x80;
			L5 = 0;
			
		}
		
	}
		else   //应该 关闭所有数码管了
	{
		P2 = (P2 & 0x1f) | 0x80;
		P0 = 0xff;
		P2 = (P2 & 0x1f);
	}
	P2 = (P2 & 0x1f); P0=0X00; //推出取消选择
	}
//========================LED=================
	void InitSystem()
{
  Output_P0(5,0x00);
  Output_P0(4,0xFF);
}
void main()
{

	InitSystem();
	Timber0init();
	Timber1init();
	while(1)
	{
		Date_mange();
		DispalySMG();
		ScanKey();
		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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值