目录
第一部分、前言
1、闲话
还是一样,这个设计也是我们《SOPC技术及应用》课程结束的期末作业。我自己的是老师题库里的第题、驱动AD9854这个模块,题目要求在第一篇已经说到了,想回去看的铁子们可以回去看。
这一题是我室友的,报酬是给我买一杯奶茶(结果没给,我亏大发了😭😭😭),效果如下:
第二部分、题目要求
1、图片
2、文字描述
使用FPGA调通DHT11温湿度传感器,并能够将温度和湿度实时显示在lcd上,系统需要使用ucosii操作系统。
3、dht11知识
关于DHT11的知识,你到CSDN搜一下,出来一大把,有些博主很详细的讲述了这个模块的工作原理,我这里就不做详述了。
第三部分、工程代码
1、软核的搭建
2、顶层文件的代码
module AC620_GHRD(
input wire clk, // clk.clk
input wire reset_n, // reset.reset_n
output wire lcd_rst, // lcd_rst.export
output wire lcd_rd_n, // lcd_rd.export
output wire lcd_bl, // lcd_bl.export
output wire lcd_wr_n, // lcd_wr.export
output wire lcd_rs, // lcd_rs.export
output wire lcd_cs_n, // lcd_cs.export
inout wire [15:0] lcd_data, // lcd_db.export
output wire sdram_clk, // sdram_clk.clk
output wire [11:0] sdram_addr, // sdram.addr
output wire [1:0] sdram_ba, // .ba
output wire sdram_cas_n, // .cas_n
output wire sdram_cke, // .cke
output wire sdram_cs_n, // .cs_n
inout wire [15:0] sdram_dq, // .dq
output wire [1:0] sdram_dqm, // .dqm
output wire sdram_ras_n, // .ras_n
output wire sdram_we_n, // .we_n
input wire uart_0_rxd, // uart_0.rxd
output wire uart_0_txd, // .txd
output wire epcs_dclk, // epcs.dclk
output wire epcs_sce, // .sce
output wire epcs_sdo, // .sdo
input wire epcs_data0, // .data0
//对PIO端口进行定义
inout wire dht11,
output wire [3:0] led
);
mysystem u0 (
.clk_clk (clk), // clk.clk
.reset_reset_n (reset_n), // reset.reset_n
.uart_0_rxd (uart_0_rxd), // uart_0.rxd
.uart_0_txd (uart_0_txd), // .txd
.epcs_dclk (epcs_dclk), // epcs.dclk
.epcs_sce (epcs_sce), // .sce
.epcs_sdo (epcs_sdo), // .sdo
.epcs_data0 (epcs_data0), //
.lcd_rst_export (lcd_rst), // lcd_rst.export
.lcd_bl_export (lcd_bl), // lcd_bl.export
.lcd_wr_n (lcd_wr_n), // lcd.wr_n
.lcd_rd_n (lcd_rd_n), // .rd_n
.lcd_data (lcd_data), // .data
.lcd_rs (lcd_rs), // .rs
.lcd_cs_n (lcd_cs_n), //
.sdram_clk_clk (sdram_clk), // sdram_clk.clk
.altpll_0_phasedone_conduit_export (), // altpll_0_phasedone_conduit.export
.altpll_0_locked_conduit_export (), // altpll_0_locked_conduit.export
.altpll_0_areset_conduit_export (), // altpll_0_areset_conduit.export
.sdram_addr (sdram_addr), // sdram.addr
.sdram_ba (sdram_ba), // .ba
.sdram_cas_n (sdram_cas_n), // .cas_n
.sdram_cke (sdram_cke), // .cke
.sdram_cs_n (sdram_cs_n), // .cs_n
.sdram_dq (sdram_dq), // .dq
.sdram_dqm (sdram_dqm), // .dqm
.sdram_ras_n (sdram_ras_n), // .ras_n
.sdram_we_n (sdram_we_n), // .we_n
//添加的PIO端口
.dht11_export (dht11), // dht11.export
.led_export (led) // led.export
);
endmodule
3、Ecplise代码
dht11.c代码
#include "dht11.h"
//复位DHT11
void DHT11_Rst(void)
{
IOWR_ALTERA_AVALON_PIO_DIRECTION(DHT11_BASE, 1);//方向为输出
IOWR_ALTERA_AVALON_PIO_DATA(DHT11_BASE, 1);
usleep(25);//初始25us为高电平
// DHT11_IO_OUT(); //SET OUTPUT
// DHT11_DQ_OUT=0; //拉低DQ
// delay_ms(20); //拉低至少18ms
IOWR_ALTERA_AVALON_PIO_DATA(DHT11_BASE, 0);
usleep(18000);
// DHT11_DQ_OUT=1; //DQ=1
// delay_us(30); //主机拉高20~40us
IOWR_ALTERA_AVALON_PIO_DATA(DHT11_BASE, 1);
usleep(30);
}
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
alt_u8 DHT11_Check(void)
{
alt_u8 retry=0;
IOWR_ALTERA_AVALON_PIO_DIRECTION(DHT11_BASE, 0);//方向为输入
while (IORD_ALTERA_AVALON_PIO_DATA(DHT11_BASE)&&retry<100)//DHT11会拉低40~80us
{
retry++;
usleep(1);
};
if(retry>=100)return 1;
else retry=0;
while (!IORD_ALTERA_AVALON_PIO_DATA(DHT11_BASE)&&retry<100)//DHT11拉低后会再次拉高40~80us
{
retry++;
usleep(1);
};
if(retry>=100)return 1;
return 0;
}
//从DHT11读取一个位
//返回值:1/0
alt_u8 DHT11_Read_Bit(void)
{
alt_u8 retry=0;
IOWR_ALTERA_AVALON_PIO_DIRECTION(DHT11_BASE, 0);//方向为输入
while(IORD_ALTERA_AVALON_PIO_DATA(DHT11_BASE)&&retry<100)//等待变为低电平
{
retry++;
// delay_us(1);
usleep(1);
}
retry=0;
while(!IORD_ALTERA_AVALON_PIO_DATA(DHT11_BASE)&&retry<100)//等待变高电平
{
retry++;
// delay_us(1);
usleep(1);
}
// delay_us(40);//等待40us
usleep(40);
if(IORD_ALTERA_AVALON_PIO_DATA(DHT11_BASE))return 1;
else return 0;
}
//从DHT11读取一个字节
//返回值:读到的数据
alt_u8 DHT11_Read_Byte(void)
{
alt_u8 i,dat;
dat=0;
for (i=0;i<8;i++)
{
dat<<=1;
dat|=DHT11_Read_Bit();
}
return dat;
}
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
alt_u8 DHT11_Read_Data(alt_u8 *temp,alt_u8 *humi)
{
alt_u8 buf[5];
alt_u8 i;
DHT11_Rst();
if(DHT11_Check()==0)
{
for(i=0;i<5;i++)//读取40位数据
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humi=buf[0];
*temp=buf[2];
}
}else return 1;
return 0;
}
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在
alt_u8 DHT11_Init(void)
{
DHT11_Rst(); //复位DHT11
return DHT11_Check();//等待DHT11的回应
}
dht11.h代码
#ifndef DHT11_H_
#define DHT11_H_
#include "stdlib.h"
#include "stdint.h"
#include "system.h"
#include "alt_types.h"
#include <stdio.h> //printf的头文件
#include "io.h" //函数类型
#include "altera_avalon_pio_regs.h"
#include "unistd.h" //延时函数的头文件
//复位DHT11
void DHT11_Rst(void);
alt_u8 DHT11_Read_Data(alt_u8 *temp,alt_u8 *humi);
alt_u8 DHT11_Read_Byte(void);
alt_u8 DHT11_Read_Bit(void);
alt_u8 DHT11_Init(void);
alt_u8 DHT11_Check(void) ;
#endif /* DHT11_H_ */
主函数代码
#include "lcd9341.h"
#include "dht11.h"
#include <stdio.h>
alt_u8 temperature;
alt_u8 humidity;
int main()
{
printf("I am 666!\n");
LCD9341_Init();
unsigned char a1[20],a2[20];
while(DHT11_Init()) //DHT11初始化
{
LCD_ShowString(30,130,"DHT11 Error");
usleep(1000000);
}
LCD_ShowString(30,130,"DHT11 OK ");
while(1)
{
DHT11_Read_Data(&temperature,&humidity); //读取温湿度值
printf("%d\n",temperature);
printf("%d\n",humidity);
sprintf(a1,"Temp = %dC",temperature);
sprintf(a2,"Hum = %d%%",humidity);
LCD_ShowString(30,150,a1);
LCD_ShowString(30,170,a2);
usleep(1000000);
}
}
第四部分、总结
1、效果演示
DHT11的数据脚接FPGA的R1管脚。这里只展示图片,视频文件我已经上传到群文件,你也可以点击这里看一下演示效果(https://live.csdn.net/v/121263)
2、感想
调试这个模块确实搞得我头都大了,虽然只用了两三个小时,但是搞得我心烦气燥。一开始是移植CSDN上面的51的时序,结果出问题,然后没法,我又重新移植32上驱动这个模块的时序,调试了好半天才搞好。(其实这两个时序都是一样的,第一次出的问题,我懒得回去看,大概是延时不准,导致时序出了问题)。
这个模块对时序的要求很严格,然后检测温度时温度值上升的很慢,但是检测湿度的值还是挺快的。
3、完整工程
嫖嫖怪时间,还是一样,扫码进群,我会放在群资料里面。或者让我骗你几个积分(https://download.csdn.net/download/Learning1232/13695741)再或者留下邮箱,我看到了就发给你。当然有问题直接留言。