求助:stc15w408使用AHT10测量温度 | 已解决
本人一个AHT10湿度 测量程序,使用IIC,在89C52测试正常,移植到STC15w408后,测量不出数值,读取的值均为0xFF。
但用STC15w408测试SHT30时正常,也是IIC方式。
请高人指点。
下面是测量代码:
#include <intrins.h>
#include "stc15.h"
#include "aht10.h"
#include <stdio.h>
sbit SCL = P1^0;
sbit SDA = P1^1;
//声明ACKflag 为字节变量
/*I2C通信初始化*/
void I2C_Start() //起始信号
{
SCL = 1;
SDA = 1;
delay5us();
SDA = 0;
delay5us();
}
void I2C_Stop() //停止信号
{
SCL = 0;
SDA = 0;
SCL = 1;
delay5us();
SDA = 1;
delay5us();
}
/*I2C应答和非应答*/
//I2C主机读从机应答
bit ReadACK()
{
SCL = 0;
SCL = 1;
delay5us();
if(SDA)//非应答
{
SCL = 0;
return (0);
}
else//应答
{
SCL = 0;
return(1);
}
}
//I2C主机发送应答
void sendACK(bit i)
{
SCL = 0;
if(i)
SDA = 1;
else
SDA = 0;
SCL = 1;
delay5us();
SCL = 0;
SDA = 1;//释放数据总线
}
uchar I2cReadByte()
{
uchar j,DAT;
for(j = 0;j<8;j++)
{
DAT <<=1;
SCL = 0;
SCL = 1;
if(SDA)
DAT |= 0X01;
}
return (DAT);
delay5us();
}
void I2CSendByte(uchar DAT) //发送一个字节
{
uchar i;
for(i = 0;i < 8; i++)
{
SCL = 0; //拉低时钟线才能允许数据变化
if(DAT & 0X80)
SDA = 1;
else
SDA = 0;
SCL = 1;
DAT <<= 1;
}
SCL = 0;
SDA = 1;//释放数据总线
}
/*1.延时40ms函数2.延时5微秒函数*/
void delayms()
{unsigned char i, j, k;
_nop_();
_nop_();
i = 1;
j = 26;
k = 223;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void delay5us()
{ unsigned char i;
_nop_();
i = 11;
while (--i);
}
//*******************************
uchar JH_Read_Status(void) //读取AHT10的状态寄存器
{
uchar Byte_first;
I2C_Start();
I2CSendByte(0x71);
if (!ReadACK()) { //检测应答
return 0;
}
Byte_first = I2cReadByte();
sendACK(1);//此处为回复NOACK,意思为停止读操作
I2C_Stop();
return Byte_first;
}
uchar JH_Read_Cal_Enable(void)//查询cal enable位有没有使能?
{
uchar val = 0;//ret = 0,
val = JH_Read_Status();
if ((val & 0x68) == 0x08)//判断NOR模式和校准输出是否有效
return 1;
else
return 0;
}
void JH_SendAC(void) //向AHT10发送AC命令
{
I2C_Start();
I2CSendByte(0x70);
if (!ReadACK()) { //检测应答
return;
}
I2CSendByte(0xac);
if (!ReadACK()) { //检测应答
return;
}
I2CSendByte(0x33);
if (!ReadACK()) { //检测应答
return;
}
I2CSendByte(0x00);
sendACK(0);
I2C_Stop();
}
void JH_Send_BA(void) //向AHT10发送BA命令
{
I2C_Start();
I2CSendByte(0x70);
if (!ReadACK()) { //检测应答
return;
}
I2CSendByte(0xba);
if (!ReadACK()) { //检测应答
return;
}
I2C_Stop();
}
uchar JH_Init(void) //初始化AHT10
{
JH_Send_BA();
delayms();
I2C_Start();
I2CSendByte(0x70);
if (!ReadACK()) { //检测应答
return 0;
}
I2CSendByte(0xe1); //写系统配置寄存器
if (!ReadACK()) { //检测应答
return 0;
}
I2CSendByte(0x08);
if (!ReadACK()) { //检测应答
return 0;
}
I2CSendByte(0x00);
if (!ReadACK()) { //检测应答
return 0;
}
I2C_Stop();
while (JH_Read_Cal_Enable() == 0)//需要等待状态字status的Bit=1时才去读数据。如果Bit不等于1 ,发软件复位0xBA给AHT10,再重新初始化AHT10,直至Bit=1
{
delayms();
JH_Send_BA();//复位
//os_delay_us(10000);
delayms();
I2C_Start();
I2CSendByte(0x70);
if (!ReadACK()) {//检测应答
return 0;
}
I2CSendByte(0xe1);//写系统配置寄存器
if (!ReadACK()) {//检测应答
return 0;
}
I2CSendByte(0x08);
if (!ReadACK()) {//检测应答
return 0;
}
I2CSendByte(0x00);
if (!ReadACK()) {//检测应答
return 0;
}
I2C_Stop();
delayms();
}
return 1;
}
void JH_Read_CTdata(unsigned int *Temp,unsigned int*Hum) //读取AHT10的温度和湿度数据
{
volatile uchar Byte_1th = 0;
volatile uchar Byte_2th = 0;
volatile uchar Byte_3th = 0;
volatile uchar Byte_4th = 0;
volatile uchar Byte_5th = 0;
volatile uchar Byte_6th = 0;
u32 RetuData = 0;
int cnt = 0;
delayms();
JH_SendAC();
delayms();
delayms();
while (((JH_Read_Status()&0x80)==0x80)) //等待忙状态结束
{
}
I2C_Start();
I2CSendByte(0x71); //0x70+1 0x70为设备地址 1为方向位
if (!ReadACK()) { //检测应答
return;
}
Byte_1th = I2cReadByte(); //状态字
sendACK(0);
Byte_2th = I2cReadByte(); //湿度字节
sendACK(0);
Byte_3th = I2cReadByte(); //湿度字节
sendACK(0);
Byte_4th = I2cReadByte(); //高4位为湿度低4位为温度
sendACK(0);
Byte_5th = I2cReadByte(); //温度字节
sendACK(0);
Byte_6th = I2cReadByte(); //温度字节
sendACK(1);//此处为回复NOACK,意思为停止读操作
I2C_Stop();
RetuData = (RetuData | Byte_2th) << 8;
RetuData = (RetuData | Byte_3th) << 8;
RetuData = (RetuData | Byte_4th);
RetuData = RetuData >> 4;
*Hum =(RetuData*1000/1024/1024);
RetuData = 0;
RetuData = (RetuData | Byte_4th) << 8;
RetuData = (RetuData | Byte_5th) << 8;
RetuData = (RetuData | Byte_6th);
RetuData = RetuData & 0xfffff;
*Temp = (RetuData*2000/1024/1024 - 500);
}
只是建议:
1,SCL/SDA, 外部要有 10K上拉电阻
2,STC15系列同频比STC89C52RC快很多,加12倍的延时 谢谢,经调整,是IIC的问题,不知什么原因。换了一套模拟IIC正常了,见下面,有兴趣的高手分析一下。:
void I2C_Start() //起始信号
{
SDA = 1; //拼接其他块,确保默认是1
SCL = 1;
SDA = 0; //时序上先拉低
SCL = 0;
}
void I2C_Stop() //停止信号
{
SDA = 0; //确保默认0,保证由低电平拉高至高电平
SCL = 1;
SDA = 1;
}
/*I2C应答和非应答*/
//I2C主机读从机应答
bit ReadACK()
{
SDA = 1;
SCL = 1;
if(SDA)//非应答
{
SCL = 0;
return (0);
}
else//应答
{
SCL = 0;
return(1);
}
}
//I2C主机发送应答
void sendACK(bit i)
{
if(i)
SDA = 1;
else
SDA = 0;
SCL = 1;
SCL = 0;
}
uchar I2cReadByte()
{unsigned char i,Byte=0x00;
SDA = 1; //接收之前,先把I2C_SDA置1,释放总线
for(i=0;i<8;i++)
{
SCL = 1; //拉高SCL,SCL读取SDA
if(SDA == 1){Byte |= (0x80>>i);}
/*如果读取到的SDA为1,把Byte最高位置1,如果读取到的SDA为0,不处理,默认最高位为0,放在循环里从高位到低位依次读取*/
SCL = 0; //拉低SCL,结束当前循环
}
return Byte;
}
void I2CSendByte(uchar Byte) //发送一个字节
{
unsigned char i;
// I2C_SCL = 0; //起始信号已经拉低了,无需重复
for (i = 0; i < 8; i ++)
{
SDA = Byte & (0x80>>i); //把Byte最高位取出,赋值给I2C_SDA,依次从高到底
SCL = 1;
// _nop_();_nop_();_nop_();_nop_();_nop_();//需要0.4us
SCL = 0;
}
} 为什么我读出来的温湿度一直都不变是怎么回事啊 硬件 I2C快,软件 I2C 慢,一定要加10K上拉电阻,这样速度才能上去
页:
[1]