第十一届预赛试题
目录
一、系统硬件框图
二、基本功能
(1)使用 PCF8591 芯片测量 AIN3 通道上获取的电压信号(电位器 Rb2 输出电压)Vain3。
(2)通过数码管实现数据、计数和参数设置三个界面的显示,界面可通过按键切换。
(3)通过 EEPROM 实现参数的掉电存储功能。
(4)通过按键实现界面切换、计数清零和参数设置等功能。
(5)通过LED 指示灯实现超时等状态提醒等功能。
(6)设计要求
-
电压数据刷新时间:≤ 0.5秒。
-
电压数据采样时间:≤ 0.1秒。
-
显示界面切换时间:≤ 0.3秒。
-
参数存储占用EEPROM一个字节,存储位置:T24C02内部地址0。
-
电压参数可设置范围:0 ≤Vp≤ 5.0。
三、显示功能
(1)数据界面
数据界面如图3.2所示,显示内容包括提示符U和PCF8591芯片AIN3通道采集到的电压值 Vain3,电压数据单位为V,保窗小数点后2位有效数字。
(2)参数界面
设置界面如图 3.3所示,显示内容包括标识符P和电压参数 Vp。
(3)计数界面
计数界面如图 3.4所示,显示内容包括标识符N 和计数值。
计数值加1触发条件如图3.5所示。
四、按键功能
(1)S4:定义为显示界面切换按键,按下此按键,循环切换数据、参数和计数界面。
(2)S5:定义为清零按键,按下此按键,可将当前计数值清零。
(3)S8:定义为减按键,按下此按键,电压参数V减小0.5V,减小到0.00V后,再次按下此按键返回 5.00V。
(4)S9:定义为加按键,按下此按键,电压参数V增加 0.5V,增加到5.00V后,再次按下此按键返回 0.00V。
(5)设计要求
-
按键 S8 和按键 S9 的加减功能仅在参数设置界面有效。
-
按键 S5 清零功能仅在计数界面有效。
-
合理设置参数边界范围,防止出现参数越界。
-
从参数界面退出时,将电压参数V放大10倍后(Vp*10),保存到 EEPROM 存储器(内部地址0),占用一个字节。
五、LED指示功能
(1)指示灯L1:当 Vain3<Vp,的状态持续时间超过5秒时,L1点亮,否则熄灭。
(2)指示灯L2:当前计数值为奇数时,L2点亮,否则熄灭。
(3)指示灯L3:连续3次以上(含3次)的无效按键操作触发L3 点亮,直到出现有效的按键操作,L3 熄灭。
六、初始状态说明
(1)初始状态上电默认处于数据显示界面,计数值为0,指示灯L2灭。
(2)设备上电后,应自EEPROM内部地址0读出数据,并将该数据处理为电压参数Vp.
七、代码示例
// Header:
// File Name:
// Author:
// Date:
/********************预编译、宏和变量********************************************/
#include "main.h"
#include <stdio.h>
#include "key.h"
#include "iic.h"
/*************************************************************
宏定义区域
**************************************************************/
#define CONTROL(x,y) P0=y;P2=x;P2=0 //为锁存器的引脚操作封装一个带参宏
enum PERIPHERAL
{
LED = 0x80,
DEVICE = 0xa0,
BIT = 0xc0,
SEG = 0xe0
};
/*******************************************************************************
变量定义
********************************************************************************/
/********************模板驱动变量****************************/
//控制LED0~7的开关量,正逻辑
bit LED0, LED1, LED2, LED3, LED4, LED5, LED6, LED7;
//控制蜂鸣器的自定义变量,正逻辑
bit Buzzer;
//控制继电器的自定义变量,正逻辑
bit Relay;
//Dsp_Bit是数码管显示的字符串数组,考虑到小数点的同位显示,所以字符串长度最长为16
uchar Dsp_Bit[16] = {0};
//数码管显示的各位段码内容,由 Dsp_Bit 通过函数Seg_Tran转换更新
uchar Dsp_Code[8] = {0};
//定时器计数
uint Tick;
/********************中断区域***************************************************/
/*******************************************************************************
函数名程: void Timer_2Init(void)
函数功能: 定时器T2 中断 1ms 配置
参数列表:
返回值 :
*******************************************************************************/
void Timer_2Init(void) //1000微秒@12.000MHz
{
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x20; //设置定时初值
T2H = 0xD1; //设置定时初值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x04; //ET2 = 1;
EA = 1;
}
/*******************************************************************************
函数名程: void Timer2_Service() interrupt 12
函数功能: 定时器T2 中断 1ms 中断处理
参数列表:
返回值 :
*******************************************************************************/
void Timer2_Service() interrupt 12
{
static uchar dsp_com;
//定时任务
Tick++;
/***********控制外设的引脚操作*****/
//更新LED的引脚操作
CONTROL(LED,~((uchar)LED0|(uchar)LED1<<1|(uchar)LED2<<2|(uchar)LED3<<3|(uchar)LED4<<4|(uchar)LED5<<5|(uchar)LED6<<6|(uchar)LED7<<7));
//更新蜂鸣器、继电器的引脚操作
CONTROL(DEVICE,(uchar)Buzzer<<6|(uchar)Relay<<4);
//更新一位数码管的引脚操作
CONTROL(BIT,0); //消影
CONTROL(SEG,Dsp_Code[dsp_com]); //放入要显示的数字到段选锁存
CONTROL(BIT,1 << (dsp_com)); //选择对应的位选锁存
if(++dsp_com > 7) //显示完一次后自增位选,位选到8之后回到1
dsp_com = 0;
}
/*******************************************************************************
函数名程: void Seg_Tran(void)
函数功能: 将Dsp_Bit[]的内容,转换成对应的段码放入Dsp_Code[];
参数列表:
返回值 :
*******************************************************************************/
void Seg_Tran(void)
{
unsigned char i, j=0, temp;
for (i=0; i<8; i++, j++)
{
switch (Dsp_Bit[j])
{ // 低电平点亮段,段码[MSB...LSB]对应码顺序为[dp g f e d c b a]
case '0': temp = 0xc0; break;
case '1': temp = 0xf9; break;
// case '1': temp = 0xcf; break;
case '2': temp = 0xa4; break;
case '3': temp = 0xb0; break;
// case '3': temp = 0x86; break;
case '4': temp = 0x99; break;
// case '4': temp = 0x8b; break;
case '5': temp = 0x92; break;
case '6': temp = 0x82; break;
// case '6': temp = 0x90; break;
case '7': temp = 0xf8; break;
// case '7': temp = 0xc7; break;
case '8': temp = 0x80; break;
case '9': temp = 0x90; break;
// case '9': temp = 0x82; break;
case 'A': temp = 0x88; break;
case 'B': temp = 0x83; break;
case 'C': temp = 0xc6; break;
case 'D': temp = 0xA1; break;
case 'E': temp = 0x86; break;
case 'F': temp = 0x8E; break;
case 'H': temp = 0x89; break;
case 'L': temp = 0xC7; break;
case 'N': temp = 0xC8; break;
case 'P': temp = 0x8c; break;
case 'U': temp = 0xC1; break;
case '-': temp = 0xbf; break;
case ' ': temp = 0xff; break;
case '^': temp = 0xfe; break; // 1 1 1 1 1 1 1 0
case '_': temp = 0xf7; break; // 1 1 1 1 0 1 1 1
default: temp = 0xff;
}
if (Dsp_Bit[j+1] == '.')
{
temp = temp&0x7f; // 点亮小数点
j++;
}
Dsp_Code[i] = temp;
}
}
/********************应用层变量****************************/
//两个参数
char KeyNum;
//界面
uchar UI;
//数据
float V_ain3;
//参数
float V_p;
float V_p10;
//计数次数
uint Count;
//清零标志
uchar Count_Flag;
//L3标志
uchar L3_Count;
//L1标志
static uchar L1_Count;
/*******************************************************************************
函数名程: void Display_Task(void)
函数功能: 显示内容执行任务,0.5s刷新一次显示内容
参数列表:
返回值 :
*******************************************************************************/
void Display_Task(void)
{
static uint Display_Tick;
if((Tick - Display_Tick) > 500)
{
Display_Tick = Tick;
switch (UI)
{
case 0://数据界面
sprintf(Dsp_Bit,"U %3.2f", (float)V_ain3);
break;
case 1://参数界面
sprintf(Dsp_Bit,"P %3.2f", (float)V_p);
break;
case 2://计数界面
if(!Count_Flag)
sprintf(Dsp_Bit,"N %02u", (uint)Count);
else//清零
sprintf(Dsp_Bit,"N 00");
LED1=(Count%2)?1:0;//指示灯L2:当前计数值为奇数时,L2点亮,否则熄灭。
break;
default:
break;
}
//sprintf(Dsp_Bit, "%9.2f", (float)KeyNum);
}
Seg_Tran();
}
/*******************************************************************************
函数名程: void Key_Task(void)
函数功能: 按键执行任务,每2ms执行一次
参数列表:
返回值 :
*******************************************************************************/
void Key_Task(void)
{
static uint Key_Tick;
char Key_Value;
if((Tick - Key_Tick) > 2)
{
Key_Tick = Tick;
Key_Value = MatKeyScan_4x4();
switch (UI)
{
case 0://数据界面
switch (Key_Value)
{
case 4://切换
UI=1;
L3_Count=0;
LED2=0;
break;
case 5://无效按键
L3_Count++;
if(L3_Count>=3)
LED2=1;
break;
case 8://无效按键
L3_Count++;
if(L3_Count>=3)
LED2=1;
break;
case 9://无效按键
L3_Count++;
if(L3_Count>=3)
LED2=1;
break;
default:
break;
}
break;
case 1://参数界面
switch (Key_Value)
{
case 4://切换
UI=2;
L3_Count=0;
LED2=0;
V_p10=V_p*10;
AT24C02_WriteBuffer((unsigned char*)&V_p10,0,1);
break;
case 5://无效按键
L3_Count++;
if(L3_Count>=3)
LED2=1;
break;
case 8://-0.5
L3_Count=0;
LED2=0;
if(V_p)
V_p-=0.5;
else
V_p=5.00;
break;
case 9://+0.5
L3_Count=0;
LED2=0;
if(V_p<5)
V_p+=0.5;
else
V_p=0;
break;
default:
break;
}
break;
case 2://计数界面
switch (Key_Value)
{
case 4://切换
UI=0;
L3_Count=0;
LED2=0;
break;
case 5://清零
Count_Flag=!Count_Flag;
L3_Count=0;
LED2=0;
break;
case 8://无效按键
L3_Count++;
if(L3_Count>=3)
LED2=1;
break;
case 9://无效按键
L3_Count++;
if(L3_Count>=3)
LED2=1;
break;
default:
break;
}
break;
default:
break;
}
}
}
/*******************************************************************************
函数名程: void Data_Task(void)
函数功能: 定时处理数据的采集、处理、传输任务
参数列表:
返回值 :
*******************************************************************************/
void Data_Task(void)
{
static uint Data_Tick;
if((Tick - Data_Tick) > 100)//电压数据采样时间
{
Data_Tick = Tick;
V_ain3=(float)PCF8591_Adc(3)/51;
}
}
/*******************************************************************************
函数名程: void LED0_Logic_Task(void)
函数功能: 定时按一定逻辑执行任务
参数列表:
返回值 :
*******************************************************************************/
void LED0_Logic_Task(void)
{
static uint LED0_Logic_Tick;
if((Tick - LED0_Logic_Tick) > 1000)//1s
{
LED0_Logic_Tick = Tick;
if(V_ain3<V_p)
{
L1_Count++;
if(L1_Count>5)
LED0=1;
else
LED0=0;
}
}
}
/*******************************************************************************
函数名程: void Jishu_Task(void)
函数功能: 定时按一定逻辑执行任务
参数列表:
返回值 :
*******************************************************************************/
void Jishu_Task(void)
{
static uint Jishu_Tick;
static uchar dat;
if((Tick - Jishu_Tick) > 100)//0.1s
{
Jishu_Tick = Tick;
switch(dat) //计数值加1
{
case 0:
if(V_ain3>V_p)
{
dat=1;
}
break;
case 1:
if(V_ain3<V_p)
{
Count++;
dat=0;
}
break;
}
}
}
/*******************************************************************************
函数名程: void P_Init(void)
函数功能: 外设初始化
参数列表:
返回值 :
*******************************************************************************/
void P_Init(void) //外设初始化
{
CONTROL(LED,0xff); //初始化LED熄灭
CONTROL(DEVICE,0x00); //初始化所有外设不工作
CONTROL(BIT,0x00); //初始化数码管位选无效
CONTROL(SEG,0xff); //初始化数码管段选无效
//定时器T2时基1ms初始化
Timer_2Init();
}
/*************************************************************
主函数
**************************************************************/
void main(void)
{
/********************初始化********************************************/
P_Init();
AT24C02_ReadBuffer((unsigned char*)&V_p10,0,1);
/********************功能函数*******************************************/
while(1)
{
Display_Task();
Key_Task();
Data_Task();
LED0_Logic_Task();
Jishu_Task();
}
}
标签:break,界面,void,蓝桥,单片机,L3,按键,省赛,Tick
From: https://blog.csdn.net/2302_79960206/article/details/142286279