2021暑假在家一起练项目一-利用ADC制作一个数字电压表
使用小脚丫FPGA核心模块的综合技能训练平台,制作了一个数字电压表
标签
FPGA
数字逻辑
显示
振青666
更新2021-09-05
1150

一、项目要求

  1. 旋转电位计可以产生0-3.3V的电压
  2. 利用板上的串行ADC对电压进行转换
  3. 将电压值在板上的OLED屏幕上显示出来

二、平台介绍

基于小脚丫FPGA的综合技能训练平台

小脚丫的fpga综合训练板具有丰富的外设,在原来小脚丫fpga开发板的外设之外,又扩展了USB转串口,OLED屏幕,ADC,温度传感器,10位R-2R网络DDS,蜂鸣器。本次设计主要使用了ADC和OLED模块。

2.1 ADC模块

训练板的AD使用ADS7868芯片,是一款8位ADC速度能达到200KSPS,通过SPI总线将输出传输出来。电路还包含了一个可调电位器产生0-3.3v的电压。

FtIJtY8K1kdba2mBcd2A1uLDZoWt

2.2 OLED模块

训练板上集成了一个OLED12832模块,使用SPI串行总线通信,屏幕集成了SSD1206驱动芯片进行屏幕驱动。

FgE0UaM83Mj0wdmPnaehMdNyKb-p

2.3 管脚分配

v2.2%E7%AE%A1%E8%84%9A%E5%88%86%E9%85%8D.png?w=500&tok=ba34a8

小脚丫FPGA模块的管脚 DAC的数据位
x ClkIn
Pin 31 DA[9]
Pin 30 DA[8]
Pin 29 DA[7]
Pin 28 DA[6]
Pin 27 DA[5]
Pin 26 DA[4]
Pin 25 DA[3]
Pin 24 DA[2]
Pin 23 DA[1]
Pin 22 DA[0]
Pin 19 PWM_Out
Pin 39 OledClk
Pin 38 OledDin
Pin 37 OledRes
Pin 36 OledDc
Pin 35 OledCs
Pin 2 UartRx
Pin 3 UartTx
Pin 12 AdcSdo
Pin 13 AdcClk
Pin 14 AdcCs
Pin 17 DS18B20
Pin 18 Beeper

三、Verilog程序编写 3.1 顶层例化

顶层例化文件,连接了各个模块,将ADC和OLED都放在了同一个文件中,读取ADC数值,将ADC获取的原始二进制数据乘以129将原始的0-255数据与0-3.3V进行对应,然后使用二进制转BCD码模块,转换得到BCD码,输出到OLED模块,在OLED中进行输出。

module Volt_Oled(
    input               clk,
    input               rst_n,
    
    output              adc_cs,
    output              adc_clk,
    input               adc_dat,

	output              oled_csn,	
	output              oled_rst,	
	output              oled_dcn,	
	output              oled_clk,	
	output              oled_dat	
);

wire adc_once;
wire [7:0] adc_data;

ADS7868 ADS7868(
.clk            (clk),
.rst_n          (rst_n),
.adc_cs         (adc_cs),
.adc_clk        (adc_clk),
.adc_dat        (adc_dat),
.adc_done       (adc_once),
.adc_data       (adc_data)

);

wire [15:0]	bin_code = adc_data * 16'd129;
wire [19:0]	bcd_code;
bin_to_bcd bin_to_bcd(
.rst_n          (rst_n),
.bin_code       (bin_code),
.bcd_code       (bcd_code)
);

OLED12832 OLED12832(
.clk            (clk),
.rst_n          (rst_n),
.datain         (bcd_code),
.oled_csn       (oled_csn),
.oled_rst       (oled_rst),
.oled_dcn       (oled_dcn),
.oled_clk       (oled_clk),
.oled_dat       (oled_dat)
);

endmodule

3.2 ADS7868驱动

ADS7868时序图:

FkESwd7RkG5clF5B35kc6BphfqSW

使用了小脚丫官方提供的ADS7868驱动程序:

module ADS7868
(
input				clk,		//系统时钟
input				rst_n,  	//系统复位,低有效

output	reg			adc_cs,		//SPI总线CS
output	reg			adc_clk,	//SPI总线SCK
input				adc_dat,	//SPI总线SDA

output	reg			adc_done,	//ADC采样完成标志
output	reg [7:0]	adc_data	//ADC采样数据
);

localparam	HIGH = 1'b1;
localparam	LOW  = 1'b0;

reg [7:0] cnt; //计数器
always @(posedge clk or negedge rst_n)
	if(!rst_n) cnt <= 1'b0;
	else if(cnt >= 8'd34) cnt <= 1'b0;
	else cnt <= cnt + 1'b1;
	
reg [7:0] data;
always @(posedge clk or negedge rst_n)
	if(!rst_n) begin
		adc_cs <= HIGH; adc_clk <= HIGH; 
		data <= 1'b0; adc_data <= 1'b0; adc_done <= LOW;
	end else case(cnt)
		8'd0 :  begin adc_cs <= HIGH; adc_clk <= HIGH; end
		8'd1 :  begin adc_cs <= LOW;  adc_clk <= HIGH; end
		8'd2,8'd4,8'd6,8'd8,8'd10,8'd12,8'd14,8'd16,
		8'd18,8'd20,8'd22,8'd24,8'd26,8'd28,8'd30,8'd32:	
				begin adc_cs <= LOW;  adc_clk <= LOW;  end
		8'd3 :  begin adc_cs <= LOW;  adc_clk <= HIGH; end //0
		8'd5 :  begin adc_cs <= LOW;  adc_clk <= HIGH; end //1
		8'd7 :  begin adc_cs <= LOW;  adc_clk <= HIGH; end //2
		8'd9 :  begin adc_cs <= LOW;  adc_clk <= HIGH; data[7] <= adc_dat; end //3
		8'd11 : begin adc_cs <= LOW;  adc_clk <= HIGH; data[6] <= adc_dat; end //4
		8'd13 : begin adc_cs <= LOW;  adc_clk <= HIGH; data[5] <= adc_dat; end //5
		8'd15 : begin adc_cs <= LOW;  adc_clk <= HIGH; data[4] <= adc_dat; end //6
		8'd17 : begin adc_cs <= LOW;  adc_clk <= HIGH; data[3] <= adc_dat; end //7
		8'd19 : begin adc_cs <= LOW;  adc_clk <= HIGH; data[2] <= adc_dat; end //8
		8'd21 : begin adc_cs <= LOW;  adc_clk <= HIGH; data[1] <= adc_dat; end //9
		8'd23 : begin adc_cs <= LOW;  adc_clk <= HIGH; data[0] <= adc_dat; end //10
		8'd25 : begin adc_cs <= LOW;  adc_clk <= HIGH; adc_data <= data; end //11
		8'd27 : begin adc_cs <= LOW;  adc_clk <= HIGH; adc_done <= HIGH; end //12
		8'd29 : begin adc_cs <= LOW;  adc_clk <= HIGH; adc_done <= LOW; end //13
		8'd31 : begin adc_cs <= LOW;  adc_clk <= HIGH; end //14
		8'd33 : begin adc_cs <= LOW;  adc_clk <= HIGH; end //15
		8'd34 : begin adc_cs <= HIGH;  adc_clk <= HIGH; end
		default : begin adc_cs <= HIGH;  adc_clk <= HIGH;  end
	endcase

endmodule

3.3 BIN转BCD模块

BCD码称为二进码十进数或BCD码(Binary-Coded Decimal‎)亦称二进码十进数或二-十进制代码。用4位二进制数来表示1位十进制数中的0~9这10个数码。

BCD码这种编码形式利用了四个位元来储存一个十进制的数码,使二进制和十进制之间的转换得以快捷的进行。这种编码技巧,最常用于会计系统的设计里,因为 会计制度经常需要对很长的数字串作准确的计算。相对于一般的浮点式记数法,采用BCD码,既可保存数值的精确度,又可免却使电脑作浮点运算时所耗费的时 间。此外,对于其他需要高精确度的计算,BCD编码亦很常用。

在本项目中,由于需要屏幕输出,所以需要将二进制数据转换成BCD码,再传输到屏幕模块进行输出。

常用的转换方式:

  1. 除法取余的方法
  2. Bin2bcd移位算法

由于除法取余算法对性能的消耗比较大,所以设计中使用了移位算法。

Bin2bcd移位算法原理:

此处要介绍的是二进制转BCD码的硬件实现,采用左移加3的算法,具体描述如下:

(此处以8-bit 二进制码为例)

  1. 左移要转换的二进制码1位
  2. 左移之后,BCD码分别置于百位、十位、个位
  3. 如果移位后所在的BCD码列大于或等于5,则对该值加3
  4. 继续左移的过程直至全部移位完成

FgdIljsYKcucNQ8HwM_QFNy6S9wJ

module bin_to_bcd
(
input						rst_n,	//系统复位,低有效
input		[15:0]			bin_code,	//需要进行BCD转码的二进制数据
output	reg	[19:0]			bcd_code	//转码后的BCD码型数据输出
);

/*
此模块为了将ADC采样的数据转换为我们常用的十进制显示而存在,
主要知识涉及数学中不同制式数据的转换,详细原理这里不做介绍,去百度搜索<FPGA 二进制转BCD码>可得
*/

reg		[35:0]		shift_reg; 
always@(bin_code or rst_n)begin
	shift_reg = {20'h0,bin_code};
	if(!rst_n) bcd_code = 0; 
	else begin 
		repeat(16) begin //循环16次  
			//BCD码各位数据作满5加3操作,
			if (shift_reg[19:16] >= 5) shift_reg[19:16] = shift_reg[19:16] + 2'b11;
			if (shift_reg[23:20] >= 5) shift_reg[23:20] = shift_reg[23:20] + 2'b11;
			if (shift_reg[27:24] >= 5) shift_reg[27:24] = shift_reg[27:24] + 2'b11;
			if (shift_reg[31:28] >= 5) shift_reg[31:28] = shift_reg[31:28] + 2'b11;
			if (shift_reg[35:32] >= 5) shift_reg[35:32] = shift_reg[35:32] + 2'b11;
			shift_reg = shift_reg << 1; 
		end
		bcd_code = shift_reg[35:16];   
	end  
end

endmodule

3.4 OLED12832驱动

这里直接使用了小脚丫提供的驱动,修改了MAIN部分

MAIN:begin
        if(cnt_main >= 5'd10) cnt_main <= 5'd5;
        else cnt_main <= cnt_main + 1'b1;
        case(cnt_main)	//MAIN状态
            5'd0:	begin state <= INIT; end
            5'd1:	begin y_p <= 8'hb1; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "    Voltage     ";state <= SCAN; end
            5'd2:	begin y_p <= 8'hb0; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "                ";state <= SCAN; end
            5'd3:	begin y_p <= 8'hb2; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "                ";state <= SCAN; end
            5'd4:	begin y_p <= 8'hb3; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "                ";state <= SCAN; end
            
            5'd5:	begin y_p <= 8'hb2; x_ph <= 8'h12; x_pl <= 8'h00; num <= 5'd 1; char <= datain[19:16]; state <= SCAN; end
            5'd6:	begin y_p <= 8'hb2; x_ph <= 8'h12; x_pl <= 8'h08; num <= 5'd 1; char <= "."; state <= SCAN; end
            5'd7:	begin y_p <= 8'hb2; x_ph <= 8'h13; x_pl <= 8'h00; num <= 5'd 1; char <= datain[15:12]; state <= SCAN; end
            5'd8:	begin y_p <= 8'hb2; x_ph <= 8'h13; x_pl <= 8'h08; num <= 5'd 1; char <= datain[11:8]; state <= SCAN; end
            5'd9:	begin y_p <= 8'hb2; x_ph <= 8'h14; x_pl <= 8'h00; num <= 5'd 1; char <= datain[7:4]; state <= SCAN; end
            5'd10:	begin y_p <= 8'hb2; x_ph <= 8'h14; x_pl <= 8'h08; num <= 5'd 1; char <= datain[3:0]; state <= SCAN; end

            default: state <= IDLE;
        endcase
    end

四、使用资源

FlAk9dUlWH13HOn74zhaJgytrko6

PAD Specification File
***************************

PART TYPE:        LCMXO2-4000HC
Performance Grade:      4
PACKAGE:          CSBGA132
Package Status:                     Final          Version 1.44

Sat Sep 04 21:59:36 2021

Pinout by Port Name:
+-----------+----------+--------------+-------+-----------+-----------+--------------------------------------+
| Port Name | Pin/Bank | Buffer Type  | Site  | PG Enable | BC Enable | Properties                           |
+-----------+----------+--------------+-------+-----------+-----------+--------------------------------------+
| adc_clk   | N5/2     | LVCMOS33_OUT | PB10A |           |           | DRIVE:8mA PULL:DOWN SLEW:SLOW        |
| adc_cs    | P6/2     | LVCMOS33_OUT | PB13B |           |           | DRIVE:8mA PULL:DOWN SLEW:SLOW        |
| adc_dat   | L3/3     | LVCMOS33_IN  | PL19B |           |           | PULL:DOWN CLAMP:ON HYSTERESIS:SMALL  |
| clk       | C1/5     | LVCMOS33_IN  | PL4A  |           |           | PULL:DOWN CLAMP:ON HYSTERESIS:SMALL  |
| oled_clk  | E12/1    | LVCMOS33_OUT | PR5A  |           |           | DRIVE:8mA PULL:DOWN SLEW:SLOW        |
| oled_csn  | F14/1    | LVCMOS33_OUT | PR8B  |           |           | DRIVE:8mA PULL:DOWN SLEW:SLOW        |
| oled_dat  | F12/1    | LVCMOS33_OUT | PR6B  |           |           | DRIVE:8mA PULL:DOWN SLEW:SLOW        |
| oled_dcn  | F13/1    | LVCMOS33_OUT | PR8A  |           |           | DRIVE:8mA PULL:DOWN SLEW:SLOW        |
| oled_rst  | G12/1    | LVCMOS33_OUT | PR9A  |           |           | DRIVE:8mA PULL:DOWN SLEW:SLOW        |
| rst_n     | L14/1    | LVCMOS33_IN  | PR16A |           |           | PULL:DOWN CLAMP:ON HYSTERESIS:SMALL  |
+-----------+----------+--------------+-------+-----------+-----------+--------------------------------------+

Vccio by Bank:
+------+-------+
| Bank | Vccio |
+------+-------+
| 1    | 3.3V  |
| 2    | 3.3V  |
| 3    | 3.3V  |
| 5    | 3.3V  |
+------+-------+

五、不足

由于时间和能力有限,没能实现所有的模块自行编写,使用了官方提供驱动。

 

附件下载
Voltage.rar
团队介绍
贵州大学,电子信息专业,一个初次接触FPGA的小渣渣
团队成员
振青666
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号