h750错误记录 卡死 ,18b20数据读取失败 解决办法

2023-10-25 18:52

本文主要是介绍h750错误记录 卡死 ,18b20数据读取失败 解决办法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  1. 1.程序运行没反应 ,debug发现卡死到 b.
  2. 在这里插入图片描述
    **> 解决办法,中断函数缺失,添加即可

2.stm32h750对18b20 读取数据失败
由于hal库没有 微秒延时,故采用nop( )函数来进行延时,死活读不到温度数据,一度怀疑硬件问题,开发板验证测试就是快
经过多块测试版对比,发现就是nop出问题,us几十的很准,神坑
这种us延时还是用抵达定时器更准确

void delay_init(uint16_t sysclk)
{
#if SYS_SUPPORT_OS                                      /* 如果需要支持OS */uint32_t reload;
#endifg_fac_us = sysclk;                                  /* 由于在HAL_Init中已对systick做了配置,所以这里无需重新配置 */
#if SYS_SUPPORT_OS                                      /* 如果需要支持OS. */reload = sysclk;                                    /* 每秒钟的计数次数 单位为M */reload *= 1000000 / delay_ostickspersec;            /* 根据delay_ostickspersec设定溢出时间,reload为24位* 寄存器,最大值:16777216,在168M下,约合0.09986s左右*/g_fac_ms = 1000 / delay_ostickspersec;              /* 代表OS可以延时的最少单位 */SysTick->CTRL |= 1 << 1;                            /* 开启SYSTICK中断 */SysTick->LOAD = reload;                             /* 每1/delay_ostickspersec秒中断一次 */SysTick->CTRL |= 1 << 0;                            /* 开启SYSTICK */
#endif 
}void delay_us(uint32_t nus)
{uint32_t ticks;uint32_t told, tnow, tcnt = 0;uint32_t reload = SysTick->LOAD;        /* LOAD的值 */ticks = nus * g_fac_us;                 /* 需要的节拍数 */#if SYS_SUPPORT_OS                          /* 如果需要支持OS */delay_osschedlock();                    /* 锁定 OS 的任务调度器 */
#endiftold = SysTick->VAL;                    /* 刚进入时的计数器值 */while (1){tnow = SysTick->VAL;if (tnow != told){if (tnow < told){tcnt += told - tnow;        /* 这里注意一下SYSTICK是一个递减的计数器就可以了 */}else{tcnt += reload - tnow + told;}told = tnow;if (tcnt >= ticks) {break;                      /* 时间超过/等于要延迟的时间,则退出 */}}}#if SYS_SUPPORT_OS                          /* 如果需要支持OS */delay_osschedunlock();                  /* 恢复 OS 的任务调度器 */
#endif }/*** @brief     延时nms* @param     nms: 要延时的ms数 (0< nms <= (2^32 / fac_us / 1000))(fac_us一般等于系统主频, 自行套入计算)* @retval    无*/
void delay_ms(uint16_t nms)
{#if SYS_SUPPORT_OS  /* 如果需要支持OS, 则根据情况调用os延时以释放CPU */if (delay_osrunning && delay_osintnesting == 0)     /* 如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度) */{if (nms >= g_fac_ms)                            /* 延时的时间大于OS的最少时间周期 */{delay_ostimedly(nms / g_fac_ms);            /* OS延时 */}nms %= g_fac_ms;                                /* OS已经无法提供这么小的延时了,采用普通方式延时 */}
#endifdelay_us((uint32_t)(nms * 1000));                   /* 普通方式延时 */
}
/******************************************************************************************************** 修改说明* V1.0 20200402* 第一次发布******************************************************************************************************/#include "main.h"
#include "ds18b20.h"/*** @brief       复位DS18B20* @param       data: 要写入的数据* @retval      无*/
static void ds18b20_reset(void)
{DS18B20_DQ_OUT(0);  /* 拉低DQ,复位 */delay_us(750);      /* 拉低750us */DS18B20_DQ_OUT(1);  /* DQ=1, 释放复位 */delay_us(15);       /* 延迟15US */
}/*** @brief       等待DS18B20的回应* @param       无* @retval      0, DS18B20正常*              1, DS18B20异常/不存在*/
uint8_t ds18b20_check(void)
{uint8_t retry = 0;uint8_t rval = 0;while (DS18B20_DQ_IN && retry < 200)    /* 等待DQ变低, 等待200us */{retry++;delay_us(1);}if (retry >= 200){rval = 1;}else{retry = 0;while (!DS18B20_DQ_IN && retry < 240)   /* 等待DQ变高, 等待240us */{retry++;delay_us(1);}if (retry >= 240) rval = 1;}return rval;
}/*** @brief       从DS18B20读取一个位* @param       无* @retval      读取到的位值: 0 / 1*/
static uint8_t ds18b20_read_bit(void)
{uint8_t data = 0;DS18B20_DQ_OUT(0);delay_us(2);DS18B20_DQ_OUT(1);delay_us(12);if (DS18B20_DQ_IN){data = 1;}delay_us(50);return data;
}/*** @brief       从DS18B20读取一个字节* @param       无* @retval      读到的数据*/
static uint8_t ds18b20_read_byte(void)
{uint8_t i, b, data = 0;for (i = 0; i < 8; i++){b = ds18b20_read_bit(); /* DS18B20先输出低位数据 ,高位数据后输出 */data |= b << i;         /* 填充data的每一位 */ }return data;
}/*** @brief       写一个字节到DS18B20* @param       data: 要写入的字节* @retval      无*/
static void ds18b20_write_byte(uint8_t data)
{uint8_t j;for (j = 1; j <= 8; j++){if (data & 0x01){DS18B20_DQ_OUT(0);  /*  Write 1 */delay_us(2);DS18B20_DQ_OUT(1);delay_us(60);}else{DS18B20_DQ_OUT(0);  /*  Write 0 */delay_us(60);DS18B20_DQ_OUT(1);delay_us(2);}data >>= 1;             /* 右移,获取高一位数据 */}
}/*** @brief       开始温度转换* @param       无* @retval      无*/
static void ds18b20_start(void)
{ds18b20_reset();ds18b20_check();ds18b20_write_byte(0xcc);   /*  skip rom */ds18b20_write_byte(0x44);   /*  convert */
}/*** @brief       初始化DS18B20的IO口 DQ 同时检测DS18B20的存在* @param       无* @retval      0, 正常*              1, 不存在/不正常*/
uint8_t ds18b20_init(void)
{GPIO_InitTypeDef gpio_init_struct;DS18B20_DQ_GPIO_CLK_ENABLE();   /* 开启DQ引脚时钟 */gpio_init_struct.Pin = DS18B20_DQ_GPIO_PIN;gpio_init_struct.Mode = GPIO_MODE_OUTPUT_OD;            /* 开漏输出 */gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;     /* 高速 */HAL_GPIO_Init(DS18B20_DQ_GPIO_PORT, &gpio_init_struct); /* 初始化DS18B20_DQ引脚 *//* DS18B20_DQ引脚模式设置,开漏输出,上拉, 这样就不用再设置IO方向了, 开漏输出的时候(=1), 也可以读取外部信号的高低电平 */ds18b20_reset();return ds18b20_check();
}/*** @brief       从ds18b20得到温度值(精度:0.1C)* @param       无* @retval      温度值 (-550~1250)*   @note      返回的温度值放大了10倍.*              实际使用的时候,要除以10才是实际温度.*/
short ds18b20_get_temperature(void)
{uint8_t flag = 1;           /* 默认温度为正数 */uint8_t TL, TH;short temp;ds18b20_start();            /*  ds1820 start convert */ds18b20_reset();ds18b20_check();ds18b20_write_byte(0xcc);   /*  skip rom */ds18b20_write_byte(0xbe);   /*  convert */TL = ds18b20_read_byte();   /*  LSB */TH = ds18b20_read_byte();   /*  MSB */if (TH > 7){   /* 温度为负,查看DS18B20的温度表示法与计算机存储正负数据的原理一致:正数补码为寄存器存储的数据自身,负数补码为寄存器存储值按位取反后+1所以我们直接取它实际的负数部分,但负数的补码为取反后加一,但考虑到低位可能+1后有进位和代码冗余,我们这里先暂时没有作+1的处理,这里需要留意 */TH = ~TH;TL = ~TL;flag = 0;   /* 温度为负 */}temp = TH;      /* 获得高八位 */temp <<= 8;temp += TL;     /* 获得底八位 *//* 转换成实际温度 */if (flag == 0){/* 将温度转换成负温度,这里的+1参考前面的说明 */temp = (double)(temp + 1) * 0.625;temp = -temp;}else{temp = (double)temp * 0.625;}return temp;
}
/******************************************************************************************************* @file        ds18b20.h* @author      正点原子团队(ALIENTEK)* @version     V1.0* @date        2020-04-2* @brief       DS18B20数字温度传感器 驱动代码* @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司***************************************************************************************************** @attention** 实验平台:正点原子 STM32H750开发板* 在线视频:www.yuanzige.com* 技术论坛:www.openedv.com* 公司网址:www.alientek.com* 购买地址:openedv.taobao.com** 修改说明* V1.0 20200402* 第一次发布******************************************************************************************************/#ifndef __DS18B20_H
#define __DS18B20_H#include "main.h"/******************************************************************************************/
/* DS18B20引脚 定义 */#define DS18B20_DQ_GPIO_PORT                GPIOC  //c5  b12 #define DS18B20_DQ_GPIO_PIN                 GPIO_PIN_5
#define DS18B20_DQ_GPIO_CLK_ENABLE()        do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)   /* PC口时钟使能 *//******************************************************************************************//* IO操作函数 */
#define DS18B20_DQ_OUT(x)   do{ x ? \HAL_GPIO_WritePin(DS18B20_DQ_GPIO_PORT, DS18B20_DQ_GPIO_PIN, GPIO_PIN_SET) : \HAL_GPIO_WritePin(DS18B20_DQ_GPIO_PORT, DS18B20_DQ_GPIO_PIN, GPIO_PIN_RESET); \}while(0)                                                       /* 数据端口输出 */
#define DS18B20_DQ_IN       HAL_GPIO_ReadPin(DS18B20_DQ_GPIO_PORT, DS18B20_DQ_GPIO_PIN)     /* 数据端口输入 */uint8_t ds18b20_init(void);         /* 初始化DS18B20 */
uint8_t ds18b20_check(void);        /* 检测是否存在DS18B20 */
short ds18b20_get_temperature(void);/* 获取温度 */#endif

这篇关于h750错误记录 卡死 ,18b20数据读取失败 解决办法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/284550

相关文章

Python获取中国节假日数据记录入JSON文件

《Python获取中国节假日数据记录入JSON文件》项目系统内置的日历应用为了提升用户体验,特别设置了在调休日期显示“休”的UI图标功能,那么问题是这些调休数据从哪里来呢?我尝试一种更为智能的方法:P... 目录节假日数据获取存入jsON文件节假日数据读取封装完整代码项目系统内置的日历应用为了提升用户体验,

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

MySQL大表数据的分区与分库分表的实现

《MySQL大表数据的分区与分库分表的实现》数据库的分区和分库分表是两种常用的技术方案,本文主要介绍了MySQL大表数据的分区与分库分表的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. mysql大表数据的分区1.1 什么是分区?1.2 分区的类型1.3 分区的优点1.4 分

MySQL错误代码2058和2059的解决办法

《MySQL错误代码2058和2059的解决办法》:本文主要介绍MySQL错误代码2058和2059的解决办法,2058和2059的错误码核心都是你用的客户端工具和mysql版本的密码插件不匹配,... 目录1. 前置理解2.报错现象3.解决办法(敲重点!!!)1. php前置理解2058和2059的错误

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

MySQL INSERT语句实现当记录不存在时插入的几种方法

《MySQLINSERT语句实现当记录不存在时插入的几种方法》MySQL的INSERT语句是用于向数据库表中插入新记录的关键命令,下面:本文主要介绍MySQLINSERT语句实现当记录不存在时... 目录使用 INSERT IGNORE使用 ON DUPLICATE KEY UPDATE使用 REPLACE

Docker镜像pull失败两种解决办法小结

《Docker镜像pull失败两种解决办法小结》有时候我们在拉取Docker镜像的过程中会遇到一些问题,:本文主要介绍Docker镜像pull失败两种解决办法的相关资料,文中通过代码介绍的非常详细... 目录docker 镜像 pull 失败解决办法1DrQwWCocker 镜像 pull 失败解决方法2总