打印
[Cortex-M0技术交流]

菜鸟学习M0第十九帖——DS18B20

[复制链接]
3225|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lixiaoxu2meng|  楼主 | 2011-9-28 16:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 lixiaoxu2meng 于 2011-9-28 16:38 编辑

直接上代码
main函数
#include "includes.h" //包含所需的头文件
/*************************************************************************************
** Function name: main
** Descriptions: DS18B20实时采集温度 并通过数码管显示出来
** input parameters: 无
** output parameters: 无
** Returned value: 无
*************************************************************************************/
int main (void)
{
Set_System();
while(1)
{
value = read_temp();
delay_ms(1000);
}
}
hw_config函数
#include "includes.h" //包含所需的头文件
//DQ对应引脚 GPB4
#define DQ_STATE DrvGPIO_GetBit(E_GPB,4) //DQ引脚的状态
#define CLR_DQ DrvGPIO_ClrBit(E_GPB, 4) //DQ引脚输出低电平
#define SET_DQ DrvGPIO_SetBit(E_GPB, 4) //DQ引脚输出高电平
#define DQ_OUTPUT DrvGPIO_Open(E_GPB, 4, E_IO_OUTPUT) //DQ引脚设置为输出
#define DQ_INPUT DrvGPIO_Open(E_GPB, 4, E_IO_INPUT) //DQ引脚设置为输入 一边读取该引脚的状态
/*************************************************************************************
** Function name: Set_System
** Descriptions: 1ms(晶振为12MHZ)延时子程序
** input parameters: count
** output parameters: 无
** Returned value: 无
*************************************************************************************/
void Set_System(void)
{
RCC_Configuration(); //配置系统时钟

GPIO_Configuration(); //配置GPIO

TIMER_Configuration(); //配置TIMER

}
/*************************************************************************************
** Function name: RCC_Configuration
** Descriptions: 系统时钟源设置
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void RCC_Configuration(void)
{
UNLOCKREG(); // 对写保护位操作时 需要一次向0x50000 0100写入 0x59,0x16,0x88,
DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1);//与其 SYSCLK->WRCON.XTL12M_EN = 1; 等同
// PWRCON寄存器(这些寄存器在上电复位到用户解锁定之前是锁定的)除了 BIT[6]位其他位都受写保护
// 解除这些需要向 0x50000 0100写入 0x59,0x16,0x88,
// 令PWRCON寄存器的BITP[0]为1(即设定12M外部晶振)
delay_ms(100); //while (DrvSYS_GetChipClockSourceStatus(E_SYS_XTL12M) != 1);//等待外部12MHZ晶振就绪
LOCKREG(); // 向“0x5000_0100”写入任何值,就可以重锁保护寄存器
}
/*************************************************************************************
** Function name: GPIO_Configuration
** Descriptions: GPIO配置
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void GPIO_Configuration()
{
DrvGPIO_Open( E_GPA, 2, E_IO_OUTPUT );//数码管段选
DrvGPIO_Open( E_GPA, 3, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 4, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 5, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 6, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 7, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 8, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 9, E_IO_OUTPUT );
DrvGPIO_Open( E_GPC, 14, E_IO_OUTPUT );//数码管位选
DrvGPIO_Open( E_GPC, 15, E_IO_OUTPUT );
DrvGPIO_Open( E_GPC, 6, E_IO_OUTPUT );
DrvGPIO_Open( E_GPC, 7, E_IO_OUTPUT );
}
/*************************************************************************************
** Function name: TIMER_Configuration
** Descriptions: TIMER配置
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void TIMER_Configuration()
{
DrvTIMER_Init(); //初始化定时器
DrvSYS_SelectIPClockSource(E_SYS_TMR0_CLKSRC, 0); //使用外设时注意必须设置该外设的时钟 设置TIMER的时钟源为外部12MHZ
DrvTIMER_Open(E_TMR0,1000,E_PERIODIC_MODE); //设定定时器 tick 周期并且启动定时器:定时器通道 TMR0 每秒1000次 周期模式
DrvTIMER_SetTimerEvent(E_TMR0,5,(TIMER_CALLBACK) Timer0_Callback,0); //安装一个定时处理事件到 timer0, timer1, timer2, timer3通道
DrvTIMER_EnableInt(E_TMR0); //使能定时器中断
DrvTIMER_Start(E_TMR0); //定时器timer0开始计数
}
/*************************************************************************************
** Function name: Timer0_Callback
** Descriptions: 定时处理事件
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void Timer0_Callback (void)
{
static uint8_t count= 0;
static uint8_t i,xx[4];
uint32_t data;
uint16_t ValueBuff ;

ValueBuff = value*10;
count++;
if(count >= 5)
count = 1;
for(i=0;i<4;i++)
{
xx = ValueBuff%10;
ValueBuff = ValueBuff/10;
}
switch(count)
{
case 1:
DrvGPIO_SetBit(E_GPC,14);
DrvGPIO_ClrBit(E_GPC,15);
DrvGPIO_ClrBit(E_GPC,6);
DrvGPIO_ClrBit(E_GPC,7);
data= 0xC6 ; //显示C
data =data <<2;
GPIOA->DOUT = data;
break;
case 2:
DrvGPIO_SetBit(E_GPC,15);
DrvGPIO_ClrBit(E_GPC,14);
DrvGPIO_ClrBit(E_GPC,6);
DrvGPIO_ClrBit(E_GPC,7);
data = Table[xx[1]]<<2;
GPIOA->DOUT = data;
break;
case 3:
DrvGPIO_SetBit(E_GPC,7);
DrvGPIO_ClrBit(E_GPC,14);
DrvGPIO_ClrBit(E_GPC,15);
DrvGPIO_ClrBit(E_GPC,6);
data = Table[xx[2]]<<2;
GPIOA->DOUT = data;
DrvGPIO_ClrBit(E_GPA,9); //显示小数点
break;
case 4:
DrvGPIO_SetBit(E_GPC,6);
DrvGPIO_ClrBit(E_GPC,14);
DrvGPIO_ClrBit(E_GPC,15);
DrvGPIO_ClrBit(E_GPC,7);
data = Table[xx[3]]<<2;
GPIOA->DOUT = data;
break;
default:break;
}
}
/*************************************************************************************
** Function name: ds1820reset
** Descriptions: DS18B20初始化
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void ds1820reset()
{
/*step1:首先主机产生RESET脉冲*/
DQ_OUTPUT; //将DQ引脚设置为输出
CLR_DQ; //DQ引脚输出低电平(即拉低至少为480us)
delay_ds18b20(300); //精确延时 大于480us
SET_DQ; //DQ引脚输出高电平(即释放数据线)
/*step2:等待15~60us后 DS18B20将把数据线拉低60~240us 以作为应答*/
DQ_INPUT; //将DQ引脚设置为输入
while(DQ_STATE); //如果没有应答也一直等待(注意在while里可加上超时处理 以免通信出错 而造成死机)
while(!DQ_STATE); //应答后等待(注意在while里可加上超时处理 以免通信出错 而造成死机)
/*step3:释放数据线,并延时480us(因为等待与应答必须大于480us才算整个初始化完成)*/
SET_DQ; //DQ引脚输出高电平(即释放数据线)
delay_ds18b20(300); //为了保证初始化完成 在延时480us
}
/*************************************************************************************
** Function name: ds1820rd
** Descriptions: DS18B20 读数据
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
uint8_t ds1820rd()//读数据
{
uint8_t i=0;
uint8_t dat = 0;
for (i=8;i>0;i--)
{
DQ_OUTPUT;//将DQ引脚设置为输出
CLR_DQ;//DQ引脚输出低电平(即拉低)
delay_ds18b20(2);
dat>>=1;
SET_DQ;//DQ引脚输出高电平
DQ_INPUT;//将DQ引脚设置为输入
delay_ds18b20(2);
if(DQ_STATE)
dat|=0x80;
delay_ds18b20(40);//大于60us
}
DQ_OUTPUT;
SET_DQ; //放数据线
return(dat);
}
/*************************************************************************************
** Function name: ds1820rd
** Descriptions: DS18B20 写数据
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void ds1820wr(uint8_t wdata)//写数据
{
uint8_t i=0;
for (i=8; i>0; i--)
{
DQ_OUTPUT; //将DQ引脚设置为输出
CLR_DQ; //DQ引脚输出低电平(小于15us )
delay_ds18b20(2); //延时小于15us
if(wdata&0x01) SET_DQ; //DQ引脚输出高电平
else CLR_DQ; //DQ引脚输出低电平
delay_ds18b20(40); //延时大于60us
SET_DQ; //DQ引脚输出高电平
wdata>>=1;
}
}
/*************************************************************************************
** Function name: read_temp
** Descriptions: 读取温度值并将读到的温度进行处理
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
uint16_t read_temp()//读取温度值并转换
{
uint8_t a,b;
temp_value = 0;
ds1820reset();
ds1820wr(0xcc);//跳过读序列号
ds1820wr(0x44);//启动温度转换
ds1820reset();
ds1820wr(0xcc);//跳过读序列号
ds1820wr(0xbe);//读取温度
a=ds1820rd();
b=ds1820rd();
temp_value=b;
temp_value<<=8;
temp_value=temp_value|a;
if(temp_value<0x0fff) //如果为正数
mark=0;
else //如果为负数
{
temp_value=~temp_value+1;
mark=1;
}
temp_value=temp_value*(0.625);//温度值扩大10倍,精确到1位小数
return(temp_value);
}
/*************************************************************************************
** Function name: delay_ms
** Descriptions: 1ms(晶振为12MHZ)延时子程序
** input parameters: count
** output parameters: 无
** Returned value: 无
*************************************************************************************/
void delay_ms(uint32_t count)
{
uint32_t i,j;
for(i=count;i>0;i--)
for(j=2395;j>0;j--);
}
/*************************************************************************************
** Function name: delay_ms
** Descriptions: 大约40us(晶振为12MHZ)延时子程序
** input parameters: count
** output parameters: 无
** Returned value: 无
*************************************************************************************/
void delay_ds18b20(uint32_t count)
{
uint32_t i,j;
for(i=count;i>0;i--)
for(j=2;j>0;j--);
}
hw_config头文件
#ifndef __HW_CONFIG_H__
#define __HW_CONFIG_H__
void Set_System(void);
void RCC_Configuration(void);
void GPIO_Configuration(void);
void TIMER_Configuration(void);
void Timer0_Callback (void);
void delay_ms(uint32_t count);
void delay_ds18b20(uint32_t count);
void ds1820reset(void);
uint8_t ds1820rd(void);
void ds1820wr(uint8_t wdata);
uint16_t read_temp(void);
#endif

明天再上图
工程 LLI-DS18B20.rar (931.78 KB)

相关帖子

沙发
hotpower| | 2011-9-28 17:58 | 只看该作者
很好!和烈火一样,都是用的延时。
不过助学板的ds18b20是接在uart1上的,
故可以用“单总线硬件控制器”的思路编写程序,
这样利用波特率产生的精准宽度以避免了编写软件延时。
楼主可以参考老师的look之ds18b20的例程编写。
两种风格不一样的感受。后者不需要任何精准的延时。

使用特权

评论回复
板凳
hotpower| | 2011-9-28 18:14 | 只看该作者
可以看到单总线的读写需要独占,有些不合理,当然短时间不会太影响其他任务。新唐的uart比较多,浪费了不如做控制器。

使用特权

评论回复
地板
lixiaoxu2meng|  楼主 | 2011-9-28 18:51 | 只看该作者
恩 有时间 研究下老师说的方法

使用特权

评论回复
5
lr441227048| | 2011-11-21 18:33 | 只看该作者
好东西,支持

使用特权

评论回复
6
hotpower| | 2011-11-21 19:41 | 只看该作者
李老师look中有一个ds18b20的例程。

使用特权

评论回复
7
wgchou| | 2012-4-18 20:57 | 只看该作者
正需要。感谢分享了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

1679

帖子

2

粉丝