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

📄 main2.c

📁 pic16f886读取LM75A温度芯片的程序
💻 C
字号:
#include<pic.h>
#define uchar unsigned char
#define uint unsigned int
#define I2C_SCL RB4
#define I2C_SDA RB3

#define SCLO TRISB4=0;

#define SDAI TRISB3=1
#define SDAO TRISB3=0

#define  rs RB0
#define rw RB1
#define en RB2
#define busy RC7
#define DATA PORTC

#define Nop(); asm("Nop");\
               asm("Nop");\
               asm("Nop");\
               asm("Nop");\
               asm("Nop")
uchar tab[2],flag,sum,temp1;

void delay(uchar i)
{
	uchar j;
	for(;i>0;i--)
		for(j=10;j>0;j++);
}

void ad_init()//ad转换IO寄存器设置
{
	TRISA|=0x01;
	ANSEL|=0x01;
	ADCON0=0x41;//Fosc/8,ADON,AN0
	ADCON1=0x00;//结果左对齐,参考电压为VDD,VSS
	GIE=1;
	PEIE=1;
	ADIE=1;
	ADIF=0;
	delay(1);
	GODONE=1;	
}

uchar  num_change(uchar tep)//计算电压,湿度值
{	
	float  y,yy;
	uchar tt;
	y=(float)(tep)/51;
	yy=y;
//	v=(uint)(100*yy);
	tt=(uchar)((y-0.8)/0.031);
	return tt;
}

void write_com(uchar com)
{
//	chkbusy();
	delay(1);
	DATA=com;
	rs=0;
	rw=0;
	en=1;
	delay(1);
	en=0;
}

void write_dat(uchar dat)
{
//	chkbusy();
	delay(1);
	DATA=dat;
	rs=1;
	rw=0;
	en=1;
	delay(1);
	en=0;
}

void write_m(uchar num,uchar location)//写1602湿度值
{
	uchar t1,t2,j;

	t1=num/10;
	t2=num%10;
	write_com(location);
	write_dat(0x4d);
	write_dat(0x3a);
	write_dat(t1+0x30);
	write_dat(t2+0x30);
	write_dat(0x25);
	write_dat(0x52);
	write_dat(0x48);

}



void lm75_io_init()
{
	TRISB=0x00;
	PORTB=0xff;
	WPUB=0xff;
	RBPU=0;
	ANSELH=0x00;
}


void lcd_init()//1602端口设置,初始化设置以及显示框架字符
{
	uchar n;
	TRISC=0x00;
	PORTC=0x00;
	TRISB&=0xf8;
	ANSELH=0x00;
	en=0;
	write_com(0x38);
	write_com(0x0c);
	write_com(0x06);
	write_com(0x01);
	write_com(0xc0);
	
}


void I2C_Delay(void)
{
	unsigned int i,j;
	for(i=4;i>0;i--)
	{
		for(j=8;j>0;j--);
    	//for(j=125;j>0;j--);
	}
}

/***********
 函数:I2C_Init()
 功能:I2C 总线初始化,使总线处于空闲状态
 说明:在main()函数的开始处,通常应当要执行一次本函数
************/
void I2C_Init(void)
{
 //I2CCONbits.I2CEN = 0; 	//关掉I2C模块功能
 //TRISG = 0x0000;		//初始化SCL和SDA引脚
 //LATG  = 0x0000;
 //PORTG = 0x0000;
 SCLO;
 SDAO;
 I2C_SDA = 1; 
 I2C_SCL = 1;
 I2C_Delay(); 
}
/******************
启动总线函数
函数:I2C_Start()
功能:产生I2C 总线的起始状态
说明:
SCL处于高电平期间,当SDA 出现下降沿时启动I2C 总线
不论SDA 和SCL 处于什么电平状态,本函数总能正确产生起始状态
本函数也可以用来产生重复起始状态
本函数执行后,I2C 总线处于忙状态
*******************/
void I2C_Start()
{
    I2C_SDA = 1;	//发送启始条件的数据信号
    Nop();
    I2C_SCL = 1;
    Nop();
    I2C_SDA = 0;	//发送起始信号
    Nop();
    I2C_SCL = 0;	//钳住I2C总线,准备发送数据或接收数据
    Nop();
}
/********************
函数:I2C_Stop()
功能:产生I2C 总线的停止状态
说明:
SCL处于高电平期间,当SDA 出现上升沿时停止I2C 总线
不论SDA 和SCL 处于什么电平状态,本函数总能正确产生停止状态
本函数执行后,I2C 总线处于空闲状态
*******************/
void I2C_Stop()
{
    I2C_SDA = 0;
    Nop();
    I2C_SCL = 1;
    Nop();
    I2C_SDA = 1;
    Nop();
    Nop();//在下一次产生Start 之前,要加一定的延时
}
/***************
函数:I2C_Write()
功能:向I2C 总线写1 个字节的数据
参数:
dat:要写到总线上的数据
***************/
void I2C_Write(char dat)
{
    unsigned char bit_count;
	I2C_SCL = 0; 		 
     for(bit_count=0;bit_count<8;bit_count++) 
     { 
         if((dat<<bit_count) & 0x80) 
         {
             I2C_SDA = 1;
         } 
         else 
         {
             I2C_SDA = 0;
         } 
	     Nop();
         I2C_SCL = 1; 
	     Nop();
         I2C_SCL = 0; 	
    } 
    Nop();
 }
/******************
函数:I2C_Read()
功能:从从机读取1 个字节的数据
返回:读取的一个字节数据
**************************/
unsigned char  I2C_Read()
{
	unsigned char  Rdat=0;
	unsigned char i = 8;
	SDAI;
	for (i=0; i<8; i++)
	{
	    I2C_SCL = 1;
	    Nop();
        Rdat <<= 1;
	    if (I2C_SDA==1) 
	        Rdat |= 0x01;
	    Nop();
	    I2C_SCL = 0;
	    Nop();
	} 
	SDAO;
	return (Rdat);
}
/*************
函数:I2C_GetAck()
功能:读取从机应答位
返回:
0:从机应答
1:从机非应答
说明:
从机在收到每个字节的数据后,要产生应答位
从机在收到最后1 个字节的数据后,一般要产生非应答位
*************/
unsigned char I2C_GetAck()
{
    unsigned char ack;
    SDAI;
    Nop();
    I2C_SCL = 1;
    ack = I2C_SDA;
    Nop();
    I2C_SCL = 0;
    Nop();
    SDAO;
    return ack;
}
/*******************
函数:I2C_PutAck()
功能:主机产生应答位或非应答位
参数:
ack=0:主机产生应答位
ack=1:主机产生非应答位
说明:
主机在接收完每一个字节的数据后,都应当产生应答位
主机在接收完最后一个字节的数据后,应当产生非应答位
*********************/
void I2C_PutAck(unsigned char ack)
{
	SDAO;
	I2C_SDA = ack;
	Nop();
	I2C_SCL = 1;
	Nop();
	I2C_SCL = 0;
	Nop();
}

/**************************
函数:I2C_Puts()
功能:I2C 总线综合发送函数,向从机发送多个字节的数据
参数:
SlaveAddr:从机地址(7 位纯地址,不含读写位)
SubAddr:从机的子地址
SubMod:子地址模式,0-无子地址,1-单字节子地址,2-双字节子地址
*dat:要发送的数据
Size:数据的字节数
返回:
0:发送成功
1:在发送过程中出现异常
说明:
本函数能够很好地适应所有常见的I2C 器件,不论其是否有子地址
当从机没有子地址时,参数SubAddr 任意,而SubMod 应当为0
*****************************/
unsigned char I2C_Puts(    unsigned char SlaveAddr,    unsigned int SubAddr,
                           unsigned char SubMod,       unsigned char *dat,   unsigned char Size
                      )
{
    //定义临时变量
    unsigned char i;
    unsigned char a[3];
    //检查长度
    if ( Size == 0 ) return 0;
    //准备从机地址
    a[0] = (SlaveAddr);
    //检查子地址模式
    if ( SubMod > 2 ) 
        SubMod = 2;
    //确定子地址
    switch ( SubMod )
    {
        case 1:
                 a[1] = SubAddr;
                 break;
        case 2:
                 a[1] = SubAddr >> 8;
                 a[2] = SubAddr;
                 break;
    }
    //发送从机地址,接着发送子地址(如果有子地址的话)
    SubMod++;
    I2C_Start();
    I2C_Delay();
    for ( i=0; i<SubMod; i++ )
    {
        I2C_Write(a[i]);
        while( I2C_GetAck() )
        {
	        I2C_Stop();
	        return 0;
        }
    }
    //发送数据
    while (Size-- != 0 )
    {
        I2C_Write(*dat++);
        if ( I2C_GetAck() ) 
        {
            I2C_Stop();
            return 0;
        }
    }
    //发送完毕,停止I2C 总线,并返回结果
    I2C_Stop();
    return 1;
   
}
/*

函数:I2C_Gets()
功能:I2C总线综合接收函数,从从机接收多个字节的数据
参数:
	SlaveAddr:从机地址(7位纯地址,不含读写位)
	SubAddr:从机的子地址
	SubMod:子地址模式,0-无子地址,1-单字节子地址,2-双字节子地址
	*dat:保存接收到的数据
	Size:数据的字节数
返回:
	0:接收成功
	1:在接收过程中出现异常
说明:
	本函数能够很好地适应所有常见的I2C器件,不论其是否有子地址
	当从机没有子地址时,参数SubAddr任意,而SubMod应当为0
*/
unsigned char I2C_Gets ( unsigned char SlaveAddr, unsigned int SubAddr,
	                     unsigned char SubMod,	char *dat,	unsigned char Size
                       )
{
    //定义临时变量
	unsigned char i;//,j;
	char a[3];
    //检查长度
	if ( Size == 0 ) 
	    return 0;
    //准备从机地址
	a[0] = SlaveAddr;
    //检查子地址模式
	if ( SubMod > 2 ) 
	    SubMod = 2;
	//确定子地址
	switch ( SubMod )
	{
		case 1:
	            a[1] = (char)(SubAddr);
	            break;
	    case 2:
	            a[1] = (char)(SubAddr >> 8);
	            a[2] = (char)(SubAddr);
	            break;
	}
	//发送从机地址,接着发送子地址
	SubMod++;
	I2C_Start();
	I2C_Delay();
	for ( i=0; i<SubMod; i++ )
	{
		I2C_Write(a[i]);
		if ( I2C_GetAck() )
		{
			I2C_Stop();
			return 0;
		}
	}
	I2C_Delay();
    //这里的I2C_Start()对于有子地址的从机是重复起始状态
    //对于无子地址的从机则是正常的起始状态
	I2C_Start();
    //发送从机地址
	I2C_Write(a[0]+1);
	if ( I2C_GetAck() )
	{
		I2C_Stop();
		return 0;
	}
    //接收数据
	while(1)
	{
		*dat= I2C_Read();
		dat++;
		if ( --Size == 0 )
		{
			I2C_PutAck(1);
			break;
		}
		I2C_PutAck(0);
	}
    //接收完毕,停止I2C总线,并返回结果
	I2C_Stop();
	return 1;
}

void tmr1_init()//定时器1初始化
{
	GIE=1;
	PEIE=1;
	TMR1IE=1;
	TMR1IF=0;
	T1CON=0x30;
	TMR1L=0xd5;//定时0.5s
	TMR1H=0x0b;
	TMR1ON=1;
	
}

void interrupt tmr1()
{
	if(TMR1IF==1)
	{
		TMR1L=0xd5;
		TMR1H=0x0b;
		TMR1IF=0;
		flag=1;
	}
	if(ADIF==1)
	{
		ADIF=0;
	}
}

void disp_temp(uchar location,uchar add)
{
	uchar th,tl,b,s,g,x1,x2,x3;
	uint xx;
	uint wd=0x0000;

		wd|=tab[0];
		wd=wd<<8;
		wd|=tab[1];
		write_com(location);
		if(add==0x02)
		{
			write_dat(0x02+0x60);
		}
		else if(add==0x04)
		{
			write_dat(0x03+0x60);
		}
		else if(add==0x00)
		{
			write_dat(0x01+0x60);
		}
		write_dat(0x3a);
		if(wd&0x8000)
		{
			write_dat(0x2d);
			wd=~wd;
		}
		else
		{
			write_dat(0x2b);
		}
		wd=wd<<1;
		wd=wd>>6;
		xx=(uint)((wd*10)/8);
		b=(uchar)(xx/1000);
		s=(uchar)((xx-b*1000)/100);
		g=(uchar)((xx-b*1000-s*100)/10);
		x1=(uchar)(xx%10);
		write_dat(b+0x30);
		write_dat(s+0x30);
		write_dat(g+0x30);
		write_dat(0x2e);
		write_dat(x1+0x30);

}

void main()
{
	tmr1_init();
	lm75_io_init();
	lcd_init();
	ad_init();
	while(1)
	{
		if(flag==1)
		{
			flag=0;
			temp1=ADRESH;
			sum=num_change(temp1);
			GODONE=1;
			I2C_Gets(0x90,0x00,1,tab,2);
 			NOP();
			disp_temp(0x80,0x00);
			delay(1);
			I2C_Gets(0x92,0x00,1,tab,2);
 			NOP();
			disp_temp(0x88,0x02);
			delay(1);
			I2C_Gets(0x94,0x00,1,tab,2);
			NOP();
			disp_temp(0xc0,0x04);
			NOP();
			write_m(sum,0xc9);
		}
		
	}
	
}

⌨️ 快捷键说明

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