打印
[AVR单片机]

【求助】AVR调DHT11不能显示,跪求大神帮忙

[复制链接]
981|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
小强强12138|  楼主 | 2015-5-31 20:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
刚开始我是用数码管来显示的,可是在检测时扫描显示不太连续,就是有闪烁,后来改用12864显示,还是不能显示出温湿度,只有我给的初值,下面是我的程序:
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define sid1        PORTA|=(1<<0)
#define sid0        PORTA&=~(1<<0)
#define clk1        PORTA|=(1<<1)
#define clk0        PORTA&=~(1<<1)

#define B_IN        DDRB&=~(1<<0)                /*设置输入*/
#define B_OUT        DDRB|=(1<<0)                /*设置输出*/
#define B_CLR        PORTB&=~(1<<0)        /*置低电平*/
#define B_SET        PORTB|=(1<<0)                /*置高电平*/
#define B_R                PINB&(1<<0)                /*读了电平*/
uchar dht_t1=14,dht_t2=0;        //依次为温度整数部分和温度小数部分
uchar dht_d1=23,dht_d2=0;        //依次为湿度整数部分和湿度小数部分
uchar dht_chk=0;                //和校验
uchar dht_num=0;

//sbit sid=P1^0;
//sbit clk=P1^1;
//sbit dht_dat=P1^2;
uchar wdj[]=
{0x00,0x00,0x01,0x80,0x02,0x40,0x02,0x40,0x02,0xC0,0x02,0x40,0x02,0xC0,0x02,0x40,
0x02,0xC0,0x02,0x40,0x03,0xC0,0x07,0xE0,0x0F,0xF0,0x0F,0xF0,0x07,0xE0,0x03,0xC0};

uchar wd[]=
{0x00,0x00,0x30,0x00,0x48,0x00,0x49,0xC0,0x33,0xE8,0x06,0x38,0x0C,0x18,0x0C,0x08,
0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x06,0x08,0x03,0x10,0x01,0xE0,0x00,0x00};

void write_byte(uchar dat)
{
        uchar i;
        for(i=0;i<8;i++)
        {
                if(dat&0x80)
                //sid=1;
                sid1;
                else
                //sid=0;
                sid0;
                //clk=1;
                clk1;
                dat<<=1;
                //clk=0;
                clk0;
        }
}
void write_com(uchar com)
{
        write_byte(0xf8);
        write_byte(com&0xf0);
        write_byte(com<<4);
}
void write_date(uchar date)
{
        write_byte(0xfa);
        write_byte(date&0xf0);
        write_byte(date<<4);
}
void write_yrsfm(uchar add,uchar date)
{
        uint shi,ge;
        shi=date/10;
        ge=date%10;
        write_com(0x80+add);
        write_date(0x30+shi);
        write_date(0x30+ge);
}

void set_LCD12864_pos(uchar x,uchar y)
{
        uchar pos;
        if(x==0) x=0x80;
        if(x==1) x=0x90;
        if(x==2) x=0x88;
        if(x==3) x=0x98;
        pos=x+y;
        write_com(pos); //地址.
}
//------------写字符串----------------
void write_12864str(uchar *s)
{
        while(*s)
        {
                write_date(*s);
                s++;
                _delay_ms(1);
        }

}
//------------------------------在任意位置开始显示图画-----------------------------
void LCD12864_set_tu(uchar X,uchar Y,uchar *tu,uchar wide,uchar high)
{         //Y确定开始行,X确定水平地址(0x80-0x87),tu是点阵字模数据
        uint hang,lie;
        write_com(0x34);//打开扩展指令集
        write_com(0x34);//绘图显示关
        if(wide%8==0) wide=wide/8;
        else wide=wide/8+1;
        for(hang=0;hang<high;hang++)
        {
                if(Y+hang>31)                          //上下屏地址转换
                {
                        write_com(0x80+Y+hang-32);//先写Y轴坐标
                        write_com(0x88+X);//再写X轴坐标  ,(0x88-0x8f)
                }                                                        //这里X只需写(0-7)
                else
                {
                        write_com(0x80+Y+hang);//先写Y轴坐标
                        write_com(0x80+X);//再写X轴坐标  ,(0x80-0x87)
                }
                for(lie=0;lie<wide;lie++)                           //根据列宽逐行写入数据
                {                                                                           //宽占几字节,就写几字节
                        write_date(tu[hang*wide+lie]);//每行写入wide个字节数据
                }
               
        }
        write_com(0x36);//绘图显示开
        write_com(0x30);//回到基本指令集
}
//------------------------------------------------
void huitu_clear()
{
        uchar i,j;
        write_com(0x34);
        for(i=0;i<32;i++)             //因为LCD有纵坐标32格,所以写三十二次
        {
                write_com(0x80+i);         //先写入纵坐标Y的值
                write_com(0x80);         //再写入横坐标X的值
                for(j=0;j<32;j++)         //横坐标有16位,每位写入两个字节的的数据,也就写入32次
                {                         //因为当写入两个字节之后横坐标会自动加1,所以就不用再次写入地址了。
                        write_date(0x00);
                }
        }
        write_com(0x36);
        write_com(0x30);
}

void LCD12864_init()
{
        write_com(0x30); //基本指令集
        _delay_ms(5);
        write_com(0x0c); //显示开,关光标
        _delay_ms(5);
        write_com(0x06); //光标的移动方向
        _delay_ms(5);
        write_com(0x01);  //清屏
        _delay_ms(5);
}

/*------------------初始化LCD屏--------------------------*/
void nit()
{
        _delay_ms(2000);
        write_com(0x30);
        _delay_ms(10);             //选择基本指令集
        write_com(0x30);       //选择8bit数据流
        _delay_ms(5);
        write_com(0x0c);       //开显示(无游标、不反白)
        _delay_ms(10);
        write_com(0x01);       //清除显示,并且设定地址指针为00H
        _delay_ms(500);
        write_com(0x06);       //指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位
}

//初始化
void init()
{
        uint num,ri=14;
        uchar table2[]="      %RH ";
        write_com(0x90);
        write_yrsfm(5,ri);
        LCD12864_set_tu(5,32,wdj,16,16);
        LCD12864_set_tu(7,32,wd,16,16);
        write_com(0x88);//星期
        for(num=0;num<10;num++)
        {
                write_date(table2[num]);
                _delay_ms(5);
        }
        write_yrsfm(10,dht_d1);
        write_yrsfm(14,dht_t1);
}

uchar dht_readat()        //接收一个8位数据,先高位后低位
{
        uchar i=0,dat=0;
        for(i=0;i<8;i++)
        {
                dht_num=2;
                while((!B_R)&&(dht_num++));
                _delay_us(40);
                dat=dat<<1;
                if(B_R)
                {
                        dht_num=2;
                        dat=dat|0x01;
                        while((B_R)&&(dht_num++));
                }
        }
        return dat;
}

void dht_getdat()         //给DHT11一个开始信号,然后读取一次数据,共五个8位字节
{
        uchar i=0;

        B_OUT;
        B_CLR;
        _delay_ms(18);
        B_IN;
        B_SET;         //单片机给起始脉冲信号
        _delay_us(40);
        B_IN;
        B_SET;          //稍作延时,等待DHT11返回响应(响应为低电平)

        if(!B_R)        //有响应才接收数据,否则不作处理
        {
                dht_num=2;while((!B_R)&&(dht_num++));
                dht_num=2;while((B_R)&&(dht_num++));
                dht_d1=dht_readat();
                dht_d2=dht_readat();
                dht_t1=dht_readat();
                dht_t2=dht_readat();
                dht_chk=dht_readat();        //一次读出五个数据
                write_yrsfm(10,dht_d1);
                write_yrsfm(14,dht_t1);
        }
        B_IN;
        B_SET;        //释放总线
        _delay_ms(100);        //稍作延时
}

void dht_init()        //DHT11的初始化函数
{
        _delay_ms(1000);        //DHT11上电前准备时间,大概1s
        B_IN;
        B_SET;        //总线准备
}

int main()
{
        DDRA = 0xff;PORTA = 0xff;
        DDRB = 0x00;PORTB = 0xff;
        dht_init();
        nit();
        huitu_clear();
        init();
//        huitu_clear();
        while(1)
        {
                dht_getdat();
        }
}
我的程序是根据以前做51万年历的程序改的,在51上显示正常,可在AVR上就没反应了,求大神们帮忙看看。

相关帖子

沙发
小强强12138|  楼主 | 2015-5-31 20:45 | 只看该作者
DDRA = 0xff; PORTA = 0xff;
DDRB = 0x00; PORTB = 0xff;
这里是这样的,不知道为什么变成了表情

使用特权

评论回复
板凳
小强强12138|  楼主 | 2015-5-31 21:49 | 只看该作者
单片机是ATMEGA16L的,编译器用的是AtmelStudio 6.0

使用特权

评论回复
地板
JY-DX-JY| | 2015-6-1 18:43 | 只看该作者
对照手册用示波器看时序。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
小强强12138 + 1 谢谢了
5
小强强12138|  楼主 | 2015-6-2 20:32 | 只看该作者
今天试了一下,发现程序进不去void dht_getdat() ;我把 “if(!B_R)        //有响应才接收数据,否则不作处理”这一句里的“!”去掉,程序可进入if,但显示的数据都为0

使用特权

评论回复
6
小强强12138|  楼主 | 2015-6-3 20:26 | 只看该作者
今日问题解决,原因竟然是因为宏定义的问题,我试着把“#define B_R                PINB&(1<<0)                /*读了电平*/”里面的 PINB&(1<<0)加上括号,居然可以了,没想到是这种问题,看来以后要注意细节
很高兴这几天的努力,虽然结果是这样,但还是很开心。
谢谢大家。
PS:下一步:AD7715,大家给我提供支持哦。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

16

帖子

0

粉丝