第十二届蓝桥杯单片机第二次省赛题(ne555,DAC)

若有错误,欢迎评论指正!

 

 

 

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); 

unsigned char Read_PCF8591(unsigned char mode);

#endif

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);
}

//发送应答
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;    
}

//电压采集函数
unsigned char Read_PCF8591(unsigned char mode)
{
	unsigned char temp;
	
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	
	if(mode == 1)
		IIC_SendByte(0x01);							//光敏电阻通道
	else if(mode == 3)
		IIC_SendByte(0x03);							//电位器2通道
		
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();	
	
	temp = IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	
	return temp;
}

smg.h

#ifndef __SMG_H
#define __SMG_H

unsigned char code SMG_duanma[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

void Delay_SMG(unsigned char t);
void Select(unsigned char channel);
void DisplaySMG_Bit(unsigned char pos,unsigned char dat);
void Display_all(unsigned char dat);

#endif

smg.c

#include "reg52.h"

void Delay_SMG(unsigned char t)
{
	while(t--);
}

void Select(unsigned char channel)
{
	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;
	}
}	

void DisplaySMG_Bit(unsigned char pos,unsigned char dat)
{
	P0 = 0xff;
	Select(6);
	P0 = 0x01 << pos;
	Select(7);
	P0 = dat;
}

void Display_all(unsigned char dat)
{
	Select(6);
	P0 = 0xff;
	Select(7);
	P0 = dat;
}

main.c

#include "STC15F2K60S2.H"
#include "smg.h"
#include "iic.h"

unsigned int count_fre;								//用于保存脉冲数量
unsigned char count_500ms;							//用于保存0.5s计数
unsigned int dat_fre;								//用于保存频率数据
unsigned char dat_per;								//用于保存周期数据
unsigned char mode = 1;								//用于判断读取的模式
unsigned int dat_Dac;								//用于保存电压数据
unsigned char flag_S4;								//用于当前显示的界面
unsigned int para_dac;								//用于保存电压参数
unsigned int para_fre;								//用于保存频率数据
unsigned char count_S7;								//用于判断S7是否是长按
unsigned char flag_S7;								//用于判断是否长按
unsigned char flag_led;								//用于判断led功能是否启用

sbit S4 = P3^3;
sbit S5 = P3^2;
sbit S6 = P3^1;
sbit S7 = P3^0;

//系统初始化函数
void Init_Sys()
{
	Select(4);
	P0 = 0xff;
	Select(5);
	P0 = 0x00;
	Select(0);
}
//ne555频率读取相关函数
void Timer0Init(void)		//@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x04;		//设置定时器模式为计数模式
	TL0 = 0xff;		//设置定时初值
	TH0 = 0xff;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	ET0 = 1;
	EA = 1;
}
void Timer1Init(void)		//10毫秒@12.000MHz
{
	AUXR &= 0xBF;		//定时器时钟12T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0xF0;		//设置定时初值
	TH1 = 0xD8;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	
	ET1 = 1;
	EA = 1;
}

void Uart_Timer0() interrupt 1
{
	count_fre++;
}
void Uart_Timer1() interrupt 3
{
	count_500ms++;
	if(count_500ms == 50)
	{
		count_500ms = 0;
		dat_fre = count_fre;
		dat_per = 1000000/dat_fre;
		count_fre = 0;
	}
}

//周期以及频率显示函数
void Display_fre()
{
	DisplaySMG_Bit(0,0x8e); Delay_SMG(100);
	
	if(dat_fre > 999999)
	{
		DisplaySMG_Bit(1,SMG_duanma[dat_fre / 1000000]); Delay_SMG(100);
	}
	if(dat_fre > 99999)
	{
		DisplaySMG_Bit(2,SMG_duanma[dat_fre / 100000 % 10]); Delay_SMG(100);
	}
	if(dat_fre > 9999)
	{
		DisplaySMG_Bit(3,SMG_duanma[dat_fre / 10000 % 10]); Delay_SMG(100);
	}
	if(dat_fre > 999)
	{
		DisplaySMG_Bit(4,SMG_duanma[dat_fre / 1000 % 10]); Delay_SMG(100);
	}
	if(dat_fre > 99)
	{
		DisplaySMG_Bit(5,SMG_duanma[dat_fre / 100 % 10]); Delay_SMG(100);
	}	
	if(dat_fre > 9)
	{
		DisplaySMG_Bit(6,SMG_duanma[dat_fre / 10 % 10]); Delay_SMG(100);
	}
	DisplaySMG_Bit(7,SMG_duanma[dat_fre % 10]); Delay_SMG(100);
	
	Display_all(0xff);	
}
void Display_per()
{
	DisplaySMG_Bit(0,0xc8); Delay_SMG(100);
	
	if(dat_per > 999999)
	{
		DisplaySMG_Bit(1,SMG_duanma[dat_per / 1000000]); Delay_SMG(100);
	}
	if(dat_per > 99999)
	{
		DisplaySMG_Bit(2,SMG_duanma[dat_per / 100000 % 10]); Delay_SMG(100);
	}
	if(dat_per > 9999)
	{
		DisplaySMG_Bit(3,SMG_duanma[dat_per / 10000 % 10]); Delay_SMG(100);
	}
	if(dat_per > 999)
	{
		DisplaySMG_Bit(4,SMG_duanma[dat_per / 1000 % 10]); Delay_SMG(100);
	}
	if(dat_per > 99)
	{
		DisplaySMG_Bit(5,SMG_duanma[dat_per / 100 % 10]); Delay_SMG(100);
	}	
	if(dat_per > 9)
	{
		DisplaySMG_Bit(6,SMG_duanma[dat_per / 10 % 10]); Delay_SMG(100);
	}
	DisplaySMG_Bit(7,SMG_duanma[dat_per % 10]); Delay_SMG(100);
	
	Display_all(0xff);
}
//电压读取及显示函数
void Read_Dac()
{
	dat_Dac = Read_PCF8591(mode) * 50.0 / 255 * 10;				//电压读取并进行转换
}
void Display_Dac()
{
	DisplaySMG_Bit(0,0xc1); Delay_SMG(100);
	DisplaySMG_Bit(1,0xbf); Delay_SMG(100);
	DisplaySMG_Bit(2,SMG_duanma[mode]); Delay_SMG(100);
	
	DisplaySMG_Bit(3,0xff); Delay_SMG(100);
	DisplaySMG_Bit(4,0xff); Delay_SMG(100);
	
	DisplaySMG_Bit(5,SMG_duanma[dat_Dac / 100] & 0x7f); Delay_SMG(100);
	DisplaySMG_Bit(6,SMG_duanma[dat_Dac / 10 % 10]); Delay_SMG(100);
	DisplaySMG_Bit(7,SMG_duanma[dat_Dac % 10]); Delay_SMG(100);

	Display_all(0xff);
}
//显示总函数
void Display()
{
	switch(flag_S4)
	{
		case 0: Display_fre(); break;
		case 1: Display_per(); break;
		case 2: Display_Dac(); break;
	}
}
//按键相关函数
void Delay_Key(unsigned char t)
{
	while(t--);
}
void Scan_Key()
{
	//S4按键界面切换
	if(S4 == 0)
	{
		Delay_Key(100);
		if(S4 == 0)
		{
			while(S4 == 0)
				Display();
			flag_S4++;
			if(flag_S4 == 3)
				flag_S4 = 0;
			if(flag_S4 == 2)
				mode = 1;
		}
	}
	//S5模式切换
	if(S5 == 0)
	{
		Delay_Key(100);
		if(S5 == 0)
		{
			while(S5 == 0)
				Display();
			if(mode == 1)
				mode = 3;
			else if(mode == 3)
				mode = 1;
		}
	}
	//S6电压缓存
	if(S6 == 0)
	{
		Delay_Key(100);
		if(S6 == 0)
		{
			while(S6 == 0)
				Display();
			para_dac = Read_PCF8591(3) * 50.0 / 255 * 10;
		}
	}
	//S7频率缓存
	if(S7 == 0)
	{
		Delay_Key(100);
		if(S7 == 0)
		{
			flag_S7 = 1;							//S7按下
			while(S7 == 0)
				Display();
			flag_S7 = 0;							//松开S7
			if(count_S7 <= 100)						//计时不到1s,判断为短按
			{
				count_S7 = 0;
				para_fre = dat_fre;			
			}
			else									//计时超过1s,判断为长按
			{
				count_S7 = 0;
				flag_led = ~flag_led;			
			}
		}
	}
}
//长按判断函数
void Timer2Init(void)		//10毫秒@12.000MHz
{
	AUXR &= 0xFB;		//定时器时钟12T模式
	T2L = 0xF0;		//设置定时初值
	T2H = 0xD8;		//设置定时初值
	AUXR |= 0x10;		//定时器2开始计时
	IE2 |= 0x04;
	
	EA = 1;
}

void Uart_Timer2() interrupt 12
{
	if(flag_S7 == 1)
	{
		count_S7++;
	}
}
//led相关函数
void led()
{
	if(flag_led == 0)								//led功能开启
	{
		if((Read_PCF8591(3) * 50.0 / 255 * 10) > para_dac)				//L1
		{
			Select(4);
			P0 = P0 & 0xfe;
			Select(0);
		}
		if(dat_fre > para_fre)																		//L2
		{
			Select(4);
			P0 = P0 & 0xfd;
			Select(0);	
		}	
		switch(flag_S4)
		{
			case 0:											//L3
				Select(4);
				P0 = P0 & 0xfb;
				Select(0);	
			break;
			case 1:											//L4
				Select(4);
				P0 = P0 & 0xf7;
				Select(0);	
			break;
			case 2:											//L5
				Select(4);
				P0 = P0 & 0xef;
				Select(0);	
			break;
		}
	}
	else														//led功能关闭
	{
		Select(4);
		P0 = 0xff;
		Select(0);		
	}
	
}
void main()
{
	Init_Sys();
	Timer0Init();
	Timer1Init();
	Timer2Init();
	while(1)
	{
		Read_Dac();
		Display();
		Scan_Key();
		led();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zz耳机

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值