【NiosII训练】第四篇、FPGA驱动DS18B20

目录

第一部分、前言

1、闲话

第二部分、题目要求

1、图片

2、文字描述

3、题目分析

第三部分、工程代码

1、软核的搭建

2、顶层文件的代码

3、Ecplise代码

第四部分、总结

1、接线图

2、实现功能阐述

3、结果演示

4、完整工程


第一部分、前言

1、闲话

还是一样,这个设计也是我们《SOPC技术及应用》课程结束的期末作业。我自己的是老师题库里的第五题、驱动AD9854这个模块《【NiosII训练】第一篇、FPGA驱动AD9854基础篇:https://blog.csdn.net/Learning1232/article/details/111193587》,想回去看的铁子们可以回去看。

这一题是我们班同学的,报酬是给我买零食,然后,我就答应了。。。。效果如下:

【NiosII训练】第四篇、FPGA驱动DS18B20

第二部分、题目要求

1、图片

【NiosII训练】第四篇、FPGA驱动DS18B20

2、文字描述

使用FPGA调成功18b20温度传感器,并能够将温度实时显示在lcd上,要求只有当某个按键按一下的时候lcd上的温度才会变一下,能够通过其他按键改变温度的阈值。当温度超过阈值时,蜂鸣器会叫。提示,ac620上的蜂鸣器时无源的,最好通过pwm核驱动蜂鸣器叫,或者使用ucosii的某个线程提供pwm信号。

3、题目分析

看了题目要求最主要的就是DS18B20的驱动代码的移植,这是最麻烦的部分。

然而DS18B20我相信大家都玩过,单总线通信方式和DHT11一样,所以在软核里面添加一个双向的PIO核,这么一想是不是简单了很多。

然后还有一个就是按键消抖

第三部分、工程代码

1、软核的搭建

还是基于小梅哥FPGA的LCD9341的例程修改,在原有的工程上面多添加一个双向的位宽为1位PIO核

【NiosII训练】第四篇、FPGA驱动DS18B20

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

	inout  wire        ds18b20,//温度传感器
	output wire  [3:0] led, //led
	
	input  wire        s0,//按键
	input  wire        s1,
	output wire        buzzer//外置蜂鸣器管脚
	
	);

    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
	
	   .ds18b20_export                    (ds18b20), //   ds18b20.export
	   .buzzer_export                     (buzzer),  //    buzzer.export
	   .led_export                        (led),     //       led.export
	   .s0_export                         (s0),      //        s0.export
	   .s1_export                         (s1)       //        s1.export
	
	
	);

3、Ecplise代码

DS18B20.c文件

/*
 * ds18b20.c
 *
 *  Created on: 2020年12月4日
 *      Author: dpt
 */
#include "ds18b20.h"

//DS18B20芯片初始化
alt_u8 Init_DS18B20(void)
{
	alt_u8 initflag = 0;

	IOWR_ALTERA_AVALON_PIO_DIRECTION(DS18B20_BASE, 1);//方向为输出
	IOWR_ALTERA_AVALON_PIO_DATA(DS18B20_BASE, 0);
	usleep(550);
	IOWR_ALTERA_AVALON_PIO_DATA(DS18B20_BASE, 1);
	usleep(40);
	IOWR_ALTERA_AVALON_PIO_DIRECTION(DS18B20_BASE, 0);//方向为输入
	initflag = IORD_ALTERA_AVALON_PIO_DATA(DS18B20_BASE);
	usleep(100);

	return initflag;				//应答信号为低电平,表示复位成功
}


//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		IOWR_ALTERA_AVALON_PIO_DIRECTION(DS18B20_BASE, 1);//方向为输出
		IOWR_ALTERA_AVALON_PIO_DATA(DS18B20_BASE, 0);
		usleep(10);

		IOWR_ALTERA_AVALON_PIO_DATA(DS18B20_BASE, dat&0x01);
		usleep(30);

		IOWR_ALTERA_AVALON_PIO_DATA(DS18B20_BASE, 1);
		dat >>= 1;						//发送下一个数据位
	}
}


//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;

	for(i=0;i<8;i++)
	{
		IOWR_ALTERA_AVALON_PIO_DIRECTION(DS18B20_BASE, 1);//方向为输出
		IOWR_ALTERA_AVALON_PIO_DATA(DS18B20_BASE, 0);
		usleep(10);

		dat >>= 1;						//数据位右移

		IOWR_ALTERA_AVALON_PIO_DATA(DS18B20_BASE, 1);

		IOWR_ALTERA_AVALON_PIO_DIRECTION(DS18B20_BASE, 0);//方向为输入
		if(IORD_ALTERA_AVALON_PIO_DATA(DS18B20_BASE))	//读取总线上的数据
		{
			dat |= 0x80;
		}
		usleep(45);
	}
	return dat;
}

 

DS18B20.h文件

/*
 * ds18b20.h
 *
 *  Created on: 2020年12月4日
 *      Author: dpt
 */

#ifndef DS18B20_H_
#define DS18B20_H_

#include <stdio.h>
#include <sys/unistd.h>
#include <io.h>
#include <string.h>
#include <stdio.h>
#include "stdlib.h"
#include "stdint.h"
#include "system.h"
#include "alt_types.h"
#include "altera_avalon_pio_regs.h"

#define OW_SKIP_ROM 0xcc
#define DS18B20_CONVERT 0x44
#define DS18B20_READ 0xbe

//函数声明
void Write_DS18B20(unsigned char dat);
alt_u8 Init_DS18B20(void);
unsigned char Read_DS18B20(void);

#endif /* DS18B20_H_ */

main.c

#include "lcd9341.h"
#include <stdio.h>
#include "ds18b20.h"
#include "alt_types.h"
#include "priv/alt_legacy_irq.h"
#include "altera_avalon_pio_regs.h"


unsigned int T_dat;
unsigned int S0 = 0;
unsigned int MAX_T_dat = 25;
char a1[10]={};
char a2[10]={};
char a3[10]={};
char a4[10]={};
char a5[10]={};
char a6[10]={};
char a7[10]={};
void Read_Temperature();

int main()
{
	printf("I am 666!\n");
 	LCD9341_Init();

 	IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE, 0xff);//灯灭
 	IOWR_ALTERA_AVALON_PIO_DATA(BUZZER_BASE, 1);//蜂鸣器不叫

	POINT_COLOR=RED;

	LCD_ShowString(20,70,"  MAX  Temp =   .0C");
	sprintf(a3,"%d",MAX_T_dat/10);
	sprintf(a4,"%d",MAX_T_dat%10);
	LCD_ShowString(132,70,a3);
	LCD_ShowString(140,70,a4);

	LCD_ShowString(20,50,"Temperature = ");

	Read_Temperature();
	printf("%d\n",T_dat);
	sprintf(a1,"%d",T_dat/10);
	sprintf(a2,"%d",T_dat%10);
	LCD_ShowString(132,50,a1);
	LCD_ShowString(148,50,".");
	LCD_ShowString(156,50,a2);
	LCD_ShowString(164,50,"C");
	usleep(1000000);
  	while(1)
	{
  		//按下S0,开始检测温度
  		if(IORD_ALTERA_AVALON_PIO_DATA(S0_BASE) == 0)
  		{
  			usleep(5000);
  			if(IORD_ALTERA_AVALON_PIO_DATA(S0_BASE) == 0)
  			{
  				if(S0 == 1)  S0 = 0;
  				else  S0 = 1;
  				while(IORD_ALTERA_AVALON_PIO_DATA(S0_BASE) == 0)//如果S0不松开
  				{
  	  				Read_Temperature();
  	  		  		printf("%d\n",T_dat);
  	  		  		sprintf(a1,"%d",T_dat/10);
  	  		  		sprintf(a2,"%d",T_dat%10);
  	  		  		LCD_ShowString(132,50,a1);
  	  		  		LCD_ShowString(148,50,".");
  	  		  		LCD_ShowString(156,50,a2);
  	  		  		LCD_ShowString(164,50,"C");
  	  				usleep(100000);
  				}
  			}
  		}
  		//按下S1阈值温度增加一个//注意这里每按下一次
  		if(IORD_ALTERA_AVALON_PIO_DATA(S1_BASE) == 0)
  		{
  			usleep(5000);
			if(IORD_ALTERA_AVALON_PIO_DATA(S1_BASE) == 0 && S0 == 0)
			{
				MAX_T_dat++;
				sprintf(a3,"%d",MAX_T_dat/10);
				sprintf(a4,"%d",MAX_T_dat%10);
				LCD_ShowString(132,70,a3);
				LCD_ShowString(140,70,a4);

				while(IORD_ALTERA_AVALON_PIO_DATA(S1_BASE) == 0);//判断按键是否松开
			}
			else if(IORD_ALTERA_AVALON_PIO_DATA(S1_BASE) == 0 && S0 == 1)
			{
				MAX_T_dat--;
				if(MAX_T_dat > 0)
				{
					sprintf(a5,"%d",MAX_T_dat/10);
					sprintf(a6,"%d",MAX_T_dat%10);
					LCD_ShowString(132,70,a5);
					LCD_ShowString(140,70,a6);
				}
				else
				{
					sprintf(a7,"%d",MAX_T_dat);
					LCD_ShowString(132,70,a7);
				}
				while(IORD_ALTERA_AVALON_PIO_DATA(S1_BASE) == 0);//判断按键是否松开
			}
  		}
  		//超过设置温度,灯亮,否则灯灭
  		if(T_dat/10> MAX_T_dat)
  		{
  			IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE, 0);
  			IOWR_ALTERA_AVALON_PIO_DATA(BUZZER_BASE, 0);//蜂鸣器叫
  		}
  	    if(T_dat/10 < MAX_T_dat)
  		{
  			IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE, 0xff);
  			IOWR_ALTERA_AVALON_PIO_DATA(BUZZER_BASE, 1);//蜂鸣器不叫
  		}

	}
}


//读温度
void Read_Temperature()
{
	unsigned char LSB,MSB ;

	Init_DS18B20();
	Write_DS18B20(0xCC);
	Write_DS18B20(0x44);

	usleep(500000);//500ms

	Init_DS18B20();
	Write_DS18B20(0xCC);
	Write_DS18B20(0xBE);


	LSB = Read_DS18B20();
	MSB = Read_DS18B20();
	Init_DS18B20();

	T_dat = 0x0000;
	T_dat = MSB;
	T_dat <<= 8;
	T_dat = T_dat | LSB;

	if((T_dat & 0xf800) == 0x0000)
	{
		T_dat >>= 4;
		T_dat = T_dat*10;
		T_dat = T_dat + (LSB&0x0f)*0.625;
	}

}

第四部分、总结

1、接线图

【NiosII训练】第四篇、FPGA驱动DS18B20

2、实现功能阐述

按照题意,只有我按下我FPGA上的按键S0不放,开始检测温度,松开后停止检测。按下S1并松开,则温度的阈值就会增加一度,如果想减小阈值温度,那么先按一下S0,然后在按一下S1,这时候温度的阈值就会减少一度。同时当温度超过阈值时蜂鸣器报警。

3、结果演示

这里只展示图片,视频文件我已经上传到群文件,你也可以点击这里看一下演示效果(https://live.csdn.net/v/121253)。

【NiosII训练】第四篇、FPGA驱动DS18B20

4、完整工程

嫖嫖怪时间到,还是一样可以自己去群资料下载,也可以留下邮箱我偷偷发链接给你,或者老板大气一下,让我骗你几个积分(https://download.csdn.net/download/Learning1232/13695461)。

【NiosII训练】第四篇、FPGA驱动DS18B20

上一篇:【蓝桥杯嵌入式拓展板】—双通道ADC采集 详解(附程序源码)


下一篇:提供汽车轮胎胎气压表方案芯片CSU8RP1186