**
第十一届蓝桥杯单片机省赛2020年四月份模拟试题
**
i2c.c
#include "i2c.h"
#include "intrins.h"
#include "STC15F2K60S2.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;
}
void init_pcf8591()
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x03);
IIC_WaitAck();
IIC_Stop();
}
unsigned char read_pcf8591()
{
unsigned char datas;
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
datas=IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
return datas;
}
void write_at24c02(unsigned char add,unsigned char datas)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(datas);
IIC_WaitAck();
IIC_Stop();
}
unsigned char read_at24c02(unsigned char add)
{
unsigned char datas;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
datas=IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
return datas;
}
i2c.h
#ifndef _i2c_h_
#define _i2c_h_
#include "intrins.h"
#include "STC15F2K60S2.H"
void IIC_Delay(unsigned char i);
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);
void init_pcf8591(void);
unsigned char read_pcf8591(void);
void write_at24c02(unsigned char add,unsigned char datas);
unsigned char read_at24c02(unsigned char add);
#endif
definit.h
#ifndef _definit_h_
#define _definit_h_
#ifndef u8
#define u8 unsigned char
#endif
#ifndef u16
#define u16 unsigned int
#endif
#include "STC15F2K60S2.H"
void led(u8 i) //重定义
{
P2&=0x1f;
P2|=0x80;
P0=i;
}
void relay(u8 i)
{
P2&=0x1f;
P2|=0xa0;
if(i)
P0|=0x10;
else
P0&=0xef;
}
void buzzer(u8 i)
{
P2&=0x1f;
P2|=0xa0;
if(i)
P0|=0x40;
else
P0&=0xbf;
}
#endif
main.c
#include "STC15F2K60S2.H"
#include "definit.h"
#include "i2c.h"
u8 count; //计数
char Referenc;//参考电压 扩大了10倍 00.0-50.0
u8 moshi;//模式
u8 key_error;//错误按键
u8 time; //5秒计时
u8 keys,keyse=0;//按键
u8 AIN3; //电压保存比较
bit L1;//LED1
bit cycle; //循环判断
u8 code sumaguan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
u8 number[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};//缓存数组
void delay1ms(u16 i) //延时
void close() //上电初始化
void led_control() //LED控制函数
void Timer0Init(void) //50毫秒@12.000MHz
void pcf_8591() //电压处理显示函数
void show() //数码管显示函数
void key() //按键检测
void moshi1() //测量界面
void moshi2() //参数设置界面
void moshi3() //计数界面
void main()
{
close();
init_pcf8591(); //pcf8591初始化
Timer0Init(); //定时器初始化
Referenc=read_at24c02(0x00); //读设置
while(1)
{
switch(moshi)
{
case(0):moshi1();break; //测量界面
case(1):moshi2();break; //参数设置
case(2):moshi3();break; //计数界面
}
}
}
void delay1ms(u16 i)
{
u16 x;
for(;i>0;i--)
{
for(x=850;x>0;x--);
}
}
void close()
{
u8 i;
for(;i<8;i++) number[i]=0xff;
led(0xff);
relay(0);
buzzer(0);
}
void led_control() //LED控制函数
{
u8 i=0xff;
if(L1) i&=0xfe; else i|=0x01;
if(count%2!=0) i&=0xfd; else i|=0x02;
if(key_error>=3) i&=0xfb; else i|=0x04;
led(i);
}
void Timer0Init(void) //50毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0xB0; //设置定时初值
TH0 = 0x3C; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=0;
EA=1;
}
void timer0ser() interrupt 1
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
time++;
if(time==100) {time=0;L1=1;ET0=0;}//定时5秒
}
void pcf_8591() //电压处理显示函数
{
// u8 i;
float datase;
u16 datas;
datase=read_pcf8591();
datas=(datase/51)*100;
AIN3=datas/10;
number[0]=0xc1; //显示U
number[5]=sumaguan[datas/100]&0x7f;
number[6]=sumaguan[datas%100/10];
number[7]=sumaguan[datas%10];
}
void show() //数码管显示函数
{
u8 i;
for(i=0;i<8;i++)
{
P2&=0x1f;
P2|=0xc0;
P0=0x01<<i;
P2&=0x1f;
P2|=0xe0;
P0=number[i];
delay1ms(3);
P0=0xff;
}
}
void key() //按键检测
{
if(keyse==0) P3=0x0f;
switch(keyse)
{
case(0):if(P3!=0x0f) keyse++; break; //第一次判断是否按下
case(1): //第二次确认按下并确定具体按键
if(P3!=0x0f)
{
if(P3==0x0b) keys=1; //第三排
else if(P3==0x07) keys=2; //最后一排
// else keys=0; //不是后两排
P3=0xf0;
if(P3==0xd0)
{if(keys==1) keys=13; else if(keys==2) keys=12;}
else if(P3==0xe0)
{if(keys==1) keys=17; else if(keys==2) keys=16;}
keyse++;
}
else keyse=0;
break;
case(2): if(P3==0xf0) keyse=0;break; //确定是否松手
}
}
void moshi1() //测量界面
{
cycle=1;
close();
while(cycle)
{
key();
show();
pcf_8591();
led_control();
if(ET0==0) {if(AIN3<Referenc) {ET0=1;time=0;}}
if(AIN3>=Referenc) {ET0=0;L1=0;}
if((keys==13)|(keys==16)|(keys==17)) {keys=0;key_error++;}
if(keys==12) {cycle=0;keys=0;key_error=0;moshi=1;}
}
}
void moshi2() //参数设置
{
cycle=1;
close();
while(cycle)
{
key();
show();
led_control();
if(keys==16) {keys=0;Referenc+=5;key_error=0;if(Referenc==55) Referenc=0;}
if(keys==17) {keys=0;Referenc-=5;key_error=0;if(Referenc<0) Referenc=50;}
if(keys==13) {keys=0;key_error++;}
if(keys==12) {cycle=0;keys=0;key_error=0;moshi=2;write_at24c02(0x00,Referenc);}
number[0]=0x8c; //显示P
number[5]=sumaguan[Referenc/10]&0x7f;
number[6]=sumaguan[Referenc%10];
number[7]=sumaguan[0];
}
}
void moshi3() //计数界面
{
u8 i=0;
u16 datas;
float datase;
cycle=1;
close();
while(cycle)
{
key();
show();
led_control();
datase=read_pcf8591();
datas=(datase/51)*100;
switch(i) //下降波形电压判断
{
case(0): if(datas>=Referenc) i++;break;
case(1): if(datas<Referenc) {i=0;count++;}break;
}
// if(ET0==0) {if(datas<Referenc) {ET0=1;time=0;}}
// if(datas>=Referenc) {ET0=0;L1=0;}
if(keys==13) {keys=0;count=0;}
if((keys==16)|(keys==17)) {keys=0;key_error++;}
if(keys==12) {cycle=0;keys=0;key_error=0;moshi=0;}
number[0]=0xc8; //显示N
number[5]=0xff;
number[6]=sumaguan[count/10];
number[7]=sumaguan[count%10];
}
}