PIC16F C语言测频率程序,【原创】PIC16F887操作DS18B20 C语言完整代码

这两天在给老师做课题,其中用到DS18B20,因为使用的是PIC16F887单片机,所以操作上要对端口方向做好处理,这里到还好,重要的是我的DS18B20是接的RE0端口,所以,麻烦的事来了,初学者一般不知道RE0默认是AN通道,这把我折腾了整整3天,我一直在调时序,白白浪费我3天时间啊....希望有缘的初学者能看到这篇文章,代码很清晰,比开发板例程易读不知多少倍!(但介于本人初学,对内存的考虑不是很周全,可能占用的RAM跟ROM比例程稍多,不过没什么关系,编译出来内存还空着啦!)

#include

__CONFIG(0x3F31);

#define DQ RE0

#define DQ_HIGH() TRISE0=1

#define DQ_LOW() TRISE0=0;DQ=0

#define E RB0

#define RW RB1

#define RS RB2

#define uchar unsigned char

#define uint unsigned int

#define delay_1us() asm("nop")

#define delay_10us()

asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop")

const uchar

nember[]={'0','1','2','3','4','5','6','7','8','9','-'};//显示采集温度数值数组

void delay(uint x)

{

uint a,b;

for(a=x;a>0;a--)

for(b=110;b>0;b--);

}

void write_com(uchar com)

{

RS=0;//命令选择端开

PORTD=com;

delay(2);//延时

E=1;//使能端送

delay(2);//延时

E=0;

}

void write_data(uchar date)

{

RS=1;//命令选择端开

PORTD=date;

delay(2);//延时

E=1;//使能端送高

delay(2);//延时

E=0;

}

void delay_100us()//9个delay_10us();与2个delay_1us();

{

delay_10us();delay_10us();delay_10us();

delay_10us();delay_10us();delay_10us();

delay_10us();delay_10us();delay_10us();

NOP(); NOP(); NOP(); NOP(); NOP();

}

void display_error(uchar

add) //显示没有检测到DS18B20

{

uchar i=0;

uchar Error[]="Error";

write_com(add);

while(Error[i]!='\0')

{

write_data(Error[i]);

i++;

delay(10);

}

}

void display_dot(uchar

add) //显示温度的小数点

{

write_com(add);

write_data('.');

}

void init_ds18b20()

{

uchar st=1;

DQ_HIGH();//选为输入时,有上拉电阻拉高

NOP();NOP();

while(st)

{

DQ_LOW();

delay_100us();delay_100us();delay_100us();delay_100us();//>=750us

delay_100us();delay_100us();delay_100us();delay_100us();

DQ_HIGH();

delay_10us();delay_10us();delay_10us();delay_10us();//70us

delay_10us();delay_10us();delay_10us();

st=DQ;

if(st==1)

{ display_error(0x80+11);

delay(2);

break; }

delay_100us();delay_100us();delay_100us();

delay_100us();delay_100us();//480us以上

}

}

void write_byte(uchar

date) //向DS18B20写入一个字节数据

{ uchar i,temp;

DQ_HIGH();

NOP();NOP();

for(i=8;i>0;i--)

{ temp=date&0x01; //0000

0001

DQ_LOW();

delay_10us();delay_10us(); //20us

if(temp==1)

DQ_HIGH();

//发“1”

delay_10us();delay_10us();

delay_10us();delay_10us();

NOP();NOP();NOP();NOP();NOP(); //45us以上

DQ_HIGH();

date=date>>1; //右移1位 }

}

uchar

read_byte() //从DS18B20读取一个字节数据

{ uchar i,date;

static bit j;

for(i=8;i>0;i--)

{

date=date>>1;

DQ_HIGH();

NOP();NOP();

DQ_LOW();

NOP();NOP();NOP();

NOP();NOP();NOP();

DQ_HIGH();

NOP();NOP();

NOP();NOP();

j=DQ;

if(j==1)

date=date|0x80; //1000 0000

delay_10us();delay_10us();delay_10us(); //30us }

return (date);

}

void init()

{

//端口方向初始化

TRISD=0;

TRISB=0;

TRISA=0;

PORTA=0;

TRISE=0;

PORTE=0;

ADCON1=0x8d;//RE全为I/O

//1602init

RS=0;

RW=0;

write_com(0x38);//打开显示模式

write_com(0x0c);//光标显示并闪烁

write_com(0x06);//读写指针、光标加,整屏不移动 write_com(0x01);//清屏

write_com(0x80);//数组指针显示

}

void main() //做好读温度的准备

{

float temp;

int temper1; int temp1,temp2;

uchar a1,a2,a3,a4,a5;

init();

while(1)

{

init_ds18b20(); //初始化DS18B20,读取应答信号

write_byte(0xcc); //

跳过读序列号的操作

write_byte(0x44); //

启动温度转换

delay(780); //750ms

delay_100us();

init_ds18b20();

write_byte(0xcc);

write_byte(0xbe); //读取温度寄存器,前两个分别是温度的低位和高位

temp1=read_byte();

temp2=read_byte();

delay(10);

temper1=(temp2<<8|temp1);

if((temper1&0xf000)==0) //高字节前5位为0表明为正温度

{

temper1*=62.5;

}

else //为负温度时,读回会数据需取反加1

{ temper1=(~temper1)+1;

temper1*=62.5;

write_com(0x80+8);

write_data(nember[10]);//显示负号

}

a1=temper1/10000;

a2=temper1000/1000;

a3=temper100/100;

a4=temper10/10;

a5=temper1;//

write_com(0x80+9);

write_data(nember[a1]);

write_data(nember[a2]);

display_dot(0x80+11);

write_com(0x80+12);

write_data(nember[a3]);

write_data(nember[a4]);

write_data(nember[a5]);

}

}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值