当前位置: 首页 > article >正文

【蓝桥杯—单片机】第十一届省赛真题代码题解题笔记 | 省赛 | 真题 | 代码题 | 刷题 | 笔记

第十一届省赛真题代码部分

  • 前言
  • 赛题代码思路笔记
    • 竞赛板配置
      • 内部振荡器频率设定
      • 键盘工作模式跳线
      • 扩展方式跳线
    • 建立模板
    • 明确设计要求和初始状态
    • 显示功能部分
      • 数据界面
        • 第一部分
        • 第二部分
        • 第三部分
        • 调试时发现的问题
      • 参数设置界面
        • 第一部分
        • 第二部分和第四部分
        • 第三部分和第五部分
    • 按键功能部分
      • S4:“界面切换”按键
        • 从数据界面切换到参数设置界面
        • 从参数设置界面切换到数据界面
        • 调试时发现的问题
      • S5:“参数切换”按键
      • S6:“加”按键 和 S7:"减"按键
      • 调试时发现的问题
    • LED指示灯功能部分
      • L1、L2、L3
      • L4
    • DAC输出功能部分
  • 最终代码
    • User文件
      • main.c
    • Driver文件
      • Init.c
      • LED.c
      • Seg.c
      • Key.c
      • onewire.c
      • iic.c
  • 结语

前言

本文是对蓝桥杯第十一届省赛真题的代码题做的解题笔记,只记录了代码的思路,大模板用的是B站西风老师的2024年版大模板,具体内容就不再重复记录了。

思路参考西风第十四讲内容(资料链接已经在下方给出)

https://www.bilibili.com/video/BV1TR4y1k7iz?p=23&vd_source=e2191f89c557f5ac44bb6c7aa3967c7c

关于蓝桥杯第十一届省赛真题可以在官网查看(资料链接已经在下方给出)

https://www.lanqiao.cn/courses/2786/learning/?id=100643&compatibility=false

赛题代码思路笔记

竞赛板配置

根据赛题要求完成竞赛板的配置
在这里插入图片描述

内部振荡器频率设定

在stc中更改输入用户程序运行时的IRC频率为12MHz
在这里插入图片描述

键盘工作模式跳线

配置为BTN按键模式
在这里插入图片描述

扩展方式跳线

配置为IO模式
在这里插入图片描述

建立模板

根据赛题中的硬件框图确定本赛题的框架
在这里插入图片描述

如图,在Driver文件夹里建立LED、数码管、按键、iic、onewire模块,在User文件夹中建立主函数模块(大模板参考西风老师的2024版大模板)。

在这里插入图片描述

明确设计要求和初始状态

在这里插入图片描述

在这里插入图片描述

显示功能部分

在这里插入图片描述

由题可知,数码管显示一共两个界面。
可以引入一个变量Seg_Disp_Mode来标记当前显示界面,因为只有两个界面,所以可以定义为bit型而不是unsigned char型以此来节省空间。

bit Seg_Disp_Mode;     //数码管显示模式变量 0-数据界面 1-参数界面

再在信息处理函数的数码管部分中对当前显示模式进行判断。
判断完成后在各部分写入供该界面显示的代码。

void Seg_Proc()
{/*数码管减速*/if(Seg_Flag) return;Seg_Flag = 1;/*信息获取区域*//*数码管显示区域*/if(Seg_Disp_Mode == 0){}else{}
}

数据界面

下面来完成第一个界面的编写。
在这里插入图片描述

由题目可知,数据界面由三部分组成:

  1. 第一部分为提示符部分,是数码管的第一位,在该界面下全程显示字母C。
  2. 第二部分为熄灭部分,是数码管的第2到6位,在该界面下全程熄灭。
  3. 第三部分为实时温度显示界面,是数码管的第7到8位,在该界面下根据实时监测的温度不同显示数字实时变动。

在Driver文件夹下的Seg模块中的显示数组中加入用于表示熄灭的0xff,表示字母,表示字母C的0xc6,表示字母P的0x8c。

//code unsigned char seg_dula[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xc6,0x8c};//0-9为数字,10为熄灭,11为C,12为P

更改主模块中对应数码管控制列表中的值来控制数码管的显示情况。

第一部分

标识部分对应的数码管为第一位,更改主模块中对应数码管控制列表Seg_Buf中第一位对应的数,使其对应上Seg模块中的显示数组中的字母C。

Seg_Buf[0] = 12;//C
第二部分

熄灭部分,是数码管的第2到6位,全程为熄灭状态,在创建主函数中的Seg_Buf列表时其中的元素已经置为对应Seg模块中的显示数组中的熄灭,所以不要再做额外的更改。

第三部分

数码管显示的后两位为实时的温度数据,可以引入一个变量Temperature来存储当前获取的温度值。又由题可知,显示的温度值不含小数部分,所以可以直接用unsigned char型。

unsigned char Temperature;  //实时温度变量

温度获取函数返回值为float型,将其返回值赋给unsigned char型时要先对其经行强制类型转换。

Temperature =unsigned char)rd_temperature()

直接用整除10和取余10的形式来取出Temperature的个位和十位。

Seg_Buf[6] = Temperature / 10 ;
Seg_Buf[7] = Temperature % 10;
调试时发现的问题

在调试中发现,上电时并不是立刻显示实时温度值,而是会先显示85.00,要去掉85.00的干扰,可以在上电后先读取温度覆盖掉默认的85.00,再调用信息处理函数实现显示。
需要注意的是,单独调用温度读取函数时要再加一个750ms的延迟,因为DS18B20实现温度读取一次是750ms,如果不用延迟的话,无法实现完整的读取。

rd_temperture();
Delay750ms();

参数设置界面

在这里插入图片描述
由题目可知,数据界面由五部分组成:

  1. 第一部分为提示符部分,是数码管的第一位,在该界面下全程显示字母P。
  2. 第二部分为熄灭部分,是数码管的第2到3位,在该界面下全程熄灭。
  3. 第三部分为温度上限参数部分,是数码管的第4到5位。
  4. 第四部分为熄灭部分,是数码管的第6位,在该界面下全程熄灭。
  5. 第五部分为温度下限参数部分,是数码管的最后两位。
第一部分

标识部分对应的数码管为第一位,更改主模块中对应数码管控制列表Seg_Buf中第一位对应的数,使其对应上Seg模块中的显示数组中的字母P。

Seg_Buf[0] = 13;//C
第二部分和第四部分

不动

第三部分和第五部分

注意:题目涉及到一个可更改大小的参数时一般需要设置两个变量来标识此参数,一个用于实时的大小更改,一个用于实现控制
为什么要用两个变量,而不用一个?
答:如果只用一个变量,那么该参数在更改时同时会对它所要控制的原件产生影响,对实际的功能有干扰。
例如:当前设置值为24,需要设置的值为26,而蜂鸣器触发条件为25,则当前设置值在更改时会触发蜂鸣,但实际外部检测值并没有到要触发它的状态。

设置两个数组变量用于温度参数的显示和控制。数组的前一位为温度上限参数,后一位为温度下限参数。

unsigned char Temp_Disp[2] = {30,20};//温度变量显示数组
unsigned char Temp_Ctorl[2] = {30,20};//温度变量控制数组

对于显示只要更改数码管控制列表Seg_Buf中对应位置的值即可实现。

Seg_Buf[3] = Temp_Disp[0] / 10 % 10;
Seg_Buf[4] = Temp_Disp[0] % 10;
Seg_Buf[6] = Temp_Disp[1] / 10 % 10;
Seg_Buf[7] = Temp_Disp[1] % 10;

按键功能部分

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

在大模板主模块的按键处理函数中,用Key_Down判断按键按下的值。因为题目中按键涉及到4、5、6、7,所以可以添加一个switch对当前按下的按键进行一个判断。
判断完成后在各部分写入供该按键需要实现的功能的代码即可。

void Key_Proc()
{if (Key_Flag)return;Key_Flag = 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:break;case 5:break;case 6:break;case 7:break;}

S4:“界面切换”按键

在这里插入图片描述
该按键按下后实现了界面的切换。
在显示功能部分,我们已经定义了一个变量Seg_Disp_Mode来标记当前显示的界面,当Seg_Disp_Mode为0时是数据界面,为1时是参数设置界面。
因为变量Seg_Disp_Mode是bit型数据,只在0和1之间变换,所以可以直接用异或来运算。

Seg_Disp_Mode ^= 1;
从数据界面切换到参数设置界面

当按键按下后,Seg_Disp_Mode数值变为1时,界面从数据界面切换到参数设置界面。

if(Seg_Disp_Mode == 1)//从数据界面切换到参数设置界面{}

在该界面中,刚完成切换时显示的是当前用于控制相关原件的温度参数的值,即Temp_Ctrol的值。
但是Temp_Ctrol在该界面完成温度参数的设置前一直保持不变,所以不能对Temp_Ctrol经行更改。而要对显示变量Temp_Disp进行更改,且使得刚切换时候显示的是控制值,所以要将控制值赋给显示值。

Temp_Disp[0] = Temp_Ctorl[0];
Temp_Disp[1] = Temp_Ctorl[1];
从参数设置界面切换到数据界面

当按键按下后,Seg_Disp_Mode数值变为0时,界面从参数设置界面切换到数据界面。
这里需要注意参数设置界面退出时要对设置的上下限进行合理性检查参数设置界面在退出时设置的参数值才生效
在这里插入图片描述

else//从参数界面切换到数据界面{if(Temp_Disp[0] >= Temp_Disp[1])//合理型检查{Temp_Ctorl[0] = Temp_Disp[0];Temp_Ctorl[1] = Temp_Disp[1];}}
调试时发现的问题

从参数设置界面切换回数据界面时,温度上限参数仍然处于点亮状态。
为解决此问题,可以在每次调用数据显示界面时,对Seg_Buf[3]和Seg_Buf[4]进行更改。

if(Seg_Disp_Mode == 0)//数据界面{Seg_Buf[0] = 11;//CSeg_Buf[3] = 10;Seg_Buf[4] = 10;Seg_Buf[6] = Temperature /10 % 10;Seg_Buf[7] = Temperature % 10;}

S5:“参数切换”按键

在这里插入图片描述
该按键是在参数设置界面下才有用的,所以,要对当前界面先进行判断,当Seg_Disp_Mode为1时,即处于参数设置界面,可以实现参数切换功能。
引入一个变量Temp_Index使其在0和1之间变换,用于对上下限的选择。

bit Temp_Index = 1;//参数数组指针

按键S5每按下一次,Temp_Index变化一次,因为Temp_Index是只在0和1之间变换的bit型数据,所以可以用异或来运算。

Temp_Index ^= 1

S6:“加”按键 和 S7:"减"按键

在这里插入图片描述
在这里插入图片描述
加减按键在参数设置界面下才有用的,所以,还是要对当前显示的界面先进行判断。
且在该界面下,需要实现温度参数的变化,即对Temp_Disp进行更改。而加减是对上限参数的操作还是下限参数的操作在上一步中已经实现了,这里只要直接调用指向温度参数的变量Temp_Index即可。
这里还要注意的一点是温度的边界。
在减中,Temp_Disp为无符号char型,最大值为255,最小值为0,当Temp_Disp为0时再减1就会变成255,但是255超出了显示范围,且不符合当前情境下的逻辑。所以,当Temp_Disp自减1时,给它重新赋值为0,实现的是,减到0之后不会再变小。加处理与之类似,不再赘述

case 6:if(Seg_Disp_Mode == 1){if(++Temp_Disp[Temp_Index] == 100) Temp_Disp[Temp_Index] = 99;}
break;case 7:if(Seg_Disp_Mode == 1){if(--Temp_Disp[Temp_Index] == 255) Temp_Disp[Temp_Index] = 0;}
break;

调试时发现的问题

在这里插入图片描述
调试时发现,无法实现上图功能。那就在数据界面切换到参数设置界面时加入对Temp_Index重置的操作。

case 4:Seg_Disp_Mode ^= 1;if(Seg_Disp_Mode == 1)//从数据界面切换到参数设置界面{Temp_Index = 1;Temp_Disp[0] = Temp_Ctorl[0];Temp_Disp[1] = Temp_Ctorl[1];}

LED指示灯功能部分

在这里插入图片描述
LED的部分比较简单,实现点亮只要对主模块中的Led显示数据存放数组ucLed中的数进行更改即可。

L1、L2、L3

在这里插入图片描述
由题目可知,实时温度和设定温度进行比较后控制对应LED的点亮与否。当条件为真时,对应LED点亮。

ucLed[0] = (Temperature > Temp_Ctorl[0]);
ucLed[1] = (Temperature <= Temp_Ctorl[0] && Temperature >= Temp_Ctorl[1]);
ucLed[2] = (Temperature < Temp_Ctorl[1]);

L4

在这里插入图片描述
不同于L1、L2和L3的是,L4不是在比较结果下进行操作的。
L4的点亮与否对应的是参数设置界面中的合理性检查是否通过。当合理性检查通过时,L4熄灭;反之,点亮。且需要注意的是,L4在下一次通过合理性检查前都保持点亮状态。
定义一个bit型变量,用于标记当前是否通过合理性检查。

bit Error_Flag; //错误标志位

L4的点亮状况与是否通过合理性检测有关,即与错误标志位有关。当通过合理性检查是,L4给0,熄灭;反之,给1,点亮。

ucLed[3] = Error_Flag;

回到与合理性检查相关的部分,根据上述添加对错误标志位的处理。

else//从参数界面切换到数据界面{if(Temp_Disp[0] >= Temp_Disp[1])//合理性检查{Error_Flag = 0;Temp_Ctorl[0] = Temp_Disp[0];Temp_Ctorl[1] = Temp_Disp[1];}else Error_Flag = 1;}

DAC输出功能部分

在这里插入图片描述
由题可知,DAC输出中的三个判断条件与L1、L2和L3正好对应。且三个条件有且仅有一个是成立的。所以可以用一个for循环来以此取出当前LED的点亮状态,当该LED点亮时,即对应的条件成立,则其他条件不成立,所以只要处理完当前条件下的DAC输出即可。

for(i=0;i<3;i++){if(ucLed[i] == 1){break;}}

调用DAC输出函数Da_Write()时需要注意的是,该函数参数为最小值为0最大值为255的unsigned char型数据。而当前题目需要的是最小为0,最大为4的DAC输出。芯片工作电压为5,可以看出成是在0-5的范围内取4、3、2三个数。
要将0-5等比例放大到0-255为51倍。
再看DAC输出值与对应条件下ucLed的关系。DAC输出4时,ucLed[0]为1;DAC输出3时,ucLed[1]为1;DAC输出2时,ucLed[2]为1。关系为4-i。

Da_Write(51*(4-i));

最终代码

User文件

main.c

/* 头文件声明区 */
#include "iic.h"
#include "onewire.h"   
#include <Init.h>		  // 初始化底层驱动专用头文件
#include <Key.h>		  // 按键底层驱动专用头文件
#include <Led.h>		  // LED底层驱动专用头文件
#include <STC15F2K60S2.H> // 单片机寄存器专用头文件
#include <Seg.h>		  // 数码管底层驱动专用头文件/* 变量声明区 */
unsigned char Key_Val, Key_Down, Key_Old, Key_Up;			 // 按键状态变量
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 char ucLed[8] = {0, 0, 0, 0, 0, 0, 0, 0};			 // LED显示数据
unsigned int Slow_Down;										 // 减速计数器
bit Seg_Flag, Key_Flag;										 // 数码管和按键的标志位
unsigned int Time_1s;										 // 1秒钟计数器
unsigned int Freq;											 // 频率计算变量
unsigned int Sys_Tick;										 // 系统时钟计数
bit Seg_Disp_Mode;  //数码管显示模式变量  0-数据界面 1-参数设置界面
unsigned char Temperature; //实时温度变量
unsigned char Temp_Disp[2] = {30,20};//温度变量显示数组
unsigned char Temp_Ctorl[2] = {30,20};//温度变量控制数组
bit Temp_Index = 1;//参数数组指针
bit Error_Flag; //错误标志位/* 键盘处理函数 */
void Key_Proc()
{if (Key_Flag)return;Key_Flag = 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:Seg_Disp_Mode ^= 1;if(Seg_Disp_Mode == 1)//从数据界面切换到参数设置界面{Temp_Index = 1;Temp_Disp[0] = Temp_Ctorl[0];Temp_Disp[1] = Temp_Ctorl[1];}else//从参数界面切换到数据界面{if(Temp_Disp[0] >= Temp_Disp[1])//合理型检查{Error_Flag = 0;Temp_Ctorl[0] = Temp_Disp[0];Temp_Ctorl[1] = Temp_Disp[1];}else Error_Flag = 1;}break;case 5:if(Seg_Disp_Mode == 1) Temp_Index ^= 1;break;case 6:if(Seg_Disp_Mode == 1){if(++Temp_Disp[Temp_Index] == 100) Temp_Disp[Temp_Index] = 99;}break;case 7:if(Seg_Disp_Mode == 1){if(--Temp_Disp[Temp_Index] == 255) Temp_Disp[Temp_Index] = 0;}break;}
}/* 信息处理函数 */
void Seg_Proc()
{if (Seg_Flag)return;Seg_Flag = 1; // 设置标志位Temperature = rd_temperature();if(Seg_Disp_Mode == 0)//数据界面{Seg_Buf[0] = 11;//CSeg_Buf[3] = 10;Seg_Buf[4] = 10;Seg_Buf[6] = Temperature /10 % 10;Seg_Buf[7] = Temperature % 10;}else//参数设置界面{Seg_Buf[0] = 12;//PSeg_Buf[3] = Temp_Disp[0] / 10 % 10;Seg_Buf[4] = Temp_Disp[0] % 10;Seg_Buf[6] = Temp_Disp[1] / 10 % 10;Seg_Buf[7] = Temp_Disp[1] % 10;}
}/* 其他显示函数 */
// LED显示处理函数,这里没有具体实现。
void Led_Proc() 
{unsigned char i;/*Led*/ucLed[0] = (Temperature > Temp_Ctorl[0]);ucLed[1] = (Temperature <= Temp_Ctorl[0] && Temperature >= Temp_Ctorl[1]);ucLed[2] = (Temperature < Temp_Ctorl[1]);ucLed[3] = Error_Flag;/*DAC*/for(i=0;i<3;i++){if(ucLed[i] == 1){Da_Write(51*(4-i));}break;}
}/* 定时器0初始化函数 */
// 初始化定时器0,用于产生1ms的时钟中断。
void Timer0_Init(void)
{AUXR &= 0x7F; // 设置定时器时钟12T模式TMOD &= 0xF0; // 设置定时器模式为16位定时器TMOD |= 0x05;TL0 = 0; // 设置定时器初始值TH0 = 0; // 设置定时器初始值TF0 = 0; // 清除TF0标志位TR0 = 1; // 启动定时器
}/* 定时器1初始化函数 */
// 初始化定时器1,用于产生1ms的时钟中断,并允许中断。
void Timer1_Init(void)
{AUXR &= 0xBF; // 设置定时器时钟12T模式TMOD &= 0x0F; // 设置定时器模式为16位定时器TL1 = 0x18;	  // 设置定时器初始值TH1 = 0xFC;	  // 设置定时器初始值TF1 = 0;	  // 清除TF1标志位TR1 = 1;	  // 启动定时器ET1 = 1;	  // 使能定时器1中断EA = 1;		  // 开启全局中断
}/* 定时器1中断服务函数 */
// 定时器1的中断服务函数,用于更新系统时钟、处理按键和数码管显示。
void Timer1_Isr(void) interrupt 3
{/*数码管400ms的减速*/if (++Slow_Down == 400) {Seg_Flag = Slow_Down = 0; // 更新数码管显示标志位}/*按键10ms的减速*/if (Slow_Down % 10 == 0){Key_Flag = 0; // 更新按键处理标志位}/*1s的计数*/if (++Time_1s == 1000)  {Time_1s = 0;		   // 重置1秒钟计数器Freq = TH0 << 8 | TL0; // 计算频率TH0 = 0;			   // 重置定时器0的值TL0 = 0;}/*信息处理*/Seg_Disp(Slow_Down % 8, Seg_Buf[Slow_Down % 8], Seg_Point[Slow_Down % 8]); // 更新数码管显示Led_Disp(Slow_Down % 8, ucLed[Slow_Down % 8]);							   // 更新LED显示
}void Delay750ms()		//@12.000MHz
{unsigned char i, j, k;i = 35;j = 51;k = 182;do{do{while (--k);} while (--j);} while (--i);
}/* 主函数 */
// 系统初始化,设置定时器和串口,然后进入主循环。
void main()
{rd_temperature();Delay750ms();Sys_Init();	// 系统初始化Timer1_Init();	// 初始化定时器1while (1){Key_Proc();	 // 处理按键Seg_Proc();	 // 更新数码管显示Led_Proc();	 // 更新LED显示}
}

Driver文件

Init.c

#include "init.h"void Sys_Init()
{P0 = 0xff;P2 = P2 & 0x1f | 0x80;P2 &= 0x1f;P0 = 0x00;P2 = P2 & 0x1f | 0xA0;P2 &= 0x1f;
}

LED.c

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

Seg.c

#include "Seg.h"code unsigned char seg_dula[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x88,0xc6,0x8c};//0-9为数字,10为熄灭,11为A,12为C,13为P
code 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;
}

Key.c

#include <Key.h>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;
}

onewire.c

#include "onewire.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_temperture(void)
{unsigned char low,high;init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0x44);init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0xbe);low = Read_DS18B20();high = Read_DS18B20();return ((high << 8) | low) / 16.0;
}

iic.c

#define DELAY_TIME	10
#include "iic.h"
#include "intrins.h"
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);
}void Da_Write(unsigned char dat)
{I2CStart();I2CSendByte(0x90);I2CWaitAck();I2CSendByte(0x41);I2CWaitAck();I2CSendByte(dat);I2CWaitAck();I2CStop();
}

结语

至此本试题代码部分的笔记就完成了,有错误的地方感谢大家指出。

相关文章:

【蓝桥杯—单片机】第十一届省赛真题代码题解题笔记 | 省赛 | 真题 | 代码题 | 刷题 | 笔记

第十一届省赛真题代码部分 前言赛题代码思路笔记竞赛板配置内部振荡器频率设定键盘工作模式跳线扩展方式跳线 建立模板明确设计要求和初始状态显示功能部分数据界面第一部分第二部分第三部分调试时发现的问题 参数设置界面第一部分第二部分和第四部分第三部分和第五部分 按键功…...

【原创】Android Studio Ladybug 中Gradle配置

使用Android Studio创建项目后&#xff0c;由于需要下载的一下文件在国外&#xff0c;加上网速的问题&#xff0c;以及防火墙的问题&#xff0c;不少文件难以下载。常常导致项目创建后&#xff0c;要等很长时间&#xff0c;各种折腾&#xff0c;结果一个demo都跑不起来。 经过…...

CLion2024.3.2版中引入vector头文件报错

报错如下&#xff1a; 在MacBook端的CLion中引入#include <vector>报 vector file not found&#xff08;引入map、set等也看参考此方案&#xff09;&#xff0c;首先可以在Settings -> Build,Execution,Deployment -> Toolchains中修改C compiler和C compiler的路…...

自动化测试工具:selenium

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 Selenium是一个用于Web应用程序测试的工具。是一个开源的Web的自动化测试工具&#xff0c;最初是为网站自动化测试而开发的&#xff0c;类型像我们玩游戏用的按键…...

MR30分布式IO模块:驱动智能制造工厂的工业互联与高效控制新范式

在工业4.0与智能制造浪潮的推动下&#xff0c;传统制造业正经历着从“机械驱动”向“数据驱动”的深刻转型。作为工业数据连接领域的领军者&#xff0c;明达技术凭借其自主研发的MR30分布式IO模块&#xff0c;以创新的技术架构与卓越的性能表现&#xff0c;为全球制造企业构建了…...

计算机领域QPM、TPM分别是什么并发指标,还有其他类似指标吗?

在计算机领域&#xff0c;QPM和TPM是两种不同的并发指标&#xff0c;它们分别用于衡量系统处理请求的能力和吞吐量。 QPM&#xff08;每分钟请求数&#xff09; QPM&#xff08;Query Per Minute&#xff09;表示每分钟系统能够处理的请求数量。它通常用于衡量系统在单位时间…...

Python截图轻量化工具

这是用Python做到截图工具&#xff0c;不过由于使用了ctypes调用了Windows的API, 同时访问了Windows中"C:/Windows/Cursors/"中的.cur光标样式文件, 这个工具只适用于Windows环境&#xff1b; 如果要提升其跨平台性的话&#xff0c;需要考虑替换ctypes的一些专属于W…...

Python----Python高级(并发编程:协程Coroutines,事件循环,Task对象,协程间通信,协程同步,将协程分布到线程池/进程池中)

一、协程 1.1、协程 协程&#xff0c;Coroutines&#xff0c;也叫作纤程(Fiber) 协程&#xff0c;全称是“协同程序”&#xff0c;用来实现任务协作。是一种在线程中&#xff0c;比线程更加轻量级的存在&#xff0c;由程序员自己写程序来管理。 当出现IO阻塞时&#xff0c;…...

DeepSeek使用技巧大全(含本地部署教程)

在人工智能技术日新月异的今天&#xff0c;DeepSeek 作为一款极具创新性和实用性的 AI&#xff0c;在众多同类产品中崭露头角&#xff0c;凭借其卓越的性能和丰富的功能&#xff0c;吸引了大量用户的关注。 DeepSeek 是一款由国内顶尖团队研发的人工智能&#xff0c;它基于先进…...

.NET Core 8 Blazor 和 Vue 3 技术构建网

以下是一个可行的解决方案&#xff0c;能够满足使用 .NET Core 8 Blazor 和 Vue 3 技术构建网站&#xff0c;并且将前后端代码放在一个站点中&#xff0c;实现一次发布部署的目标。 解决方案概述 技术栈选择&#xff1a; 后端&#xff1a;.NET Core 8 Blazor Server 或 Blazor …...

ElasticSearch集群因索引关闭重打开导致飘红问题排查

背景 某组件向 ElasticSearch 写入数据&#xff0c;从最近某一天开始写入速度变慢&#xff0c;数据一直有积压。推测是 ElasticSearch 集群压力导致的&#xff0c;查看 ElasticSearch 集群状态&#xff0c;发现集群确实处于 red 状态。 本文记录 ElasticSearch 集群因索引关闭…...

计算机毕业设计Tensorflow+LSTM空气质量监测及预测系统 天气预测系统 Spark Hadoop 深度学习 机器学习 人工智能

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

手搓基于CNN的Chest X-ray图像分类

数据集Chest X-ray PD Dataset 数据集介绍 - 知乎https://zhuanlan.zhihu.com/p/661311561 CPU版本 import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import Dataset, DataLoader from torchvision import transforms, models import …...

使用java代码操作rabbitMQ收发消息

SpringAMQP 将来我们开发业务功能的时候&#xff0c;肯定不会在控制台收发消息&#xff0c;而是应该基于编程的方式。由于RabbitMQ采用了AMQP协议&#xff0c;因此它具备跨语言的特性。任何语言只要遵循AMQP协议收发消息&#xff0c;都可以与RabbitMQ交互。并且RabbitMQ官方也…...

【数据结构】(7) 栈和队列

一、栈 Stack 1、什么是栈 栈是一种特殊的线性表&#xff0c;它只能在固定的一端&#xff08;栈顶&#xff09;进行出栈、压栈操作&#xff0c;具有后进先出的特点。 2、栈概念的例题 答案为 C&#xff0c;以C为例进行讲解&#xff1a; 第一个出栈的是3&#xff0c;那么 1、…...

【Pytorch实战教程】让数据飞轮转起来:PyTorch Dataset与Dataloader深度指南

文章目录 让数据飞轮转起来:PyTorch Dataset与Dataloader深度指南一、为什么需要数据管理组件?二、Dataset:数据集的编程接口2.1 自定义Dataset三要素2.2 实战案例:图像分类数据集三、Dataloader:高效数据流水线3.1 核心参数解析3.2 数据流可视化3.3 多卡训练支持四、综合…...

Python的秘密基地--[章节13] Python 数据分析与可视化

第13章&#xff1a;Python 数据分析与可视化 在大数据时代&#xff0c;数据分析与可视化是至关重要的技能。Python 提供了多个强大的库&#xff0c;如 NumPy、Pandas、Matplotlib 和 Seaborn&#xff0c;用于数据处理、分析和可视化。本章将介绍如何使用 Python 进行数据分析&…...

Python 入门:文件操作、读写、管理

目录 1. 引言 2. 文件基础操作 2.1 打开文件&#xff08;open()&#xff09; 2.2 读取文件内容 2.3 写入文件 3. 处理 CSV 文件 3.1 读取 CSV 文件 3.2 写入 CSV 文件 4. 处理 JSON 文件 4.1 读取 JSON 文件 4.2 写入 JSON 文件 5. 文件管理操作 5.1 删除文件 5.…...

Composo:企业级AI应用的质量守门员

在当今快速发展的科技世界中,人工智能(AI)的应用已渗透到各行各业。然而,随着AI技术的普及,如何确保其可靠性和一致性成为了企业面临的一大挑战。Composo作为一家致力于为企业提供精准AI评估服务的初创公司,通过无代码和API双模式,帮助企业监测大型语言模型(LLM)驱动的…...

crictl和ctr命令详解

一&#xff0c;crictl crictl 是 CRI 兼容的容器运行时命令行接口。 你可以使用它来检查和调试 Kubernetes 节点上的容器运行时和应用程序。 crictl 和它的源代码在 cri-tools 代码库。 1&#xff0c;安装 需要下载与kubernetes相对应的版本&#xff0c;我的k8s版本是1.30的…...

Python数据分析案例71——基于十种模型的信用违约预测实战

背景 好久没写这种基础的做机器学习流程了&#xff0c;最近过完年感觉自己代码忘了好多.....复习一下。 本次带来的是信贷违约的预测&#xff0c;即根据这个人的特征&#xff08;年龄收入什么的&#xff09;&#xff0c;预测他是不是会违约&#xff0c;会违约就拒绝贷款&…...

Lesson 131 Don‘t be so sure

Lesson 131 Don’t be so sure 词汇 Egypt n. 埃及 相关&#xff1a;Egyptian n. 埃及人&#xff0c;埃及的    camel n. 骆驼    Mummy n. 木乃伊    Pyramid n. 金字塔    Pharaoh n. 法老 例句&#xff1a;你去过埃及吗&#xff1f;    Have you been to E…...

python康威生命游戏的图形化界面实现

康威生命游戏&#xff08;Conway’s Game of Life&#xff09;是由英国数学家约翰何顿康威&#xff08;John Horton Conway&#xff09;在1970年发明的一款零玩家的细胞自动机模拟游戏。尽管它的名字中有“游戏”&#xff0c;但实际上它并不需要玩家参与操作&#xff0c;而是通…...

区块链技术:Facebook 重塑社交媒体信任的新篇章

在这个信息爆炸的时代&#xff0c;社交媒体已经成为我们生活中不可或缺的一部分。然而&#xff0c;随着社交平台的快速发展&#xff0c;隐私泄露、数据滥用和虚假信息等问题也日益凸显。这些问题的核心在于传统社交媒体依赖于中心化服务器存储和管理用户数据&#xff0c;这种模…...

【自学笔记】文言一心的基础知识点总览-持续更新

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 文心一言知识点总览一、文心一言简介二、文心一言的核心功能三、文心一言的技术特点四、文心一言的应用场景五、文心一言的使用技巧六、文心一言的未来发展 总结 文…...

UE求职Demo开发日志#25 试试网络同步和尝试打包

1 改了一些时序上的bug&#xff0c;成功运行了多端 &#xff08;UE一些网络相关的功能都弄好了&#xff0c;只需要标记哪个变量或Actor需要复制&#xff09; 2 以前遗留的bug太多了&#xff0c;改到晚上才打包好一个能跑的版本&#xff0c;而且有的特效还不显示&#xff08;悲…...

2021 年 9 月青少年软编等考 C 语言五级真题解析

目录 T1. 问题求解思路分析T2. 抓牛思路分析T3. 交易市场思路分析T4. 泳池思路分析T1. 问题求解 给定一个正整数 N N N,求最小的 M M M 满足比 N N N 大且 M M M 与 N N N 的二进制表示中有相同数目的 1 1 1。 举个例子,假如给定 N N N 为 78 78 78,二进制表示为 …...

Win10环境使用ChatBox集成Deep Seek解锁更多玩法

Win10环境使用ChatBox集成Deep Seek解锁更多玩法 前言 之前部署了14b的Deep Seek小模型&#xff0c;已经验证了命令行及接口方式的可行性。但是纯命令行或者PostMan方式调用接口显然不是那么友好&#xff1a; https://lizhiyong.blog.csdn.net/article/details/145505686 纯…...

第 26 场 蓝桥入门赛

2.对联【算法赛】 - 蓝桥云课 问题描述 大年三十&#xff0c;小蓝和爷爷一起贴对联。爷爷拿出了两副对联&#xff0c;每副对联都由 N 个“福”字组成&#xff0c;每个“福”字要么是正的&#xff08;用 1 表示&#xff09;&#xff0c;要么是倒的&#xff08;用 0 表示&#…...

CodeGPT + IDEA + DeepSeek,在IDEA中引入DeepSeek实现AI智能开发

CodeGPT IDEA DeepSeek&#xff0c;在IDEA中引入DeepSeek 版本说明 建议和我使用相同版本&#xff0c;实测2022版IDEA无法获取到CodeGPT最新版插件。&#xff08;在IDEA自带插件市场中搜不到&#xff0c;可以去官网搜索最新版本&#xff09; ToolsVersionIntelliJ IDEA202…...