目录
概述
1 软硬件
1.1 软硬件环境信息
1.2 开发板信息
1.3 调试器信息
2 FSP和KEIL配置
2.1 硬件接口电路
2.2 FSB配置DS18B20的IO
2.3 生成Keil工程文件
3 DS18B20驱动代码
3.1 DS18B20介绍
3.2 DS18B20驱动实现
3.2.1 IO状态定义
3.2.2 读IO状态函数
3.2.3 其他函数
4 测试程序
4.1 应用程序设计
4.2 测试
5 附件
Renesas R7FA8D1BH (Cortex®-M85) 控制DS18B20和ADC,实现两个页面的跳转功能
概述
本文主要介绍Renesas R7FA8D1BH (Cortex®-M85)设计一个综合的应用案例:应用R7FA8D1BH的IO实现单总线协议,实现驱动ds18b20的功能,其主要完成读取温度值,并将该值格式化显示在OLED屏幕上。还通过串口终端将温度数据发送至串口终端上。
1 软硬件
1.1 软硬件环境信息
软硬件信息 | 版本信息 |
---|---|
Renesas MCU | R7FA8D1BH |
Keil | MDK ARM 5.38 |
FSP 版本 | 5.3.0 |
调试工具:N32G45XVL-STB | DAP-LINK |
1.2 开发板信息
笔者选择使用野火耀阳开发板_瑞萨RA8,该板块的主控MCU为R7FA8D1BHECBD,7FA8D1BHECBD的内核为ARM Contex-M85。
1.3 调试器信息
对于R7FA8D1BHECBD芯片,其使用的内核为Cortex®-M85 Core, ST-LINK-V2或者J-LINK-V9不支持下载和调试功能。笔者经过多次尝试,发现N32G45XVL-STB板卡上自带的DAP-LINK可以下载和调试R7FA8D1BHECBD。
下图为N32G45XVL-STB开发板实物图:
2 FSP和KEIL配置
2.1 硬件接口电路
耀阳开发板_瑞萨RA8上已经设计了DS18B20的接口电路,其使用P809接口作为DS18B20的DQ控制信号。
2.2 FSB配置DS18B20的IO
配置P809为普通的IO接口,然后在代码中动态配置该IO的输出或者输出状态
2.3 生成Keil工程文件
完成FSP的参数配置之后,就可以Generate Project。打开项目文件,其架构如下:
创建ds18b20.c文件,实现驱动代码
3 DS18B20驱动代码
3.1 DS18B20介绍
笔者在之前的文章中,已经详细分析过DS18B20的时序以及实现逻辑,这里不在做介绍。
DS18B20应用笔记_ds18b20读取数据的波形-CSDN博客
3.2 DS18B20驱动实现
3.2.1 IO状态定义
代码第14行:定义us步长延时函数
代码第15行:定义ms步长延时函数
代码第18行:定义DS18B20的IO PIN
代码第21行:输入端口配置
代码第22行:输出端口配置
代码第24行:设置IO低电平
代码第25行:设置IO高电平
3.2.2 读IO状态函数
代码第47行:读取输入模式下IO的状态
3.2.3 其他函数
函数:ds18b20Init, 检测DS18B20是否在线
函数:ds18b20BlockModeProcess。 读取DS18B20的数值
/*** @brief reset DS18B20* @note if reset ds18b20 sucess, the return value is TRUE* @param None* @retval True or Flalse*/
static uint8_t ds18b20Init( void )
{uint16_t tempCnt = 0;bsp_io_level_t status;// Set PIN mode outputDS_Mode_Out_PP();// Master pin is high DQ_SET_HIGH;timeDelayUS(10);// Master pin is low DQ_SET_LOW;// wait for 600 us timeDelayUS(750);// Set PIN mode inputDS_Mode_IN_PUT();while(1){status = DQ_RAD_PIN();if( status == 0){tempCnt = 0;return TRUE;}else{timeDelayUS(1);tempCnt++;if( tempCnt > 480 )return FALSE;}}
}static uint8_t readBit( void )
{uint8_t readCnt = 2;uint8_t bitVal = 1;DQ_SET_LOW;timeDelayUS(3);DQ_SET_HIGH;timeDelayUS(5); // 15 us while(readCnt-- ){//read DQ value if( DQ_RAD_PIN() == 0){bitVal = 0;}timeDelayUS(2); // 15 us }timeDelayUS(30); // 15 us return bitVal;
}static uint8_t ds18b20ReadByte( void )
{uint8_t byteVal = 0;for ( uint8_t i = 0; i < 8; i++ ){byteVal >>= 1;uint8_t bitVal = readBit(); if( bitVal > 0){byteVal |= 0x80;}}return byteVal;
}/*** @brief write one byte to DS18B20* @note * @param byte: the data that is sended to ds18b20* @retval None*/
void ds18b20WriteByte( uint8_t byte)
{unsigned char k;// Set PIN mode outputDS_Mode_Out_PP();for ( k = 0; k < 8; k++ ){if (byte & (1<<k)){DQ_SET_LOW;timeDelayUS(2); DQ_SET_HIGH;timeDelayUS(65); }else{DQ_SET_LOW;timeDelayUS(65); DQ_SET_HIGH;timeDelayUS(2); }}
}uint8_t ds18b20BlockModeProcess( void )
{uint16_t tempValue;uint8_t tempL, tempH;if (ds18b20Init() == FALSE){return FALSE;}// wait for 600 us timeDelayUS(600);ds18b20WriteByte(0xcc);ds18b20WriteByte(0x44); // start convert temperature if (ds18b20Init() == FALSE){return FALSE;}// wait for 600 us timeDelayUS(600);ds18b20WriteByte(0xcc);ds18b20WriteByte(0xbe); // read temperature data registertempL = ds18b20ReadByte();tempH = ds18b20ReadByte();if (tempH > 0x7f) {tempL = ~tempL;tempH = ~tempH+1; st_ds1b20val.sign = 1;}tempValue = (uint16_t)((tempH << 8) | tempL);st_ds1b20val.temperatureVal = (float)(tempValue * 0.0625);return TRUE;
}// NO blocking mode operate ds18b20
uint8_t ds18b20NoBlockingProcess( void )
{uint16_t tempValue;static uint16_t waitCnt = 0;uint8_t tempL, tempH;static uint8_t runState = 0;switch( runState ){default:case INIT_DQ:if (ds18b20Init() == FALSE){return FALSE;}runState = WAIT_READY;break;case WAIT_READY:timeDelayUS(2); // IDEL runState = SKIDROM_CMD;break;case SKIDROM_CMD:ds18b20WriteByte(0xcc);ds18b20WriteByte(0x44); // begin to convert temperature datawaitCnt = 0;runState = WAIT_CONVERT;break;case WAIT_CONVERT:waitCnt++;if( waitCnt > WAIT_CNT_CONVERT){waitCnt = 0;runState = RESET_CMD;}break;case RESET_CMD:if (ds18b20Init() == FALSE){return FALSE;}runState = WAIT_DATA_READY;break;case WAIT_DATA_READY: timeDelayUS(2); // IDEL runState = READ_CMD;break;case READ_CMD:ds18b20WriteByte(0xcc);ds18b20WriteByte(0xbe); // read temperature data registerrunState = GET_VALUE;break;case GET_VALUE:tempL = ds18b20ReadByte();tempH = ds18b20ReadByte();if (tempH > 0x7f) {tempL = ~tempL;tempH = ~tempH+1; st_ds1b20val.sign = 1;}tempValue = (uint16_t)((tempH << 8) | tempL);st_ds1b20val.temperatureVal = (float)(tempValue * 0.0625);runState = INIT_DQ;return TRUE;}return FALSE;
}
4 测试程序
4.1 应用程序设计
代码113行:读取ds18b20的值
代码130行:获得ds18b20的结果数据
代码131行:格式化显示数据
代码132行:显示数据到OLED上
4.2 测试
编译代码,并下载代码到板卡中,其运行结果如下:
5 附件
DS18B20的驱动代码
1)创建ds18b20.c文件,编写如下代码
/*FILE NAME : ds18b20.cDescription: user ds18b20 interface Author : tangmingfei2013@126.comDate : 2024/06/03*/
#include "ds18b20.h"
#include "hal_data.h"typedef enum{INPUT = 0,OUTPUT = 1,
}IO_TYPE;typedef enum{FALSE = 0,TRUE = 1,
}RETURN_RESULT;typedef enum{INIT_DQ = 0,WAIT_READY,SKIDROM_CMD,WAIT_CONVERT,RESET_CMD,READ_CMD,WAIT_DATA_READY,GET_VALUE,IDLE_NULL
}RUN_STATE;ds18b20Struc st_ds1b20val;ds18b20Struc get_ds18b20_value( void )
{return st_ds1b20val;
}static bsp_io_level_t DQ_RAD_PIN(void)
{bsp_io_level_t state;// READ ioR_IOPORT_PinRead(&g_ioport_ctrl, DS_IO_PORT_PIN, &state);return state;
}/*** @brief reset DS18B20* @note if reset ds18b20 sucess, the return value is TRUE* @param None* @retval True or Flalse*/
static uint8_t ds18b20Init( void )
{uint16_t tempCnt = 0;bsp_io_level_t status;// Set PIN mode outputDS_Mode_Out_PP();// Master pin is high DQ_SET_HIGH;timeDelayUS(10);// Master pin is low DQ_SET_LOW;// wait for 600 us timeDelayUS(750);// Set PIN mode inputDS_Mode_IN_PUT();while(1){status = DQ_RAD_PIN();if( status == 0){tempCnt = 0;return TRUE;}else{timeDelayUS(1);tempCnt++;if( tempCnt > 480 )return FALSE;}}
}static uint8_t readBit( void )
{uint8_t readCnt = 2;uint8_t bitVal = 1;DQ_SET_LOW;timeDelayUS(3);DQ_SET_HIGH;timeDelayUS(5); // 15 us while(readCnt-- ){//read DQ value if( DQ_RAD_PIN() == 0){bitVal = 0;}timeDelayUS(2); // 15 us }timeDelayUS(30); // 15 us return bitVal;
}static uint8_t ds18b20ReadByte( void )
{uint8_t byteVal = 0;for ( uint8_t i = 0; i < 8; i++ ){byteVal >>= 1;uint8_t bitVal = readBit(); if( bitVal > 0){byteVal |= 0x80;}}return byteVal;
}/*** @brief write one byte to DS18B20* @note * @param byte: the data that is sended to ds18b20* @retval None*/
void ds18b20WriteByte( uint8_t byte)
{unsigned char k;// Set PIN mode outputDS_Mode_Out_PP();for ( k = 0; k < 8; k++ ){if (byte & (1<<k)){DQ_SET_LOW;timeDelayUS(2); DQ_SET_HIGH;timeDelayUS(65); }else{DQ_SET_LOW;timeDelayUS(65); DQ_SET_HIGH;timeDelayUS(2); }}
}uint8_t ds18b20BlockModeProcess( void )
{uint16_t tempValue;uint8_t tempL, tempH;if (ds18b20Init() == FALSE){return FALSE;}// wait for 600 us timeDelayUS(600);ds18b20WriteByte(0xcc);ds18b20WriteByte(0x44); // start convert temperature if (ds18b20Init() == FALSE){return FALSE;}// wait for 600 us timeDelayUS(600);ds18b20WriteByte(0xcc);ds18b20WriteByte(0xbe); // read temperature data registertempL = ds18b20ReadByte();tempH = ds18b20ReadByte();if (tempH > 0x7f) {tempL = ~tempL;tempH = ~tempH+1; st_ds1b20val.sign = 1;}tempValue = (uint16_t)((tempH << 8) | tempL);st_ds1b20val.temperatureVal = (float)(tempValue * 0.0625);return TRUE;
}// NO blocking mode operate ds18b20
uint8_t ds18b20NoBlockingProcess( void )
{uint16_t tempValue;static uint16_t waitCnt = 0;uint8_t tempL, tempH;static uint8_t runState = 0;switch( runState ){default:case INIT_DQ:if (ds18b20Init() == FALSE){return FALSE;}runState = WAIT_READY;break;case WAIT_READY:timeDelayUS(2); // IDEL runState = SKIDROM_CMD;break;case SKIDROM_CMD:ds18b20WriteByte(0xcc);ds18b20WriteByte(0x44); // begin to convert temperature datawaitCnt = 0;runState = WAIT_CONVERT;break;case WAIT_CONVERT:waitCnt++;if( waitCnt > WAIT_CNT_CONVERT){waitCnt = 0;runState = RESET_CMD;}break;case RESET_CMD:if (ds18b20Init() == FALSE){return FALSE;}runState = WAIT_DATA_READY;break;case WAIT_DATA_READY: timeDelayUS(2); // IDEL runState = READ_CMD;break;case READ_CMD:ds18b20WriteByte(0xcc);ds18b20WriteByte(0xbe); // read temperature data registerrunState = GET_VALUE;break;case GET_VALUE:tempL = ds18b20ReadByte();tempH = ds18b20ReadByte();if (tempH > 0x7f) {tempL = ~tempL;tempH = ~tempH+1; st_ds1b20val.sign = 1;}tempValue = (uint16_t)((tempH << 8) | tempL);st_ds1b20val.temperatureVal = (float)(tempValue * 0.0625);runState = INIT_DQ;return TRUE;}return FALSE;
}/* End of this file */
2)创建ds18b20.h文件,编写如下代码
/*FILE NAME : ds18b20.hDescription: user ds18b20 interface Author : tangmingfei2013@126.comDate : 2024/06/03
*/
#ifndef DS18B20_H
#define DS18B20_H
#include "hal_data.h"#define WAIT_CNT_CONVERT 500 #define timeDelayUS(us) R_BSP_SoftwareDelay(us, BSP_DELAY_UNITS_MICROSECONDS);
#define DS_DELAY_MS(ms) R_BSP_SoftwareDelay(ms, BSP_DELAY_UNITS_MILLISECONDS);#define DS_IO_PORT_PIN BSP_IO_PORT_08_PIN_09#define DS_Mode_IN_PUT() R_IOPORT_PinCfg(&g_ioport_ctrl, DS_IO_PORT_PIN, IOPORT_CFG_PORT_DIRECTION_INPUT)
#define DS_Mode_Out_PP() R_IOPORT_PinCfg(&g_ioport_ctrl, DS_IO_PORT_PIN, IOPORT_CFG_PORT_DIRECTION_OUTPUT)#define DQ_SET_LOW R_IOPORT_PinWrite(&g_ioport_ctrl, DS_IO_PORT_PIN, BSP_IO_LEVEL_LOW)
#define DQ_SET_HIGH R_IOPORT_PinWrite(&g_ioport_ctrl, DS_IO_PORT_PIN, BSP_IO_LEVEL_HIGH)typedef struct{float temperatureVal; bool sign;
}ds18b20Struc;uint8_t ds18b20BlockModeProcess( void );
ds18b20Struc get_ds18b20_value( void );#endif /* DS18B20_H */