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

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

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

  • 前言
  • 赛题代码思路笔记
    • 竞赛板配置
      • 内部振荡器频率设定
      • 键盘工作模式跳线
      • 扩展方式跳线
    • 建立模板
    • 明确设计要求和初始状态
    • 显示功能部分
      • 数据界面
        • 第一部分
        • 第二部分
        • 第三部分
        • 调试时发现的问题
      • 参数设置界面
        • 第一部分
        • 第二部分和第四部分
        • 第三部分和第五部分
    • 按键功能部分
      • 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();
}

结语

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

相关文章:

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

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

数据分析:企业数字化转型的金钥匙

引言&#xff1a;数字化浪潮下的数据金矿 在数字化浪潮席卷全球的背景下&#xff0c;有研究表明&#xff0c;只有不到30%的企业能够充分利用手中掌握的数据&#xff0c;这是否让人深思&#xff1f;数据已然成为企业最为宝贵的资产之一。然而&#xff0c;企业是否真正准备好从数…...

网络工程师 (23)OSI模型层次结构

前言 OSI&#xff08;Open System Interconnect&#xff09;模型&#xff0c;即开放式系统互联模型&#xff0c;是一个完整的、完善的宏观模型&#xff0c;它将计算机网络体系结构划分为7层。 OSI七层模型 1. 物理层&#xff08;Physical Layer&#xff09; 功能&#xff1a;负…...

DeepSeek添加知识库

1、下载dify 项目地址:https://github.com/langgenius/dify 2、通过docker安装 端口报错 修改端口 .env文件下所有80端口替换成了其它端口 执行正常了 查看 docker容器 <...

2、k8s的cni网络插件和基本操作命令

kube-prxoy属于节点组件&#xff0c;网络代理&#xff0c;实现服务的自动发现和负载均衡。 k8s的内部网络模式 1、pod内的容器于容器之间的通信。 2、一个节点上的pod之间的通信&#xff0c;docker0网桥直接通信。 3、不同节点上的pod之间的通信&#xff1a; 通过物理网卡的…...

Next.js简介:现代 Web 开发的强大框架(ChatGPT-4o回答)

prompt: 你是一位专业的技术博客撰稿人&#xff0c;你将写一篇关于介绍next.js这个开发框架的技术博文&#xff0c;语言是中文&#xff0c;风格专业严谨&#xff0c;用词自然、引人入胜且饶有趣味 在现代 Web 开发的世界中&#xff0c;选择合适的框架可以显著提升开发效率和应用…...

【DeepSeek:国产大模型的崛起与ChatGPT的全面对比】

DeepSeek&#xff1a;国产大模型的崛起与ChatGPT的全面对比 目录 引言DeepSeek的技术架构 2.1 混合专家&#xff08;MoE&#xff09;架构2.2 动态路由机制2.3 训练数据与成本 ChatGPT的技术架构 3.1 Transformer架构3.2 训练数据与成本 性能对比 4.1 推理能力4.2 语言处理4.3…...

input 超出maxlength限制后,输入框变红

一、前言 最近收到产品的一个需求&#xff1a;输入框限制了maxlength“11”&#xff0c;需要在输入第12位时&#xff0c;输入框变红&#xff1b;当然&#xff0c;第12位是不能真正输入到输入框中的。 二、实现难点 其实&#xff0c;单纯的要监听 字母和数字以及字符 还是比较容…...

Docker 构建镜像并搭建私人镜像仓库教程

构建镜像教程 步骤 1&#xff1a;安装 Docker #在安装 Docker 之前&#xff0c;建议先更新系统软件包。 sudo yum update -y # 移除旧的Docker版本和Podman、runc软件包及其相关依赖。 yum remove -y docker docker-client docker-client-latest docker-ce-cli docker-commo…...

doris:MySQL Dump

Doris 在 0.15 之后的版本已经支持通过 mysqldump 工具导出数据或者表结构 使用示例​ 导出​ 导出 test 数据库中的 table1 表&#xff1a;mysqldump -h127.0.0.1 -P9030 -uroot --no-tablespaces --databases test --tables table1 导出 test 数据库中的 table1 表结构&am…...

OpenBMC:通过qemu-system-arm运行编译好的image

OpenBMC&#xff1a;编译_openbmc meson.build file-CSDN博客 讲述了如何编译生成openbmc的image 完成编译后可以通过qemu-system-arm进行模拟加载&#xff0c;以便在没有BMC硬件的情况下进行调试 1.下载qemu-system-arm 在openbmc的上级目录上执行 wget https://jenkins.op…...

STM32的HAL库开发---通用定时器(TIMER)---定时器脉冲计数

一、脉冲计数实验原理 1、 外部时钟模式1&#xff1a;核心为蓝色部分的时基单元&#xff0c;时基单元的时钟源可以来自四种&#xff0c;分别是内部时钟PCLK、外部时钟模式1&#xff0c;外部时钟模式2、内部定时器触发&#xff08;级联&#xff09;。而脉冲计数就是使用外部时钟…...

动态规划LeetCode-121.买卖股票的最佳时机1

给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔交易中获取的最大利润。…...

网安三剑客:DNS、CDN、VPN

DNS&#xff08;网络地址转换系统&#xff09;的技术原理与安全应用 1. 网络地址转换系统的基本原理 DNS通过解析用户的访问URL&#xff08;超链接&#xff09;&#xff0c;将其映射到服务器上存储的信息。具体来说&#xff1a; 解析URL&#xff1a;DNS从URL中提取出 hostna…...

Linux在x86环境下制作ARM镜像包

在x86环境下制作ARM镜像包&#xff08;如qemu.docker&#xff09;&#xff0c;可以通过QEMU和Docker的结合来实现。以下是详细的步骤&#xff1a; 安装QEMU-user-static QEMU-user-static是一个静态编译的QEMU二进制文件&#xff0c;用于在非目标架构上运行目标架构的二进制文…...

Vue3+codemirror6实现公式(规则)编辑器

实现截图 实现/带实现功能 插入标签 插入公式 提示补全 公式验证 公式计算 需要的依赖 "codemirror/autocomplete": "^6.18.4","codemirror/lang-javascript": "^6.2.2","codemirror/state": "^6.5.2","cod…...

Lua中文语言编程源码-第十一节,其它小改动汉化过程

__tostring 汉化过程 liolib.c metameth[] {"__转换为字符串", f_tostring}, lauxlib.c luaL_callmeta(L, idx, "__转换为字符串") lua.c luaL_callmeta(L, 1, "__转换为字符串") __len 汉化过程 ltm.c luaT_eventname[] ltablib.c c…...

Safari常用快捷键

一、书签边栏 1、显示或隐藏书签边栏&#xff1a;Control-Command-1 2、选择下一个书签或文件夹&#xff1a;向上头键或向下头键 3、打开所选书签&#xff1a;空格键 4、打开所选文件夹&#xff1a;空格键或右箭头键 5、关闭所选文件夹&#xff1a;空格键或左箭头键 6、更…...

Git登录并解决 CAPTCHA

修改公司域账户密码之后&#xff0c;导致今天pull代码时显示&#xff1a;remote error: CAPTCHA required 本文将介绍如何解决 Git 中的常见错误“fatal: Authentication failed for git”。该问题通常出现在尝试访问远程 Git 仓库时&#xff0c;表示身份验证失败。以下是几种常…...

Websocket从原理到实战

引言 WebSocket 是一种在单个 TCP 连接上进行全双工通信的网络协议&#xff0c;它使得客户端和服务器之间能够进行实时、双向的通信&#xff0c;既然是通信协议一定要从发展历史到协议内容到应用场景最后到实战全方位了解 发展历史 WebSocket 最初是为了解决 HTTP 协议在实时…...

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_get_options函数

声明 就在 main函数所在的 nginx.c 中&#xff1a; static ngx_int_t ngx_get_options(int argc, char *const *argv); 实现 static ngx_int_t ngx_get_options(int argc, char *const *argv) {u_char *p;ngx_int_t i;for (i 1; i < argc; i) {p (u_char *) argv[i]…...

判断您的Mac当前使用的是Zsh还是Bash:echo $SHELL、echo $0

要判断您的Mac当前使用的是Zsh还是Bash&#xff0c;可以使用以下方法&#xff1a; 查看默认Shell: 打开“终端”应用程序&#xff0c;然后输入以下命令&#xff1a; echo $SHELL这将显示当前默认使用的Shell。例如&#xff0c;如果输出是/bin/zsh&#xff0c;则说明您使用的是Z…...

Centos执行yum命令报错

错误描述 错误&#xff1a;为仓库 ‘appstream’ 下载元数据失败 : Cannot prepare internal mirrorlist: Curl error (6): Couldn’t resolve host name for http://mirrorlist.centos.org/?release8&archx86_64&repoAppStream&infrastock [Could not resolve h…...

订单超时设计(1)--- 如何使用redis实现订单超时实时关闭功能

如何使用redis实现订单超时实时关闭功能 准备工作实现步骤解释注意事项&#xff08;重点&#xff09; 使用Redis实现订单超时实时关闭功能&#xff0c;可以利用Redis的延时队列&#xff08;使用Sorted Set实现&#xff09;和过期键&#xff08;使用TTL和Keyspace Notifications…...

485网关数据收发测试

目录 1.UDP SERVER数据收发测试 使用产品&#xff1a; || ZQWL-GW1600NM 产品||【智嵌物联】智能网关型串口服务器 1.UDP SERVER数据收发测试 A&#xff08;TX&#xff09;连接RX B&#xff08;RX&#xff09;连接TX 打开1个网络调试助手&#xff0c;模拟用户的UDP客户端设…...

RabbitMQ快速上手及入门

概念 概念&#xff1a; publisher&#xff1a;生产者&#xff0c;也就是发送消息的一方 consumer&#xff1a;消费者&#xff0c;也就是消费消息的一方 queue&#xff1a;队列&#xff0c;存储消息。生产者投递的消息会暂存在消息队列中&#xff0c;等待消费者处理 exchang…...

4种架构的定义和关联

文章目录 **1. 各架构的定义****业务架构&#xff08;Business Architecture&#xff09;****应用架构&#xff08;Application Architecture&#xff09;****数据架构&#xff08;Data Architecture&#xff09;****技术架构&#xff08;Technology Architecture&#xff09;*…...

109,【1】攻防世界 web 题目名称-文件包含

进入靶场 直接显示源代码 提示我们通过get方式传递名为filename的参数&#xff0c;同时给出了文件名check.php filenamecheck.php 显示使用了正确的用法&#xff0c;错误的方法 filename./check.php 还是一样的回显 傻了&#xff0c;题目名称是文件包含&#xff0c;需要用到…...

leetcode90 子集II

1. 题意 给一个可能含有重复元素的数组&#xff0c;求这个数组的所有子集。 2. 题解 跟leetcode 72 子集的差别在于&#xff0c;我们需要将重复的元素给去掉。那如何去重呢&#xff0c;实际上我们可以先排序将重复的元素给放在一起。然后在回溯后&#xff0c;找到下一个不与…...

DeepSeek模型构建与训练

在完成数据预处理之后,下一步就是构建和训练深度学习模型。DeepSeek提供了简洁而强大的API,使得模型构建和训练变得非常直观。无论是简单的全连接网络,还是复杂的卷积神经网络(CNN)或循环神经网络(RNN),DeepSeek都能轻松应对。本文将带你一步步构建一个深度学习模型,并…...