第十四届蓝桥杯单片机第一场模拟赛程序
题目来源于4T评测网 www.4t.wiki
赛题:
一、基本要求
使用大赛组委会提供的国信长天单片机竞赛实训平台,完成本试题的程序设计与调试。程序编写、调试完成后,选手需通过考试系统提交以准考证号命名的hex文件。不符合以上文件提交要求的作品将被评为零分或者被酌情扣分。
硬件设置:
将IAP15F2K61S2单片机内部振荡器频率设定为12MHz,串口通信波特率为9600bps。
键盘工作模式跳线J5配置为KBD矩阵按键模式。
扩展方式跳线J13配置为IO模式。
请注意:选手需严格按照以上要求配置竞赛板,编写和调试程序,不符合以上配置要求的作品将被评为零分或者被酌情扣分。
二、硬件框图
图1 系统硬件框图
三、功能描述
3.1 基本功能描述
1) 通过PCF8591的ADC通道测量电位器RB2的输出电压,模拟噪音分贝。噪音数据与电压关系曲线如下图所示。
图2 噪音分贝与电压采集关系曲线
2)通过数码管显示模拟的噪音分贝和分贝参数,显示界面可以通过按键切换。
3)通过串口向PC端返回当前噪音数据。
4)通过按键实现界面的切换和分贝参数的调整。
5)通过LED指示灯完成题目要求的输出指示功能。
3.2 数码管显示
1)噪音界面
噪音界面如图3所示,显示内容包括界面提示符(U1)和噪音数据,噪音数据保留小数点后1位有效数据。
固定使用三位数码管显示噪音数据,当数据长度不足3位时,高侧(左侧)数码管熄灭。
图3 噪音分贝显示界面(54.6dB)
2)参数界面
参数界面如图3所示,显示内容包括界面提示符(U2)和参数数据。
固定使用两位数码管显示分贝参数数据,当数据长度不足2位时,高侧(左侧)数码管熄灭。
图4 分贝参数显示界面(65dB)
3.3 按键功能
1)按键S12定义为“切换”按键,按下S12按键,能够切换“噪音分贝显示界面”、“分贝参数显示界面”。
图5 按键S12‘切换’
2)按键S16定义为“加”按键,在“分贝参数显示界面”时,按下S16按键,当前分贝参数加5dB。
图6 按键S16‘加’
3)按键S17定义为“减”按键,在“分贝参数显示界面”时,按下S17按键,当前分贝参数减5dB。
图7 按键S17‘减’
注意:
按键S16和按键S17仅在“参数界面”有效
判断按键是否按下时,需进行消抖操作,避免单次按键操作,触发多次结果。
3.4 串口通信功能
当前界面处于噪音分贝显示界面时,当串口收到字符串“Return”时,将当前检测的噪音数据发送给PC端的串口调试工具。
串口打印格式为: “Noises:54.6dB”
设备串口返回数据格式为字符串。
串口通信波特率:9600bps,请使用竞赛平台上的USB转串口单元完成此项功能。
3.5 LED指示灯功能
1) 当前界面处于噪音分贝显示界面时,L1指示灯点亮,否则熄灭。
2) 当前界面处于分贝参数显示界面时,L2指示灯点亮,否则熄灭。
3) 当噪音分贝超过分贝参数时,L8指示灯以0.1s为间隔切换亮灭状态;否则熄灭。
4) 指示灯L3-L7处于熄灭状态。
3.6 初始化
1) 数码管默认处于噪音分贝显示界面。
2) 上电默认分贝参数为65dB,参数设置范围为0-90。
程序 :
main.c
/*
第十四届蓝桥杯单片机第一场模拟赛程序
by Wul
*/
#include "STC15F2K60S2.h"
#include "iic.h"
#include "stdio.h"
#define uchar unsigned char
#define uint unsigned int
sbit LED8=P0^7;
code unsigned char Seg_Table[] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e, //F
0xff, //灭 16
0xc1 //U 17 1100 0001
};
uchar dspbuff[8]={16,16,16,16,16,16,16,16};
uchar dspcom=0;
uchar temp,JieMian,Canshu=65;
uchar ad_value;
uchar intr=0,intr1=0;
uchar JieMian=1;
code uchar s1[]={"Noises:"};
code uchar s2[]={"dB"};
uchar str[10];
uchar str1[10];
uchar rxcnt=0;
uchar str_re='R';
uint v_value,Zaoyin;
bit flag,L8,rxc=0,state=0;
// *********** 初始化函数 ******************************************
void InitAll()
{
P2=(P2&0x1f)|0x80;
P0=0xff;
P2=(P2&0x1f)|0xa0;
P0=0x00;
P2=(P2&0x1f);
}
void UartInit(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器时钟12T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xE6; //设置定时初始值
TH1 = 0xFF; //设置定时初始值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
ES=1;EA=1;
}
void Timer0_Init(void) //2毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x30; //设置定时初始值
TH0 = 0xF8; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;EA=1;
}
void DisplaySMG()
{
P2=(P2&0x1f)|0xe0;
P0=0xff;
P2=(P2&0x1f);
P2=(P2&0x1f)|0xc0;
P0=1<<dspcom;
P2=(P2&0x1f)|0xe0;
P0=Seg_Table[dspbuff[dspcom]];
P2=(P2&0x1f);
if(JieMian==1)
{
if(dspcom==6)
{
P2=(P2&0x1f)|0xe0;
P0=Seg_Table[dspbuff[dspcom]]&0x7f;
P2=(P2&0x1f);
}
}
if(++dspcom==8) {dspcom=0;}
}
void Delay5ms() //@12.000MHz
{
unsigned char i, j;
i = 59;
j = 90;
do
{
while (--j);
} while (--i);
}
void SendByte(uchar dat)
{
SBUF=dat;
while(TI==0);
TI=0;
}
void SendString(uchar *s)
{
unsigned char *p;
p = s;
while(*p != '\0')
{
SBUF = *p;
while(TI == 0); //等待发送标志位置位
TI = 0;
p++;
}
}
//**************************** 显示 *****************************
void displayZaoyin()
{
dspbuff[0]=17; //U1
dspbuff[1]=1;
if(Zaoyin>99)dspbuff[5]=Zaoyin/100%10;
else dspbuff[5]=16;
if(Zaoyin>9)dspbuff[6]=Zaoyin/10%10;
dspbuff[7]=Zaoyin%10;
}
void displayCanshu()
{
dspbuff[0]=17; //U2
dspbuff[1]=2;
dspbuff[5]=16;
if(Canshu>9) dspbuff[6]=Canshu/10;
else dspbuff[6]=16;
dspbuff[7]=Canshu%10;
}
void ScanKey()
{
P32=1;P33=1;P34=1;P35=0;
if(P33==0) //S12
{
Delay5ms();
if(P33==0)
{
if(JieMian==1) JieMian=2;
else if(JieMian==2)
{
JieMian=1;
}
}
while(!P33);
}
P32=1;P33=1;P34=0;P35=1;
if(P32==0) //S17
{
Delay5ms();
if(P32==0)
{
if(JieMian==2)
{
if(Canshu<=0) Canshu=90;
else Canshu=Canshu-5;
}
}
while(!P32);
}
if(P33==0) //S16
{
Delay5ms();
if(P33==0)
{
if(JieMian==2)
{
if(Canshu>=90) Canshu=0;
else Canshu=Canshu+5;
}
}
while(!P33);
}
}
//*********************** MAIN.H ***************************
void main()
{
InitAll();
Timer0_Init();
UartInit();
while(1)
{
if(flag)
{
flag=1;
ad_value=Read_PCF8591();
v_value=ad_value*10/51;
Zaoyin=v_value*18;
}
if(JieMian==1)
{
displayZaoyin();
P2=(P2&0x1f)|0x80;
P0=0xfe;
}
else if(JieMian==2)
{
displayCanshu();
P2=(P2&0x1f)|0x80;
P0=0xfd;
}
if((Zaoyin/10)>Canshu)
{
if(intr1<=50)
{
LED8=0;
}
else
{
LED8=1;
}
}
if(rxc == 1)
{
rxc = 0;
switch(str_re)
{
case 'R':
{
sprintf(str,"%s",s1);
sprintf(str1,"%s",s2);
SendString(str);
SendByte(0x30+Zaoyin/100);
SendByte(0x30+Zaoyin%100/10);
SendByte('.');
SendByte(0x30+Zaoyin%10);
SendString(str1);
SendByte('\r');
SendByte('\n');
}
break;
}
ES = 1;
}
ScanKey();
}
}
void intr_Timer0() interrupt 1
{
DisplaySMG();
if(++intr==50)
{
intr=0;
flag=1;
}
if(++intr1==100)
{
intr1=0;
}
}
void isr_uart(void) interrupt 4
{
if(RI)
{
RI = 0; //清除接收标志位
str_re=SBUF;
ES = 0;
rxc = 1;
}
}
iic.c
/* # I2C代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "STC15F2K60S2.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 char Read_PCF8591()
{
unsigned char temp;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x03);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
temp=I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return temp;
}
iic.h
#ifndef __IIC_H
#define __IIC_H
static void I2C_Delay(unsigned char n);
void I2CStart(void);
void I2CStop(void);
void I2CSendByte(unsigned char byt);
unsigned char I2CReceiveByte(void);
unsigned char I2CWaitAck(void);
void I2CSendAck(unsigned char ackbit);
unsigned char Read_PCF8591();
#endif