一、基本要求
使用大赛组委会提供的国信长天单片机竞赛实训平台,完成本试题的程序设计与调试。程序编写、调试完成后,选手需通过考试系统提交以准考证号命名的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。
题目来源——4T官网
代码参考如下,4T测评其他功能都没问题,就只有L8闪烁周期有问题,实在找不出问题所在,如有大佬知晓,望指正
#include <STC15F2K60S2.H>
#include "iic.h"
#include "intrins.h"
#include "string.h"
#include "stdio.h"
#define TSMG 500
void send_mydat();
void SelectHC573(unsigned char channel,unsigned char dat);
sbit h3 = P3^2;
sbit h4 = P3^3;
sbit s3 = P3^5;
sbit s4 = P3^4;
code unsigned char Seg_Table[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82,0xf8,
0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86,0x8e };
code unsigned char nodot[] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
unsigned char adc_value = 0;
float adc_volt = 0;
float dB_value = 0;
unsigned int dB_smg = 0;
unsigned char dB_param = 65;
unsigned char UI = 0;//0-噪音界面 1-参数界面
unsigned char stat_dat = 0;//数据接收完成状态
unsigned char str_dat[20];//储存接收的数据
unsigned char receve_dat = 0;//接受的一位数据
unsigned char send_dat[20];//要发送的数据
unsigned char stat_RX = 0;
unsigned char num = 0;
unsigned char stat_led = 0xff;
unsigned char count_01s = 0;
unsigned char stat_warn = 0;
void Delay20ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 1;
j = 234;
k = 113;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Timer5Init(void) //50毫秒@12.000MHz
{
AUXR &= 0xFB; //定时器时钟12T模式
T2L = 0xB0; //设置定时初值
T2H = 0x3C; //设置定时初值
AUXR |= 0x10; //定时器2开始计时
EA = 1;
IE2 |= 0x04;
}
void Sevice_timer2() interrupt 12
{
if(stat_warn == 1)
{
count_01s++;
if(count_01s == 2)
{
count_01s = 0;
if((stat_led & 0x80) == 0x00)//亮状态
{
stat_led |= 0x80;
SelectHC573(4,stat_led);
}
else
{
stat_led &= 0x7f;
SelectHC573(4,stat_led);
}
}
}
}
void Init_Uart()
{
PCON &= 0x7f;
SCON = 0x50;
AUXR |= 0x40;
AUXR &= 0xfe;
TMOD &= 0x0f;
TMOD |= 0x20;
TL1 = 0xd9;
TH1 = 0xd9;
ET1 = 0;
TR1 = 1;
EA = 1;
ES = 1;
}
void sevice_Uart() interrupt 4
{
if(RI == 1)
{
RI = 0;
receve_dat = SBUF;
if((stat_RX == 0) && (stat_dat == 0))
{
if(receve_dat == 'R')
{
num = 0;
stat_RX = 1;
str_dat[num++] = receve_dat;
}
}
else if(stat_RX == 1)
{
str_dat[num++] = receve_dat;
if(num == 6)
{
stat_dat = 1;
str_dat[num] = '\0';
stat_RX = 0;
}
}
}
}
void Uart_sendbyt(unsigned char dat)
{
SBUF = dat;
while(TI == 0);
TI = 0;
}
void Uart_sendsting(char *dat)
{
while(*dat != '\0')
{
Uart_sendbyt(*dat++);
}
}
void read_myvolt()
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x03);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
adc_value = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
adc_volt = adc_value * (5.0 / 255);
dB_value = adc_volt * 18;
dB_smg = dB_value * 10;
}
void SelectHC573(unsigned char channel,unsigned char dat)
{
P2 = (P2 & 0x1f) | 0x00;
P0 = dat;
switch(channel)
{
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 DelaySMG(unsigned int t)
{
while(t--);
}
void DisplaySMG_Bit(unsigned char pos,unsigned char value)
{
SelectHC573(6,0x01 << pos);
SelectHC573(7,value);
DelaySMG(TSMG);
SelectHC573(6,0x01 << pos);
SelectHC573(7,0xff);
}
void DisplaySMG_ALL(unsigned char value)
{
SelectHC573(6,0xff);
SelectHC573(7,value);
}
void DisplaySMG_Info()
{
if(UI == 0)
{
DisplaySMG_Bit(0,0xc1);
DisplaySMG_Bit(1,Seg_Table[1]);
if(dB_smg > 99)
DisplaySMG_Bit(5,Seg_Table[dB_smg / 100]);
DisplaySMG_Bit(6,nodot[dB_smg / 10 % 10]);
DisplaySMG_Bit(7,Seg_Table[dB_smg % 10]);
}
else if(UI == 1)
{
DisplaySMG_Bit(0,0xc1);
DisplaySMG_Bit(1,Seg_Table[2]);
if(dB_param > 9)
DisplaySMG_Bit(6,Seg_Table[dB_param / 10]);
DisplaySMG_Bit(7,Seg_Table[dB_param % 10]);
}
}
void Scan_key()
{
h4 = 0;
s3 = s4 = h3 = 1;
if(s3 == 0)//12
{
Delay20ms();
if(s3 == 0)
{
if(UI == 0)
{
UI = 1;
}
else
{
UI = 0;
}
while(s3 == 0)
{
DisplaySMG_Info();
}
}
}
if(s4 == 0)//16
{
Delay20ms();
if(s4 == 0)
{
if(dB_param == 90)
{
dB_param = 0;
}
else
{
dB_param+=5;
}
while(s4 == 0)
{
DisplaySMG_Info();
}
}
}
h3 = 0;
h4 = s3 = s3 = 1;
if(s4 == 0)//17
{
Delay20ms();
if(s4 == 0)
{
if(dB_param == 0)
{
dB_param = 90;
}
else
{
dB_param -= 5;
}
while(s4 == 0)
{
DisplaySMG_Info();
}
}
}
}
void send_mydat()
{
if(stat_dat == 1)
{
if(UI == 0)
{
if(strcmp(str_dat,"Return") == 0)
{
sprintf(send_dat,"Noises:%.1fdB",dB_value);
Uart_sendsting(send_dat);
}
}
stat_dat = 0;
}
}
void led_control()
{
if(UI == 0)
{
stat_led = 0xfe;
SelectHC573(4,stat_led);
}
if(UI == 1)
{
stat_led = 0xfd;
SelectHC573(4,stat_led);
}
if((int)dB_value > dB_param)
{
stat_warn = 1;
}
else
{
stat_warn = 0;
stat_led |= 0x80;
SelectHC573(4,stat_led);
}
}
void main()
{
Init_Uart();
Timer5Init();
DisplaySMG_ALL(0xff);
SelectHC573(4,0xff);
SelectHC573(5,0x00);
while(1)
{
led_control();
send_mydat();
Scan_key();
DisplaySMG_Info();
read_myvolt();
}
}