【蓝桥杯单片机】蓝桥杯单片机第十一届国赛程序设计试题及其详细题解

既然大家想要了解十一届蓝桥杯单片机国赛,那小编话不多说,大家先来看看十一届单片机的程序设计试题吧。

相信大家看完试题后有了大概的思路了,十一届国赛试题有基本的三大块数码管、按键、LED,外加DS1302、i2c、与DS18B20。现在小编在这里奉上个人的代码。

主函数main.c

#include "config.h"

extern unsigned char mod4 ,mod5,segbuff[],hour,minute,second,flag_v;//S4 界面控制   显示界面
extern unsigned int temp,flag_L31;//温度存取 电压存取
unsigned char light = 0;//光照读取
unsigned char count_temp = 0,count_v = 0;//计时读取温度 计时读取电压
unsigned int cc = 0,old_liht = 0,count_L3 = 0;//计时读取温度  保存上次的光敏  暗状态计时
extern unsigned int k_temp1,k_hour1,k_led1,k_temp,k_hour,k_led,date_v;
float temp232 = 0;

void main(){
	unsigned char key_num = 20;
	sysinit();
	init_ds1302(0x16,0x59,0x50);
	Timer1Init();
	while(1){
		key_num = scankbd();
		switch(key_num){
			case 0://切换数据界面与参数界面
				if(++mod4 == 2) mod4 = 0;
				break;
			case 1://切换显示
				if(++mod5 == 3) mod5 = 0;
				break;
			case 4://参数加
				if(mod4 == 1) S8();
				break;
			case 5://参数减
				if(mod4 == 1) S9();
				break;
			default:
				break;
		}
		if(cc >= 200){//读取温度
			temp = rd_temperature();
			cc = 0;
		}
		if(count_v == 50){//获取光照
			light = adc(1);
			temp232 = (float)(light/51.0);
			date_v = temp232*100;
			if(light>130){
				flag_v = 1;//亮状态
			}else{
				flag_v = 0;//暗状态
			}
			count_v = 0;
		}
		if(mod4 == 0){k_hour = k_hour1;k_temp = k_temp1;k_led = k_led1;}
		read_ds1302();//获取时间
		S4();//判断界面
	}
}

void tiem1() interrupt 3{
	cc++;
	segs();
	count_v++;
	if(flag_v == 0){
		count_L3++;
	}else{
		count_L3 = 0;
	}
	ledpaly();
}

系统各个模块的函数配置函数

config.c

该文件主要写一些用于配置系统工作的函数,如按系统初始化函数、键扫描函数、数码管显示函数、各个显示函数等。

#include "config.h"

sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit L4 = P0^3;
sbit L5 = P0^4;
sbit L6 = P0^5;
sbit L7 = P0^6;
sbit L8 = P0^7;
sbit relay = P0^4;
sbit buzzer = P0^6;

#define kbd_io P3
#define kbd_maskrow 0x0f
#define state_0 0
#define state_1 1
#define state_2 2

unsigned char segbuff[] = {10,10,10,10,10,10,10,10};
unsigned char segtab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,
0xc0&0x7f,0xf9&0x7f,0xa4&0x7f,0xb0&0x7f,0x99&0x7f,0x92&0x7f,0x82&0x7f,0xf8&0x7f,0x90&0x7f,0x90&0x7f,0xbf,0xff,
0xc6,0x86,0x8c};// C E  P 
unsigned char mod5 = 0;//S5 显示控制
unsigned int temp = 0,k_temp = 25,k_hour = 0x17,k_led = 4,date_v = 0;//存放温度 存放分压值 温度参数 小时参数 LED参数
unsigned char flag_v = 0,flag_L31 = 0,hour1 = 0;//显示亮暗(1暗 0亮)
unsigned char mod4 = 0,hour_temp = 0;//S4 界面控制
unsigned int k_temp1 = 25,k_hour1 = 17,k_led1 = 4;

extern unsigned char hour,minute,second;//时 分 秒 
extern unsigned int count_L3;

void sysinit(){
	P2 = P2&0x1f|0x80;P0 = 0xff; P2 &= 0x1f;
	P2 = P2&0x1f|0xa0;relay = 0;buzzer = 0;P2 &= 0x1f;
	P2 = P2&0x1f|0xe0;P0 = 0xff;P2 &= 0x1f;
	P2 = P2&0x1f|0xc0;P0 =  0x00;P2 &= 0x1f;
}

void segs(){
	static unsigned char segaddr = 0;
	P2 = P2&0x1f|0xe0;P0 = 0xff;P2 &= 0x1f;
	P2 = P2&0x1f|0xc0;P0 = 1<<segaddr;P2 &= 0x1f;
	P2 = P2&0x1f|0xe0;P0 = segtab[segbuff[segaddr]];P2 &= 0x1f;
	if(++segaddr == 8) segaddr = 0;
}

unsigned char scankbd(){
	unsigned char key_num = 20;
	static unsigned char kbd_state = 0;
	unsigned char kbd_press;
	switch(kbd_state){
		case state_0:
			kbd_io = 0x0f;P42 = 0;P44 = 0;kbd_press = kbd_io;
			if(kbd_press != kbd_maskrow){
				kbd_state = state_1;
			}
			break;
		case state_1:
			kbd_press = kbd_io;
			if(kbd_press != kbd_maskrow){
				if((kbd_io&0x08)==0) key_num = 0;
				if((kbd_io&0x04)==0) key_num = 1;
				if((kbd_io&0x02)==0) key_num = 2;
				if((kbd_io&0x01)==0) key_num = 3;
				kbd_io = 0xf0;P44 = 1;P42 = 1;
				if(P44 == 0) key_num += 0;
				if(P42 == 0) key_num += 4;
				if((kbd_io&0x20)==0) key_num += 8;
				if((kbd_io&0x10)==0) key_num += 12;
				kbd_state = state_2;
			}else{
				kbd_state = state_0;
			}
			break;
			case state_2:
				kbd_io = 0x0f;P42 = 0;P44 = 0;kbd_press = kbd_io;
				if(kbd_press == kbd_maskrow){
					kbd_state = state_0;
				}
				break;
			default :
				break;
	}
	return key_num;
}

void S4(){//界面控制 数据界面 参数界面
	switch(mod4){
		case 0://数据界面
			S51();
			break;
		case 1://参数界面
			S52();
			break;
	}
}

void S51(){//显示界面切换 时间 温度 亮度状态
	switch(mod5){//显示时间
		case 0:
			segbuff[0] = hour/16;
			segbuff[1] = hour%16;
			segbuff[2] = 10;
			segbuff[3] = minute/16;
			segbuff[4] = minute%16;
			segbuff[5] = 10;
			segbuff[6] = second/16;
			segbuff[7] = second%16;
			break;
		case 1://显示温度
			segbuff[0] = 24;
			segbuff[1] = 10;
			segbuff[2] = 10;
			segbuff[3] = 10;
			segbuff[4] = 10;	
			segbuff[5] = temp/1000;
			segbuff[6] = temp%1000/100+12;
			segbuff[7] = temp%1000%100/10;	
			break;
		case 2://显示分压 亮度
			segbuff[0] = 25;
			segbuff[1] = 10;
			segbuff[2] = date_v/100+12;
			segbuff[3] = date_v/10%10;
			segbuff[4] = date_v%10;
			segbuff[5] = 10;
			segbuff[6] = 10;
			segbuff[7] = flag_v;
			break;
	}
}

void S52(){//显示参数
	switch(mod5){//显示时间参数
		case 0:
			segbuff[0] = 26;
			segbuff[1] = 1;
			segbuff[2] = 10;
			segbuff[3] = hour_temp/10;
			segbuff[4] = hour_temp%10;
			segbuff[5] = 10;
			segbuff[6] = k_hour/10;
			segbuff[7] = k_hour%10;
			break;
		case 1://显示温度参数
			segbuff[0] = 26;
			segbuff[1] = 2;
			segbuff[2] = 10;
			segbuff[3] = 10;
			segbuff[4] = 10;
			segbuff[5] = 10;
			segbuff[6] = k_temp/10;
			segbuff[7] = k_temp%10;
			break;
		case 2://显示指示灯参数
			segbuff[0] = 26;
			segbuff[1] = 3;
			segbuff[2] = 10;
			segbuff[3] = 10;
			segbuff[4] = 10;
			segbuff[5] = 10;
			segbuff[6] = 10;
			segbuff[7] = k_led%10;
			break;
	}
}

//mod5 0表示小时参数  1表示温度参数 2表示led参数
void S8(){//当前参数减1
	switch(mod5){
		case 0:
			if(--k_hour1 >= 24) k_hour1 = 23;
			break;
		case 1:
			if(--k_temp1 >=100) k_temp1 = 99;
			break;
		case 2:
			if(--k_led1 <= 3) k_led1 = 8;
			break;
	}
}

void S9(){//当前参数加1
		switch(mod5){
		case 0:
			if(++k_hour1 >= 24) k_hour1 = 0;
			break;
		case 1:
			if(++k_temp1 >=100) k_temp1 = 0;
			break;
		case 2:
			if(++k_led1 >=9) k_led1 = 4;
			break;
	}
}

void ledpaly(){
	P2 = P2&0x1f|0x80;P0 = 0xff;P2 &= 0x1f;
	hour_temp = hour/16*10+hour%16;
	if(hour_temp>=k_hour || hour_temp<=8){//条件不够
		P2 = P2&0x1f|0x80;L1 = 0;P2 &= 0x1f;//L1亮
	}else{
		P2 = P2&0x1f|0x80;L1 = 1;P2 &= 0x1f;//L1灭
	}
	if(temp <= k_temp*100){
		P2 = P2&0x1f|0x80;L2 = 0;P2 &= 0x1f;//L2亮
	}else{
		P2 = P2&0x1f|0x80;L2 = 1;P2 &= 0x1f;//L2灭
	}
	if(count_L3 >= 3000){
		P2 = P2&0x1f|0x80;L3 = 0;P2 &= 0x1f;//L3亮
	}else{
		P2 = P2&0x1f|0x80;L3 = 1;P2 &= 0x1f;//L3灭
	}
	if(flag_v == 0){
		switch(k_led){//选择亮L4-L8
			case 4:	P2 = P2&0x1f|0x80;L4 = 0;P2 &= 0x1f;
				break;
			case 5:	P2 = P2&0x1f|0x80;L5 = 0;P2 &= 0x1f;
				break;
			case 6:	P2 = P2&0x1f|0x80;L6 = 0;P2 &= 0x1f;
				break;
			case 7:	P2 = P2&0x1f|0x80;L7 = 0;P2 &= 0x1f;
				break;
			case 8:	P2 = P2&0x1f|0x80;L8 = 0;P2 &= 0x1f;
				break;
			default: break;
		}
	}
}	

void Timer1Init(void)		//1毫秒@12.000MHz
{
	AUXR &= 0xBF;		//定时器时钟12T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x18;		//设置定时初始值
	TH1 = 0xFC;		//设置定时初始值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	EA = 1;
	ET1 = 1;
}

iic.c模块

iic.c

IIC代码也可以自行在官方资源包中提取,但是需要注意细节,某些地方可能会出现一两个bug,

/*
  程序说明: IIC总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include <STC15F2K60S2.h>
#include "intrins.h"

#define DELAY_TIME 5

#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//总线引脚定义
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */

void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}
//总线启动条件
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

//总线停止条件
void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//发送应答
void IIC_SendAck(bit ackbit)
{
    SCL = 0;
    SDA = ackbit;  					// 0:应答,1:非应答
    IIC_Delay(DELAY_TIME);
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SCL = 0; 
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//等待应答
bit IIC_WaitAck(void)
{
    bit ackbit;
	
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SDA  = 1;
        else SDA  = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
    unsigned char i, da;
    for(i=0; i<8; i++)
    {   
    	SCL = 1;
	IIC_Delay(DELAY_TIME);
	da <<= 1;
	if(SDA) da |= 1;
	SCL = 0;
	IIC_Delay(DELAY_TIME);
    }
    return da;    
}

unsigned char adc(unsigned char add){
	unsigned char dat = 0;
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	dat = IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	
	return dat;
}

iic.h

#ifndef _IIC_H
#define _IIC_H

void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendAck(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 
unsigned char adc(unsigned char add);

#endif

ds1302模块

ds1302.c

ds1302的基本函数官方也提供了,目前来看没有留下过“坑”,大家可以放心使用。

/*
  程序说明: DS1302驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include <STC15F2K60S2.h>
#include "intrins.h"
#include "ds1302.h"

sbit SCK=P1^7;		
sbit SDA=P2^3;		
sbit RST = P1^3;   // DS1302复位												

void Write_Ds1302(unsigned  char temp) 
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK=0;
		SDA=temp&0x01;
		temp>>=1; 
		SCK=1;
	}
}   

void Write_Ds1302_Byte( unsigned char address,unsigned char dat )     
{
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1; 	_nop_();  
 	Write_Ds1302(address);	
 	Write_Ds1302(dat);		
 	RST=0; 
}

unsigned char Read_Ds1302_Byte ( unsigned char address )
{
 	unsigned char i,temp=0x00;
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1;	_nop_();
 	Write_Ds1302(address);
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;
		temp>>=1;	
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
	SCK=1;	_nop_();
	SDA=0;	_nop_();
	SDA=1;	_nop_();
	return (temp);			
}

unsigned char hour = 0,minute = 0,second = 0;

void init_ds1302(unsigned char h,unsigned char m,unsigned char s){
	Write_Ds1302_Byte(0x8e,0);
	Write_Ds1302_Byte(0x84,h);
	Write_Ds1302_Byte(0x82,m);
	Write_Ds1302_Byte(0x80,s);
	Write_Ds1302_Byte(0x8e,0x80);
}

void read_ds1302(){
	hour = Read_Ds1302_Byte(0x85);
	minute = Read_Ds1302_Byte(0x83);
	second = Read_Ds1302_Byte(0x81);
}

ds1302.h

#ifndef __DS1302_H
#define __DS1302_H

void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );
void init_ds1302(unsigned char h,unsigned char m,unsigned char s);
void read_ds1302();

#endif

onewire模块

onewire.c

onewire系列的基本函数官方也有提供,大家可自行提取,目前来看,代码也是可以直接使用的,不用担心出现bug。

/*
  程序说明: 单总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
  日    期: 2011-8-9
*/
#include "STC15F2K60S2.h"
#include "onewire.h"

sbit DQ = P1^4;  //单总线接口

//单总线延时函数
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	unsigned char i;
	while(t--){
		for(i =0;i<12;i++)
			;
	}
}

//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);
}

//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}

//DS18B20设备初始化
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(12);
  	DQ = 0;
  	Delay_OneWire(80);
  	DQ = 1;
  	Delay_OneWire(10); 
    initflag = DQ;     
  	Delay_OneWire(5);
  
  	return initflag;
}

unsigned int rd_temperature(void){
	unsigned char low,high;
	unsigned int result;
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	Delay_OneWire(200);
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	low = Read_DS18B20();
	high = Read_DS18B20();
	result = high&0x0f;
	result <<= 8;
	result |= low;
	result = result*6.25;//0.0625*100;
	
	return result;
}

onewire.h

#ifndef __ONEWIRE_H
#define __ONEWIRE_H

unsigned int rd_temperature(void); 
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);

#endif
  • 12
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
蓝桥杯是一个国内著名的计算机比赛,为了帮助参赛者更好地准备和了解比赛的题型,组委会会公布历年的真题并提供相应的题解。 首先,我们需要了解蓝桥杯是一个综合性的计算机比赛,测试的对象包括计算机基础知识、编程能力以及解决实际问题的能力。 在历年的真题中,参赛者将面临不同类型的题目,包括算法设计与优化问题、数据结构与算法问题、编程题等。其中针对Python B组的题目主要考察的是对Python语言的掌握和应用能力。 题目解答一般会包含以下几个方面的内容: 1. 题目分析与理解:读取题目,理解题目的要求和限制条件。通过仔细分析题目,确定题目的输入与输出,以及问题的核心。 2. 设计解决方案:根据题目要求和限制条件,设计一个合适的解决方案。可以使用合适的算法和数据结构来解决问题,并做出相应的性能优化。 3. 编写代码实现:根据设计的方案编写相应的代码实现。需要注意的是,Python语言有其独特的语法和特性,掌握好这些特性可以更好地完成编程任务。 4. 调试与测试:编写完代码后,需要进行调试和测试。通过运行样例输入和输出,检查代码是否符合题目要求,并且没有逻辑上的错误。 5. 总结与优化:在完成题目解答后,可以进行总结和优化。包括分析算法复杂度、代码风格和可读性等方面,以便在比赛中更好地表现。 在准备蓝桥杯时,可以通过阅读历年的真题和题解来了解比赛的难度和类型,针对性地进行练习和提高。同时也可以参加相关的培训班和讨论活动,与其他参赛者交流经验和技巧。 总而言之,历年蓝桥杯真题的解答对于提高自己的编程能力和应对比赛非常有帮助。通过认真分析和实践,可以更好地理解并掌握Python编程,并在比赛中取得更好的成绩。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值