第十四届蓝桥杯又开始啦,XDM都在做准备了麦,明年的蓝桥杯将是自己大学期间最后一个比赛了,希望可以取得一个更好的成绩,努力勿辜负,加油。
一、题目要求
二、软件部分
#include "reg52.h"
#include "iic.h"
/******************************************************************
*第十三届蓝桥杯省赛软件部分实现 *
*Author:小殷童鞋 *
*Date:2022-12-13 *
*******************************************************************/
sbit S4 = P3^3;
sbit S5 = P3^2;
sbit S6 = P3^1;
sbit S7 = P3^0;
unsigned int f_count = 0,count = 0,period = 0; //频率 显示频率 周期变量
unsigned char Rd_Data = 0,Rd_Volt = 0, channel = 1; //通道模拟数据 电压 和通道变量
unsigned char interface = 1; //界面
unsigned int old_volt = 0,old_f = 0; //缓存电压和频率
unsigned char long_press_flag = 0,t_count = 0,press_count = 0; //长按标志 计时 长按次数变量
unsigned char led_flag = 1,led_status = 0xff,old_led_status = 0xff;//led启动标志 led状态 led旧状态变量
//共阳
unsigned char code SMG_Duan[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xbf}; //数码管段码
unsigned char code smg_dot[] ={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //带小数点
//简单延时
void delay(unsigned int t)
{
while(t--);
}
//744HC138初始化
void Init_74HC138(unsigned char dat)
{
switch(dat)
{
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;
}
P2 = (P2 & 0x1f) | 0x00;
}
//数码管按位操作
void SMG_DisplayByBit(unsigned char pos,unsigned char dat)
{
P0 = (0x01 << pos);
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
//操作所有数码管
void Controal_All_SMG(unsigned char dat)
{
P0 = 0xff;
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
//数码管数据显示频率
void SMG_Display_Frequent(void)
{
SMG_DisplayByBit(0,SMG_Duan[15]);
delay(200);
if(count > 999999)
{
SMG_DisplayByBit(1,SMG_Duan[count/1000000]);
delay(200);
}
if(count > 99999)
{
SMG_DisplayByBit(2,SMG_Duan[count/100000%10]);
delay(200);
}
if(count > 9999)
{
SMG_DisplayByBit(3,SMG_Duan[count/10000%10]);
delay(200);
}
if(count > 999)
{
SMG_DisplayByBit(4,SMG_Duan[count/1000%10]);
delay(200);
}
if(count > 99)
{
SMG_DisplayByBit(5,SMG_Duan[count/100%10]);
delay(200);
}
if(count > 9)
{
SMG_DisplayByBit(6,SMG_Duan[count/10%10]);
delay(200);
}
SMG_DisplayByBit(7,SMG_Duan[count%10]);
delay(200);
Controal_All_SMG(0xff);
delay(200);
}
//周期显示
void SMG_Display_Period(void)
{
SMG_DisplayByBit(0,~0x37);
delay(200);
if(count > 999999)
{
SMG_DisplayByBit(1,SMG_Duan[period/1000000]);
delay(200);
}
if(count > 99999)
{
SMG_DisplayByBit(2,SMG_Duan[period/100000%10]);
delay(200);
}
if(count > 9999)
{
SMG_DisplayByBit(3,SMG_Duan[period/10000%10]);
delay(200);
}
if(count > 999)
{
SMG_DisplayByBit(4,SMG_Duan[period/1000%10]);
delay(200);
}
if(count > 99)
{
SMG_DisplayByBit(5,SMG_Duan[period/100%10]);
delay(200);
}
if(count > 9)
{
SMG_DisplayByBit(6,SMG_Duan[period/10%10]);
delay(200);
}
SMG_DisplayByBit(7,SMG_Duan[period%10]);
delay(200);
Controal_All_SMG(0xff);
delay(200);
}
//PCF8591电压采集
void PCF8591_Volt_Rd1(unsigned char channel)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
if(channel == 1)
{
IIC_SendByte(0x01); //光敏
}
else if(channel == 3)
{
IIC_SendByte(0x03); //电压
}
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
Rd_Data = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
Rd_Volt = Rd_Data * (5.0/255) * 100; //扩大100倍方便显示
}
//数码管电压显示数据
void SMG_Display_Volt(void)
{
SMG_DisplayByBit(0,~0x3e);
delay(200);
SMG_DisplayByBit(1,0xbf);
delay(200);
SMG_DisplayByBit(2,SMG_Duan[channel]); //通道编号
delay(200);
SMG_DisplayByBit(3,0xff);
delay(200);
SMG_DisplayByBit(4,0xff);
delay(200);
SMG_DisplayByBit(5,smg_dot[Rd_Volt/100]); //电压
delay(200);
SMG_DisplayByBit(6,SMG_Duan[Rd_Volt/10%10]);
delay(200);
SMG_DisplayByBit(7,SMG_Duan[Rd_Volt%10]);
delay(200);
Controal_All_SMG(0xff);
delay(200);
}
//按键控制
void Key_Scans(void)
{
if(S4 == 0)
{
delay(20);
if(S4 == 0)
{
while(S4 == 0)
{
//在按键一直按下时 避免数码管熄灭 根据相应的界面显示相应的数据
if(interface == 1)
{
SMG_Display_Frequent();
}
else if(interface == 2)
{
SMG_Display_Period();
}
else if(interface == 3)
{
SMG_Display_Volt();
}
}
if(interface == 1)
{
interface = 2;
}
else if(interface == 2)
{
interface = 3;
}
else if(interface == 3)
{
interface = 1;
}
}
}
if(interface == 3)
{
//S5通道切换
if(S5 == 0)
{
delay(20);
if(S5 == 0)
{
while(S5 == 0)
{
PCF8591_Volt_Rd1(channel);
SMG_Display_Volt();
}
if(channel == 1)
{
channel = 3;
}
else if(channel == 3)
{
channel = 1;
}
}
}
}
//S6缓存channel 电压
if(S6 == 0)
{
delay(20);
if(S6 == 0)
{
t_count = 0;
long_press_flag = 0;
while(S6 == 0)
{
//在按键一直按下时 避免数码管熄灭 根据相应的界面显示相应的数据
if(interface == 1)
{
SMG_Display_Frequent();
}
else if(interface == 2)
{
SMG_Display_Period();
}
else if(interface == 3)
{
SMG_Display_Volt();
}
if(long_press_flag == 1) //长按
{
if(press_count == 0)
{
press_count = 1;
led_flag = 0; //禁用LED 全部熄灭
old_led_status = led_status; //缓存Led状态
P0 = 0xff;
Init_74HC138(4);
}
else if(press_count == 1)
{
//恢复LED功能
press_count = 0;
led_status = old_led_status; //将缓存的LED状态重新赋值给led_status
led_flag = 1; //启用LED功能
}
}
else{
if(channel == 3)
{
old_volt = Rd_Volt;
}
}
}
}
}
//S7缓存频率
if(S7 == 0)
{
delay(20);
if(S7 == 0)
{
while(S7 == 0)
{
//在按键一直按下时 避免数码管熄灭 根据相应的界面显示相应的数据
if(interface == 1)
{
SMG_Display_Frequent();
}
else if(interface == 2)
{
SMG_Display_Period();
}
else if(interface == 3)
{
SMG_Display_Volt();
}
}
old_f = count; //将实时采集的频率count的值缓存到old_f变量中
}
}
}
//定时器初始化
void Init_Timer(void)
{
TMOD = 0x16; //定时器0计数 定时器1定时
TH0 = 0xff;
TL0 = 0xff;
TH1 = (65535 - 50000)/256; //高八位50ms
TL1 = (65535 - 50000)%256;
ET0 = 1;
ET1 = 1;
TR0 = 1;
TR1 = 1;
EA = 1;
}
//系统初始化
void Init_System(void)
{
Init_74HC138(0);
Controal_All_SMG(0xff);
P0 = 0xff;
Init_74HC138(4);
P0 = 0x00;
Init_74HC138(5);
}
//主函数
void main(void)
{
Init_System(); //系统初始化
Init_Timer(); //定时器初始化
while(1)
{
PCF8591_Volt_Rd1(channel);
Key_Scans();
switch(interface)
{
case 1:SMG_Display_Frequent();break;
case 2:SMG_Display_Period();break;
case 3:SMG_Display_Volt();break;
}
if(led_flag == 1)
{
if(old_volt < Rd_Volt) //L1 open
{
led_status = 0xfe; //0111 1111
}
if(old_f < count)
{
led_status &= 0xfd; //1011 1111
}
if(interface == 1)
{
led_status &= 0xfb; //1101 1111
}
if(interface == 2)
{
led_status &= 0xf7; //1110 1111
}
if(interface == 3)
{
led_status &= 0xef; //1111 0111
}
P0 = led_status;
Init_74HC138(4);
}
}
}
void Timer0_Server() interrupt 1
{
f_count++;
}
void Timer1_Server() interrupt 3
{
static unsigned char t = 0;
TH1 = (65535 - 50000)/256; //高八位50ms
TL1 = (65535 - 50000)%256;
t++;
t_count++;
if(t == 20) //1s
{
count = f_count;
period = (1.0/count) * 1000000;
f_count = 0;
t = 0;
}
if(t_count >= 20) //超过或等于1s
{
long_press_flag = 1;
}
}
有时间就多多练习,You Can Make It