#include <reg51.h> #include <intrins.h> typedef unsigned char u8; typedef unsigned int u16; #define SMG_PORT P0 sbit LSA = P2^2; sbit LSB = P2^3; sbit LSC = P2^4; // 修正后的段码表(共阴) u8 gsmg_code[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; void Delay1000ms() { u16 i,j; for(i=0; i<1000; i++) for(j=0; j<120; j++); } void SMG_SHOW() { u8 i = 0; u8 display_data[8] = {2,0,2,5,0,3,2,1}; // 显示内容:20250321 for(i=0; i<8; i++) { SMG_PORT = 0x00; // 消影 // 位选解码(i的二进制位对应LSC-LSA) LSC = (i & 0x04) >> 2; LSB = (i & 0x02) >> 1; LSA = (i & 0x01); SMG_PORT = gsmg_code[display_data[i]]; Delay1000ms(); } } void main() { P0 = 0x00; // 初始化端口 P2 = 0x00; while(1) { SMG_SHOW(); } }把这段代码数码管的显示方向反过来

时间: 2025-03-21 08:00:56 浏览: 39
<think>好的,用户想要把数码管的显示方向反过来。我需要先理解原代码的显示逻辑。原代码中的SMG_SHOW函数循环从i=0到7,依次显示display_data数组中的数字。每个i对应一个数码管的位置,通过LSC、LSB、LSA这三个控制位来选择具体的数码管。现在用户希望显示方向反过来,也就是从最后一个数码管开始显示,比如原来的顺序是0到7,现在要变成7到0。 首先,我需要确认数码管的位选是如何映射的。原代码中使用的是i的值来控制LSC、LSB、LSA,这三个引脚可能连接到一个3-8译码器,比如74HC138,这样i的值0到7对应译码器的输出,从而选择第0到第7个数码管。用户希望显示顺序反过来,也就是第7个数码管显示第一个数字,第6显示第二个,依此类推。 接下来,我需要调整display_data数组的顺序,或者调整i的循环方式。原display_data数组是{2,0,2,5,0,3,2,1},对应的数字是20250321。如果直接反转显示顺序,可能需要将数组也反转,或者保持数组不变,但改变数码管的选择顺序。 不过,仔细看原代码中的display_data数组,每个元素对应的是数码管的位置i所显示的数字。例如,i=0时显示2,i=1时显示0,依此类推。如果希望数码管的显示方向反过来,也就是最右边的数码管先显示,那么应该让i从7开始递减到0,同时display_data数组中的顺序可能需要调整,或者保持数组不变,但索引改为从7-i的位置获取数据。 例如,原display_data[0]是2,对应第一个数码管显示2,现在希望第八个数码管显示2,那么可能需要将display_data的顺序调整为{1,2,3,0,5,2,0,2},这样当i从0到7时,数码管0显示1,数码管1显示2,依此类推,最终显示为12305202,但用户的目标是显示20250321,只是方向反过来,可能需要更仔细的分析。 或者,保持display_data数组不变,但改变数码管的位选顺序。原来的i从0到7对应数码管0到7,现在需要i从7到0,这样数码管7显示display_data[0],数码管6显示display_data[1],依此类推,最终显示的是倒序的数组。但用户想要的是显示内容20250321反过来,即12305022?或者保持内容顺序不变,但显示的位置从右到左? 这里可能存在理解上的歧义。用户可能希望数码管的显示顺序从右到左,即原本从左到右显示20250321,现在希望从右到左显示12305022?或者保持数字顺序不变,但数码管的点亮顺序反过来? 需要明确用户的需求。假设用户希望数码管的物理位置从右到左依次显示20250321,即原本数码管0(最左边)显示2,数码管1显示0,数码管2显示2,数码管3显示5,数码管4显示0,数码管5显示3,数码管6显示2,数码管7显示1,显示顺序是从左到右。现在用户希望反过来,即数码管7(最右边)显示2,数码管6显示0,数码管5显示2,数码管4显示5,数码管3显示0,数码管2显示3,数码管1显示2,数码管0显示1,这样整体显示的数字顺序是12305022,这可能不是用户想要的。 或者,用户希望保持显示的数字顺序为20250321,但数码管的点亮顺序从右到左,即原本从左到右依次显示,现在改为从右到左依次显示,但每个数码管显示的内容顺序不变,即数码管7显示2,数码管6显示0,数码管5显示2,数码管4显示5,数码管3显示0,数码管2显示3,数码管1显示2,数码管0显示1。这样整体看起来数字顺序是反向的,但用户可能希望内容顺序不变,只是显示位置反向。 可能用户的实际需求是保持数字内容20250321的显示,但让数码管的位置从右到左排列。例如,原本数码管0(左边)显示第一个数字2,数码管1显示第二个0,依此类推,数码管7显示最后一个1。现在希望数码管7(右边)显示第一个数字2,数码管6显示第二个0,依此类推,数码管0显示最后一个1。这样整体显示的数字顺序还是20250321,但物理位置从右到左排列。 为了达到这个效果,需要调整display_data数组的顺序,使其对应到正确的数码管位置。原来的display_data数组是{2,0,2,5,0,3,2,1},对应的数码管0到7显示这些数字。如果现在要让数码管7到0显示同样的数字顺序,需要将display_data数组反转为{1,2,3,0,5,2,0,2},这样当i从0到7时,数码管i显示的是反转后的数组元素,即数码管0显示1,数码管1显示2,依此类推,数码管7显示2,这样从右到左看就是20250321。 但是原代码中的display_data数组是{2,0,2,5,0,3,2,1},对应的数码管0到7显示2、0、2、5、0、3、2、1,所以从左到右显示的是20250321。如果要让从右到左显示同样的数字顺序,需要数码管7显示2,数码管6显示0,数码管5显示2,数码管4显示5,数码管3显示0,数码管2显示3,数码管1显示2,数码管0显示1,因此display_data数组应该是{1,2,3,0,5,2,0,2},并且i从0到7选择数码管0到7,这样数码管7不会在循环中被选中,因为原循环是i从0到7,对应数码管0到7。因此,可能需要修改位选逻辑,使得i对应的数码管位置是7-i,即当i=0时,选择数码管7;i=1时,选择数码管6,依此类推。 因此,修改方法是在位选部分,将i转换为7-i,然后计算LSC、LSB、LSA的值。例如,对于每个i,实际要选择的数码管位置是7-i。这样,当i=0时,数码管7被选中,显示display_data[0]即2;i=1时,数码管6被选中,显示display_data[1]即0,依此类推,i=7时,数码管0被选中,显示display_data[7]即1。这样从右到左显示的数字顺序就是20250321。 具体实现步骤可能包括: 1. 在SMG_SHOW函数中,循环i从0到7,但实际选择的数码管位是7-i。 2. 对于每个i,计算7-i对应的位选信号LSC、LSB、LSA。 3. 保持display_data数组不变,因为display_data[i]仍然对应第i个数字,但数码管的位置变为7-i。 例如,原来的i=0对应数码管0,现在i=0对应数码管7,此时需要将数码管7的位选信号设置为对应的LSC、LSB、LSA值。数码管7的位选信号通常由译码器的输入决定,假设使用3-8译码器,数码管0到7对应的二进制选择信号是000到111(即LSC、LSB、LSA的组合)。数码管7对应的二进制是111(即LSC=1,LSB=1,LSA=1),对应的i=7。现在,当i=0时,我们希望选择数码管7,即对应的位选信号为111,所以需要将i转换为7-i=7,然后分解为LSC、LSB、LSA。然而,原代码中的位选解码是将i分解为三位二进制,其中LSC是最高位。例如,i=7时,二进制是111,LSC=1, LSB=1, LSA=1。因此,当需要选择数码管7-i的位置时,即对于每个循环中的i,实际数码管位置是7-i,因此需要将i替换为7-i,然后分解为三位二进制。 因此,修改位选部分的代码,将原来的i替换为(7 - i),然后计算LSC、LSB、LSA的值。例如: LSC = ((7 - i) & 0x04) >> 2; LSB = ((7 - i) & 0x02) >> 1; LSA = (7 - i) & 0x01; 这样,当i从0到7时,7-i的值从7到0,对应的位选信号依次选择数码管7到0,从而实现了显示方向的反转。 同时,display_data数组保持为{2,0,2,5,0,3,2,1},因为此时i=0对应数码管7显示2,i=1对应数码管6显示0,依此类推,i=7对应数码管0显示1,整个显示从右到左为20250321。 因此,修改的关键点在于将位选信号的计算从i改为7-i,并保持display_data数组不变。这样就能实现显示方向的反转。 此外,需要检查延时函数是否正确,原代码中的Delay1000ms函数使用双重循环,可能在实际硬件上需要根据晶振频率调整循环次数,但用户可能希望保持其他功能不变,只需修改显示方向,因此延时部分可以不做调整。 总结修改步骤: 1. 在SMG_SHOW函数中,将位选信号的计算基于(7 - i)而不是i。 2. 保持display_data数组和其余代码不变。 这样修改后,数码管的显示顺序将从右到左,显示内容仍然是20250321。</think>我们将通过以下步骤实现数码管显示方向的反转(从右向左显示): **一、关键修改原理** 数码管位选地址映射关系调整为: $$ 新位选位置 = 7 - 原位置 \quad (i \in [0,7]) $$ 对应二进制关系: $$ 当i=0时选择第7个数码管,i=1时选择第6个,...,i=7时选择第0个 $$ **二、具体修改步骤** ```c void SMG_SHOW() { u8 i = 0; u8 display_data[8] = {2,0,2,5,0,3,2,1}; // 保持原数据顺序 for(i=0; i<8; i++) { SMG_PORT = 0x00; // 消影 /* 修改点:位选反序 */ u8 reversed_i = 7 - i; // 新增反序计算 LSC = (reversed_i & 0x04) >> 2; // 原i改为reversed_i LSB = (reversed_i & 0x02) >> 1; LSA = reversed_i & 0x01; SMG_PORT = gsmg_code[display_data[i]]; Delay1000ms(); } } ``` **三、硬件连接验证** 数码管物理位置与位选对应关系应满足: | 显示位置 | LSC | LSB | LSA | 译码输出 | |---------|-----|-----|-----|---------| | 最右端 | 1 | 1 | 1 | Y7 | | ... | ... | ... | ... | ... | | 最左端 | 0 | 0 | 0 | Y0 | **四、动态扫描优化版** ```c void SMG_SHOW() { static u8 pos = 0; // 添加static保持位置状态 SMG_PORT = 0x00; // 消影 // 反序位选计算 u8 reversed_pos = 7 - pos; LSC = (reversed_pos >> 2) & 0x01; LSB = (reversed_pos >> 1) & 0x01; LSA = reversed_pos & 0x01; SMG_PORT = gsmg_code[display_data[pos]]; pos = (pos + 1) % 8; // 自动循环 } // main函数中改为短延时扫描 void main() { P0 = 0x00; P2 = 0x00; while(1) { SMG_SHOW(); Delay1ms(); // 需新增1ms延时函数 } } ``` **五、修改效果对比** | 特性 | 原代码 | 修改后代码 | |--------------|---------------------|---------------------| | 显示方向 | 从左到右 | 从右到左 | | 位选计算 | i直接解码 | 7-i反序解码 | | 数据索引 | 正向索引 | 正向索引 | | 物理位置映射 | 0对应最左 | 0对应最右 | **六、常见问题排查** 1. **显示错位**:检查译码器输入是否ABC顺序对应LSC-LSB-LSA 2. **数字镜像**:若段码顺序错误(如a段接错线),需重新校准段码表 3. **亮度不均**:缩短延时时间至1-2ms,保证刷新率>50Hz **七、扩展应用** 可通过修改reversed_i的计算公式实现其他显示模式: ```c // 中心对称显示 u8 reversed_i = (i < 4) ? (3 - i) : i; // 奇偶交替显示 u8 reversed_i = (i % 2) ? (7 - i) : i; ``` 最终显示效果将呈现从右向左的"20250321"显示序列,其他功能保持与原设计一致。
阅读全文

相关推荐

#include <reg52.h> // 包含8051单片机寄存器定义头文件 #include <intrins.h> // 包含 intrins 库,提供空操作指令 _nop_() typedef unsigned char u8; // 定义无符号8位类型 typedef unsigned int u16; // 定义无符号16位类型 #define SMG_PORT P0 // 定义数码管段选信号端口为P0 // 定义数码管位选控制引脚(通过3-8译码器选择显示位) sbit LSA = P2^2; // 位选控制线最低位 sbit LSB = P2^3; // 位选控制线中间位 sbit LSC = P2^4; // 位选控制线最高位 /*------------------------------------------------ 函数名称:Delay1000ms 功能说明:实现约1000ms的延时(基于11.0592MHz晶振估算) 注:实际延时时间需根据单片机主频精确计算 ------------------------------------------------*/ void Delay1000ms() { u16 i, j; for(i=0; i<1000; i++) for(j=0; j<120; j++); // 双重循环实现延时 } /*------------------------------------------------ 函数名称:GetSegCode 功能说明:获取0-9数字对应的七段数码管段码(共阴极) 参数说明:num - 要显示的数字(0-9) 返回值:对应数字的段码数据 ------------------------------------------------*/ u8 GetSegCode(u8 num) { switch(num) { // 根据数字返回对应段码 case 0: return 0x3F; // 0 的段码(ABCDEF段亮) case 1: return 0x06; // 1 的段码(BC段亮) case 2: return 0x5B; // 2 的段码(ABGED段亮) case 3: return 0x4F; // 3 的段码(ABGCD段亮) case 4: return 0x66; // 4 的段码(FBGC段亮) case 5: return 0x6D; // 5 的段码(AFGCD段亮) case 6: return 0x7D; // 6 的段码(AFGCDE段亮) case 7: return 0x07; // 7 的段码(ABC段亮) case 8: return 0x7F; // 8 的段码(全部段亮) case 9: return 0x6F; // 9 的段码(ABCDFG段亮) default: return 0x00; // 默认关闭所有段 } } /*------------------------------------------------ 函数名称:SMG_DisplayAll 功能说明:逐个显示数码管内容(测试模式,每个数码管显示1秒) 参数说明:display_data - 包含8个显示数据的数组 注:此函数主要用于检测各个数码管是否正常工作 ------------------------------------------------*/ void SMG_DisplayAll(u8 display_data[]) { int i; for(i=7; i>=0; i--) { // 遍历8个数码管(从高位到低位) SMG_PORT = 0x00; // 关闭所有段选(消隐) // 通过3-8译码器设置位选(i的二进制表示对应LSC/LSB/LSA) LSC = (i & 0x04) >> 2; // 获取bit2(最高位) LSB = (i & 0x02) >> 1; // 获取bit1 LSA = (i & 0x01); // 获取bit0 SMG_PORT = GetSegCode(display_data[i]); // 输出段码 Delay1000ms(); // 保持显示1秒 SMG_PORT = 0x00; // 再次消隐 } } /*------------------------------------------------ 函数名称:SMG_StableDisplay 功能说明:持续动态扫描显示数码管内容(稳定显示模式) 参数说明:display_data - 包含8个显示数据的数组 注:通过快速扫描实现所有数码管同时显示效果(视觉暂留效应) ------------------------------------------------*/ void SMG_StableDisplay(u8 display_data[]) { int i; while(1) { // 无限循环保持显示 for(i=7; i>=0; i--) { // 循环扫描8个数码管 SMG_PORT = 0x00; // 消隐 // 设置位选信号 LSC = (i & 0x04) >> 2; // 解析位选控制线 LSB = (i & 0x02) >> 1; LSA = (i & 0x01); SMG_PORT = GetSegCode(display_data[i]); // 输出段码 // 短暂延时保持显示(约4个机器周期) _nop_(); _nop_(); // 空操作指令(每个约1us) _nop_(); _nop_(); } } } /*------------------------------------------------ 函数名称:SMG_SHOW 功能说明:数码管显示演示流程 执行过程: 1. 先逐个显示各个数码管内容(每个显示1秒) 2. 进入持续稳定显示模式 ------------------------------------------------*/ void SMG_SHOW() { // 定义显示数据数组(对应数码管位7到位0) u8 display_data[8] = {1,2,3,0,5,2,0,2}; SMG_DisplayAll(display_data); // 测试模式显示 SMG_StableDisplay(display_data);// 进入稳定显示模式 } /*------------------------------------------------ 主函数 ------------------------------------------------*/ void main() { P0 = 0x00; // 初始化P0端口(关闭所有段选) P2 = 0x00; // 初始化P2端口(关闭所有位选) while(1) { // 主循环 SMG_SHOW(); // 执行显示流程 // 注意:SMG_StableDisplay包含无限循环,此处不会重复执行 } }这个代码的延时函数能换其他吗

#include "reg52.h" typedef unsigned int u16; //对系统默认数据类型进行重定义 typedef unsigned char u8; //定义ULN2003控制步进电机管脚 sbit IN1_A=P1^0; sbit IN2_B=P1^1; sbit IN3_C=P1^2; sbit IN4_D=P1^3; //定义独立按键控制脚 sbit KEY1=P3^1; sbit KEY2=P3^0; sbit KEY3=P3^2; sbit KEY4=P3^3; //使用宏定义独立按键按下的键值 #define KEY1_PRESS 1 #define KEY2_PRESS 2 #define KEY3_PRESS 3 #define KEY4_PRESS 4 #define KEY_UNPRESS 0 // 定义步进电机速度,值越小,速度越快 // 最小不能小于1 #define STEPMOTOR_MAXSPEED 1 #define STEPMOTOR_MINSPEED 5 /******************************************************************************* * 函 数 名 : delay_10us * 函数功能 : 延时函数,ten_us=1时,大约延时10us * 输 入 : ten_us * 输 出 : 无 *******************************************************************************/ void delay_10us(u16 ten_us) { while(ten_us--); } /******************************************************************************* * 函 数 名 : delay_ms * 函数功能 : ms延时函数,ms=1时,大约延时1ms * 输 入 : ten_us * 输 出 : 无 *******************************************************************************/ void delay_ms(u16 ms) { u16 i,j; for(i=ms;i>0;i--) for(j=110;j>0;j--); } /******************************************************************************* * 函 数 名 : step_motor_28BYJ48_send_pulse * 函数功能 : 输出一个数据给ULN2003从而实现向步进电机发送一个脉冲 * 输 入 : step:指定步进序号,可选值0~7 dir:方向选择,1:顺时针,0:逆时针 * 输 出 : 无 *******************************************************************************/ void step_motor_28BYJ48_send_pulse(u8 step,u8 dir) { u8 temp=step; if(dir==0) //如果为逆时针旋转 temp=7-step;//调换节拍信号 switch(temp)//8个节拍控制:A->AB->B->BC->C->CD->D->DA { case 0: IN1_A=1;IN2_B=0;IN3_C=0;IN4_D=0;break; case 1: IN1_A=1;IN2_B=1;IN3_C=0;IN4_D=0;break; case 2: IN1_A=0;IN2_B=1;IN3_C=0;IN4_D=0;break; case 3: IN1_A=0;IN2_B=1;IN3_C=1;IN4_D=0;break; case 4: IN1_A=0;IN2_B=0;IN3_C=1;IN4_D=0;break; case 5: IN1_A=0;IN2_B=0;IN3_C=1;IN4_D=1;break; case 6: IN1_A=0;IN2_B=0;IN3_C=0;IN4_D=1;break; case 7: IN1_A=1;IN2_B=0;IN3_C=0;IN4_D=1;break; default: IN1_A=0;IN2_B=0;IN3_C=0;IN4_D=0;break;//停止相序 } } /******************************************************************************* * 函 数 名 : key_scan * 函数功能 : 检测独立按键是否按下,按下则返回对应键值 * 输 入 : mode=0:单次扫描按键 mode=1:连续扫描按键 * 输 出 : KEY1_PRESS:K1按下 KEY2_PRESS:K2按下 KEY3_PRESS:K3按下 KEY4_PRESS:K4按下 KEY_UNPRESS:未有按键按下 *******************************************************************************/ u8 key_scan(u8 mode) { static u8 key=1; if(mode)key=1;//连续扫描按键 if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))//任意按键按下 { delay_10us(1000);//消抖 key=0; if(KEY1==0) return KEY1_PRESS; else if(KEY2==0) return KEY2_PRESS; else if(KEY3==0) return KEY3_PRESS; else if(KEY4==0) return KEY4_PRESS; } else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1) //无按键按下 { key=1; } return KEY_UNPRESS; } /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void main() { u8 key=0; u8 dir=0;//默认逆时针方向 u8 speed=STEPMOTOR_MAXSPEED;//默认最大速度旋转 u8 step=0; while(1) { key=key_scan(0); if(key==KEY1_PRESS)//换向 { dir=!dir; } else if(key==KEY2_PRESS)//加速 { if(speed>STEPMOTOR_MAXSPEED) speed-=1; } else if(key==KEY3_PRESS)//减速 { if(speed<STEPMOTOR_MINSPEED) speed+=1; } step_motor_28BYJ48_send_pulse(step++,dir); if(step==8)step=0; delay_ms(speed); } }将该代码与以下代码结合,去掉按键控制,使dsb20的温度控制步进电机选择,若温度大于25步进电机顺时针旋转,温度小于25就逆时针旋转,#include "reg52.h" #include "intrins.h" // 定义数据类型 typedef unsigned char u8; typedef unsigned int u16; // 定义端口 sbit LSA = P2^2; sbit LSB = P2^3; sbit LSC = P2^4; sbit DS18B20_PORT = P3^7; #define SMG_A_DP_PORT P0 // 共阳极数码管显示0~F的段码数据 u8 gsmg_code[17] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; // 函数声明(添加分号) void smg_display(u8 dat[], u8 pos); void ds18b20_reset(void); u8 ds18b20_check(void); u8 ds18b20_read_bit(void); u8 ds18b20_read_byte(void); void ds18b20_write_byte(u8 dat); void ds18b20_start(void); u8 ds18b20_init(void); float ds18b20_read_temperture(void); void delay_10us(u16 ten_us); void delay_ms(u16 ms); // 主函数 void main() { u8 i = 0; int temp_value; u8 temp_buf[5]; ds18b20_init(); // 初始化DS18B20 while(1) { i++; if(i%50 == 0) // 间隔一段时间读取温度值,间隔时间要大于温度传感器转换温度时间 temp_value = ds18b20_read_temperture() * 10; // 保留温度值小数点后一位 if(temp_value < 0) // 负温度 { temp_value = -temp_value; temp_buf[0] = 0x40; // 显示负号 } else temp_buf[0] = 0x00; // 不显示 temp_buf[1] = gsmg_code[temp_value/1000]; // 百位 temp_buf[2] = gsmg_code[temp_value%1000/100]; // 十位 temp_buf[3] = gsmg_code[temp_value%1000%100/10]; // 个位 temp_buf[4] = gsmg_code[temp_value%10] | 0x80; // 显示小数点位 smg_display(temp_buf, 1); } } // 动态数码管显示 void smg_display(u8 dat[], u8 pos) { u8 i = 0; u8 pos_temp = pos - 1; for(i = pos_temp; i < pos_temp + 5; i++) // 只显示5位数码管 { switch(i) // 位选 { case 0: LSC = 1; LSB = 1; LSA = 1; break; case 1: LSC = 1; LSB = 1; LSA = 0; break; case 2: LSC = 1; LSB = 0; LSA = 1; break; case 3: LSC = 1; LSB = 0; LSA = 0; break; case 4: LSC = 0; LSB = 1; LSA = 1; break; case 5: LSC = 0; LSB = 1; LSA = 0; break; case 6: LSC = 0; LSB = 0; LSA = 1; break; case 7: LSC = 0; LSB = 0; LSA = 0; break; } SMG_A_DP_PORT = dat[i - pos_temp]; // 传输段选数据 delay_10us(100); // 延时一段时间,等待显示稳定 SMG_A_DP_PORT = 0x00; // 消隐 } } // 延时函数,ten_us=1时,大约延时10us void delay_10us(u16 ten_us) { while(ten_us--); } // ms延时函数,ms=1时,大约延时1ms void delay_ms(u16 ms) { u16 i, j; for(i = ms; i > 0; i--) for(j = 110; j > 0; j--); } // DS18B20相关函数 // 复位DS18B20 void ds18b20_reset(void) { DS18B20_PORT = 0; // 拉低DQ delay_10us(75); // 拉低750us DS18B20_PORT = 1; // DQ=1 delay_10us(2); // 20US } // 检查DS18B20是否存在 u8 ds18b20_check(void) { u8 time_temp = 0; while(DS18B20_PORT && time_temp < 20) // 等待DQ为低电平 { time_temp++; delay_10us(1); } if(time_temp >= 20) return 1; // 如果超时则强制返回1 else time_temp = 0; while((!DS18B20_PORT) && time_temp < 20) // 等待DQ为高电平 { time_temp++; delay_10us(1); } if(time_temp >= 20) return 1; // 如果超时则强制返回1 return 0; } // 从DS18B20读取一个位 u8 ds18b20_read_bit(void) { u8 dat = 0; DS18B20_PORT = 0; _nop_(); _nop_(); DS18B20_PORT = 1; _nop_(); _nop_(); // 该段时间不能过长,必须在15us内读取数据 if(DS18B20_PORT) dat = 1; // 如果总线上为1则数据dat为1,否则为0 else dat = 0; delay_10us(5); return dat; } // 从DS18B20读取一个字节 u8 ds18b20_read_byte(void) { u8 i = 0; u8 dat = 0; u8 temp = 0; for(i = 0; i < 8; i++) // 循环8次,每次读取一位,且先读低位再读高位 { temp = ds18b20_read_bit(); dat = (temp << 7) | (dat >> 1); } return dat; } // 写一个字节到DS18B20 void ds18b20_write_byte(u8 dat) { u8 i = 0; u8 temp = 0; for(i = 0; i < 8; i++) // 循环8次,每次写一位,且先写低位再写高位 { temp = dat & 0x01; // 选择低位准备写入 dat >>= 1; // 将次高位移到低位 if(temp) { DS18B20_PORT = 0; _nop_(); _nop_(); DS18B20_PORT = 1; delay_10us(6); } else { DS18B20_PORT = 0; delay_10us(6); DS18B20_PORT = 1; _nop_(); _nop_(); } } } // 开始温度转换 void ds18b20_start(void) { ds18b20_reset(); // 复位 ds18b20_check(); // 检查DS18B20 ds18b20_write_byte(0xcc); // SKIP ROM ds18b20_write_byte(0x44); // 转换命令 } // 初始化DS18B20的IO口DQ同时检查DS的存在 u8 ds18b20_init(void) { ds18b20_reset(); return ds18b20_check(); } // 从ds18b20得到温度值 float ds18b20_read_temperture(void) { float temp; u8 dath = 0; u8 datl = 0; u16 value = 0; ds18b20_start(); // 开始转换 ds18b20_reset(); // 复位 ds18b20_check(); ds18b20_write_byte(0xcc); // SKIP ROM ds18b20_write_byte(0xbe); // 读存储器 datl = ds18b20_read_byte(); // 低字节 dath = ds18b20_read_byte(); // 高字节 value = (dath << 8) + datl; // 合并为16位数据 if((value & 0xf800) == 0xf800) // 判断符号位,负温度 { value = (~value) + 1; // 数据取反再加1 temp = value * (-0.0625); // 乘以精度 } else // 正温度 { temp = value * 0.0625; } return temp; }

#include <reg52.h> #include <intrins.h> typedef unsigned int u16; typedef unsigned char u8; // 定义DS18B20温度传感器控制管脚 sbit DS18B20_PORT = P3^7; // 定义直流电机控制管脚 sbit DC_Motor = P1^0; // 定义数码管控制引脚 sbit LSA = P2^2; sbit LSB = P2^3; sbit LSC = P2^4; #define SMG_A_DP_PORT P0 // 共阴极数码管段码表(0-F) u8 gsmg_code[17] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; /******************************************************************************* * 函 数 名 : delay_10us * 函数功能 : 延时函数,ten_us=1时约延时10us * 输 入 : ten_us - 延时参数 * 输 出 : 无 *******************************************************************************/ void delay_10us(u16 ten_us) { while (ten_us--); } /******************************************************************************* * 函 数 名 : delay_ms * 函数功能 : 毫秒级延时函数 * 输 入 : ms - 延时毫秒数 * 输 出 : 无 *******************************************************************************/ void delay_ms(u16 ms) { u16 i, j; for (i = ms; i > 0; i--) for (j = 110; j > 0; j--); } /******************************************************************************* * 函 数 名 : ds18b20_reset * 函数功能 : 复位DS18B20传感器 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void ds18b20_reset(void) { DS18B20_PORT = 0; delay_10us(75); DS18B20_PORT = 1; delay_10us(2); } /******************************************************************************* * 函 数 名 : ds18b20_check * 函数功能 : 检测DS18B20是否存在 * 输 入 : 无 * 输 出 : 1-未检测到,0-存在 *******************************************************************************/ u8 ds18b20_check(void) { u8 time_temp = 0; while (DS18B20_PORT && time_temp < 20) { time_temp++; delay_10us(1); } if (time_temp >= 20) return 1; time_temp = 0; while ((!DS18B20_PORT) && time_temp < 20) { time_temp++; delay_10us(1); } if (time_temp >= 20) return 1; return 0; } /******************************************************************************* * 函 数 名 : ds18b20_read_bit * 函数功能 : 从DS18B20读取一个位 * 输 入 : 无 * 输 出 : 读取的位数据(1/0) *******************************************************************************/ u8 ds18b20_read_bit(void) { u8 dat = 0; DS18B20_PORT = 0; _nop_(); _nop_(); DS18B20_PORT = 1; _nop_(); _nop_(); if (DS18B20_PORT) dat = 1; else dat = 0; delay_10us(5); return dat; } /******************************************************************************* * 函 数 名 : ds18b20_read_byte * 函数功能 : 从DS18B20读取一个字节 * 输 入 : 无 * 输 出 : 读取的字节数据 *******************************************************************************/ u8 ds18b20_read_byte(void) { u8 i = 0, dat = 0, temp = 0; for (i = 0; i < 8; i++) { temp = ds18b20_read_bit(); dat = (temp << 7) | (dat >> 1); } return dat; } /******************************************************************************* * 函 数 名 : ds18b20_write_byte * 函数功能 : 向DS18B20写入一个字节 * 输 入 : dat - 要写入的字节 * 输 出 : 无 *******************************************************************************/ void ds18b20_write_byte(u8 dat) { u8 i = 0, temp = 0; for (i = 0; i < 8; i++) { temp = dat & 0x01; dat >>= 1; if (temp) { DS18B20_PORT = 0; _nop_(); _nop_(); DS18B20_PORT = 1; delay_10us(6); } else { DS18B20_PORT = 0; delay_10us(6); DS18B20_PORT = 1; _nop_(); _nop_(); } } } /******************************************************************************* * 函 数 名 : ds18b20_start * 函数功能 : 启动DS18B20温度转换 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void ds18b20_start(void) { ds18b20_reset(); ds18b20_check(); ds18b20_write_byte(0xCC); ds18b20_write_byte(0x44); } /******************************************************************************* * 函 数 名 : ds18b20_init * 函数功能 : 初始化DS18B20 * 输 入 : 无 * 输 出 : 1-初始化失败,0-初始化成功 *******************************************************************************/ u8 ds18b20_init(void) { ds18b20_reset(); return ds18b20_check(); } /******************************************************************************* * 函 数 名 : ds18b20_read_temperture * 函数功能 : 读取DS18B20温度值 * 输 入 : 无 * 输 出 : 温度值(单位:0.1℃) *******************************************************************************/ float ds18b20_read_temperture(void) { float temp; u8 dath = 0, datl = 0; u16 value = 0; ds18b20_start(); ds18b20_reset(); ds18b20_check(); ds18b20_write_byte(0xCC); ds18b20_write_byte(0xBE); datl = ds18b20_read_byte(); dath = ds18b20_read_byte(); value = (dath << 8) | datl; if ((value & 0xF800) == 0xF800) { value = (~value) + 1; temp = value * (-0.0625); } else { temp = value * 0.0625; } return temp; } /******************************************************************************* * 函 数 名 : smg_display * 函数功能 : 动态数码管显示 * 输 入 : dat - 显示数据数组, pos - 起始显示位置 * 输 出 : 无 *******************************************************************************/ void smg_display(u8 dat[], u8 pos) { u8 i = 0, pos_temp = pos - 1; for (i = pos_temp; i < 8; i++) { switch (i) { case 0: LSC = 1; LSB = 1; LSA = 1; break; case 1: LSC = 1; LSB = 1; LSA = 0; break; case 2: LSC = 1; LSB = 0; LSA = 1; break; case 3: LSC = 1; LSB = 0; LSA = 0; break; case 4: LSC = 0; LSB = 1; LSA = 1; break; case 5: LSC = 0; LSB = 1; LSA = 0; break; case 6: LSC = 0; LSB = 0; LSA = 1; break; case 7: LSC = 0; LSB = 0; LSA = 0; break; } SMG_A_DP_PORT = dat[i - pos_temp]; delay_10us(100); SMG_A_DP_PORT = 0x00; } } /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数,温度高于29℃启动电机,低于29℃停止电机,同时数码管显示温度 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void main() { u8 i = 0; float temp = 0; u8 temp_buf[5] = {0}; ds18b20_init(); // 初始化DS18B20温度传感器 while (1) { i++; if (i % 50 == 0) { // 每50次循环读取一次温度 temp = ds18b20_read_temperture(); // 读取温度 } // 根据温度控制电机启停 if (temp > 29.0) { // 温度高于29℃,启动电机 DC_Motor = 1; } else { // 温度低于29℃,停止电机 DC_Motor = 0; } // 处理温度显示,这里简化显示逻辑,只显示整数部分 if (temp < 0) { temp_buf[0] = 0x40; // 显示负号 temp = -temp; } else { temp_buf[0] = 0x00; // 不显示符号 } // 分解温度数据到显示缓冲区 temp_buf[1] = gsmg_code[(int)temp / 100]; // 百位 temp_buf[2] = gsmg_code[(int)temp % 100 / 10]; // 十位 temp_buf[3] = gsmg_code[(int)temp % 10] | 0x80; // 个位,带小数点 temp_buf[4] = gsmg_code[(int)(temp * 10) % 10]; // 小数位 smg_display(temp_buf, 4); // 从第4位开始显示 } }上述代码不用改,是完全正确的,帮我加入超出温度值29度时蜂鸣器报警的代码,51单片机

/************************************************************************************** 深圳市普中科技有限公司(PRECHIN 普中) 技术支持:www.prechin.net 实验名称:直流电机实验 接线说明: 实验现象:下载程序后,直流电机旋转5S后停止 注意事项:将直流电机两根线分别连接到“步进电机模块”输出端子J47的5V和O1上。 ***************************************************************************************/ #include "reg52.h" typedef unsigned int u16; //对系统默认数据类型进行重定义 typedef unsigned char u8; //定义直流电机控制管脚 sbit DC_Motor=P1^0; #define DC_MOTOR_RUN_TIME 5000 //定义直流电机运行时间为5000ms /******************************************************************************* * 函 数 名 : delay_ms * 函数功能 : ms延时函数,ms=1时,大约延时1ms * 输 入 : ms:ms延时时间 * 输 出 : 无 *******************************************************************************/ void delay_ms(u16 ms) { u16 i,j; for(i=ms;i>0;i--) for(j=110;j>0;j--); } /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void main() { DC_Motor=1;//开启电机 delay_ms(DC_MOTOR_RUN_TIME); DC_Motor=0;//关闭电机 while(1) { } }/*-------------------------------------------------------------------------- REG52.H Header file for generic 80C52 and 80C32 microcontroller. Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc. All rights reserved. --------------------------------------------------------------------------*/ #ifndef __REG52_H__ #define __REG52_H__ /* BYTE Registers */ sfr P0 = 0x80; sfr P1 = 0x90; sfr P2 = 0xA0; sfr P3 = 0xB0; sfr PSW = 0xD0; sfr ACC = 0xE0; sfr B = 0xF0; sfr SP = 0x81; sfr DPL = 0x82; sfr DPH = 0x83; sfr PCON = 0x87; sfr TCON = 0x88; sfr TMOD = 0x89; sfr TL0 = 0x8A; sfr TL1 = 0x8B; sfr TH0 = 0x8C; sfr TH1 = 0x8D; sfr IE = 0xA8; sfr IP = 0xB8; sfr SCON = 0x98; sfr SBUF = 0x99; /* 8052 Extensions */ sfr T2CON = 0xC8; sfr RCAP2L = 0xCA; sfr RCAP2H = 0xCB; sfr TL2 = 0xCC; sfr TH2 = 0xCD; /* BIT Registers */ /* PSW */ sbit CY = PSW^7; sbit AC = PSW^6; sbit F0 = PSW^5; sbit RS1 = PSW^4; sbit RS0 = PSW^3; sbit OV = PSW^2; sbit P = PSW^0; //8052 only /* TCON */ sbit TF1 = TCON^7; sbit TR1 = TCON^6; sbit TF0 = TCON^5; sbit TR0 = TCON^4; sbit IE1 = TCON^3; sbit IT1 = TCON^2; sbit IE0 = TCON^1; sbit IT0 = TCON^0; /* IE */ sbit EA = IE^7; sbit ET2 = IE^5; //8052 only sbit ES = IE^4; sbit ET1 = IE^3; sbit EX1 = IE^2; sbit ET0 = IE^1; sbit EX0 = IE^0; /* IP */ sbit PT2 = IP^5; sbit PS = IP^4; sbit PT1 = IP^3; sbit PX1 = IP^2; sbit PT0 = IP^1; sbit PX0 = IP^0; /* P3 */ sbit RD = P3^7; sbit WR = P3^6; sbit T1 = P3^5; sbit T0 = P3^4; sbit INT1 = P3^3; sbit INT0 = P3^2; sbit TXD = P3^1; sbit RXD = P3^0; /* SCON */ sbit SM0 = SCON^7; sbit SM1 = SCON^6; sbit SM2 = SCON^5; sbit REN = SCON^4; sbit TB8 = SCON^3; sbit RB8 = SCON^2; sbit TI = SCON^1; sbit RI = SCON^0; /* P1 */ sbit T2EX = P1^1; // 8052 only sbit T2 = P1^0; // 8052 only /* T2CON */ sbit TF2 = T2CON^7; sbit EXF2 = T2CON^6; sbit RCLK = T2CON^5; sbit TCLK = T2CON^4; sbit EXEN2 = T2CON^3; sbit TR2 = T2CON^2; sbit C_T2 = T2CON^1; sbit CP_RL2 = T2CON^0; #endif 学习上述代码。#include <reg52.h> #include <intrins.h> // 数据类型定义 typedef unsigned int u16; typedef unsigned char u8; // 硬件引脚定义 sbit DS18B20_PORT = P3^7; // DS18B20数据口 sbit LSA = P2^2; // 数码管位选信号 sbit LSB = P2^3; sbit LSC = P2^4; #define SMG_A_DP_PORT P0 // 数码管段选端口 // 共阴极数码管段码表(0-F) u8 gsmg_code[17] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; /******************************************************************************* * 函 数 名 : delay_10us * 函数功能 : 延时函数,ten_us=1时约延时10us * 输 入 : ten_us - 延时参数 * 输 出 : 无 *******************************************************************************/ void delay_10us(u16 ten_us) { while (ten_us--); } /******************************************************************************* * 函 数 名 : delay_ms * 函数功能 : 毫秒级延时函数 * 输 入 : ms - 延时毫秒数 * 输 出 : 无 *******************************************************************************/ void delay_ms(u16 ms) { u16 i, j; for (i = ms; i > 0; i--) for (j = 110; j > 0; j--); } /******************************************************************************* * 函 数 名 : ds18b20_reset * 函数功能 : 复位DS18B20传感器 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void ds18b20_reset(void) { DS18B20_PORT = 0; // 拉低DQ线 delay_10us(75); // 保持750us DS18B20_PORT = 1; // 释放DQ线 delay_10us(2); // 等待20us } /******************************************************************************* * 函 数 名 : ds18b20_check * 函数功能 : 检测DS18B20是否存在 * 输 入 : 无 * 输 出 : 1-未检测到,0-存在 *******************************************************************************/ u8 ds18b20_check(void) { u8 time_temp = 0; // 等待DQ线变为低电平 while (DS18B20_PORT && time_temp < 20) { time_temp++; delay_10us(1); } if (time_temp >= 20) return 1; time_temp = 0; // 等待DQ线变为高电平 while ((!DS18B20_PORT) && time_temp < 20) { time_temp++; delay_10us(1); } if (time_temp >= 20) return 1; return 0; } /******************************************************************************* * 函 数 名 : ds18b20_read_bit * 函数功能 : 从DS18B20读取一个位 * 输 入 : 无 * 输 出 : 读取的位数据(1/0) *******************************************************************************/ u8 ds18b20_read_bit(void) { u8 dat = 0; DS18B20_PORT = 0; _nop_(); _nop_(); DS18B20_PORT = 1; _nop_(); _nop_(); if (DS18B20_PORT) dat = 1; else dat = 0; delay_10us(5); return dat; } /******************************************************************************* * 函 数 名 : ds18b20_read_byte * 函数功能 : 从DS18B20读取一个字节 * 输 入 : 无 * 输 出 : 读取的字节数据 *******************************************************************************/ u8 ds18b20_read_byte(void) { u8 i = 0, dat = 0, temp = 0; for (i = 0; i < 8; i++) { temp = ds18b20_read_bit(); dat = (temp << 7) | (dat >> 1); } return dat; } /******************************************************************************* * 函 数 名 : ds18b20_write_byte * 函数功能 : 向DS18B20写入一个字节 * 输 入 : dat - 要写入的字节 * 输 出 : 无 *******************************************************************************/ void ds18b20_write_byte(u8 dat) { u8 i = 0, temp = 0; for (i = 0; i < 8; i++) { temp = dat & 0x01; dat >>= 1; if (temp) { DS18B20_PORT = 0; _nop_(); _nop_(); DS18B20_PORT = 1; delay_10us(6); } else { DS18B20_PORT = 0; delay_10us(6); DS18B20_PORT = 1; _nop_(); _nop_(); } } } /******************************************************************************* * 函 数 名 : ds18b20_start * 函数功能 : 启动DS18B20温度转换 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void ds18b20_start(void) { ds18b20_reset(); ds18b20_check(); ds18b20_write_byte(0xCC); // SKIP ROM ds18b20_write_byte(0x44); // 温度转换命令 } /******************************************************************************* * 函 数 名 : ds18b20_init * 函数功能 : 初始化DS18B20 * 输 入 : 无 * 输 出 : 1-初始化失败,0-初始化成功 *******************************************************************************/ u8 ds18b20_init(void) { ds18b20_reset(); return ds18b20_check(); } /******************************************************************************* * 函 数 名 : ds18b20_read_temperture * 函数功能 : 读取DS18B20温度值 * 输 入 : 无 * 输 出 : 温度值(单位:0.1℃) *******************************************************************************/ float ds18b20_read_temperture(void) { float temp; u8 dath = 0, datl = 0; u16 value = 0; ds18b20_start(); // 启动温度转换 ds18b20_reset(); // 复位 ds18b20_check(); ds18b20_write_byte(0xCC); // SKIP ROM ds18b20_write_byte(0xBE); // 读温度寄存器 datl = ds18b20_read_byte(); // 读低字节 dath = ds18b20_read_byte(); // 读高字节 value = (dath << 8) | datl; // 合并为16位数据 if ((value & 0xF800) == 0xF800) { // 负温度 value = (~value) + 1; temp = value * (-0.0625); } else { // 正温度 temp = value * 0.0625; } return temp; } /******************************************************************************* * 函 数 名 : smg_display * 函数功能 : 动态数码管显示 * 输 入 : dat - 显示数据数组, pos - 起始显示位置 * 输 出 : 无 *******************************************************************************/ void smg_display(u8 dat[], u8 pos) { u8 i = 0, pos_temp = pos - 1; for (i = pos_temp; i < 8; i++) { // 位选控制 switch (i) { case 0: LSC = 1; LSB = 1; LSA = 1; break; case 1: LSC = 1; LSB = 1; LSA = 0; break; case 2: LSC = 1; LSB = 0; LSA = 1; break; case 3: LSC = 1; LSB = 0; LSA = 0; break; case 4: LSC = 0; LSB = 1; LSA = 1; break; case 5: LSC = 0; LSB = 1; LSA = 0; break; case 6: LSC = 0; LSB = 0; LSA = 1; break; case 7: LSC = 0; LSB = 0; LSA = 0; break; } SMG_A_DP_PORT = dat[i - pos_temp]; // 段选数据 delay_10us(100); // 延时稳定显示 SMG_A_DP_PORT = 0x00; // 消隐 } } /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void main() { u8 i = 0; int temp_value; u8 temp_buf[5] = {0}; ds18b20_init(); // 初始化DS18B20 while (1) { i++; if (i % 50 == 0) { // 每50次循环读取一次温度(约500ms) temp_value = ds18b20_read_temperture() * 10; // 保留一位小数 } // 处理负温度显示 if (temp_value < 0) { temp_value = -temp_value; temp_buf[0] = 0x40; // 负号段码 } else { temp_buf[0] = 0x00; // 不显示符号 } // 分解温度数据到显示缓冲区 temp_buf[1] = gsmg_code[temp_value / 1000]; // 百位 temp_buf[2] = gsmg_code[temp_value % 1000 / 100]; // 十位 temp_buf[3] = gsmg_code[temp_value % 1000 % 100 / 10] | 0x80; // 个位+小数点 temp_buf[4] = gsmg_code[temp_value % 1000 % 100 % 10]; // 小数位 smg_display(temp_buf, 4); // 从第4位开始显示 } }学习这段自动温控装置代码和电机控制代码以后,帮我生成自动温控装置代码 设计内容:用51单片机、DS18B20温度传感器、数码管、直流电机设计一款自动温度控制装置。 基本要求:1、能用DS18B20测量温度,并将温度值显示在数码管上; 2、能在温度高于29度时,启动直流电机风扇进行降温,低于该设定值时,停止风扇。

#include <reg52.h> #include <intrins.h> // 数据类型定义 typedef unsigned int u16; typedef unsigned char u8; // 硬件引脚定义 sbit DS18B20_PORT = P3^7; // DS18B20数据口 sbit LSA = P2^2; // 数码管位选信号 sbit LSB = P2^3; sbit LSC = P2^4; #define SMG_A_DP_PORT P0 // 数码管段选端口 // 共阴极数码管段码表(0-F) u8 gsmg_code[17] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; /******************************************************************************* * 函 数 名 : delay_10us * 函数功能 : 延时函数,ten_us=1时约延时10us * 输 入 : ten_us - 延时参数 * 输 出 : 无 *******************************************************************************/ void delay_10us(u16 ten_us) { while (ten_us--); } /******************************************************************************* * 函 数 名 : delay_ms * 函数功能 : 毫秒级延时函数 * 输 入 : ms - 延时毫秒数 * 输 出 : 无 *******************************************************************************/ void delay_ms(u16 ms) { u16 i, j; for (i = ms; i > 0; i--) for (j = 110; j > 0; j--); } /******************************************************************************* * 函 数 名 : ds18b20_reset * 函数功能 : 复位DS18B20传感器 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void ds18b20_reset(void) { DS18B20_PORT = 0; // 拉低DQ线 delay_10us(75); // 保持750us DS18B20_PORT = 1; // 释放DQ线 delay_10us(2); // 等待20us } /******************************************************************************* * 函 数 名 : ds18b20_check * 函数功能 : 检测DS18B20是否存在 * 输 入 : 无 * 输 出 : 1-未检测到,0-存在 *******************************************************************************/ u8 ds18b20_check(void) { u8 time_temp = 0; // 等待DQ线变为低电平 while (DS18B20_PORT && time_temp < 20) { time_temp++; delay_10us(1); } if (time_temp >= 20) return 1; time_temp = 0; // 等待DQ线变为高电平 while ((!DS18B20_PORT) && time_temp < 20) { time_temp++; delay_10us(1); } if (time_temp >= 20) return 1; return 0; } /******************************************************************************* * 函 数 名 : ds18b20_read_bit * 函数功能 : 从DS18B20读取一个位 * 输 入 : 无 * 输 出 : 读取的位数据(1/0) *******************************************************************************/ u8 ds18b20_read_bit(void) { u8 dat = 0; DS18B20_PORT = 0; _nop_(); _nop_(); DS18B20_PORT = 1; _nop_(); _nop_(); if (DS18B20_PORT) dat = 1; else dat = 0; delay_10us(5); return dat; } /******************************************************************************* * 函 数 名 : ds18b20_read_byte * 函数功能 : 从DS18B20读取一个字节 * 输 入 : 无 * 输 出 : 读取的字节数据 *******************************************************************************/ u8 ds18b20_read_byte(void) { u8 i = 0, dat = 0, temp = 0; for (i = 0; i < 8; i++) { temp = ds18b20_read_bit(); dat = (temp << 7) | (dat >> 1); } return dat; } /******************************************************************************* * 函 数 名 : ds18b20_write_byte * 函数功能 : 向DS18B20写入一个字节 * 输 入 : dat - 要写入的字节 * 输 出 : 无 *******************************************************************************/ void ds18b20_write_byte(u8 dat) { u8 i = 0, temp = 0; for (i = 0; i < 8; i++) { temp = dat & 0x01; dat >>= 1; if (temp) { DS18B20_PORT = 0; _nop_(); _nop_(); DS18B20_PORT = 1; delay_10us(6); } else { DS18B20_PORT = 0; delay_10us(6); DS18B20_PORT = 1; _nop_(); _nop_(); } } } /******************************************************************************* * 函 数 名 : ds18b20_start * 函数功能 : 启动DS18B20温度转换 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void ds18b20_start(void) { ds18b20_reset(); ds18b20_check(); ds18b20_write_byte(0xCC); // SKIP ROM ds18b20_write_byte(0x44); // 温度转换命令 } /******************************************************************************* * 函 数 名 : ds18b20_init * 函数功能 : 初始化DS18B20 * 输 入 : 无 * 输 出 : 1-初始化失败,0-初始化成功 *******************************************************************************/ u8 ds18b20_init(void) { ds18b20_reset(); return ds18b20_check(); } /******************************************************************************* * 函 数 名 : ds18b20_read_temperture * 函数功能 : 读取DS18B20温度值 * 输 入 : 无 * 输 出 : 温度值(单位:0.1℃) *******************************************************************************/ float ds18b20_read_temperture(void) { float temp; u8 dath = 0, datl = 0; u16 value = 0; ds18b20_start(); // 启动温度转换 ds18b20_reset(); // 复位 ds18b20_check(); ds18b20_write_byte(0xCC); // SKIP ROM ds18b20_write_byte(0xBE); // 读温度寄存器 datl = ds18b20_read_byte(); // 读低字节 dath = ds18b20_read_byte(); // 读高字节 value = (dath << 8) | datl; // 合并为16位数据 if ((value & 0xF800) == 0xF800) { // 负温度 value = (~value) + 1; temp = value * (-0.0625); } else { // 正温度 temp = value * 0.0625; } return temp; } /******************************************************************************* * 函 数 名 : smg_display * 函数功能 : 动态数码管显示 * 输 入 : dat - 显示数据数组, pos - 起始显示位置 * 输 出 : 无 *******************************************************************************/ void smg_display(u8 dat[], u8 pos) { u8 i = 0, pos_temp = pos - 1; for (i = pos_temp; i < 8; i++) { // 位选控制 switch (i) { case 0: LSC = 1; LSB = 1; LSA = 1; break; case 1: LSC = 1; LSB = 1; LSA = 0; break; case 2: LSC = 1; LSB = 0; LSA = 1; break; case 3: LSC = 1; LSB = 0; LSA = 0; break; case 4: LSC = 0; LSB = 1; LSA = 1; break; case 5: LSC = 0; LSB = 1; LSA = 0; break; case 6: LSC = 0; LSB = 0; LSA = 1; break; case 7: LSC = 0; LSB = 0; LSA = 0; break; } SMG_A_DP_PORT = dat[i - pos_temp]; // 段选数据 delay_10us(100); // 延时稳定显示 SMG_A_DP_PORT = 0x00; // 消隐 } } /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void main() { u8 i = 0; int temp_value; u8 temp_buf[5] = {0}; ds18b20_init(); // 初始化DS18B20 while (1) { i++; if (i % 50 == 0) { // 每50次循环读取一次温度(约500ms) temp_value = ds18b20_read_temperture() * 10; // 保留一位小数 } // 处理负温度显示 if (temp_value < 0) { temp_value = -temp_value; temp_buf[0] = 0x40; // 负号段码 } else { temp_buf[0] = 0x00; // 不显示符号 } // 分解温度数据到显示缓冲区 temp_buf[1] = gsmg_code[temp_value / 1000]; // 百位 temp_buf[2] = gsmg_code[temp_value % 1000 / 100]; // 十位 temp_buf[3] = gsmg_code[temp_value % 1000 % 100 / 10] | 0x80; // 个位+小数点 temp_buf[4] = gsmg_code[temp_value % 1000 % 100 % 10]; // 小数位 smg_display(temp_buf, 4); // 从第4位开始显示 } }这是一段自动温控装置代码,数码管实时显示都是正确的,不要修改这段,帮我加入一段温度高于 30℃启动电机、低于该温度时停止的代码

zip
资源下载链接为: https://pan.quark.cn/s/abbae039bf2a 在IT领域,序列化是将对象的状态转换为可存储或传输的形式的过程,而反序列化则是将这种形式恢复为原始对象。本文将深入探讨四种常用的序列化工具:Gson、Jackson、FastJson和ProtoBuf,以及与ProtoBuf相关的proto.exe工具。 Gson(Google Gson):Gson是Google提供的Java库,用于将Java对象转换为JSON字符串,反之亦然。它使用简单,支持复杂的类型转换,包括泛型、枚举、自定义序列化和反序列化策略。Gson的优势在于其灵活性和强大的类型处理能力,使得处理JSON数据非常便捷。 Jackson(FasterXML Jackson):Jackson是另一个流行的Java JSON库,提供流式API、树模型和数据绑定等多种方式来处理JSON。Jackson以其速度和效率著称,支持注解和配置,适应不同的序列化需求。其数据绑定特性允许直接将JSON映射到Java对象,简化了JSON处理。 FastJson(阿里巴巴FastJson):FastJson是阿里巴巴开发的高性能JSON库,支持Java对象与JSON之间的转换。它以极快的速度和较低的内存消耗而闻名,特别适合处理大数据量的场景。FastJson提供简单的API,使得在Java中操作JSON变得直观且高效。 ProtoBuf(Protocol Buffers):ProtoBuf是Google开发的数据序列化协议,将结构化数据序列化为二进制格式,便于存储和网络传输。相比于JSON和XML,ProtoBuf的数据体积更小,解析速度更快。proto.exe是ProtoBuf的编译器,可以将.proto文件编译成不同语言(如Java、Python、C++)的源代码,使得在这些语言中可以直接使用

最新推荐

recommend-type

高分子与计算机模拟.doc

高分子与计算机模拟.doc
recommend-type

模块化多无人机配送系统的设计和控制.zip

Matlab领域上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作
recommend-type

河南鼎诺通信有限公司空调柜手册-PPT课件.ppt

河南鼎诺通信有限公司空调柜手册-PPT课件.ppt
recommend-type

基于PLC的三台电动机顺序启停-控制设计.doc

基于PLC的三台电动机顺序启停-控制设计.doc
recommend-type

哈工大c语言课件.ppt

哈工大c语言课件.ppt
recommend-type

iBatisNet基础教程:入门级示例程序解析

iBatisNet是一个流行的.NET持久层框架,它提供了数据持久化层的解决方案。这个框架允许开发者通过配置文件或XML映射文件来操作数据库,从而将数据操作与业务逻辑分离,提高了代码的可维护性和扩展性。由于它具备与Java领域广泛使用的MyBatis类似的特性,对于Java开发者来说,iBatisNet易于上手。 ### iBatisNet入门关键知识点 1. **框架概述**: iBatisNet作为一个持久层框架,其核心功能是减少数据库操作代码。它通过映射文件实现对象与数据库表之间的映射,使得开发者在处理数据库操作时更加直观。其提供了一种简单的方式,让开发者能够通过配置文件来管理SQL语句和对象之间的映射关系,从而实现对数据库的CRUD操作(创建、读取、更新和删除)。 2. **配置与初始化**: - **配置文件**:iBatisNet使用配置文件(通常为`SqlMapConfig.xml`)来配置数据库连接和SQL映射文件。 - **环境设置**:包括数据库驱动、连接池配置、事务管理等。 - **映射文件**:定义SQL语句和结果集映射到对象的规则。 3. **核心组件**: - **SqlSessionFactory**:用于创建SqlSession对象,它类似于一个数据库连接池。 - **SqlSession**:代表一个与数据库之间的会话,可以执行SQL命令,获取映射对象等。 - **Mapper接口**:定义与数据库操作相关的接口,通过注解或XML文件实现具体方法与SQL语句的映射。 4. **基本操作**: - **查询(SELECT)**:使用`SqlSession`的`SelectList`或`SelectOne`方法从数据库查询数据。 - **插入(INSERT)**:使用`Insert`方法向数据库添加数据。 - **更新(UPDATE)**:使用`Update`方法更新数据库中的数据。 - **删除(DELETE)**:使用`Delete`方法从数据库中删除数据。 5. **数据映射**: - **一对一**:单个记录与另一个表中的单个记录之间的关系。 - **一对多**:单个记录与另一个表中多条记录之间的关系。 - **多对多**:多个记录与另一个表中多个记录之间的关系。 6. **事务处理**: iBatisNet不会自动处理事务,需要开发者手动开始事务、提交事务或回滚事务。开发者可以通过`SqlSession`的`BeginTransaction`、`Commit`和`Rollback`方法来控制事务。 ### 具体示例分析 从文件名称列表可以看出,示例程序中包含了完整的解决方案文件`IBatisNetDemo.sln`,这表明它可能是一个可视化的Visual Studio解决方案,其中可能包含多个项目文件和资源文件。示例项目可能包括了数据库访问层、业务逻辑层和表示层等。而`51aspx源码必读.txt`文件可能包含关键的源码解释和配置说明,帮助开发者理解示例程序的代码结构和操作数据库的方式。`DB_51aspx`可能指的是数据库脚本或者数据库备份文件,用于初始化或者恢复数据库环境。 通过这些文件,我们可以学习到如何配置iBatisNet的环境、如何定义SQL映射文件、如何创建和使用Mapper接口、如何实现基本的CRUD操作,以及如何正确地处理事务。 ### 学习步骤 为了有效地学习iBatisNet,推荐按照以下步骤进行: 1. 了解iBatisNet的基本概念和框架结构。 2. 安装.NET开发环境(如Visual Studio)和数据库(如SQL Server)。 3. 熟悉示例项目结构,了解`SqlMapConfig.xml`和其他配置文件的作用。 4. 学习如何定义和使用映射文件,如何通过`SqlSessionFactory`和`SqlSession`进行数据库操作。 5. 逐步实现增删改查操作,理解数据对象到数据库表的映射原理。 6. 理解并实践事务处理机制,确保数据库操作的正确性和数据的一致性。 7. 通过`51aspx源码必读.txt`学习示例项目的代码逻辑,加深理解。 8. 在数据库中尝试运行示例程序的SQL脚本,观察操作结果。 9. 最后,尝试根据实际需求调整和扩展示例程序,加深对iBatisNet的掌握。 ### 总结 iBatisNet是一个为.NET环境量身定制的持久层框架,它使数据库操作变得更加高效和安全。通过学习iBatisNet的入门示例程序,可以掌握.NET中数据持久化的高级技巧,为后续的复杂数据处理和企业级应用开发打下坚实的基础。
recommend-type

【Dify工作流应用搭建指南】:一站式掌握文档图片上传系统的构建与优化

# 1. Dify工作流应用概述 在现代IT行业中,工作流自动化逐渐成为推动效率和减少人为错误的关键因素。本章将介绍Dify工作流应用的基本概念、核心优势以及应用场景,以助于理解其在企业流程中的重要性。 ## 工作流的定义与重要性 工作流是一系列按照既定顺序完成任务的过程,它旨在实现任务分配、管理和监控的自动化。在企业环境中,工作流应用可以提高任务执行效率、降低
recommend-type

Tree-RAG

<think>我们正在讨论Tree-RAG技术,需要结合用户提供的引用和之前对话中的技术背景。用户之前的问题是关于电力行业设备分析报告中Fine-tuned LLM与RAG的结合,现在转向Tree-RAG技术原理、应用场景及与传统RAG的对比。 根据引用[1]和[4]: - 引用[1]提到GraphRAG与传统RAG的7大区别,指出GraphRAG有更好的数据扩展性,但索引创建和查询处理更复杂。 - 引用[4]提到RAPTOR(Recursive Abstractive Processing for Tree-Organized Retrieval),这是一种Tree-RAG的实现,通过层次
recommend-type

VC数据库实现员工培训与仓库管理系统分析

### VC数据库实例:员工培训系统、仓库管理系统知识点详解 #### 员工培训系统 员工培训系统是企业用来管理员工教育和培训活动的平台,它使得企业能够有效地规划和执行员工的培训计划,跟踪培训进程,评估培训效果,并且提升员工的技能水平。以下是员工培训系统的关键知识点: 1. **需求分析**:首先需要了解企业的培训需求,包括员工当前技能水平、岗位要求、职业发展路径等。 2. **课程管理**:系统需要具备创建和管理课程的能力,包括课程内容、培训方式、讲师信息、时间安排等。 3. **用户管理**:包括员工信息管理、培训师信息管理以及管理员账户管理,实现对参与培训活动的不同角色进行有效管理。 4. **培训进度跟踪**:系统能够记录员工的培训情况,包括参加的课程、完成的课时、获得的证书等信息。 5. **评估系统**:提供考核工具,如考试、测验、作业提交等方式,来评估员工的学习效果和知识掌握情况。 6. **报表统计**:能够生成各种统计报表,如培训课程参与度报表、员工培训效果评估报表等,以供管理层决策。 7. **系统集成**:与企业其它信息系统,如人力资源管理系统(HRMS)、企业资源规划(ERP)系统等,进行集成,实现数据共享。 8. **安全性设计**:确保培训资料和员工信息的安全,需要有相应的权限控制和数据加密措施。 #### 仓库管理系统 仓库管理系统用于控制和管理仓库内部的物资流转,确保物资的有效存储和及时供应,以及成本控制。以下是仓库管理系统的关键知识点: 1. **库存管理**:核心功能之一,能够实时监控库存水平、跟踪库存流动,预测库存需求。 2. **入库操作**:系统要支持对物品的接收入库操作,包括物品验收、编码、上架等。 3. **出库操作**:管理物品的出库流程,包括订单处理、拣货、打包、发货等环节。 4. **物料管理**:对物料的分类管理、有效期管理、质量状态管理等。 5. **仓库布局优化**:系统应具备优化仓库布局功能,以提高存储效率和拣选效率。 6. **设备管理**:管理仓库内使用的各种设备,如叉车、货架、输送带等的维护和调度。 7. **数据报表**:生成各类数据报表,如库存报表、周转报表、成本报表等,提供管理决策支持。 8. **条码与RFID技术**:通过条码扫描或RFID技术,实现仓库作业的自动化和快速识别。 9. **系统集成**:与供应链管理系统(SCM)、制造执行系统(MES)、订单管理系统等进行集成,提升整个供应链的效率。 #### 文件名称列表解读 1. **第04章仓库管理系统**:这部分内容很可能是整个培训或教学材料中关于仓库管理系统的核心章节。它可能详细介绍了仓库管理系统的功能模块、操作流程、数据结构、安全性和维护等内容。 2. **第03章员工培训系统**:这一章节专注于讲解员工培训系统的设计和实施。可能包含培训系统的架构设计、用户交互设计、数据库设计、安全性考虑、系统测试及案例分析等。 通过对以上系统的学习和应用,可以理解IT系统在企业管理中所扮演的角色,提升企业管理效率和员工技能水平。同时,掌握这些系统的设计与实现,对于IT专业人员来说具有重要的实践价值。
recommend-type

【IFIX 4.5 MB1 驱动更新深度解析】:专家分享关键步骤,避免更新陷阱

# 摘要 本文全面介绍了IFIX 4.5 MB1驱动更新的各个方面,包括技术基础、更新的必要性、实践步骤、避免更新陷阱的策略和案例分析。首先概述了IFIX 4.5 MB1的驱动更新概览和技术架构,强调了更新对于提升系统性能和安全性的重要性。然后,具体阐述了更新前的准备、具体操作步骤以及更新后的验证和问题处理。为规避风险,文章接着提出风险评估、预防措施以及更新后的监控和维护方法。最后,通过成功和失败的案例分析,提供了实用的专