【蓝桥杯-单片机组】第十一届初赛

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
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_From_AT24C02();
void Write_to_AT24C02(unsigned char dat);
unsigned char Read_AIN3_From_PCF8951();

#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;
		EA=0;
    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);
    }
		EA=1;
    SCL  = 0;  
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
    unsigned char i, da;
	EA=0;
    for(i=0; i<8; i++)
    {   
    	SCL = 1;
	IIC_Delay(DELAY_TIME);
	da <<= 1;
	if(SDA) da |= 1;
	SCL = 0;
	IIC_Delay(DELAY_TIME);
    }
		EA=1;
    return da;    
}
unsigned char Read_AIN3_From_PCF8951()
{
	unsigned char dat;
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x03);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	dat=IIC_RecByte();
	IIC_SendAck(0);
	IIC_Stop();
	return dat;
}
void Write_to_AT24C02(unsigned char dat)
{
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(0x00);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}
unsigned char Read_From_AT24C02()
{
	unsigned char dat;
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(0x00);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	dat=IIC_RecByte();
	IIC_SendAck(0);
	IIC_Stop();
	return dat;
}

key.h

#include <stc15f2k60s2.h>
#include <iic.h>


sbit KEY_OUT_0=P4^4;
sbit KEY_OUT_1=P4^2;
sbit KEY_OUT_2=P3^5;
sbit KEY_OUT_3=P3^4;

sbit KEY_IN_0=P3^0;
sbit KEY_IN_1=P3^1;
sbit KEY_IN_2=P3^2;
sbit KEY_IN_3=P3^3;

unsigned char keySta[4][4]={
															{1,1,1,1},
															{1,1,1,1},
															{1,1,1,1},
															{1,1,1,1},
																					};
unsigned char keybuff[4][4]={
															{0xff,0xff,0xff,0xff},
															{0xff,0xff,0xff,0xff},
															{0xff,0xff,0xff,0xff},
															{0xff,0xff,0xff,0xff},
																											};
unsigned char backup[4][4]={
															{1,1,1,1},
															{1,1,1,1},
															{1,1,1,1},
															{1,1,1,1},
																					};
unsigned char code keymap[4][4]={
																		{1,2,3,4},
																		{5,6,7,8},
																		{9,10,11,12},
																		{13,14,15,16},
																									};
unsigned char dat=0;
//=======================全局变量

unsigned char mode=0;
char Vol_p=25;
unsigned char Now_count=0;
unsigned char NO_Reflect=0;
//==============================


unsigned char Scope=0;

void keyscan()
{
	unsigned char i,j;
	keybuff[0][Scope]=(keybuff[0][Scope]<<1)|KEY_IN_0;
	keybuff[1][Scope]=(keybuff[1][Scope]<<1)|KEY_IN_1;
	keybuff[2][Scope]=(keybuff[2][Scope]<<1)|KEY_IN_2;
	keybuff[3][Scope]=(keybuff[3][Scope]<<1)|KEY_IN_3;
	
	Scope++;
	Scope&=0x03;
	switch(Scope)
	{
		case 0: KEY_OUT_3=1;KEY_OUT_0=0;  break;
		case 1: KEY_OUT_0=1;KEY_OUT_1=0;  break;
		case 2: KEY_OUT_1=1;KEY_OUT_2=0;  break;
		case 3: KEY_OUT_2=1;KEY_OUT_3=0;  break;
	}
	for(i=0;i<4;i++)
	{
		for(j=0;j<4;j++)
		{
			if((keybuff[i][j]&0x0f)==0x00) keySta[i][j]=0;
			else if((keybuff[i][j]&0x0f)==0x0f) keySta[i][j]=1;
		}
	}
}
void keyAction(unsigned char keycode)
{
	if(keycode==12)//S17
	{
		if(mode==1)
		{
			NO_Reflect=0;
			Vol_p=Vol_p-5;
			if(Vol_p<0) Vol_p=50;
		}
		if(mode==0) NO_Reflect++;
		if(mode==2) NO_Reflect++;
	}
	if(keycode==16)//S16
	{
		if(mode==1)
		{
			NO_Reflect=0;
			Vol_p=Vol_p+5;
			if(Vol_p>50) Vol_p=0;
		}
		if(mode==0) NO_Reflect++;
		if(mode==2) NO_Reflect++;
	}
	if(keycode==11)//S13
	{
		if(mode==2) {Now_count=0;NO_Reflect=0;}
		if(mode==0) NO_Reflect++;
		if(mode==1) NO_Reflect++;
	}
	if(keycode==15)  //S12
	{
		mode++;
		NO_Reflect=0;
		if(mode!=1) Write_to_AT24C02(Vol_p);
		if(mode>2) mode=0;
	}
}
void key_drive()
{
	unsigned char i,j;
	for(i=0;i<4;i++)
	{
		for(j=0;j<4;j++)
		{
			if(backup[i][j]!=keySta[i][j])
			{
				if(keySta[i][j]==0)
				{
					keyAction(keymap[i][j]);
				}
			}
			backup[i][j]=keySta[i][j];
		}
	}
}

display.h

#ifndef _display_h
#define _display_h

void ledscan();
void led_play();

extern unsigned int Vol_in;

#endif

display.c

#include <stc15f2k60s2.h>
#include <key.h>
#include <iic.h>

unsigned char code smgduan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char index=0;
unsigned char disbuff[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};

unsigned int Vol_in=0;

void ledscan()
{
	P2=(P2&0x1f)|0xe0;
	P0=0xff;
	P2&=0x1f;
	
	P2=(P2&0x1f)|0xc0;
	P0=0x80>>index;
	P2&=0x1f;
	
	P2=(P2&0x1f)|0xe0;
	P0=disbuff[index];
	P2&=0x1f;
	
	if(++index>8) index=0;
}
void led_play()
{
	Vol_in=Read_AIN3_From_PCF8951()*1.960784;
	if(mode==0)
	{
		disbuff[7]=0xc1;
		disbuff[6]=0xff;
		disbuff[5]=0xff;
		disbuff[4]=0xff;
		disbuff[3]=0xff;
		disbuff[2]=smgduan[Vol_in/100]&0x7f;
		disbuff[1]=smgduan[Vol_in%100/10];
		disbuff[0]=smgduan[Vol_in%10];
	}
	else if(mode==1)
	{
		disbuff[7]=0x8c;
		disbuff[6]=0xff;
		disbuff[5]=0xff;
		disbuff[4]=0xff;
		disbuff[3]=0xff;
		disbuff[2]=smgduan[Vol_p/10]&0x7f;
		disbuff[1]=smgduan[Vol_p%10];
		disbuff[0]=smgduan[0];
	}
	else if(mode==2)
	{
		disbuff[7]=0xc8;
		disbuff[6]=0xff;
		disbuff[5]=0xff;
		disbuff[4]=0xff;
		disbuff[3]=0xff;
		disbuff[2]=0xff;
		disbuff[1]=0xff;
		if(Now_count>=0 && Now_count<9)
		{
			disbuff[0]=smgduan[Now_count];
		}else if(Now_count>=9 && Now_count<99)
		{
			disbuff[1]=smgduan[Now_count/10];
			disbuff[0]=smgduan[Now_count%10];
		}
	}
}

main.c

#include <stc15f2k60s2.h>
#include <display.h>
#include <key.h>
#include <iic.h>

//===========================变量定义
sbit LED1=P0^0;
sbit LED2=P0^1;
sbit LED3=P0^2;

unsigned int LED1_count=0;
bit Before_big=0,Now_equall=0;
unsigned char i=0;
//==================================

//===========================函数声明
void InitSystem();
void Timer0Init(void);
void led_show();
void Count_add();
//==================================
void main()
{
	Vol_p=Read_From_AT24C02();
	InitSystem();
	Write_to_AT24C02(25);
	Timer0Init();
	EA=1;
	while(1)
	{
		key_drive();
		led_play();
		led_show();
		Count_add();
	}
}
void InitSystem()
{
	P2=(P2&0x1f)|0x80;
	P0=0xff;
	P2&=0x1f;
	
	P2=(P2&0x1f)|0xa0;
	P0=0x00;
	P2&=0x1f;
	
	P2=(P2&0x1f)|0xc0;
	P0=0xff;
	P2&=0x1f;
	
	P2=(P2&0x1f)|0xe0;
	P0=0xff;
	P2&=0x1f;
}
void Timer0Init(void)		//2毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x9A;		//设置定时初值
	TH0 = 0xA9;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0=1;
}
void Timer0() interrupt 1
{
	if(Vol_in<Vol_p*10) LED1_count++;
	TL0 = 0x9A;		//设置定时初值
	TH0 = 0xA9;		//设置定时初值
	keyscan();
	ledscan();
}
void led_show()
{
	P2=(P2&0x1f)|0x80;
	P0=0xff;
	
	if(Vol_in<Vol_p*10)
	{
		if(LED1_count>2500) LED1=0;
		else LED1=1;
	}
	if(Vol_in>=Vol_p*10) {LED1=1;LED1_count=0;}
	if(Now_count%2==1) LED2=0;
	else LED2=1;
	
	if(NO_Reflect>=3) LED3=0;
	else if(NO_Reflect<3) LED3=1;
	
	P2&=0x1f;
}
void Count_add()
{
	if(Vol_in>Vol_p*10)    //Vol_in 是AD转换值 范围0-500
	{
		Before_big=1;        // Before_big是前一刻 输入电压比参考电压大的 表示位
	}
	if(Before_big==1)
	{
		if(Vol_in==Vol_p*10) //Vol_p是参考电压  范围0-50
		{
			Now_equall=1;      //Now_equall是 输入电压比参考电压 相等的标志位
		}
	}
	if((Before_big==1) && (Now_equall==1))
	{
		Now_count++;         //Now_count是计数值
		Before_big=0;
		Now_equall=0;
	}
}

避坑指南:
①计数界面计数值不正常显示,可以试试在IIC通信中,读数据和写数据时关闭EA,结束后打开EA;
②做完NE555模块时一定要把短接帽拿下来!!!不然矩阵键盘最右侧一列就没用了!!!!估计这个憨批问题就出在我这个憨批身上了!!
③用到的S12 S13 S17 S16按键我是用矩阵键盘识别(状态机法)的,个人感觉只要背过了,比赛稳拿把掐 就是码的有点多;
④分文件编程时巧用全局变量,太方便了!!!如果main.c的变量想在其他.c文件里用,可以在非main.c文件里定义全局变量,main.c文件再引用全局变量。
.
.
保省二冲国二!!!!!!!!!!冲冲冲

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值