第十三届蓝桥杯单片机省赛模拟冲刺02
题目来自电子设计工坊
最后一两周的时间在做两套模拟题,将各个模块的使用都练习一遍
#include "reg52.h"
#include "iic.h"
/**************************************
*第十三届蓝桥杯单片机省赛模拟
*Date:2022-3-29
*Author:小殷
***************************************/
sfr P4 = 0xc0;
sbit H1 = P3^0;
sbit H2 = P3^1;
sbit H3 = P3^2;
sbit H4 = P3^3;
sbit L1 = P3^4;
sbit L2 = P3^5;
sbit L3 = P4^2;
sbit L4 = P4^4;
sbit LED1 = P0^0;
sbit LED2 = P0^1;
unsigned char s_press = 0,s_count = 0; //按键按下标志位和计时
unsigned char count = 0,led_flag = 0; //计时 led标志位
unsigned int count_value = 0,count_value2 = 0;//按键值 和保存值
unsigned char interface = 1; //界面
//数码管段码
unsigned char code smg_data[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,
0x82,0xF8,0x80,0x90,0xbf,0xff};
//1简单延时
void delay(unsigned int t)
{
while(t--);
}
//操作锁存器
void Init_74HC138(unsigned char channel)
{
switch(channel)
{
case 4:P2 = (P2 & 0x1f) | 0x80;break; //Y4
case 5:P2 = (P2 & 0x1f) | 0xa0;break; //Y5
case 6:P2 = (P2 & 0x1f) | 0xc0;break; //Y6
case 7:P2 = (P2 & 0x1f) | 0xe0;break; //Y7
case 0:P2 = (P2 & 0x1f) | 0x00;break; //不选通任何一个
}
P2 = (P2 & 0x1f) | 0x00;
}
//数码管安位操作
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
P0 = (0x01 << pos);
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
//操作所有数码管
void SMG_All(unsigned char dat)
{
P0 = 0xff;
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
//显示数码管数据 累加和减的数据
void SMG_Display_Data1(void)
{
//0001 0001 ->0x88
SMG_DisplayBit(0,0x88);
delay(200);
// SMG_DisplayBit(0,0xff);
SMG_DisplayBit(1,0xff);
delay(200);
SMG_DisplayBit(2,0xff);
delay(200);
SMG_DisplayBit(3,0xff);
delay(200);
SMG_DisplayBit(4,0xff);
delay(200);
//3位数码管来显示键值
if(count_value > 99)
{
SMG_DisplayBit(5,smg_data[count_value/100]);
delay(200);
}
if(count_value > 9)
{
SMG_DisplayBit(6,smg_data[count_value/10%10]);
delay(200);
}
SMG_DisplayBit(7,smg_data[count_value%10]);
delay(200);
SMG_All(0xff);
delay(200);
}
//系统初始化
void Init_System(void)
{
P0 = 0xff;
Init_74HC138(4);
P0 = 0x00;
Init_74HC138(5);
SMG_All(0xff);
}
//回显数据显示
void SMG_Display_Data2(void)
{
//1001 0001 ->0x89
SMG_DisplayBit(0,0x89);
delay(200);
// SMG_DisplayBit(0,0xff);
SMG_DisplayBit(1,0xff);
delay(200);
SMG_DisplayBit(2,0xff);
delay(200);
SMG_DisplayBit(3,0xff);
delay(200);
SMG_DisplayBit(4,0xff);
delay(200);
//3位数码管来显示键值
if(count_value > 99)
{
SMG_DisplayBit(5,smg_data[count_value2/100]);
delay(200);
}
if(count_value > 9)
{
SMG_DisplayBit(6,smg_data[count_value2/10%10]);
delay(200);
}
SMG_DisplayBit(7,smg_data[count_value2%10]);
delay(200);
SMG_All(0xff);
delay(200);
}
//EEPROM写操作
void Write_AT24C02(unsigned char addr,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
//读操作
unsigned char Read_AT24C02(unsigned char addr)
{
unsigned int temp = 0;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return temp;
}
void Key_Scan(void)
{
H3 = 0;
H1 = H2 = H4 = 1;
L1 = L2 = L3 = L4 = 1;
//S9 回显
if(L3 == 0)
{
delay(20);
if(L3 == 0)
{
while(L3 == 0){
if(interface == 1)
{
interface = 2; //界面切换
SMG_Display_Data1();
}
else if(interface == 2)
{
interface = 1;
SMG_Display_Data2();
}
}
}
}
//S5 减
else if(L4 == 0)
{
delay(20);
if(L4 == 0)
{
while(L4 == 0)
{
SMG_Display_Data1();
}
//在计数界面下进行键值的减
if(interface == 1)
{
count_value--;
}
}
}
H4 = 0;
H1 = H2 = H3 = 1;
L1 = L2 = L3 = L4 = 1;
//S8 存储
if(L3 == 0)
{
delay(20);
if(L3 == 0)
{
//每次按下时将计时和标志位清零
s_press = 0;
s_count = 0;
while(L3 == 0)
{
SMG_Display_Data1();
}
if(s_press == 1) //长按标志
{
count_value = 0; //计数清零
}
//短按
else
{
if(interface == 1)
{
//count_value2 = count_value; //保存当前值
Write_AT24C02(0x00,count_value);
}
}
}
}
//S4 加
else if(L4 == 0)
{
delay(20);
if(L4 == 0)
{
while(L4 == 0)
{
SMG_Display_Data1();
}
//在计数界面下 进行键值的累加
if(interface == 1)
{
count_value++;
}
}
}
}
//dac数据
void Read_DAC(float dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
//电压显示
void Voltage_Tackle(void)
{
//为5非0 整数倍 DAC->4 ELSE DAC ->1
if((count_value % 5)== 0)
{
Read_DAC(204); //数字转模拟 0-5 ->0-255
//5/255 = 4/x 4x51 = 204
}
else
{
Read_DAC(51);
}
}
void Led_Tackle(void)
{
if(interface == 1)
{
LED1 = 0;
}
else
{
LED1 = 1;
}
if(count_value > count_value2)
{
if(led_flag == 0)
{
LED2 = 0;
}
else if(led_flag == 1)
{
LED2 = 1;
}
}
Init_74HC138(4);
}
void Init_Timer(void)
{
TMOD = 0x01;
TH0 = (65535-50000)/256; //50ms
TL0 = (65535-50000)%256;
ET0 = 1;
TR0 = 1;
EA = 1;
}
//主函数
void main(void)
{
Init_System();
Init_Timer();
while(1)
{
Key_Scan();
switch(interface)
{
case 1:SMG_Display_Data1();break;
case 2:
count_value2 = Read_AT24C02(0x00);
SMG_Display_Data2();break;
}
Led_Tackle();
Voltage_Tackle();
}
}
void Server_Timer0() interrupt 1
{
TH0 = (65535-50000)/256; //50ms
TL0 = (65535-50000)%256;
count++;
s_count++;
if(count == 4) //0.2s 开启led标志位
{
count = 0;
if(led_flag == 0)
{
led_flag = 1;
}
else if(led_flag == 1)
{
led_flag = 0;
}
}
if(s_count == 40) //定时2s
{
s_press = 1; //长按标志位置1 代表已进入长按模式
}
}