目錄
概述
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 */