用的c8051f340,读ds18b20,然后用串口发送数据在串口调试软件上显示,显示的数字一直就是10,各位帮忙看看程序哪里有问题啊?系统时钟是内部晶振,48M系统时钟。#include <c8051F340.h>
#include <stdio.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define SYSCLK 48000000 // SYSCLK frequency in Hz
#define BAUDRATE0 9600 // Baud rate of UART0 in bps
#define BAUDRATE1 9600 // Baud rate of UART1 in bps
sfr16 SBRL1 = 0xB4;
sbit ds=P2^2;
uchar flag ;
uint temp;
float wendu;
bit UART = 0;
void SYSCLK_Init (void)
{
unsigned int iTmp;
OSCICN |= 0x83;
//Enable internal 4X MULL
if( !( CLKMUL & ( 1<<5 ) ) )
{
CLKMUL = 0;
CLKMUL = 0x00;
CLKMUL |= ( 1<<7 );
for( iTmp = 0; iTmp < 200; iTmp ++ );
CLKMUL |= ( 1<<6 ) | ( 1<<7 );
for( iTmp = 0; iTmp < 2000; iTmp ++ );
while( !( CLKMUL & ( 1<<5 ) ) );
}
//USB clock: 48MHz, system clock : 48MHz
CLKSEL = 0x03;
}
void delayus(int a)
{
int y ;
for(;a>0;a--)
{
for(y=0;y<5;y++);
}
}
void delayms(int a)
{
int y ;
for(;a>0;a--)
{
for(y=0;y<4800;y++);
}
}
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits are zeros
// clear RI0 and TI0 bits
if (SYSCLK/BAUDRATE0/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE0/2);
CKCON &= ~0x0B; // T1M = 1; SCA1:0 = xx
CKCON |= 0x08;
} else if (SYSCLK/BAUDRATE0/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE0/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x09;
} else if (SYSCLK/BAUDRATE0/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE0/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE0/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
}
TL1 = TH1; // init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
TI0 = 1; // Indicate TX0 ready
}
void ds_rst() //初始化DS18B20
{
ds=1; // 数据线置1
delayus(1); //延时1us
ds=0; //数据线置0
delayus(700); //延时700us
ds=1; //数据线置1
delayus(44); // 延时44us
if(ds==0) //判断DS18B20的返回的低电平
flag=1;
else
flag=0;
delayus(140);
ds=1;
}
bit ds_read_bit(void)//读一位
{
bit dat;
ds=0;//单片机(微处理器)将总线拉低
delayus(1);//读时隙起始于微处理器将总线拉低至少1us
ds=1;//拉低总线后接着释放总线,让从机18b20能够接管总线,输出有效数据
delayus(2);//小延时一下,读取18b20上的数据 ,因为从ds18b20上输出的数据
//在读"时间隙"下降沿出现15us内有效
dat=ds;//主机读从机18b20输出的数据,这些数据在读时隙的下降沿出现//15us内有效
delayus(77);//所有读"时间隙"必须60~120us,这里77us
return(dat);//返回有效数据
}
uchar ds_read_byte(void ) //读一字节
{
uchar value,i,j;
value=0;//一定别忘了给初值
for(i=0;i<8;i++)
{
j=ds_read_bit();
value=(j<<7)|(value>>1);//这一步的说明在一个word文档里面
}
return(value);//返回一个字节的数据
}
void ds_write_byte(uchar dat) //写一个字节
{
uchar i;
bit onebit;//一定不要忘了,onebit是一位
for(i=1;i<=8;i++)
{
onebit=dat&0x01;
dat=dat>>1;
if(onebit)//写 1
{
ds=0;
delayus(1);
delayus(1);//看时序图,至少延时1us,才产生写"时间隙"
ds=1;//写时间隙开始后的15μs内允许数据线拉到高电平
delayus(60);//所有写时间隙必须最少持续60us
}
else//写 0
{
ds=0;
delayus(63);//主机要生成一个写0 时间隙,必须把数据线拉到低电平并保持至少60μs,这里64us
ds=1;
_nop_();
_nop_();
}
}
}
void tem_change()
{
ds_rst();
delayms(2);//约2ms
ds_write_byte(0xcc);
ds_write_byte(0x44);
delayms(750);
}
uint get_temperature()
{
uchar a,b;
ds_rst();
delayms(2);//约2ms
ds_write_byte(0xcc);
ds_write_byte(0xbe);
a=ds_read_byte();
b=ds_read_byte();
temp=b;
temp<<=8;
temp=temp|a;
wendu=temp*0.0625;
temp=wendu*10+0.5;
wendu=wendu+0.5;
return temp;
}
void main()
{
char input_char;
PCA0MD &= ~0x40;
SYSCLK_Init ();
XBR0 = 0x01;
XBR1 = 0x40;
P0MDOUT |= 0x11;
P2MDOUT |= 0x04;
UART0_Init ();
while(1)
{
tem_change();//12位转换时间最大为750ms
get_temperature();
input_char = getchar();
switch (input_char) {
case '1':
printf ("%x\n",&wendu);
break;
default:
break;
}
}
}
char putchar (char c) {
if (UART == 0) {
if (c == '\n') { // check for newline character
while (!TI0); // wait until UART0 is ready to transmit
TI0 = 0; // clear interrupt flag
SBUF0 = 0x0d; // output carriage return command
}
while (!TI0); // wait until UART0 is ready to transmit
TI0 = 0; // clear interrupt flag
return (SBUF0 = c); // output <c> using UART 0
}
else if (UART == 1) {
if (c == '\n') { // check for newline character
while (!(SCON1 & 0x02)); // wait until UART1 is ready to transmit
SCON1 &= ~0x02; // clear TI1 interrupt flag
SBUF1 = 0x0d; // output carriage return
}
while (!(SCON1 & 0x02)); // wait until UART1 is ready to transmit
SCON1 &= ~0x02; // clear TI1 interrupt flag
return (SBUF1 = c); // output <c> using UART 1
}
}
//-----------------------------------------------------------------------------
// _getkey
//-----------------------------------------------------------------------------
//
// Return Value : byte received from UART0/1
// Parameters : none
// This is an overloaded fuction found in the stdio library. When the
// function _getkey is called, either by user code or through calls to stdio
// routines such as scanf, the following routine will be executed instead
// of the function located in the stdio library.
//
// The function checks the UART global variable to determine which UART to
// use to receive a character.
//
// The routine waits for RI0/RI1 to be set, indicating that a byte has
// been received across the UART0/UART1 RX line. The routine saves the
// received character into a local variable, clears the RI0/RI1 interrupt
// flag, and returns the received character value.
//
//-----------------------------------------------------------------------------
char _getkey () {
char c;
if (UART == 0) {
while (!RI0); // wait until UART0 receives a character
c = SBUF0; // save character to local variable
RI0 = 0; // clear UART0 receive interrupt flag
return (c); // return value received through UART0
}
else if (UART == 1) {
while (!(SCON1 & 0x01)); // wait until UART1 receives a character
c = SBUF1; // save character to local variable
SCON1 &= ~0x01; // clear UART1 receive interrupt flag
return (c); // return value received through UART1
}
}
|