目录
概述
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 output
DS_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 input
DS_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 output
DS_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 register
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);
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 data
waitCnt = 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 register
runState = 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.c
Description: user ds18b20 interface
Author : tangmingfei2013@126.com
Date : 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 io
R_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 output
DS_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 input
DS_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 output
DS_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 register
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);
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 data
waitCnt = 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 register
runState = 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.h
Description: user ds18b20 interface
Author : tangmingfei2013@126.com
Date : 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 */