刚开始我是用数码管来显示的,可是在检测时扫描显示不太连续,就是有闪烁,后来改用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上就没反应了,求大神们帮忙看看。 |