第十五届蓝桥杯单片机模拟考试II
目录
一、基本要求
使用大赛组委会提供的四梯/国信长天单片机竞赛实训平台,完成本试题的程序设计与调试。程序编写、调试完成后,选手需通过考试系统提交以准考证号命名的hex文件。不符合以上文件提交要求的作品将被评为零分或者被酌情扣分。硬件设置:
-
将IAP15F2K61S2单片机内部振荡器频率设定为12MHZ。
-
键盘工作模式跳线J5配置为KBD矩阵按键模式。
-
扩展方式跳线J13配置为IO模式。
请注意:选手需严格按照以上要求配置竟赛板,编写和调试程序,不符合以上配置要求的作品将被评为零分或者被酌情扣分。
二、硬件框图
三、功能描述
3.1基本功能描述
-
通过获取DS18B20温度传感器的温度数据,完成温度测量功能;
-
通过PCF8591 AD/DA芯片完成环境光测量和DAC输出功能;
-
通过LED指示灯完成试题要求的状态指示功能;
-
通过数码管、按键完成试题要求的数据显示和界面切换功能。
3.2显示功能
1、模式界面
-
模式界面如图2所示,显示内容包括模式编号,测量的参数数据。
-
模式1为温度控制模式,显示内容包括编号'1’和测量的温度参数。
-
温度参数单位为'C,保留小数点后1位,固定使用3位数码管显示。
-
模式2为光照度控制模式,显示内容包括编号“2”和测量的光照度参数。
-
光照度参数单位为Lux,保留整数,固定使用3位数码管显示,不足3位时,高位(左侧)数码管熄灭。
2、输出界面
-
输出界面如图3所示,由标识符(U)和输出的DAC数据组成。
-
输出的DAC数据单位为V,保留小数点后1位,固定使用2位数码管显示
3、显示要求
-
按照题目要求的界面格式和切换方式进行设计。
-
数码管显示无重影、闪烁、过暗、亮度不均匀等严重影响显示效果的缺陷。
3.3按键功能
1、功能说明
1)S4:定义为“模式切换”,在模式界面下,按下S4按键,切 换2种控制模式,切换顺序如下图所示。
2)S5:定义为“界面切换”,按下S5按键,切换模式界面和输出界面,切换顺序如图所示。
2、按键要求
-
按键应做好消抖处理,避免出现一次按键动作导致功能多次触发。
-
按键动作不影响数码管显示等其他功能。
-
按键S4仅在“模式界面”有效。
3.4输出功能
模式1,DAC输出与测量的温度参数有关,温度参数与DAC输出关系如图6.1所示。
模式2,DAC输出与测量的光照度参数有关,光照度参数与DAC输出关系如图6.2所示。
3.5LED指示灯功能
1)温度控制模式下,指示灯L1点亮,否则指示灯L1熄灭。
2)光照度控制模式下,指示灯L2点亮,否则指示灯L2熄灭,其余指示灯均处于熄灭状态。
3.6初始状态
请严格按照以下要求设计作品的上电初始状态。 处于模式界面,温度控制模式。
四、代码示例
// Header:
// File Name:
// Author:
// Date:
/********************预编译、宏和变量********************************************/
#include "main.h"
#include <stdio.h>
#include "key.h"
#include "iic.h"
#include "onewire.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 Page;
//温度
float Temp;
//光照度
uchar Lux;
//DAC数据
float Dac;
//模式切换
uchar Ms_Flag;
/*******************************************************************************
函数名程: void Display_Task(void)
函数功能: 显示内容执行任务,0.5s刷新一次显示内容
参数列表:
返回值 :
*******************************************************************************/
void Display_Task(void)
{
static uint Display_Tick;
if((Tick - Display_Tick) > 500)
{
Display_Tick = Tick;
switch (Page)
{
case 0://模式界面
if(!Ms_Flag)//温度控制模式
{
LED0=1;LED1=0;
sprintf(Dsp_Bit, "1 %3.1f", (float)Temp);
}
else//光照度控制模式
{
LED0=0;LED1=1;
sprintf(Dsp_Bit, "2 %3bu", (uchar)Lux);
}
break;
case 1://输出界面
sprintf(Dsp_Bit, "U %2.1f",Dac );
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 (Page)
{
case 0://模式界面
switch (Key_Value)
{
case 4://切换模式
Ms_Flag=!Ms_Flag;
break;
case 5://切面切换
Page=1;
break;
default:
break;
}
break;
case 1://输出界面
switch (Key_Value)
{
case 5://切面切换
Page=0;
break;
default:
break;
}
break;
default:
break;
}
}
}
/*******************************************************************************
函数名程: void Data_Task(void)
函数功能: 定时处理数据的采集、处理、传输任务
参数列表:
返回值 :
*******************************************************************************/
void Data_Task(void)
{
static uint Data_Tick;
uchar Dac_Data;
if((Tick - Data_Tick) > 500)
{
if(!Ms_Flag)//温度控制模式
{
//READ_Temperature_f();
Temp=READ_Temperature_f();
//Dac=Temp*(4/30)-(1-4/3);
Dac=Temp*0.1333-0.3333;
//输出限位
Dac=(Dac<1)?1:Dac;
Dac=(Dac>5)?5:Dac;
}
else//亮度控制模式
{
//PCF8591_Adc(1);
Lux=PCF8591_Adc(1);
//Dac=Lux*(4/230)+(1-4/23);
Dac=Lux*0.0174+0.8261;
//输出限位
Dac=(Dac<1)?1:Dac;
Dac=(Dac>5)?5:Dac;
}
Dac_Data=Dac*255/5;
PCF8591_Dac(Dac_Data);
}
}
/*******************************************************************************
函数名程: void Data_Task(void)
函数功能: 定时按一定逻辑执行任务
参数列表:
返回值 :
*******************************************************************************/
void Logic_Task(void)
{
static uint Logic_Tick;
if((Tick - Logic_Tick) > 500)
{
Logic_Tick = Tick;
}
}
/*******************************************************************************
函数名程: Trans_Task(void)
函数功能: 定时按一定逻辑执行任务
参数列表:
返回值 :
*******************************************************************************/
void Trans_Task(void)
{
static uint Trans_Tick;
if((Tick - Trans_Tick) > 500)
{
Trans_Tick = Tick;
}
}
/*******************************************************************************
函数名程: 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();
/********************功能函数*******************************************/
while(1)
{
Display_Task();
Key_Task();
Data_Task();
Logic_Task();
}
}