CodevisionAVR SHT11 只读温度或湿度
CodevisionAVR SHT11 Read just Temperature or Humidity
我尝试对 shtxx 库进行个性化设置,但此代码存在问题。
当我 运行 它 lcd 停留在“你好”但如果我评论 readHumi 或 readTemp 时,编程 运行s 没有问题。
就在两个都没有注释时,程序卡在第二个上,而第一个并不重要。
我已经测试了他们之间的延迟,尝试在一个空白处阅读所有我认为应该解决但没有解决的事情
#include <mega16.h>
#include <delay.h>
#include <stdio.h>
#include <alcd.h>
int temp,humi;
char buffer[16];
#define SCK PORTB.0
#define DATA PINB.1
#define DATAO PORTB.1
#define DATAD DDRB.1
void shtStart(void){
DATAD = 1; //set B1 Output
DATAO = 1; //set B1 High
SCK = 0; //set B0 Low
SCK = 1; //set B0 High
DATAO = 0; //set B1 Low
SCK = 0; //set B0 Low
SCK = 1; //set B0 High
DATAO = 1; //set B1 High
SCK = 0; //set B0 Low
}
char shtWrite(unsigned char Byte){
unsigned char in, err = 0;
DATAD = 1; //set B1 Output
delay_us(5);
for(in = 0b10000000; in > 0; in /= 2){
SCK = 0;
if(in & Byte) DATAO = 1; //send 1s
else DATAO = 0; //send 0s
SCK = 1;
}
SCK = 0;
DATAD = 0; //set B1 Input
SCK = 1;
err = DATA;
SCK = 0;
return(err);
}
unsigned char shtRead(unsigned char ack){
unsigned char in, val = 0;
DATAD = 0; //set B1 Input
delay_us(5);
for(in = 0b10000000; in > 0; in /= 2){
SCK = 1;
if (DATA) val = val | in; //save 1s
SCK = 0;
}
DATAD = 1; //set B1 Output
DATAO = !ack;
SCK = 1;
SCK = 0;
return(val);
}
int readTemp(){
long int ttmp;
unsigned char tlsb, tmsb;
shtStart();
shtWrite(0b00000011);
while(DATA);
tmsb = shtRead(1);
tlsb = shtRead(1);
ttmp = (((unsigned long) tmsb << 8) | (unsigned long) tlsb);
return (-40 + 0.01 * ttmp) * 10;
}
int readHumi(){
long int htmp;
unsigned char hlsb, hmsb;
shtStart();
shtWrite(0b00000101);
while(DATA);
hmsb = shtRead(1);
hlsb = shtRead(1);
htmp = (((unsigned long) hmsb << 8) | (unsigned long) hlsb);
return (-4 + (0.0405 * htmp) + (-2.8E-6 * (htmp * htmp))) * 10;
}
void main(void)
{
DDRA=(1<<DDA7) | (1<<DDA6) | (1<<DDA5) | (1<<DDA4) | (1<<DDA3) | (1<<DDA2) | (1<<DDA1) | (1<<DDA0);
PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (1<<DDB0);
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (1<<PORTB1) | (0<<PORTB0);
lcd_init(16);
lcd_puts("Hello");
while (1)
{
humi = readHumi();
temp = readTemp();
lcd_clear();
sprintf(buffer, "T= %d.%d" "\xdf" "C, ", temp / 10, temp % 10);
lcd_puts(buffer);
sprintf(buffer, "H= %d.%d", humi / 10, humi % 10);
lcd_puts(buffer);
delay_ms(500);
}
}
您始终可以在代码中添加更多 lcd_puts
以缩小程序暂停的区域。
当程序停止时,通常意味着某个地方发生了死循环。
因此,您必须密切注意所有循环。例如在 readHumi()
基本上只有三个循环:
for(in = 0b10000000; in > 0; in /= 2)
在 shtWrite
for(in = 0b10000000; in > 0; in /= 2)
在 shtRead
那些循环看起来不错,它们有一个退出条件,在 8 次迭代后总是满足。
但是你也有这样的循环:
while(DATA);
如果传感器不接受命令,则没有退出条件。可能这会暂停您的程序。
传感器不理解命令的原因可能是SCK上升沿和下降沿之间的时间太短。根据 datasheet(第 6 页),SCK 下降和上升之间的时间至少应为 100ns。
如果你是运行 10+MHz,那么序列
SCK = 0; //set B0 Low
SCK = 1; //set B0 High
可以产生小于100ns的脉冲
此外,DDR
的 SCK 引脚从未在您的代码中初始化。
通过在 readHumi 和 readTemp 函数末尾添加传感器重置解决了问题:
shtStart();
shtWrite(0x1e);
我尝试对 shtxx 库进行个性化设置,但此代码存在问题。
当我 运行 它 lcd 停留在“你好”但如果我评论 readHumi 或 readTemp 时,编程 运行s 没有问题。
就在两个都没有注释时,程序卡在第二个上,而第一个并不重要。
我已经测试了他们之间的延迟,尝试在一个空白处阅读所有我认为应该解决但没有解决的事情
#include <mega16.h>
#include <delay.h>
#include <stdio.h>
#include <alcd.h>
int temp,humi;
char buffer[16];
#define SCK PORTB.0
#define DATA PINB.1
#define DATAO PORTB.1
#define DATAD DDRB.1
void shtStart(void){
DATAD = 1; //set B1 Output
DATAO = 1; //set B1 High
SCK = 0; //set B0 Low
SCK = 1; //set B0 High
DATAO = 0; //set B1 Low
SCK = 0; //set B0 Low
SCK = 1; //set B0 High
DATAO = 1; //set B1 High
SCK = 0; //set B0 Low
}
char shtWrite(unsigned char Byte){
unsigned char in, err = 0;
DATAD = 1; //set B1 Output
delay_us(5);
for(in = 0b10000000; in > 0; in /= 2){
SCK = 0;
if(in & Byte) DATAO = 1; //send 1s
else DATAO = 0; //send 0s
SCK = 1;
}
SCK = 0;
DATAD = 0; //set B1 Input
SCK = 1;
err = DATA;
SCK = 0;
return(err);
}
unsigned char shtRead(unsigned char ack){
unsigned char in, val = 0;
DATAD = 0; //set B1 Input
delay_us(5);
for(in = 0b10000000; in > 0; in /= 2){
SCK = 1;
if (DATA) val = val | in; //save 1s
SCK = 0;
}
DATAD = 1; //set B1 Output
DATAO = !ack;
SCK = 1;
SCK = 0;
return(val);
}
int readTemp(){
long int ttmp;
unsigned char tlsb, tmsb;
shtStart();
shtWrite(0b00000011);
while(DATA);
tmsb = shtRead(1);
tlsb = shtRead(1);
ttmp = (((unsigned long) tmsb << 8) | (unsigned long) tlsb);
return (-40 + 0.01 * ttmp) * 10;
}
int readHumi(){
long int htmp;
unsigned char hlsb, hmsb;
shtStart();
shtWrite(0b00000101);
while(DATA);
hmsb = shtRead(1);
hlsb = shtRead(1);
htmp = (((unsigned long) hmsb << 8) | (unsigned long) hlsb);
return (-4 + (0.0405 * htmp) + (-2.8E-6 * (htmp * htmp))) * 10;
}
void main(void)
{
DDRA=(1<<DDA7) | (1<<DDA6) | (1<<DDA5) | (1<<DDA4) | (1<<DDA3) | (1<<DDA2) | (1<<DDA1) | (1<<DDA0);
PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (1<<DDB0);
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (1<<PORTB1) | (0<<PORTB0);
lcd_init(16);
lcd_puts("Hello");
while (1)
{
humi = readHumi();
temp = readTemp();
lcd_clear();
sprintf(buffer, "T= %d.%d" "\xdf" "C, ", temp / 10, temp % 10);
lcd_puts(buffer);
sprintf(buffer, "H= %d.%d", humi / 10, humi % 10);
lcd_puts(buffer);
delay_ms(500);
}
}
您始终可以在代码中添加更多 lcd_puts
以缩小程序暂停的区域。
当程序停止时,通常意味着某个地方发生了死循环。
因此,您必须密切注意所有循环。例如在 readHumi()
基本上只有三个循环:
for(in = 0b10000000; in > 0; in /= 2)
在shtWrite
for(in = 0b10000000; in > 0; in /= 2)
在shtRead
那些循环看起来不错,它们有一个退出条件,在 8 次迭代后总是满足。
但是你也有这样的循环:
while(DATA);
如果传感器不接受命令,则没有退出条件。可能这会暂停您的程序。
传感器不理解命令的原因可能是SCK上升沿和下降沿之间的时间太短。根据 datasheet(第 6 页),SCK 下降和上升之间的时间至少应为 100ns。 如果你是运行 10+MHz,那么序列
SCK = 0; //set B0 Low
SCK = 1; //set B0 High
可以产生小于100ns的脉冲
此外,DDR
的 SCK 引脚从未在您的代码中初始化。
通过在 readHumi 和 readTemp 函数末尾添加传感器重置解决了问题:
shtStart();
shtWrite(0x1e);