|
[color=rgb(51, 102, 153) !important]复制代码
//首先查到到相关的DS18b20驱动
//然后打开驱动 打开方式为RT_NULL
//打开成功就可以调用rt_device_read函数读取温度
//
#include <rtdevice.h>
#include <rthw.h>
#include <board.h>
//还没有添加调试信息
//应该添加一个.h文件
#IF 0 /* 库函数方式 */
#define DQ_0(PORT_DQ,PIN_DQ) GPIO_ResetBits(PORT_DQ, PIN_DQ)
#define DQ_1(PORT_DQ,PIN_DQ) GPIO_SetBits(PORT_DQ, PIN_DQ)
/* 判断DQ输入是否为低 */
#define DQ_IS_HIGH() GPIO_ReadInputDataBit(PORT_DQ, PIN_DQ)
#else /* 直接操作寄存器,提高速度 */
#define DQ_0(PORT_DQ,PIN_DQ) PORT_DQ->BSRR |= (PIN_DQ<<16)
#define DQ_1(PORT_DQ,PIN_DQ) PORT_DQ->BSRR |= (PIN_DQ)
/* 判断DQ输入是否为低 */
#define DQ_IS_HIGH(PORT_DQ,PIN_DQ) (PORT_DQ->IDR & PIN_DQ)
#endif
//设置IO口方向
#define _IO_IN(CR,BIT_AND,BIT_OR) {*CR&=BIT_AND;*CR|=BIT_OR;}
#define _IO_OUT(CR,BIT_AND,BIT_OR) {*CR&=BIT_AND;*CR|=BIT_OR;}
//驱动名字
#define HARD_DEVICE_NAME_FORMAT "18b20_%d"
#define HARD_DEVICE_NAME_SIZE (sizeof(HARD_DEVICE_NAME_FORMAT) + 2)
//获得数组元素个数
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
#endif
//IO口相关信息
struct ds18b20_gpio_desc
{
uint32_t rcc;
GPIO_TypeDef *gpio;
uint32_t pin;
};
//在这里添加DS18B20相关引脚信息
//如果有多个DS18B20,依次添加即可
//目前只支持一个引脚上挂一个DS18B20
const static struct ds18b20_gpio_desc _hard_desc[] =
{
{RCC_APB2Periph_GPIOA, GPIOA, GPIO_Pin_3},
};
//其他地方不需要修改
//设置IO方向
struct _IO_
{
uint32_t _IO_IN_and;
uint32_t _IO_IN_or;
uint32_t _IO_OUT_and;
uint32_t _IO_OUT_or;
volatile uint32_t * _CRx;
};
//DS18B20驱动
struct _ds18b20_drv
{
struct rt_device device;
struct _IO_ io;
const struct ds18b20_gpio_desc * hard_desc;
rt_mutex_t mutex;
};
//内部使用,左移四位
static uint32_t _crol_(uint32_t c)
{
uint32_t temp;
temp = c<<4;
c = c>>(sizeof(uint32_t)*8-4);
return c |= temp;
}
//DS18B20复位
static rt_err_t _ds18b20_reset(struct _ds18b20_drv * _drv)
{
uint8_t retry = 0;
_IO_OUT(_drv->io._CRx,_drv->io._IO_OUT_and,_drv->io._IO_OUT_or);
DQ_0(_drv->hard_desc->gpio,_drv->hard_desc->pin);
rt_delay_us(750);//拉低750us
DQ_1(_drv->hard_desc->gpio,_drv->hard_desc->pin);
rt_delay_us(10);
_IO_IN(_drv->io._CRx,_drv->io._IO_IN_and,_drv->io._IO_IN_or);
while(DQ_IS_HIGH(_drv->hard_desc->gpio,_drv->hard_desc->pin)&&retry<200)
{
retry++;
rt_delay_us(1);
}
if(retry>=200)
return RT_ERROR;
while((!DQ_IS_HIGH(_drv->hard_desc->gpio,_drv->hard_desc->pin))&&retry<240)
{
retry++;
rt_delay_us(1);
}
if(retry>=240)
return RT_ERROR;
return RT_EOK;
}
//DS18B20读一个字节
static rt_err_t _ds18b20_read_byte(struct _ds18b20_drv * _drv, uint8_t * data)
{
uint8_t bit = 0,result = 0;
uint8_t i = 0;
for(i = 0;i<8;i++)
{
_IO_OUT(_drv->io._CRx,_drv->io._IO_OUT_and,_drv->io._IO_OUT_or);
DQ_0(_drv->hard_desc->gpio,_drv->hard_desc->pin);
rt_delay_us(1);
DQ_1(_drv->hard_desc->gpio,_drv->hard_desc->pin);
_IO_IN(_drv->io._CRx,_drv->io._IO_IN_and,_drv->io._IO_IN_or);
rt_delay_us(12);
if(DQ_IS_HIGH(_drv->hard_desc->gpio,_drv->hard_desc->pin)) bit=1;
else bit=0;
result=(bit<<7)|(result>>1);
rt_delay_us(50);
}
*data = result;
return RT_EOK;
}
//DS18B20写一个字节
static uint8_t _ds18b20_write_byte(struct _ds18b20_drv * _drv, uint8_t data)
{
uint8_t i, testb;
_IO_OUT(_drv->io._CRx,_drv->io._IO_OUT_and,_drv->io._IO_OUT_or);
for (i=0;i<8;i++)
{
testb=data&0x01;
data=data>>1;
if (testb)
{
DQ_0(_drv->hard_desc->gpio,_drv->hard_desc->pin);
rt_delay_us(2);
DQ_1(_drv->hard_desc->gpio,_drv->hard_desc->pin);
rt_delay_us(60);
}
else
{
DQ_0(_drv->hard_desc->gpio,_drv->hard_desc->pin);
rt_delay_us(60);
DQ_1(_drv->hard_desc->gpio,_drv->hard_desc->pin);
rt_delay_us(2);
}
}
return RT_EOK;
}
//DS18B20转换一次
static rt_err_t _ds18b20_start(struct _ds18b20_drv * _drv)
{
rt_base_t level;
if(_ds18b20_reset(_drv) == RT_EOK)
{
level = rt_hw_interrupt_disable();
_ds18b20_write_byte(_drv,0xcc); // skip rom
_ds18b20_write_byte(_drv,0x44); // convert
rt_hw_interrupt_enable(level);
return RT_EOK;
}
return RT_ERROR;
}
//ds18b20读取温度
static rt_err_t _ds18b20_read_data(struct _ds18b20_drv * _drv, float * result)
{
rt_base_t level;
uint8_t data_H, data_L;
short data;
_ds18b20_reset(_drv);
level = rt_hw_interrupt_disable();
_ds18b20_write_byte(_drv,0xcc); // skip rom
_ds18b20_write_byte(_drv,0xbe); // convert
_ds18b20_read_byte(_drv, &data_L); // LSB
_ds18b20_read_byte(_drv, &data_H); // MSB
rt_hw_interrupt_enable(level);
data = data_H;
data <<= 8;
data |= data_L;
if(data&0xF800)
*result=(~data+1)*0.0625*10;
else
*result=data*0.0625;
if(*result>-55 && *result<125)
return RT_EOK;
else
return RT_ERROR;
}
static rt_err_t STM32_ds18b20_init(rt_device_t dev)
{
GPIO_InitTypeDef GPIO_InitStructure;
uint32_t TempInAnd,TempInOr,TempOutAnd,TempOutOr;
uint16_t GPIO_Pin_x = 0;
struct _ds18b20_drv * ds18b20 = (struct _ds18b20_drv *)dev;
RCC_APB2PeriphclockCmd(ds18b20->hard_desc->rcc, ENABLE); //使能时钟
GPIO_InitStructure.GPIO_Pin = ds18b20->hard_desc->pin; // 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ds18b20->hard_desc->gpio, &GPIO_InitStructure);
GPIO_SetBits(ds18b20->hard_desc->gpio,ds18b20->hard_desc->pin);//输出1
TempInAnd = 0xFFFFFFF0;
TempOutAnd = 0xFFFFFFF0;
TempInOr = 0x00000008;
TempOutOr = 0x00000003;
if (((uint32_t)GPIO_InitStructure.GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
{
ds18b20->io._CRx = &(ds18b20->hard_desc->gpio->CRL);
GPIO_Pin_x = ds18b20->hard_desc->pin>>1;
}
if((GPIO_InitStructure.GPIO_Pin > 0x00FF))
{
ds18b20->io._CRx = &(ds18b20->hard_desc->gpio->CRH);
GPIO_Pin_x = ds18b20->hard_desc->pin>>9;
}
while(GPIO_Pin_x)
{
TempInAnd = _crol_(TempInAnd);
TempOutAnd = _crol_(TempOutAnd);
TempInOr = _crol_(TempInOr);
TempOutOr = _crol_(TempOutOr);
GPIO_Pin_x >>= 1;
}
ds18b20->io._IO_IN_and = TempInAnd;
ds18b20->io._IO_IN_or = TempInOr;
ds18b20->io._IO_OUT_and = TempOutAnd;
ds18b20->io._IO_OUT_or = TempOutOr;
return RT_EOK;
}
static rt_err_t stm32_ds18b20_open(rt_device_t dev, rt_uint16_t oflag)
{
struct _ds18b20_drv * ds18b20 = (struct _ds18b20_drv *)dev;
return _ds18b20_reset(ds18b20);
}
static rt_err_t stm32_ds18b20_close(rt_device_t dev)
{
return RT_EOK;
}
static rt_size_t stm32_ds18b20_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
float temp;
int count = 0,i = 0;
float * data = (float *)buffer;
struct _ds18b20_drv * ds18b20 = (struct _ds18b20_drv *)dev;
while(i<(size/sizeof(float)))
{
rt_mutex_take(ds18b20->mutex,RT_WAITING_FOREVER);
if(_ds18b20_start(ds18b20) == RT_EOK)
{
rt_thread_delay(800);
if(_ds18b20_read_data(ds18b20, &temp) == RT_EOK)
{
data = temp;
count++;
}
else
{
data = 85;
}
}
rt_mutex_release(ds18b20->mutex);
i++;
}
return count;
}
static rt_err_t stm32_ds18b20_control(rt_device_t dev, rt_uint8_t cmd, void *args)
{
return RT_EOK;
}
int ds18b20_drv_init(void)
{
int i = 0, count = 0;
char dev_name[HARD_DEVICE_NAME_SIZE] = "";
struct _ds18b20_drv *_dev = RT_NULL;
for(i=0; i<ARRAY_SIZE(_hard_desc);i++)
{
_dev = (struct _ds18b20_drv *)rt_malloc(sizeof(struct _ds18b20_drv));
if (RT_NULL == _dev)
{
continue;
}
rt_sprintf(dev_name, HARD_DEVICE_NAME_FORMAT, i);
if(RT_NULL ==rt_device_find(dev_name))
{
_dev->hard_desc = &(_hard_desc);
_dev->device.init = stm32_ds18b20_init;
_dev->device.open = stm32_ds18b20_open;
_dev->device.close = stm32_ds18b20_close;
_dev->device.read = stm32_ds18b20_read;
_dev->device.write = RT_NULL;
_dev->device.control = stm32_ds18b20_control;
_dev->device.user_data = RT_NULL;
rt_device_register(&(_dev->device),dev_name,RT_DEVICE_FLAG_RDONLY);
_dev->mutex = rt_mutex_create(dev_name,RT_IPC_FLAG_FIFO); //创建信号量没有判断是否成功
count++;
}
}
return count;
}
INIT_DEVICE_EXPORT(ds18b20_drv_init);
|
|