【平头哥RVB2601创意应用开发】温湿度传感器测量
[复制链接]
收到之后,我开始测试其接口功能,发现CDK方便是很方便,但是就是找调用关系还是比较麻烦的,目前也发现里面的包比较混乱。不过不影响本次测试,基本上还是和STM32开发是基本相同的。
本次体验我使用的是其IIC接口,但是使用的是软件模拟IIC的方式。如下图,我把跳帽给去掉了。
然后接线实物如下图:
同时也使用了板子上的供电。
接下来就是移植了,我使用其GUI历程,也就是里面有测试显示屏的代码了。方便后续使用。
就是在其基础上增加了两个文件。
#include "sht20.h"
#include "oled.h"
IIC_INFO iicInfo;
const int16_t POLYNOMIAL = 0x131;
SHT20_INFO sht20Info;
static void sht20_pinmux_init()
{
csi_pin_set_mux(PA8, PIN_FUNC_GPIO); //scl
csi_pin_set_mux(PA9, PIN_FUNC_GPIO); //sda
}
static void sht20_gpio_init()
{
//
csi_gpio_pin_init(&pin_scl, PA8);
csi_gpio_pin_dir(&pin_scl, GPIO_DIRECTION_OUTPUT);
// csi_gpio_pin_dir(&pin_sda, GPIO_DIRECTION_INPUT);
csi_gpio_pin_mode(&pin_scl, GPIO_MODE_OPEN_DRAIN);
csi_gpio_pin_init(&pin_sda, PA9);
csi_gpio_pin_dir(&pin_sda, GPIO_DIRECTION_OUTPUT);
csi_gpio_pin_mode(&pin_sda, GPIO_MODE_OPEN_DRAIN);
}
/*
************************************************************
* 函数名称: IIC_SpeedCtl
*
* 函数功能: 软件IIC速度控制
*
* 入口参数: speed:延时参数
*
* 返回参数: 无
*
* 说明: 单位:微秒
************************************************************
*/
void IIC_SpeedCtl(unsigned short speed)
{
iicInfo.speed = speed;
}
/*
************************************************************
* 函数名称: IIC_Start
*
* 函数功能: 软件IIC开始信号
*
* 入口参数: 无
*
* 返回参数: 无
*
* 说明:
************************************************************
*/
void IIC_Start(void)
{
csi_gpio_pin_dir(&pin_sda, GPIO_DIRECTION_OUTPUT);
SDA_H; //拉高SDA线
SCL_H; //拉高SCL线
uDelay(iicInfo.speed); //延时,速度控制
SDA_L; //当SCL线为高时,SDA线一个下降沿代表开始信号
uDelay(iicInfo.speed); //延时,速度控制
SCL_L; //钳住SCL线,以便发送数据
}
/*
************************************************************
* 函数名称: IIC_Stop
*
* 函数功能: 软件IIC停止信号
*
* 入口参数: 无
*
* 返回参数: 无
*
* 说明:
************************************************************
*/
void IIC_Stop(void)
{
csi_gpio_pin_dir(&pin_sda, GPIO_DIRECTION_OUTPUT);
SDA_L; //拉低SDA线
SCL_L; //拉低SCL先
uDelay(iicInfo.speed); //延时,速度控制
SCL_H; //拉高SCL线
SDA_H; //拉高SDA线,当SCL线为高时,SDA线一个上升沿代表停止信号
uDelay(iicInfo.speed);
}
/*
************************************************************
* 函数名称: IIC_WaitAck
*
* 函数功能: 软件IIC等待应答
*
* 入口参数: timeOut:超时时间
*
* 返回参数: 无
*
* 说明: 单位:微秒
************************************************************
*/
bool IIC_WaitAck(unsigned int timeOut)
{
csi_gpio_pin_dir(&pin_sda, GPIO_DIRECTION_INPUT);
SDA_H;uDelay(iicInfo.speed); //拉高SDA线
SCL_H;uDelay(iicInfo.speed); //拉高SCL线
while(SDA_R) //如果读到SDA线为1,则等待。应答信号应是0
{
if(--timeOut == 0)
{
// UsartPrintf(USART1, "WaitAck TimeOut\r\n");
IIC_Stop(); //超时未收到应答,则停止总线
return IIC_Err; //返回失败
}
uDelay(iicInfo.speed);
}
SCL_L; //拉低SCL线,以便继续收发数据
return IIC_OK; //返回成功
}
/*
************************************************************
* 函数名称: IIC_Ack
*
* 函数功能: 软件IIC产生一个应答
*
* 入口参数: 无
*
* 返回参数: 无
*
* 说明: 当SDA线为低时,SCL线一个正脉冲代表发送一个应答信号
************************************************************
*/
void IIC_Ack(void)
{
csi_gpio_pin_dir(&pin_sda, GPIO_DIRECTION_OUTPUT);
SCL_L; //拉低SCL线
SDA_L; //拉低SDA线
uDelay(iicInfo.speed);
SCL_H; //拉高SCL线
uDelay(iicInfo.speed);
SCL_L; //拉低SCL线
}
/*
************************************************************
* 函数名称: IIC_NAck
*
* 函数功能: 软件IIC产生一非个应答
*
* 入口参数: 无
*
* 返回参数: 无
*
* 说明: 当SDA线为高时,SCL线一个正脉冲代表发送一个非应答信号
************************************************************
*/
void IIC_NAck(void)
{
csi_gpio_pin_dir(&pin_sda, GPIO_DIRECTION_OUTPUT);
SCL_L; //拉低SCL线
SDA_H; //拉高SDA线
uDelay(iicInfo.speed);
SCL_H; //拉高SCL线
uDelay(iicInfo.speed);
SCL_L; //拉低SCL线
}
/*
************************************************************
* 函数名称: IIC_SendByte
*
* 函数功能: 软件IIC发送一个字节
*
* 入口参数: byte:需要发送的字节
*
* 返回参数: 无
*
* 说明:
************************************************************
*/
void IIC_SendByte(unsigned char byte)
{
unsigned char count = 0;
csi_gpio_pin_dir(&pin_sda, GPIO_DIRECTION_OUTPUT);
SCL_L; //拉低时钟开始数据传输
for(; count < 8; count++) //循环8次,每次发送一个bit
{
if(byte & 0x80) //发送最高位
SDA_H;
else
SDA_L;
byte <<= 1; //byte左移1位
uDelay(iicInfo.speed);
SCL_H;
uDelay(iicInfo.speed);
SCL_L;
}
}
/*
************************************************************
* 函数名称: IIC_RecvByte
*
* 函数功能: 软件IIC接收一个字节
*
* 入口参数: 无
*
* 返回参数: 接收到的字节数据
*
* 说明:
************************************************************
*/
unsigned char IIC_RecvByte(void)
{
unsigned char count = 0, receive = 0;
csi_gpio_pin_dir(&pin_sda, GPIO_DIRECTION_INPUT);
SDA_H; //拉高SDA线,开漏状态下,需线拉高以便读取数据
for(; count < 8; count++ ) //循环8次,每次发送一个bit
{
SCL_L;
uDelay(iicInfo.speed);
SCL_H;
receive <<= 1; //左移一位
if(SDA_R) //如果SDA线为1,则receive变量自增,每次自增都是对bit0的+1,然后下一次循环会先左移一次
receive++;
uDelay(iicInfo.speed);
}
return receive;
}
/*
************************************************************
* 函数名称: I2C_WriteByte
*
* 函数功能: 软件IIC写一个数据
*
* 入口参数: slaveAddr:从机地址
* regAddr:寄存器地址
* byte:需要写入的数据
*
* 返回参数: 0-写入成功 1-写入失败
*
* 说明: *byte是缓存写入数据的变量的地址,因为有些寄存器只需要控制下寄存器,并不需要写入值
************************************************************
*/
bool I2C_WriteByte(unsigned char slaveAddr, unsigned char regAddr, unsigned char *byte)
{
unsigned char addr = 0;
addr = slaveAddr << 1; //IIC地址是7bit,这里需要左移1位,bit0:1-读 0-写
IIC_Start(); //起始信号
IIC_SendByte(addr); //发送设备地址(写)
if(IIC_WaitAck(5000)) //等待应答
return IIC_Err;
IIC_SendByte(regAddr); //发送寄存器地址
if(IIC_WaitAck(5000)) //等待应答
return IIC_Err;
if(byte)
{
IIC_SendByte(*byte); //发送数据
if(IIC_WaitAck(5000)) //等待应答
return IIC_Err;
}
IIC_Stop(); //停止信号
return IIC_OK;
}
/*
************************************************************
* 函数名称: I2C_ReadByte
*
* 函数功能: 软件IIC读取一个字节
*
* 入口参数: slaveAddr:从机地址
* regAddr:寄存器地址
* val:需要读取的数据缓存
*
* 返回参数: 0-成功 1-失败
*
* 说明: val是一个缓存变量的地址
************************************************************
*/
bool I2C_ReadByte(unsigned char slaveAddr, unsigned char regAddr, unsigned char *val)
{
unsigned char addr = 0;
addr = slaveAddr << 1; //IIC地址是7bit,这里需要左移1位,bit0:1-读 0-写
IIC_Start(); //起始信号
IIC_SendByte(addr); //发送设备地址(写)
if(IIC_WaitAck(5000)) //等待应答
return IIC_Err;
IIC_SendByte(regAddr); //发送寄存器地址
if(IIC_WaitAck(5000)) //等待应答
return IIC_Err;
IIC_Start(); //重启信号
IIC_SendByte(addr + 1); //发送设备地址(读)
if(IIC_WaitAck(5000)) //等待应答
return IIC_Err;
*val = IIC_RecvByte(); //接收
IIC_NAck(); //产生一个非应答信号,代表读取接收
IIC_Stop(); //停止信号
return IIC_OK;
}
/*
************************************************************
* 函数名称: I2C_WriteBytes
*
* 函数功能: 软件IIC写多个数据
*
* 入口参数: slaveAddr:从机地址
* regAddr:寄存器地址
* buf:需要写入的数据缓存
* num:数据长度
*
* 返回参数: 0-写入成功 1-写入失败
*
* 说明: *buf是一个数组或指向一个缓存区的指针
************************************************************
*/
bool I2C_WriteBytes(unsigned char slaveAddr, unsigned char regAddr, unsigned char *buf, unsigned char num)
{
unsigned char addr = 0;
addr = slaveAddr << 1; //IIC地址是7bit,这里需要左移1位,bit0:1-读 0-写
IIC_Start(); //起始信号
IIC_SendByte(addr); //发送设备地址(写)
if(IIC_WaitAck(5000)) //等待应答
return IIC_Err;
IIC_SendByte(regAddr); //发送寄存器地址
if(IIC_WaitAck(5000)) //等待应答
return IIC_Err;
while(num--) //循环写入数据
{
IIC_SendByte(*buf); //发送数据
if(IIC_WaitAck(5000)) //等待应答
return IIC_Err;
buf++; //数据指针偏移到下一个
uDelay(10);
}
IIC_Stop(); //停止信号
return IIC_OK;
}
/*
************************************************************
* 函数名称: I2C_ReadBytes
*
* 函数功能: 软件IIC读多个数据
*
* 入口参数: slaveAddr:从机地址
* regAddr:寄存器地址
* buf:需要读取的数据缓存
* num:数据长度
*
* 返回参数: 0-写入成功 1-写入失败
*
* 说明: *buf是一个数组或指向一个缓存区的指针
************************************************************
*/
bool I2C_ReadBytes(unsigned char slaveAddr, unsigned char regAddr, unsigned char *buf, unsigned char num)
{
unsigned short addr = 0;
addr = slaveAddr << 1; //IIC地址是7bit,这里需要左移1位,bit0:1-读 0-写
IIC_Start(); //起始信号
IIC_SendByte(addr); //发送设备地址(写)
if(IIC_WaitAck(5000)) //等待应答
return IIC_Err;
IIC_SendByte(regAddr); //发送寄存器地址
if(IIC_WaitAck(5000)) //等待应答
return IIC_Err;
IIC_Start(); //重启信号
IIC_SendByte(addr + 1); //发送设备地址(读)
if(IIC_WaitAck(5000)) //等待应答
return IIC_Err;
while(num--)
{
*buf = IIC_RecvByte();
buf++; //偏移到下一个数据存储地址
if(num == 0)
{
IIC_NAck(); //最后一个数据需要回NOACK
}
else
{
IIC_Ack(); //回应ACK
}
}
IIC_Stop();
return IIC_OK;
}
/*
************************************************************
* 函数名称: SHT20_reset
*
* 函数功能: SHT20复位
*
* 入口参数: 无
*
* 返回参数: 无
*
* 说明:
************************************************************
*/
void SHT20_reset(void)
{
I2C_WriteByte(SHT20_ADDRESS, SHT20_SOFT_RESET, (void *)0);
}
/*
************************************************************
* 函数名称: SHT20_read_user_reg
*
* 函数功能: SHT20读取用户寄存器
*
* 入口参数: 无
*
* 返回参数: 读取到的用户寄存器的值
*
* 说明:
************************************************************
*/
unsigned char SHT20_read_user_reg(void)
{
unsigned char val = 0;
I2C_ReadByte(SHT20_ADDRESS, SHT20_READ_REG, &val);
return val;
}
/*
************************************************************
* 函数名称: SHT2x_CheckCrc
*
* 函数功能: 检查数据正确性
*
* 入口参数: data:读取到的数据
* nbrOfBytes:需要校验的数量
* checksum:读取到的校对比验值
*
* 返回参数: 校验结果
*
* 说明: 0-成功 1-失败
************************************************************
*/
char SHT2x_CheckCrc(char data[], char nbrOfBytes, char checksum)
{
char crc = 0;
char bit = 0;
char byteCtr = 0;
//calculates 8-Bit checksum with given polynomial
for(byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr)
{
crc ^= (data[byteCtr]);
for ( bit = 8; bit > 0; --bit)
{
if (crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;
else crc = (crc << 1);
}
}
if(crc != checksum)
return 1;
else
return 0;
}
/*
************************************************************
* 函数名称: SHT2x_CalcTemperatureC
*
* 函数功能: 温度计算
*
* 入口参数: u16sT:读取到的温度原始数据
*
* 返回参数: 计算后的温度数据
*
* 说明:
************************************************************
*/
float SHT2x_CalcTemperatureC(unsigned short u16sT)
{
float temperatureC = 0; // variable for result
u16sT &= ~0x0003; // clear bits [1..0] (status bits)
//-- calculate temperature [癈] --
temperatureC = -46.85 + 175.72 / 65536 * (float)u16sT; //T= -46.85 + 175.72 * ST/2^16
return temperatureC;
}
/*
************************************************************
* 函数名称: SHT2x_CalcRH
*
* 函数功能: 湿度计算
*
* 入口参数: u16sRH:读取到的湿度原始数据
*
* 返回参数: 计算后的湿度数据
*
* 说明:
************************************************************
*/
float SHT2x_CalcRH(unsigned short u16sRH)
{
float humidityRH = 0; // variable for result
u16sRH &= ~0x0003; // clear bits [1..0] (status bits)
//-- calculate relative humidity [%RH] --
//humidityRH = -6.0 + 125.0/65536 * (float)u16sRH; // RH= -6 + 125 * SRH/2^16
humidityRH = ((float)u16sRH * 0.00190735) - 6;
return humidityRH;
}
/*
************************************************************
* 函数名称: SHT2x_MeasureHM
*
* 函数功能: 测量温湿度
*
* 入口参数: cmd:测量温度还是湿度
* pMeasurand:不为空则保存为ushort值到此地址
*
* 返回参数: 测量结果
*
* 说明:
************************************************************
*/
char data[2]; //data array for checksum verification
float SHT2x_MeasureHM(unsigned char cmd, unsigned short *pMeasurand)
{
char checksum = 0; //checksum
unsigned char addr = 0;
unsigned short tmp = 0;
float t = 0;
addr = SHT20_ADDRESS << 1;
IIC_Start();
IIC_SendByte(addr);
if(IIC_WaitAck(50000)) //等待应答
return 0.0;
IIC_SendByte(cmd);
if(IIC_WaitAck(50000)) //等待应答
return 0.0;
IIC_Start();
IIC_SendByte(addr + 1);
while(IIC_WaitAck(50000)) //等待应答
{
IIC_Start();
IIC_SendByte(addr + 1);
}
Delay(70);
data[0] = IIC_RecvByte();
IIC_Ack();
data[1] = IIC_RecvByte();
IIC_Ack();
checksum = IIC_RecvByte();
IIC_NAck();
IIC_Stop();
SHT2x_CheckCrc(data, 2, checksum);
tmp = (data[0] << 8) + data[1];
if(cmd == SHT20_Measurement_T_HM)
{
t = SHT2x_CalcTemperatureC(tmp);
}
else
{
t = SHT2x_CalcRH(tmp);
}
if(pMeasurand)
{
*pMeasurand = (unsigned short)t;
}
return t;
}
void SHT20_Init(void)
{
sht20_pinmux_init();
sht20_gpio_init();
}
/*
************************************************************
* 函数名称: SHT20_GetValue
*
* 函数功能: 获取温湿度数据
*
* 入口参数: 无
*
* 返回参数: 无
*
* 说明: 温湿度结果保存在SHT20结构体里
************************************************************
*/
void SHT20_GetValue(void)
{
unsigned char val = 0;
IIC_SpeedCtl(5);
SHT20_read_user_reg();
uDelay(100);
sht20Info.tempreture = SHT2x_MeasureHM(SHT20_Measurement_T_HM, (void *)0);
Delay(70);
sht20Info.humidity = SHT2x_MeasureHM(SHT20_Measurement_RH_HM, (void *)0);
Delay(25);
SHT20_read_user_reg();
Delay(25);
I2C_WriteByte(SHT20_ADDRESS, SHT20_WRITE_REG, &val);
uDelay(100);
SHT20_read_user_reg();
uDelay(100);
SHT20_reset();
uDelay(100);
printf("sht20Info.tempreture:%f\r\n",sht20Info.tempreture);
printf("sht20Info.humidity:%f\r\n",sht20Info.humidity);
}
这里直接附上代码,上面是C文件。
#ifndef sht20_H
#define sht20_H
#include <drv/gpio_pin.h>
#include <drv/pin.h>
csi_gpio_pin_t pin_scl;
csi_gpio_pin_t pin_sda;
//SDA PB11
//SCL PB10
#define SDA_H csi_gpio_pin_write(&pin_sda, GPIO_PIN_HIGH)
#define SDA_L csi_gpio_pin_write(&pin_sda, GPIO_PIN_LOW)
#define SDA_R csi_gpio_pin_read(&pin_sda)
#define SCL_H csi_gpio_pin_write(&pin_scl, GPIO_PIN_HIGH)
#define SCL_L csi_gpio_pin_write(&pin_scl, GPIO_PIN_LOW)
#define IIC_OK 0
#define IIC_Err 1
typedef struct
{
unsigned short speed;
} IIC_INFO;
//extern IIC_INFO iicInfo;
/*SHT20 设备操作相关宏定义,详见手册*/
#define SHT20_ADDRESS 0X40
#define SHT20_Measurement_RH_HM 0XE5
#define SHT20_Measurement_T_HM 0XE3
#define SHT20_Measurement_RH_NHM 0XF5
#define SHT20_Measurement_T_NHM 0XF3
#define SHT20_READ_REG 0XE7
#define SHT20_WRITE_REG 0XE6
#define SHT20_SOFT_RESET 0XFE
typedef struct
{
float tempreture;
float humidity;
} SHT20_INFO;
extern SHT20_INFO sht20Info;
void IIC_Init(void);
void IIC_SpeedCtl(unsigned short speed);
bool I2C_WriteByte(unsigned char slaveAddr, unsigned char regAddr, unsigned char *byte);
bool I2C_ReadByte(unsigned char slaveAddr, unsigned char regAddr, unsigned char *val);
bool I2C_WriteBytes(unsigned char slaveAddr, unsigned char regAddr, unsigned char *buf, unsigned char num);
bool I2C_ReadBytes(unsigned char slaveAddr, unsigned char regAddr, unsigned char *buf, unsigned char num);
void IIC_Start(void);
void IIC_Stop(void);
bool IIC_WaitAck(unsigned int timeOut);
void IIC_Ack(void);
void IIC_NAck(void);
void IIC_SendByte(unsigned char byte);
unsigned char IIC_RecvByte(void);
void SHT20_Init(void);
void SHT20_GetValue(void);
#endif
这个是头文件。
本次是一个OS系统,所以要新增一个任务用来读取传感器值。
实际效果如图,可以直接读出数据了。
|