📄 main2.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 + -