-1

我尝试个性化 shtxx 库,但此代码存在问题。

当我运行它时,lcd 卡在“Hello”上,但如果我在 while 中评论 readHumi 或 readTemp,程序运行没有问题。

就在两者都没有评论时,程序会卡在第二个上,而哪个是第一个并不重要。

我已经测试了它们之间的延迟,尝试在一个空白中阅读以及我认为应该解决但未解决的每一件事

#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);
      }
}
4

2 回答 2

1

您始终可以在代码中添加更多内容lcd_puts以缩小程序停止的区域。

当程序停止时,通常意味着某处发生了死循环。因此,您必须密切注意所有循环。例如,readHumi() 基本上只有三个循环:

  1. for(in = 0b10000000; in > 0; in /= 2)shtWrite
  2. for(in = 0b10000000; in > 0; in /= 2)shtRead

这些循环看起来不错,它们有一个退出条件,在 8 次迭代后总是满足。

但你也有这样的循环:

  1. while(DATA);

如果传感器不接受命令,则没有退出条件。可能这会停止您的程序。

传感器无法理解命令的原因可能是 SCK 上升沿和下降沿之间的时间太短。根据数据表(第 6 页),SCK 下降和上升之间的时间应至少为 100ns。如果你运行的是 10+MHz,那么序列

    SCK = 0;   //set B0 Low
    SCK = 1;   //set B0 High

可产生小于 100ns 的脉冲

此外,DDR对于 SCK 引脚永远不会在您的代码中初始化。

于 2020-08-12T12:54:40.277 回答
0

它通过在 readHumi 和 readTemp 函数末尾添加传感器重置来解决:

shtStart();
shtWrite(0x1e);
于 2020-08-13T19:00:34.957 回答