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

📄 18b20.c

📁 温度传感器18B20(数码管显示)开发平台为WINAVR
💻 C
字号:
/************************************************************************************/
/*     程序名:温度显示                                                          	*/
/*                                                                                  */
/*     晶振:1.0 M                                         CPU型号:mega8           */
/*                                                                                  */
/*                                                                                  */
/*     功能描述: 将J14和J11,J16和J18的跳帽短上,用杜邦线把J21的AD0和J9的13连上    */
/*					本实验用AVR的SPI(即595送段码显示)								*/
/*                                                                                  */
/*     QQ:276193028                            			                            */
/*     E-mail:shenchangwei945@163.com                                               */
/*   													 					    	*/
/*                                                                                  */
/*                                                现代虚拟仪器仪表研究所            */
/*                                                         2007-09-19               */
/************************************************************************************/ 
#include "config.h"
#define lat_on 	PORTB|=0x04
#define lat_off PORTB&=~0X04

const unsigned char DISP_TAB[13] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82,0xf8, 0x80, 0x90, 0xbf,0xff,0xc6};
unsigned char DISP_BUFFER[6] = {1,2,3,4,5,6};
uchar temperature_low=0;	//温度读取寄存器,低字节
uchar temperature_high=0;	//温度读取寄存器,高字节

/*----------------函数申明-------------------------*/

void Init_DS18B20(void);
uchar read_ds18b20(void);
void write_ds18b20(uchar data);
void read_temperature(void);
void display_temperature(void);

void spi_init(void)
{
	/* 设置MOSI 和SCK 为输出,其他为输入 */
	PORTB = (1<<PB3)|(1<<PB5);
	/* 使能SPI 主机模式,设置时钟速率为fck/16 */
	SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
    //SPCR=0x76;//主机模式
    //SPSR=0X01;//时钟加位,Focs/2
}
    
void spi_send(uchar dd)
{
    /* 启动数据传输 */
	SPDR = dd;
	/* 等待传输结束 */
	//while(!(SPSR & 0x80));
	//SPDR=dd;
    while((SPSR&0X80) == 0);
	SPSR &= 0X7F;
	//PORTB &= ~0X01;  
}
	

/****************初始化I/O口************************************************/
void Init_R(void)
{
    DDRB=0xef;
    PORTB=0xFF;
    DDRC = 0XFF;
    PORTC=0xFF; 
    DDRD = 0XFF;
    PORTD=0xFF;
	spi_init();
}

/*-------------------------温度传感程序------------------------*/

void Init_DS18B20(void)//初始化ds1820
{
	unsigned char x = 0;
	DDRC |= 0X01;
	PORTC |= 0X01; // DQO = 1;    //DQ复位
	_delay_us(50); // Time_Delay(8);  //稍做延时

	PORTC &= 0XFE; // DQO = 0;    //单片机将DQ拉低
	_delay_us(480); //Time_Delay(80); //精确延时 大于 480us

	PORTC |= 0X01; //DQO = 1;    //拉高总线
	_delay_us(60);//Time_Delay(14);
	
	DDRC &= 0XFE;
	x = PINC&0X01;//DQI;      //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
    _delay_us(120);//Time_Delay(20);
}
/*--------------------------------------------------------*/
unsigned char read_ds18b20(void)//读一个字节
{
	unsigned char i = 0;
	unsigned char dat = 0;

	for (i = 8; i > 0; i--)
	{    
	    DDRC |= 0X01;
  		PORTC &= 0XFE; //DQO = 0; // 给脉冲信号
		_delay_us(1);//1us
  		dat >>= 1;
  		PORTC |= 0X01; //DQO = 1; // 给脉冲信号
  		DDRC &= 0XFE;
		_delay_us(2);//2us
  		if((PINC&0X01) == 1)
  			dat |= 0x80;
  		_delay_us(60);//Time_Delay(4);
	}

	return (dat);
}

/**********************************************************************************/
void write_ds18b20(unsigned char dat)//写一个字节
{
	unsigned char i = 0;
	for (i = 8; i > 0; i--)
	{   
	    DDRC |= 0X01;
  		PORTC &= 0XFE; //DQO = 0;
  		PORTC = dat&0x01; //DQO = dat&0x01;
  		_delay_us(30);//Time_Delay(5);
  		PORTC |= 0X01; //DQO = 1;
  		dat>>=1;
	}
}

void read_temperature(void)
{
	float tt = 0;
	uchar temp,a,b,dot;
	uchar data=0;
	
	Init_DS18B20();
	write_ds18b20(0xCC); // 跳过读序号列号的操作
	write_ds18b20(0x44); // 启动温度转换

	Init_DS18B20();
	write_ds18b20(0xCC); //跳过读序号列号的操作
	write_ds18b20(0xBE); //读取温度寄存器
	
	temperature_low = read_ds18b20();	//先读取低字节
	temperature_high= read_ds18b20();	//后读取高字节

	temp=temperature_high<<4;				//取高字节的低四位
	temp+=temperature_low>>4;				//取低字节的高四位再相加得温度计数的整数部分数值
	dot = temperature_low&0x0f;				//取低字节的低四位得小数部分的相对值
	
	
	if(temp>0x80)//负数
	{	
		tt=((~(dot-1))&0x0f)*0.0625;		//求相对值的原码再*0.0625得小数部分的真实值
		temp=~temp;
		DISP_BUFFER[0] = 10; //Write_Data( '-' );	//bit0为负,显示'-'
	}
	else
	{
		tt=dot*0.0625;						//求相对值的原码再*0.0625得小数部分的真实值
		data=temp/100;
		if(data==1)
			DISP_BUFFER[0] = data;//Write_Data( flash_array[ data ] );	//bit0,如果最高位为1则显示
		else
			DISP_BUFFER[0] = 11;//Write_Data( ' '  );				//bit0,如果最高位为0则消隐
	}
	//小数部分
	tt = tt*1000;							//放大一1000位
	a = (uint)tt/100;						//取得十分位值
	b = (uint)tt%100/10;					//取得百分位值
	
	data=(temp%100)/10;
	DISP_BUFFER[1] = data;//Write_Data( flash_array[data] );		//bit1显示十位
	data=temp%10;
	DISP_BUFFER[2] = data;//Write_Data( flash_array[data] );		//bit2显示个位	
	//Write_Data( '.' );						//bit3显示'.'
	DISP_BUFFER[3] = a;//Write_Data( flash_array[ a ] );			//bit3显示小数位
	DISP_BUFFER[4] = b;//Write_Data( flash_array[ b ] );			//bit4显示小数位
	DISP_BUFFER[5] = 12;//Write_Data( 'C' ); 						//bit5显示'C'
}

/*------------------温度显示程序--------------------------*/
void display_temperature(void)
{
	unsigned char i,temp;
	temp = 0xfe;
	for(i = 0;i<6;i++)
	{
		lat_off;
		if(i == 2)
			spi_send(DISP_TAB[DISP_BUFFER[i]]&0x7f);//显示小数点
		else
			spi_send(DISP_TAB[DISP_BUFFER[i]]);
		lat_on;
		PORTD = temp;
		temp<<=1;
		temp|=0x01;
		_delay_ms(1);
	}
}
/*-----------------------------主程序-------------------------------*/
int main(void)
{
	Init_R();
	while(1)
	{
		read_temperature();				//读取温度
		display_temperature();				//显示温度
	}
	return(0);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -