蓝桥杯单片机---第十二届省赛题目解析

news2024/9/27 7:18:06

文章目录

  • 比赛题目
  • 一、代码相关定义、声明
    • 1.头文件声明
    • 2.变量声明
  • 二、主要函数
    • 1.main函数
    • 2.按键扫描
    • 3.数码管显示
    • 4.电压模式1、2输出 & LED显示
    • 5.定时器中断
    • 6.消除85°C显示
  • 三、次要函数
    • 1.初始化函数Init
    • 2.按键函数Key
    • 3.LED函数Led
    • 4.数码管函数Seg
    • 5.iic函数中
    • 6.onewire函数中

比赛题目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一、代码相关定义、声明

1.头文件声明

/* 头文件声明区 */
#include <STC15F2K60S2.H>//单片机寄存器专用头文件
#include <Init.h>//初始化底层驱动专用头文件
#include <Led.h>//Led底层驱动专用头文件
#include <Key.h>//按键底层驱动专用头文件
#include <Seg.h>//数码管底层驱动专用头文件
#include "onewire.h"
#include "iic.h"

2.变量声明

/* 变量声明区 */
unsigned char Key_Val,Key_Down,Key_Old,Key_Up;//按键专用变量
unsigned char Key_Slow_Down;//按键减速专用变量
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10};//数码管显示数据存放数组
unsigned char Seg_Point[8] = {0,0,0,0,0,0,0,0};//数码管小数点数据存放数组
unsigned char Seg_Pos;//数码管扫描专用变量
unsigned int Seg_Slow_Down;//数码管减速专用变量
unsigned char ucLed[8] = {0,0,0,0,0,0,0,0};//Led显示数据存放数组
unsigned char Seg_Disp_Mode;//数码管显示变量 0-温度显示 1-参数设置 2-DA输出
float Temperature;//实时温度变量
unsigned char Seg_temp_Disp = 25;//显示参数
unsigned char Seg_temp_contorl = 25;//参数控制
float Volat;//AD
bit Out_Put;//AD模式转换变量

二、主要函数

1.main函数

/* Main */
void main()
{
	rd_temperature();
	Delay750ms();
	System_Init();
	Timer0Init();
	while (1)
	{
		Key_Proc();
		Seg_Proc();
		Led_Proc();
	}
}

2.按键扫描

/* 键盘处理函数 */
void Key_Proc()
{
	if(Key_Slow_Down) return;
	Key_Slow_Down = 1;//键盘减速程序

	Key_Val = Key_Read();//实时读取键码值
	Key_Down = Key_Val & (Key_Old ^ Key_Val);//捕捉按键下降沿
	Key_Up = ~Key_Val & (Key_Old ^ Key_Val);//捕捉按键上降沿
	Key_Old = Key_Val;//辅助扫描变量
	
	switch(Key_Down)
	{
		case 4:
			if(++Seg_Disp_Mode == 3) Seg_Disp_Mode = 0;
			if(Seg_Disp_Mode == 1) Seg_temp_Disp = Seg_temp_contorl;
			if(Seg_Disp_Mode == 2) Seg_temp_contorl = Seg_temp_Disp;
		break;
		case 8:
			if(Seg_Disp_Mode == 1)
			{
				if(--Seg_temp_Disp == 255) Seg_temp_Disp = 0;
			}
		break;
		case 9:
			if(Seg_Disp_Mode == 1)
			{
				if(++Seg_temp_Disp == 100) Seg_temp_Disp = 99;
			}
		break;
		case 5:
			Out_Put ^= 1;
		break;
	}
}

3.数码管显示

/* 信息处理函数 */
void Seg_Proc()
{
	if(Seg_Slow_Down) return;
	Seg_Slow_Down = 1;//数码管减速程序
	
	//信息获取区域
	Temperature = rd_temperature();//实时读取温度值
	Volat = Ad_Read();
	
	switch(Seg_Disp_Mode)
	{
		case 0://温度显示界面
			Seg_Buf[0] = 11;//C
			Seg_Buf[4] = (unsigned char)Temperature / 10 % 10;
			Seg_Buf[5] = (unsigned char)Temperature % 10;
			Seg_Buf[6] = (unsigned int)(Temperature * 100) / 10 % 10;
			Seg_Buf[7] = (unsigned int)(Temperature * 100)% 10;
			Seg_Point[5] = 1;
		break;
		case 1:
			Seg_Buf[0] = 12;//P
			Seg_Buf[4] = 10;
			Seg_Buf[5] = 10;
			Seg_Buf[6] = Seg_temp_Disp / 10 % 10;
			Seg_Buf[7] = Seg_temp_Disp % 10;
			Seg_Point[5] = 0;
		break;
		case 2:
			Seg_Buf[0] = 13;//P
			Seg_Buf[5] = (unsigned char)Volat;
			Seg_Buf[6] = (unsigned int)(Volat * 100) / 10 % 10;
			Seg_Buf[7] = (unsigned int)(Volat * 100) % 10;
			Seg_Point[5] = 1;
		break;
	}
}

4.电压模式1、2输出 & LED显示

/* 其他显示函数 */
void Led_Proc()
{
	unsigned char i = 0;
	if(Out_Put == 0)
	{
		if(Temperature < Seg_temp_Disp)
			Volat = 0;
		else Volat = 5;
	}
	else
	{
		if(Temperature < 20)
			Volat = 1;
		else if(Temperature > 40)
			Volat = 4;
		else Volat = 0.15 * (Temperature - 20) + 1;
	}
	Da_Write(Volat * 51);
	
	ucLed[0] = !Out_Put;
	for(i = 0 ; i < 3 ; ++ i)
		ucLed[i + 1] = (i == Seg_Disp_Mode);
}

5.定时器中断

/* 定时器0中断初始化函数 */
void Timer0Init(void)		//1毫秒@12.000MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x18;		//设置定时初始值
	TH0 = 0xFC;		//设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;    //定时器中断0打开
	EA = 1;     //总中断打开
}

/* 定时器0中断服务函数 */
void Timer0Server() interrupt 1
{  
	if(++Key_Slow_Down == 10) Key_Slow_Down = 0;//键盘减速专用
	if(++Seg_Slow_Down == 500) Seg_Slow_Down = 0;//数码管减速专用
	if(++Seg_Pos == 8) Seg_Pos = 0;//数码管显示专用
	Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
	Led_Disp(Seg_Pos,ucLed[Seg_Pos]);
}

6.消除85°C显示

void Delay750ms(void)	//@12.000MHz
{
	unsigned char data i, j, k;
	i = 35;
	j = 51;
	k = 182;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

三、次要函数

1.初始化函数Init

在Init.c文件当中

#include <Init.h>

void System_Init()
{
	P0 = 0xff;
	P2 = P2 & 0x1f | 0x80;
	P2 &= 0x1f;
	
	P0 = 0x00;
	P2 = P2 & 0x1f | 0xa0;
	P2 &= 0x1f;
}

在Init.h文件当中

#include <STC15F2K60S2.H>
void System_Init();

2.按键函数Key

在Key.c文件当中

#include <Key.h>

unsigned char Key_Read()
{
	unsigned char temp = 0;
	P44 = 0;P42 = 1;P35 = 1;P34 = 1;
	if(P33 == 0) temp = 4;
	if(P32 == 0) temp = 5;
	if(P31 == 0) temp = 6;
	if(P30 == 0) temp = 7;
	P44 = 1;P42 = 0;P35 = 1;P34 = 1;
	if(P33 == 0) temp = 8;
	if(P32 == 0) temp = 9;
	if(P31 == 0) temp = 10;
	if(P30 == 0) temp = 11;
	P44 = 1;P42 = 1;P35 = 0;P34 = 1;
	if(P33 == 0) temp = 12;
	if(P32 == 0) temp = 13;
	if(P31 == 0) temp = 14;
	if(P30 == 0) temp = 15;
	P44 = 1;P42 = 1;P35 = 1;P34 = 0;
	if(P33 == 0) temp = 16;
	if(P32 == 0) temp = 17;
	if(P31 == 0) temp = 18;
	if(P30 == 0) temp = 19;
	return temp;
}
/*
unsigned char Key_Read()
{
	unsigned char temp = 0;
	if(P33 == 0) temp = 4;
	if(P32 == 0) temp = 5;
	if(P31 == 0) temp = 6;
	if(P30 == 0) temp = 7;
	return temp;
}
*/

在Key.h文件当中

#include <STC15F2K60S2.H>
unsigned char Key_Read();

3.LED函数Led

#include <Led.h>

void Led_Disp(unsigned char addr,enable)
{
	static unsigned char temp = 0x00;
	static unsigned char temp_old = 0xff;
	if(enable)
		temp |= 0x01 << addr;
	else
		temp &= ~(0x01 << addr);
	if(temp != temp_old)
	{
		P0 = ~temp;
		P2 = P2 & 0x1f | 0x80;
		P2 &= 0x1f;
		temp_old = temp;
	}
}

void Beep(unsigned char flag)
{
	static unsigned char temp = 0x00;
	static unsigned char temp_old = 0xff;
	if(flag)
		temp |= 0x40;
	else
		temp &= ~0x40;
	if(temp != temp_old)
	{
		P0 = temp;
		P2 = P2 & 0x1f | 0xa0;
		P2 &= 0x1f;
		temp_old = temp;		
	}
}

void Relay(unsigned char flag)
{
	static unsigned char temp = 0x00;
	static unsigned char temp_old = 0xff;
	if(flag)
		temp |= 0x10;
	else
		temp &= ~0x10;
	if(temp != temp_old)
	{
		P0 = temp;
		P2 = P2 & 0x1f | 0xa0;
		P2 &= 0x1f;
		temp_old = temp;		
	}	
}

4.数码管函数Seg

#include <Seg.h>

unsigned char seg_dula[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xc6,0x8c,0x88};
unsigned char seg_wela[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

void Seg_Disp(unsigned char wela,dula,point)
{
	P0 = 0xff;
	P2 = P2 & 0x1f | 0xe0;
	P2 &= 0x1f;

	P0 = seg_wela[wela];
	P2 = P2 & 0x1f | 0xc0;
	P2 &= 0x1f;
	
	P0 = seg_dula[dula];
	if(point)
		P0 &= 0x7f;
	P2 = P2 & 0x1f | 0xe0;
	P2 &= 0x1f;	
}

5.iic函数中

/*	#   I2C代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "iic.h"

#define DELAY_TIME	5

//
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 Ad_Read(unsigned char addr)
{
	unsigned char temp;
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(addr);
	I2CWaitAck();
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	temp = I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	return temp;
} 

void Da_Write(unsigned char dat)
{
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x41);
	I2CWaitAck();
	I2CSendByte(dat);
	I2CWaitAck();
	I2CStop();
}

6.onewire函数中

/*	# 	单总线代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <reg52.h>
sbit DQ = P1^4;
//
void Delay_OneWire(unsigned int t)  
{
	unsigned char i;
	while(t--){
		for(i=0;i<12;i++);
	}
}

//
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);
}

//
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;
}

//
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;
}


//========================

float rd_temperature(void)
{
	unsigned char low,high;//返回温度的高低八位
	init_ds18b20();//初始化
	Write_DS18B20(0xcc);//跳过ROM
	Write_DS18B20(0x44);//进行温度转换
	
	init_ds18b20();//初始化
	Write_DS18B20(0xcc);//跳过ROM
	Write_DS18B20(0xbe);//读取温度
	
	low = Read_DS18B20();//读取低位
	high = Read_DS18B20();//读取高位
	
	return ((high << 8) | low ) / 16.0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1507234.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python(5)之处理数组

上次代码结果如下&#xff1a; 1、处理数组的缺失值 1、isnan&#xff08;&#xff09;函数 isnan&#xff08;&#xff09;函数是Numpy模块里的一个可以标记数组中缺失值的位置 代码示例如下&#xff1a; import numpy as np ac np.array([1,2,3,2,3,4,5,9,np.nan,1]) p…

分布式CAP原理详解

引言 随着互联网的飞速发展&#xff0c;越来越多的应用开始采用分布式系统来提高系统的可用性和扩展性。在分布式系统中&#xff0c;CAP原理是一个非常重要的理论&#xff0c;它描述了分布式系统在面临网络分区时&#xff0c;如何在一致性、可用性和分区容错性之间进行权衡。本…

PDF24 Creator PDF工具箱 v11.17.0

软件介绍 可将大部分文件转成pdf格式的免费软件&#xff0c;安装好后会在你的打印机里看到一个叫PDF24的虚拟打印机&#xff0c;你可将要转成pdf格式的文件打印时选虚拟打印机PDF24&#xff0c;也可以直接将文件以拖拉方式拉进这软件的主视窗编辑区里&#xff0c;它会自动转成…

信息系统项目管理师006:车联网(1信息化发展—1.2现代化基础设施—1.2.3车联网)

文章目录 1.2.3 车联网1.体系框架2.链接方式3.场景应用 记忆要点总结 1.2.3 车联网 车联网是新一代网络通信技术与汽车、电子、道路交通运输等领域深度融合的新兴产业形态。智能网联汽车是搭载先进的车载传感器、控制器、执行器等装置&#xff0c;并融合现代通信与网络技术&…

模型驱动架构MDA

MDE 模型驱动工程&#xff08;MDE, Model-Driven Engineering&#xff09;是软件工程的一个分支&#xff0c;它将模型与建模拓展到软件开发的所有方面&#xff0c;形成一个多维建模空间&#xff0c;从而将工程活动建立在这些模型的映射和转换之上。[1] MDE的基本原则是将模型视…

【leetcode热题】对链表进行插入排序

给定单个链表的头 head &#xff0c;使用 插入排序 对链表进行排序&#xff0c;并返回 排序后链表的头 。 插入排序 算法的步骤: 插入排序是迭代的&#xff0c;每次只移动一个元素&#xff0c;直到所有元素可以形成一个有序的输出列表。每次迭代中&#xff0c;插入排序只从输…

代码训练LeetCode(7)删除有序数组中的重复项

代码训练(7)LeetCode之删除有序数组中的重复项 Author: Once Day Date: 2024年3月10日 漫漫长路&#xff0c;才刚刚开始… 全系列文章可参考专栏: 十年代码训练_Once-Day的博客-CSDN博客 参考文章: 26. 删除有序数组中的重复项 - 力扣&#xff08;LeetCode&#xff09;力扣…

割点原理及封装好的割点类

作者推荐 视频算法专题 预备知识 本分析针对&#xff1a;连通无向图G。 搜索树 节点的父子关系&#xff1a;任意 节点的邻接 节点除了已处理 节点&#xff0c;都是它的子 节点。 以任意一点为根开始DFS&#xff0c;计算所有 节点的父子关系。只保留个子 节点到父 节点形成…

C++学习随笔(2)——引用与函数

经过上章对C有了一个初步认识后&#xff0c;本章我们来学习一下C的一些与C语言不同的新玩样引用&#xff0c;还有C的函数规则。 目录 1. 引用 1.1 引用概念 1.2 引用特性 1.3 常引用 1.4 使用场景 &#xff08;1&#xff09; 做参数 &#xff08;2&#xff09; 做返回值…

【Emgu CV教程】9.1、形态学常用操作之腐蚀

文章目录 一、相关概念1.什么叫形态学2.形态学操作的目的3.形态学都包含哪些操作4.结构元素StructuringElement 二、腐蚀1.什么叫腐蚀2.腐蚀的作用3.腐蚀的函数 三、演示1.原始素材2.代码3.运行结果 一、相关概念 1.什么叫形态学 形态学&#xff0c;英文名称morphology&#…

无需编程技能:Python爬虫与数据可视化毕业论文代写服务

引言 作为一名在软件技术领域深耕多年的专业人士&#xff0c;我不仅在软件开发和项目部署方面积累了丰富的实践经验&#xff0c;更以卓越的技术实力获得了&#x1f3c5;30项软件著作权证书的殊荣。这些成就不仅是对我的技术专长的肯定&#xff0c;也是对我的创新精神和专业承诺…

网络协议常见问题

网络协议常见问题 OSI&#xff08;Open Systems Interconnection&#xff09;模型OSI 封装 TCP/IP协议栈IP数据报的报头TCP头格式UDP头格式TCP (3-way shake)三次握手建立连接&#xff1a;为什么三次握手才可以初始化 Socket、序列号和窗口大小并建立 TCP 连接。每次建立TCP连接…

揭秘海外媒体运营:扩大影响力、跨越边界的创新之道

导语&#xff1a;随着全球化的不断深入&#xff0c;海外市场对于企业和个人的影响力已变得至关重要。在这一背景下&#xff0c;海外媒体运营崭露头角&#xff0c;成为扩大影响力、跨越边界的创新方式。本文将揭秘海外媒体运营的真正含义和功能&#xff0c;以及它如何通过原创内…

easyexcel文件上传

easyexcel文件上传 前言&#xff1a;功能开发中&#xff0c;难免碰到数据上传下载功能&#xff0c;excel上传常见用于报表上传&#xff0c;绩效上传&#xff0c;考勤上传… 使用步骤&#xff1a; 1&#xff0c;编写业务层&#xff1a; 1&#xff0c;添加easyexcel依赖 <…

linux:线程的控制

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》《C》《Linux》 文章目录 前言一、线程的总结1. 线程的优点2. 线程的缺点3. 线程异常4.线程和进程 二、线程的控制创建线程线程终止线程等待获取返回值 线程分离 总结 前言 本文作为我对于线程的…

基于美洲狮优化算法(Puma Optimizar Algorithm ,POA)的无人机三维路径规划(提供MATLAB代码)

一、无人机路径规划模型介绍 无人机三维路径规划是指在三维空间中为无人机规划一条合理的飞行路径&#xff0c;使其能够安全、高效地完成任务。路径规划是无人机自主飞行的关键技术之一&#xff0c;它可以通过算法和模型来确定无人机的航迹&#xff0c;以避开障碍物、优化飞行…

架构学习总结:企业架构=业务+数据+技术+应用架构

最近再次研读DAMA数据管理知识体系,结合工作对什么是企业架构?如何开展企业架构设计工作有一些新的认识,供大家参考。企业架构包括企业的业务架构、数据架构、技术架构和应用架构,要想做好企业的信息化数字化建设规划,这四个架构都不可缺少,这四个方面的内容共同组成了企…

药品管理系统|基于SSM 框架+ Mysql+Java+的药品管理系统设计与实现(可运行源码+数据库+设计文档+部署说明)

目录 文末获取源码 系统实现 前台首页功能 用户功能模块 管理员功能 员工功能模块 系统设计 数据库设计 lunwen参考 概述 源码获取 文末获取源码 系统实现 前台首页功能 用户功能模块 管理员功能 员工功能模块 系统设计 数据库设计 lunwen参考 概述 随着科学技术的…

区块链和人工智能的关系以及经典案例

目录 1.区块链与人工智能的关系 2.应用案例&#xff1a;基于区块链的医疗数据共享平台 2.1背景 2.2方案 2.3优势 2.4挑战 区块链技术和人工智能&#xff08;AI&#xff09;是两种不同的技术&#xff0c;但它们之间存在着互补关系。区块链技术提供了一种安全、透明、去中心…

设置文件管理器默认列宽 - Win系统

问题 当我们使用Windows系统自带的文件管理器时&#xff0c;手动调整列宽后&#xff0c;进入其他文件夹并不会生效更改&#xff0c;下文介绍解决方案&#xff0c;即如何设置文件管理器默认列宽。 解决方案 打开文件管理器&#xff0c;调整好每一列的列宽&#xff0c;然后点击…