📄 main.c
字号:
// ICC-AVR application builder : 2007-6-12 17:11:46
// Target : M16
// Crystal: 7.3728Mhz
// AVR与虚拟仪器 http://www.avrvi.com
// 用途: DS18B20 演示程序
// 连接: 电源跳线,晶振跳线(一定要使用7.3728M晶振),DS18B20 接PD3,串口跳线连接
// 使用串口延长线连接PC和开发板,在串口调试助手里面观察,发回的值,用手捏住18B20,可以看到值变大
#include <iom16v.h>
#include <macros.h>
#define F_CPU 7372800
//数据类型的定义
#define uint8 unsigned char
#define uint16 unsigned int
//位变量操作宏定义
#define BIT_SET(a,b) a|=BIT(b)
#define BIT_CLR(a,b) a&=~BIT(b)
#define BIT_INV(a,b) a^=BIT(b)
#define BIT_STATUS(a,b) a&BIT(b)
//DS18B20操作定义
#define CLR_DS18B20 BIT_CLR(PORTD,PD3) //数据线强制拉低
#define SET_DS18B20 BIT_SET(PORTD,PD3) //数据线强制拉高,上拉
#define HLD_DS18B20 BIT_SET(DDRD,PD3) //Mega16控制总线
#define RLS_DS18B20 BIT_CLR(DDRD,PD3) //释放总线
#define STU_DS18B20 BIT_STATUS(PIND,PD3) //数据线的状态
void port_init(void)
{
PORTA = 0xFF;
DDRA = 0x00;
PORTB = 0xFF;
DDRB = 0xFF; //输出
PORTC = 0xFF; //m103 output only
DDRC = 0xFF; //输出
DDRD = 0xFF;
PORTD = 0xFF;
}
/**********************************************************************
functionName: void delayUs(BYTE temp)
description :延时函数 晶振频率:7.3728MHZ
delayUs(1); //2.71us
delayUs(2); //3.53us
delayUs(4); //5.15us
delayUs(8); //8.41us
delayUs(16); //14.92us
delayUs(32); //27.94us
delayUs(64); //53.98us
delayUs(128); //106.07us
delayUs(255); //209.42us
delayUs(18); //16.55us
delayUs(34); //29.57us
delayUs(35); //30.38us
delayUs(100); //83.28
_NOP(); //0.14us
**********************************************************************/
void delayUs(uint8 temp)
{
while(temp--);
}
//延时约1s
void longdelay(void)
{
unsigned int i;
for(i=4761;i!=0;i--)
delayUs(255);
}
/*******************************************************************************
functionName: uint8 resetDS18B20(void)
description :DS18B20初始化
********************************************************************************/
uint8 resetDS18B20(void)
{
uint8 errTime=0;
RLS_DS18B20; //释放总线
_NOP();
HLD_DS18B20; //Maga16控制总线
CLR_DS18B20; //强制拉低
delayUs(255); //209.42us
delayUs(255); //209.42us
delayUs(255); //83.28us
//以上的三个延时大于480us
RLS_DS18B20; //释放总线,总线自动上拉
_NOP();
while(STU_DS18B20)
{
delayUs(4); //5.15us
errTime++;
if(errTime>20)
return(0x00); //如果等带大于约 5.15us*20就返回0x00,报告复位失败(实际上只要等待15-60us)
}
errTime=0;
while(!(STU_DS18B20))
{
delayUs(4); //5.15us
errTime++;
if(errTime>50)
return(0x00); //如果等带大于约 5.15us*50就返回0x00,报告复位失败(实际上只要等待60-240us)
}
return(0xff);
}
/**********************************************************************
functionName: uint8 readuint8DS18B20(void)
description :读DS18B20一个字节
**********************************************************************/
uint8 readuint8DS18B20(void)
{
uint8 i;
uint8 retVal=0;
RLS_DS18B20; //释放总线
for(i=8;i>0;i--)
{
retVal>>=1;
HLD_DS18B20; //Maga16控制总线
CLR_DS18B20; //强制拉低
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP(); //延时大于1us
RLS_DS18B20; //释放总线,DS18B20会将总线强制拉低
NOP();
NOP();
NOP();
if(STU_DS18B20)
retVal|=0x80;
delayUs(16); //14.92us
delayUs(16); //14.92us
RLS_DS18B20; //释放总线
delayUs(35); //30.38us
}
delayUs(1); //2.71us(大于1us就行了)
return(retVal);
}
/*******************************************************************************
functionName: uint8 readuint8DS18B20(void)
description :写DS18B20一个字节
********************************************************************************/
void writeuint8DS18B20(uint8 wb)
{
uint8 i;
uint8 temp;
RLS_DS18B20; //释放总线
for(i=0;i<8;i++)
{
HLD_DS18B20; //Maga16控制总线
CLR_DS18B20; //强制拉低
delayUs(16); //14.92us
temp=wb>>i;
temp&=0x01;
if(temp)
RLS_DS18B20; //释放总线
else
CLR_DS18B20; //强制拉低
delayUs(16); //14.92us
delayUs(35); //30.38us
RLS_DS18B20; //释放总线
delayUs(1); //2.71us(大于1us就行了)
}
}
/*******************************************************************************
functionName: unsigned int readTempDS18B20(void)
description :读DS18B20温度
********************************************************************************/
unsigned int readTempDS18B20(void)
{
uint8 tempL,tempH;
uint16 x;
resetDS18B20();
writeuint8DS18B20(0xcc); //跳过ROM
writeuint8DS18B20(0x44); //启动温度转换
delayUs(1);
resetDS18B20();
writeuint8DS18B20(0xcc); //跳过ROM
writeuint8DS18B20(0xbe); //读数据
tempL=readuint8DS18B20();
tempH=readuint8DS18B20();
x=(tempH<<8)|tempL;
return(x);
}
/*******************************************************************************
串口操作相关函数
*******************************************************************************/
void USART_Init( unsigned int baud )
{
unsigned int tmp;
/* 设置波特率*/
tmp= F_CPU/baud/16-1;
UBRRH = (unsigned char)(tmp>>8);
UBRRL = (unsigned char)tmp;
/* 接收器与发送器使能*/
UCSRB = (1<<RXEN)|(1<<TXEN);
/* 设置帧格式: 8 个数据位, 2 个停止位*/
UCSRC = (1<<URSEL)|(1<<USBS)|(1<<UCSZ0)|(1<<UCSZ1);
}
// 数据发送【发送5 到8 位数据位的帧】
void USART_Transmit( unsigned char data )
{
/* 等待发送缓冲器为空 */
while ( !( UCSRA & (1<<UDRE)) )
;
/* 将数据放入缓冲器,发送数据 */
UDR = data;
}
uint16 i; //读温度值的暂存变量
void main(void)
{
unsigned char temp=0;
port_init();
USART_Init(9600); //波特率9600 初始化串口
USART_Transmit('O');
USART_Transmit('K');
while(1)
{
i=resetDS18B20();
i=readTempDS18B20();
//下面开始对读到的数进行处理,说明,这里用的一位精度
if(i&(1<<3)) //判断倒数第四位是1还是0
{
temp=i>>4+1;
}
else
{
temp=i>>4;
}
USART_Transmit(temp); //结果发到串口中
longdelay(); //等待1S
}
}
/*
假设你只要精确到1度
换算温度用很简单的方法就可以处理:
首先判断是正温度还是负温度
然后判断倒数第四位是1还是0
如果是1且温度为正,那么 温度=x>>4+1;
如果是1且温度为负,那么 温度=x>>4-1;
如果是0,温度=x>>4;
这样的操作可以节省很多的flah空间。
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -