问题描述:用STC12C5A60S2(LCD1602显示)单独测温度(DS18B20)OK;用STC12C5A60S2(LCD1602显示)测电压OK;但是,当用STC12C5A60S2同时测温度(DS18B20)和电压时电压显示会出现错误。
图片传不上去,本人大致说一下,单独显示温度和电压都正常,同时测量温度和电压时温度显示正常,电压显示不正常(烧录后第一次正常,后来变为0.0/)。显示温度和电压输入的引脚并没有复用,不知为什么电压值读不出来。
主要部分代码:
图片传不上去,本人大致说一下,单独显示温度和电压都正常,同时测量温度和电压时温度显示正常,电压显示不正常(烧录后第一次正常,后来变为0.0/)。显示温度和电压输入的引脚并没有复用,不知为什么电压值读不出来。
主要部分代码:
#include <STC12C5A60S2.H>
#include "temp.h"
#include "uart.h"
#include "lcd1602.h"
#include "adc_12c5a.h"
sbit RS485E=P2^0; //定义485的使能脚
#define uchar unsigned char
#define uint unsigned int
uchar code Text[10]={"0","1","2","3","4","5","6","7","8","9"};//十进制数组
uchar code Text1[]={" "};//空格
uchar code Text2[]={"."};////小数点
//用来存放要显示的8位数的值
int SendData,volt;
uchar symbol;
//--声明全局函数--//
void Lcd_ReadTemp(int);
void Display();
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
uchar u1,u2,u3;
UsartConfiguration();
AD_init();
lcd_config();
while(1)
{
Lcd_ReadTemp(ReadTemp());
volt=AD_work(7)*100+0.5;//转化为三位整数
Display();
}
}
/*******************************************************************************
* 函 数 名 : ReadTemp()
* 函数功能 : 读取温度
* 输 入 : v
* 输 出 : 无
*******************************************************************************/
void Lcd_ReadTemp(int temp)
{
float tp;
if(temp< 0) //当温度值为负数
{
symbol=1;
temp=temp-1;//原因是读取的温度是实际温度的补码,所以减1,再取反求出原码
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;
}
else
{
tp=temp;//原因是数据处理有小数点所以将温度赋给一个浮点型变量
//假如温度是正的那么,那么正数的原码就是补码它本身
temp=tp*0.0625*100+0.5;
}
SendData=temp % 10000 / 10;
}
/*******************************************************************************
* 函 数 名 : Display()
* 函数功能 : LCD显示温度、电压
* 输 入 : v
* 输 出 : 无
*******************************************************************************/
void Display()
{
lcd_writecom(0x80);//写入地址位置,0x80第一行,0xc0第二行
lcdwritedat("T");//TEMP
lcdwritedat("E");
lcdwritedat("M");
lcdwritedat("P");
lcdwritedat(":");
if(symbol)
lcdwritedat("-");
if((SendData / 100)>0)
lcdwritedat("0"+SendData / 100);
lcdwritedat("0"+SendData % 100 /10);
lcdwritedat(".");
lcdwritedat("0"+SendData % 10);
lcdwritedat(0xdf);
lcdwritedat(0x43);
lcd_writecom(0xc0);//写入地址位置,0x80第一行,0xc0第二行
lcdwritedat("V");//VOLT
lcdwritedat("O");
lcdwritedat("L");
lcdwritedat("T");
lcdwritedat(":");
lcdwritedat("0"+ volt / 100);
lcdwritedat(".");
lcdwritedat("0"+ volt % 100 /10);
lcdwritedat("0"+ volt % 10);
lcdwritedat("V");
}
/*adc_12c5a.c文件*/
//****************************************STC12C5A60S2 AD转换***********************************************//
#include "adc_12c5a.h"
/*获取AD转换值*/
uint AD_get(uchar channel)
{
ADC_CONTR=0x88|channel; //开启AD转换1000 1000 即POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0
_nop_(); _nop_(); _nop_(); _nop_();//要经过4个CPU时钟的延时,其值才能够保证被设置进ADC_CONTR 寄存器
while(!(ADC_CONTR&0x10)); //等待转换完成
// ADC_CONTR&=0xe7; //关闭AD转换,ADC_FLAG位由软件清0
ADC_CONTR&=~0x10;
return(ADC_RES*4+ADC_RESL); //返回AD转换完成的10位数据(16进制)
}
/*进行AD转换*/
float AD_work(uchar channel)
{
float AD_val; //定义处理后的数值AD_val为浮点数
uchar i;
for(i=0;i<100;i++)
AD_val+=AD_get(channel); //转换100次求平均值(提高精度)
AD_val/=100;
AD_val=(AD_val*4.86)/1024; //AD的参考电压是单片机上的4.86v,所以乘4.86即为实际电压值
return AD_val;
}
/*延时函数*/
void delay_1ms(uint a) //延时约1ms
{
uint i;
while (a--)
for(i=600;i>0;i--); //1T单片机i=600,若是12T单片机i=125
}
/*AD转换配置*/
void AD_init()
{
P1ASF=0xff; //P1口全部作为模拟功能AD使用
ADC_RES=0; //清零转换结果寄存器高8位
ADC_RESL=0; //清零转换结果寄存器低2位
ADC_CONTR=0x80;//开启AD电源
delay_1ms(2); //等待1ms,让AD电源稳定
}
/*"temp.c"文件*/
//***********************************ds18b20测温度***************************************//
#include "temp.h"
void delay_18B20(uint i)
{
while(i--);
}
void Init_DS18B20(void)
{
uchar x=0;
DQ = 1; //DQ复位
delay_18B20(80); //稍做延时
DQ = 0; //单片机将DQ拉低
delay_18B20(800); //精确延时 大于 480us
DQ = 1; //拉高总线
delay_18B20(140);
x=DQ;
delay_18B20(200);
}
uchar ReadOneChar(void)
{
uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(40); //40
}
return(dat);
}
void WriteOneChar(uchar dat)
{
uchar i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay_18B20(50); //50
DQ = 1;
dat>>=1;
}
}
uint ReadTemp(void)
{
uchar a=0;
uchar b=0;
uint temp_value=0;
Init_DS18B20();
WriteOneChar(0xCC);
WriteOneChar(0x44);
delay_18B20(1000);
Init_DS18B20();
WriteOneChar(0xCC);
WriteOneChar(0xBE);
delay_18B20(1000);
a=ReadOneChar(); //读取温度值低位
b=ReadOneChar(); //读取温度值高位
temp_value = b<<8;
temp_value |= a;
return temp_value;
}
/*附上两个.h文件*/
#ifndef __LCD1602_H_
#define __LCD1602_H_
//--重定义关键词--//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
#define LCD_DAT P0
sbit LCD_EN=P2^7;
sbit LCD_WR=P2^5;
sbit LCD_RS=P2^6;
void lcd_writecom(uchar com);/*lcd1602写入指令*/
void lcdwritedat(uchar dat);/*lcd1602写入数据*/
void lcd_config();/*lcd1602配置初始化*/
#endif
#ifndef __ADC_12C5A_H_
#define __ADC_12C5A_H_
#include <STC12C5A60S2.H>
#include "intrins.h"
//--重定义关键词--//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
//--声明全局函数--//
void AD_init();
void delay_1ms(uint a);
float AD_work(uchar channel);
uint AD_get(uchar channel);
#endif
其中lcd1602的配置文件省略可以不用看,没什么问题。
ds18b20的数据输出接P3^7/WR,输入电压接的是P1^7/ADC7。是程序的问题还是引脚复用的冲突还是。?
请各位高手帮看看怎么回事,跪谢!
解决方案
100
个人经验:delay或sleep的时间加大再试试。