第十四届蓝桥杯单片机第一场模拟赛程序

第十四届蓝桥杯单片机第一场模拟赛程序

题目来源于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

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值