【蓝桥杯单片机】第十一届第一场解题

 

 

 

 

若代码有误,欢迎在评论区批评指正!735e0ffd926f4406975f70be33a82150.jpeg

 b31fb3d2a04f496084b2adedbe94f103.jpeg

 110873ed90654f11b6053c6909cf6d01.jpeg

 main.c

#include <REGX52.H>
#include <iic.H>


#define uchar unsigned char 
#define uint unsigned int

//==============================变量区============================
sbit K1 = P3^2;
sbit K2 = P3^3;
sbit K3 = P3^4;
sbit K4 = P3^5;
sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;

sfr  AUXR = 0x8e;
uchar flag_S12,key,canshu=30,amount,count_L3,flag_2,flag_3;
uint U,count,flag_U;
code uchar Seg_Table[] ={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xc1,0x8c,0xc8}; //a[16]U  a[17]P  a[18] N
code uchar Seg_Table_dot[] ={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0e};

//========================函数定义区========================
void delay_s(uint t);
void hc573(uchar channel);
void Nixie(uchar loc,num);
void Init_System();
void Nixie_dot(uchar loc,num);
void display();
void LED();
void Timer0_Init(void);		//1毫秒@12.000MHz
//============================================================
void delay_s(uint t)
{
	while(t--);
}

void hc573(uchar channel)
{
	switch(channel)
	{
		case 4: P2 =(P2 & 0x1f) | 0x80; break;   //LED
		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 Nixie(uchar loc,num)
{
	hc573(0);
	P0 = 0x01<<(loc - 1);
	hc573(6);
	hc573(0);
	P0 = Seg_Table[num];
	hc573(7);
	delay_s(500);
	P0 = 0xff;
	hc573(0);
}
//======================含小数点的数码管显示====================
void Nixie_dot(uchar loc,num)
{
	hc573(0);
	P0 = 0x01<<(loc - 1);
	hc573(6);
	hc573(0);
	P0 = Seg_Table_dot[num];
	hc573(7);
	delay_s(500);
	P0 = 0xff;
	hc573(0);
}

//============================按键检验==================================
void KeyScan()
{
	K4 = 0; K1 = K2 = K3 =1;
	if(K2 == 0||K1 == 0)
	{
		delay_s(100);
		if(K2 == 0) //S12按下
		{
			count_L3=0;
			flag_S12 = (flag_S12+1)%3;
			while(K2 == 0)
			{
				display();
				LED();
				U=Read_AIN3();
				Read_Rom(0x01);
			}
		}
		if(K1 == 0) //S13按下
		{
			if(flag_S12 == 2) 
			{
				amount = 0;
				count_L3=0;
			}
			else  count_L3++;
			while(K1 == 0)
			{
				display();
				LED();
				U=Read_AIN3();
				Read_Rom(0x01);
			}
		}
	}
	K3 = 0; K1 = K2 = K4 =1;
	if(K2 == 0||K1 == 0)
	{
		delay_s(100);
		if(K2 == 0) //S16按下
		{
			if(flag_S12 == 1)
			{
				count_L3=0;
				if(canshu==50) canshu=0;
				else canshu=canshu+5;
			}
			else count_L3++;
				while(K2 == 0)
				{
					display();
					LED();
					Write_Rom(0x01,canshu);
					Read_Rom(0x01);
				}
	   	}
			
		}
		if(K1 == 0) //S17按下
		{
			if(flag_S12 == 1)
			{
				count_L3=0;
				if(canshu==0) canshu=50;
				else canshu-=5;
			}
			else count_L3++;
			while(K1 == 0)
			{
				display();
				Write_Rom(0x01,canshu);
				Read_Rom(0x01);
			 }
	  }
}

//=============================对LED灯的控制================================
void LED()
{
	hc573(0);
	if(amount%2 == 1) 
	{
		L2 = 0;
	}
	else
	{
		L2 = 1;
	}
	if(count>=5000) L1 = 0;
	else L1 = 1;
	if(count_L3>=3) L3 = 0;
	else L3 = 1;
	hc573(4);
	hc573(0);
	
}

//=====================所有需要数码管显示的界面======================
void display()
{
	if(flag_S12 == 0)
	{
		Nixie(1,16);
		Nixie_dot(6,U/100);
		Nixie(7,U%100/10);
		Nixie(8,U%10);
	}
	if(flag_S12 == 1)
	{
		Nixie(1,17);
		Nixie_dot(6,canshu/10);
		Nixie(7,canshu%10);
		Nixie(8,0);
	}

	if(flag_S12 == 2)
	{
		Nixie(1,18);
		if(amount<10) Nixie(8,amount);
		if(amount<100&&amount>=10) 
		{
			Nixie(7,amount/10);
			Nixie(8,amount%10);
		}
		if(amount<1000&&amount>=100) 
		{
			Nixie(6,amount/100);
			Nixie(7,amount%100/10);
			Nixie(8,amount%10);
		}
	}
}

//=======================定时器0实现L1灯的5秒检验==================
void Timer0_Isr(void) interrupt 1
{
	if(count<=5000)
	{
		if(flag_U) count++;
		else if(!flag_U) count=0;
  }
}

void Timer0_Init(void)		//1毫秒@12.000MHz
{
	AUXR &= 0x7F;			//定时器时钟12T模式
	TMOD &= 0xF0;			//设置定时器模式
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0 = 1;				//使能定时器0中断
	EA = 1;
}

//=======================计数amount=======================
void Count_TJ()
{
 if(U > canshu*10)
 {
  flag_2 = 1;
 }
 
 if(U < canshu*10)
 {
  if(flag_2 == 1)
  {
   flag_3 = 1;
  }
 }
 if(flag_3 == 1)
 {
  amount ++;
  flag_2 = 0;
  flag_3 = 0;
  if(amount > 99)
  {
   amount = 0;
  }
 }
}
//========================系统初始化==============================
void Init_System()
{
	hc573(0);
	P0 = 0x00;
	hc573(5);
	hc573(0);
	P0 = 0xff;
	hc573(4);
	hc573(0);
}

void main()
{
	Init_System();
	Timer0_Init();
	while(1)
	{	
		LED();
		canshu=Read_Rom(0x01);
		U=Read_AIN3();
		KeyScan();
		display();
		if(U <canshu*10) flag_U = 1;
		else flag_U = 0;
		Count_TJ();
	}
}

iic.c

/*	#   I2C代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <REGX52.H>
#include <intrins.H>

#define DELAY_TIME	5

sbit scl = P2^0;
sbit sda = P2^1;

static void I2C_Delay(unsigned char n)
{
    do
    {
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();		
    }
    while(n--);      	
}

void I2CStart(void)
{
    sda = 1;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 0;
	I2C_Delay(DELAY_TIME);
    scl = 0;    
}

//
void I2CStop(void)
{
    sda = 0;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 1;
	I2C_Delay(DELAY_TIME);
}

//
void I2CSendByte(unsigned char byt)
{
    unsigned char i;
	
    for(i=0; i<8; i++){
        scl = 0;
		I2C_Delay(DELAY_TIME);
        if(byt & 0x80){
            sda = 1;
        }
        else{
            sda = 0;
        }
		I2C_Delay(DELAY_TIME);
        scl = 1;
        byt <<= 1;
		I2C_Delay(DELAY_TIME);
    }
	
    scl = 0;  
}

//
unsigned char I2CReceiveByte(void)
{
	unsigned char da;
	unsigned char i;
	for(i=0;i<8;i++){   
		scl = 1;
		I2C_Delay(DELAY_TIME);
		da <<= 1;
		if(sda) 
			da |= 0x01;
		scl = 0;
		I2C_Delay(DELAY_TIME);
	}
	return da;    
}

//
unsigned char I2CWaitAck(void)
{
	unsigned char ackbit;
	
    scl = 1;
	I2C_Delay(DELAY_TIME);
    ackbit = sda; 
    scl = 0;
	I2C_Delay(DELAY_TIME);
	
	return ackbit;
}

//
void I2CSendAck(unsigned char ackbit)
{
    scl = 0;
    sda = ackbit; 
	I2C_Delay(DELAY_TIME);
    scl = 1;
	I2C_Delay(DELAY_TIME);
    scl = 0; 
	sda = 1;
	I2C_Delay(DELAY_TIME);
}

unsigned int Read_AIN3()//读取Rb2电压
{
	unsigned int U;
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x03);
	I2CWaitAck();
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	U=I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	U = (U*100)/51;
	return U;
}

void Write_Rom(unsigned char addr,dat)//E2PROM写入数据
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(addr);
	I2CWaitAck();
	I2CSendByte(dat);
	I2CWaitAck();
	I2CStop();
}

unsigned int Read_Rom(unsigned char addr) //E2PROM读数据
{
	unsigned int dat;
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(addr);
	I2CWaitAck();
	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	dat=I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	return dat;
}

iic.h

#ifndef __iic_H__
#define __iic_H__


unsigned int Read_AIN3();  //读取Rb2电压
void Write_Rom(unsigned char addr,dat);   //E2PROM写入数据
unsigned char Read_Rom(unsigned char addr);  //E2PROM读数据


#endif

 

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
由于本题的具体内容并未给出,因此无法给出完整的参考答案。以下为一些可能出现的题目类型及解题思路: 1. LED 灯闪烁 题目描述:使用单片机控制 LED 灯闪烁,每隔一段时间改变 LED 灯的亮灭状态。 解题思路:可以通过单片机的 GPIO 端口控制 LED 灯的亮灭状态。使用定时器可以实现定时改变 LED 灯的状态。具体实现方法可以参考以下代码: ```c #include <reg52.h> sbit LED = P1^0; void main() { TMOD = 0x01; // 设置定时器 0 为模式 1 TH0 = 0xFC; // 定时器 0 初始值高位 TL0 = 0x66; // 定时器 0 初始值低位 TR0 = 1; // 启动定时器 0 while (1) { if (TF0) { // 定时器 0 溢出 TF0 = 0; // 清零定时器 0 溢出标志 LED = ~LED; // 改变 LED 灯状态 } } } ``` 2. 数码管显示 题目描述:使用单片机控制数码管显示一个固定的数字。 解题思路:可以通过单片机的 GPIO 端口控制数码管的显示。数码管的显示是通过给数码管的每个段发送控制信号来实现的。具体控制方法可以参考以下代码: ```c #include <reg52.h> sbit D1 = P1^0; sbit D2 = P1^1; sbit D3 = P1^2; sbit D4 = P1^3; void delay(unsigned int x) { // 延时函数 while (x--); } void main() { unsigned char num = 5; // 要显示的数字 while (1) { D1 = 1; D2 = 1; D3 = 1; D4 = 0; // 数码管 4 显示位 P0 = num % 10; // 显示个位数 delay(1000); // 延时 D1 = 1; D2 = 1; D3 = 0; D4 = 1; // 数码管 3 显示位 P0 = num / 10; // 显示十位数 delay(1000); // 延时 } } ``` 3. 按键控制 LED 灯 题目描述:使用单片机控制一个 LED 灯的亮灭状态,按下按键时改变 LED 灯的状态。 解题思路:可以通过单片机的 GPIO 端口控制 LED 灯的亮灭状态。按键的状态可以通过检测 GPIO 端口的输入状态来判断。具体实现方法可以参考以下代码: ```c #include <reg52.h> sbit LED = P1^0; sbit KEY = P3^2; void delay(unsigned int x) { // 延时函数 while (x--); } void main() { unsigned char key_state = 0; // 按键状态 while (1) { key_state = KEY; if (key_state == 0) { // 按键按下 LED = ~LED; // 改变 LED 灯状态 delay(1000); // 延时 } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值