⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 一个关于AVR单片机的例程
💻 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 + -