PART1 硬件介绍
-
核心器件:Lattice LCMXO2-4000HC-4MG132
-
板载资源:
- 两位7段数码管;
- 两个RGB三色LED;
- 8路用户LED;
- 4路拨码开关;
- 4路按键;
-
36个用户可扩展I/O(其中包括一路SPI硬核接口和一路I2C硬核接口)
-
支持的开发工具Lattice Diamond
-
支持MICO32/8软核处理器
-
板上集成FPGA编程器
-
一路Micro USB接口
PART2 任务分析
0.利用ADC制作一个数字电压表
- 旋转电位计可以产生0-3.3V的电压
- 利用板上的串行ADC对电压进行转换
- 将电压值在板上的OLED屏幕上显示出来
1.顶层设计
2.主要使用的器件分析
- SSD1306驱动的oled
- ads7868
PART3 代码构建
3.1 adc数据采集(ads7868)
3.1.1 ads7868
8 位 280KSPS SPI接口的串行ADC,可以采集电位计上的电压
参考资料ADS7868 数据表, 产品信息与支持 | TI.com.cn
[简易电压表设计电子森林] (eetree.cn)
3.1.2 ads7868管脚说明
从上图可以看出:SDO信号在SCLK的节拍下传输数据,当SCLK下降沿时SDO更新数据输出,当驱动程序编程时我们要在上升沿采样数据可以得到稳定的输出。
3.1.3 ads7868串行通信时序
- SCLK空闲为高电平,CPOL=1,上升沿(第二个边沿)采样,CPHA = 1 spi模式3
- CS信号拉低有效,经过12个时钟完成一次ADC转换并采样,采样回来的数据前3位无效,接下来为MSB~MSB-7(有效数据),再接下来为无效数据。
3.1.4 构建驱动
参考ti官网手册
想要达到280ksps,需要时钟频率为3.4MHz,此项目采用3MHz的adc主频,6M/25=240ksps,所以先构建一个时钟分频module,产生6MHz的频率。
时钟分频
module clock ( clk,rst_n,clkout);
input clk,rst_n;
output clkout;
parameter WIDTH = 3;
parameter N = 2;
reg [WIDTH-1:0] cnt_p,cnt_n;
reg clk_p,clk_n;
always @ (posedge clk or negedge rst_n )
begin
if(!rst_n)
cnt_p<=0;
else if (cnt_p==(N-1))
cnt_p<=0;
else
cnt_p<=cnt_p+1;
end
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
clk_p<=0;
else if (cnt_p<(N>>1))
clk_p<=0;
else
clk_p<=1;
end
always @ (negedge clk or negedge rst_n)
begin
if(!rst_n)
cnt_n<=0;
else if (cnt_n==(N-1))
cnt_n<=0;
else
cnt_n<=cnt_n+1;
end
always @ (negedge clk)
begin
if(!rst_n)
clk_n<=0;
else if (cnt_n<(N>>1))
clk_n<=0;
else
clk_n<=1;
end
assign clkout = (N==1)?clk:(N[0])?(clk_p&clk_n):clk_p;
endmodule
参考资料:[5.时钟分频 [STEP FPGA开源社区]](https://www.stepfpga.com/doc/5.时钟分频)
构建25位计数器
reg [7:0] cnt;
always @(posedge clkout or negedge rst_n)
if(!rst_n)
cnt <= 1'b0;
else if(cnt >= 8'd24)
cnt <= 1'b0;
else
cnt <= cnt + 1'b1;
构建adc采样代码
always @(posedge clkout or negedge rst_n)
if(!rst_n)
begin
adc_cs <= 1;
adc_clk <= 1;
end
else
if(En)
begin
case(cnt)
8'd0 :
begin
adc_cs <= 1;
adc_clk <= 1;
end
8'd1 :
begin
adc_cs <= 0;
adc_clk <= 1;
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 :
begin
adc_cs <= 0;
adc_clk <= 0;
end
8'd3 :
begin
adc_cs <= 0;
adc_clk <= 1;
end
8'd5 :
begin
adc_cs <= 0;
adc_clk <= 1;
end
8'd7 :
begin
adc_cs <= 0;
adc_clk <= 1;
end
8'd9 :
begin
adc_cs <= 0;
adc_clk <= 1;
data[7] <= ADC_Din;
end
8'd11 :
begin
adc_cs <= 0;
adc_clk <= 1;
data[6] <= ADC_Din;
end
8'd13 :
begin
adc_cs <= 0;
adc_clk <= 1;
data[5] <= ADC_Din;
end
8'd15 :
begin
adc_cs <= 0;
adc_clk <= 1;
data[4] <= ADC_Din;
end
8'd17 :
begin
adc_cs <= 0;
adc_clk <= 1;
data[3] <= ADC_Din;
end
8'd19 :
begin
adc_cs <= 0;
adc_clk <= 1;
data[2] <= ADC_Din;
end
8'd21 :
begin
adc_cs <= 0;
adc_clk <= 1;
data[1] <= ADC_Din;
end
8'd23 :
begin
adc_cs <= 1;
adc_clk <= 1;
data[0] <= ADC_Din;
end
default :
begin
adc_cs <= 1;
adc_clk <= 1;
end
endcase
end
3.2 OLED图形化信息显示
OLED显示模块借鉴电子森林应用案例及参考代码OLED显示模块相关代码,修改显示模式为垂直显示模式。
使用三贝线上取模软件进行对字库的取模(字体大小为长32,宽16)
参考资料[oled_spi_verilog 电子森林] (eetree.cn)
代码过长,摘取主要部分
MAIN:
begin
if(cnt_main == 5'd8)
cnt_main <= 5'd1;
else
cnt_main <= cnt_main + 1'b1;
case(cnt_main)
5'd0:
begin
state <= INIT;
end
5'd1:
begin
x_ph <= 8'h7f;
x_pl <= 8'h00;
y_ph <= 8'h03;
y_pl <= 8'h00;
num1 <= 8'd8;
char <= 8'd88;
state <= SCAN;
end
5'd2:
begin
x_ph <= 8'h7f;
x_pl <= 8'h10;
y_ph <= 8'h03;
y_pl <= 8'h00;
num1 <= 8'd8;
char <= dac_data[19:16]<<3;
state <= SCAN;
end
5'd3:
begin
x_ph <= 8'h7f;
x_pl <= 8'h20;
y_ph <= 8'h03;
y_pl <= 8'h00;
num1 <= 8'd8;
char <= 8'd80;
state <= SCAN;
end
5'd4:
begin
x_ph <= 8'h7f;
x_pl <= 8'h30;
y_ph <= 8'h03;
y_pl <= 8'h00;
num1 <= 8'd8;
char <= dac_data[15:12]<<3;
state <= SCAN;
end
5'd5:
begin
x_ph <= 8'h7f;
x_pl <= 8'h40;
y_ph <= 8'h03;
y_pl <= 8'h00;
num1 <= 8'd8;
char <= dac_data[11:8]<<3;
state <= SCAN;
end
5'd6:
begin
x_ph <= 8'h7f;
x_pl <= 8'h50;
y_ph <= 8'h03;
y_pl <= 8'h00;
num1 <= 8'd8;
char <= 8'd96;
state <= SCAN;
end
5'd7:
begin
x_ph <= 8'h7f;
x_pl <= 8'h60;
y_ph <= 8'h03;
y_pl <= 8'h00;
num1 <= 8'd8;
char <= 8'd88;
state <= SCAN;
end
5'd8:
begin
x_ph <= 8'h7f;
x_pl <= 8'h70;
y_ph <= 8'h03;
y_pl <= 8'h00;
num1 <= 8'd8;
char <= 8'd88;
state <= SCAN;
end
default:
state <= IDLE;
endcase
end
字库
always@(posedge rst_n)
begin
//0
mem1[ 0] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'hF0, 8'h1F, 8'h00};
mem1[ 1] = {8'h00, 8'hFE, 8'hFF, 8'h00, 8'h00, 8'hFF, 8'hFF, 8'h03};
mem1[ 2] = {8'h80, 8'h07, 8'hC0, 8'h03, 8'hC0, 8'h01, 8'h00, 8'h07};
mem1[ 3] = {8'hC0, 8'h00, 8'h00, 8'h06, 8'hC0, 8'h00, 8'h00, 8'h0E};
mem1[ 4] = {8'hC0, 8'h00, 8'h00, 8'h0E, 8'hC0, 8'h00, 8'h00, 8'h06};
mem1[ 5] = {8'hC0, 8'h03, 8'h00, 8'h07, 8'h80, 8'h0F, 8'hE0, 8'h03};
mem1[ 6] = {8'h00, 8'hFF, 8'hFF, 8'h01, 8'h00, 8'hFC, 8'h7F, 8'h00};
mem1[ 7] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00};
//1
mem1[ 8] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00};
mem1[ 9] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h1C, 8'h00, 8'h00};
mem1[10] = {8'h00, 8'h0C, 8'h00, 8'h00, 8'h00, 8'h06, 8'h00, 8'h00};
mem1[11] = {8'h00, 8'h03, 8'h00, 8'h00, 8'hC0, 8'hFF, 8'hFF, 8'h07};
mem1[12] = {8'hC0, 8'hFF, 8'hFF, 8'h07, 8'hC0, 8'hFF, 8'hFF, 8'h07};
mem1[13] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00};
mem1[14] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00};
mem1[15] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00};
//2
mem1[16] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h04, 8'h00, 8'h00};
mem1[17] = {8'h00, 8'h07, 8'h00, 8'h07, 8'h80, 8'h07, 8'h80, 8'h07};
mem1[18] = {8'hC0, 8'h03, 8'hC0, 8'h07, 8'hC0, 8'h01, 8'hE0, 8'h07};
mem1[19] = {8'hC0, 8'h00, 8'h70, 8'h06, 8'hC0, 8'h00, 8'h38, 8'h06};
mem1[20] = {8'hC0, 8'h00, 8'h1E, 8'h06, 8'hC0, 8'h00, 8'h0F, 8'h06};
mem1[21] = {8'hC0, 8'hC1, 8'h03, 8'h06, 8'h80, 8'hFF, 8'h01, 8'h06};
mem1[22] = {8'h80, 8'hFF, 8'h00, 8'h06, 8'h00, 8'h1E, 8'h00, 8'h06};
mem1[23] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00};
//3
mem1[24] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h40, 8'h00};
mem1[25] = {8'h00, 8'h06, 8'hC0, 8'h01, 8'h00, 8'h0F, 8'hE0, 8'h03};
mem1[26] = {8'h80, 8'h03, 8'h80, 8'h07, 8'hC0, 8'h01, 8'h00, 8'h07};
mem1[27] = {8'hC0, 8'h80, 8'h01, 8'h06, 8'hC0, 8'h80, 8'h01, 8'h0E};
mem1[28] = {8'hC0, 8'h80, 8'h01, 8'h0E, 8'hC0, 8'hC0, 8'h03, 8'h06};
mem1[29] = {8'hC0, 8'hC1, 8'h03, 8'h07, 8'h80, 8'h7F, 8'hDF, 8'h03};
mem1[30] = {8'h80, 8'h7F, 8'hFE, 8'h03, 8'h00, 8'h1E, 8'hFC, 8'h00};
mem1[31] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00};
//4
mem1[32] = {8'h00, 8'h00, 8'h70, 8'h00, 8'h00, 8'h00, 8'h78, 8'h00};
mem1[33] = {8'h00, 8'h00, 8'h7E, 8'h00, 8'h00, 8'h00, 8'h7F, 8'h00};
mem1[34] = {8'h00, 8'hC0, 8'h73, 8'h00, 8'h00, 8'hE0, 8'h71, 8'h00};
mem1[35] = {8'h00, 8'h70, 8'h70, 8'h00, 8'h00, 8'h3C, 8'h70, 8'h00};
mem1[36] = {8'h00, 8'h1E, 8'h70, 8'h00, 8'h80, 8'h07, 8'h70, 8'h00};
mem1[37] = {8'hC0, 8'hFF, 8'hFF, 8'h07, 8'hC0, 8'hFF, 8'hFF, 8'h07};
mem1[38] = {8'h00, 8'h00, 8'h70, 8'h00, 8'h00, 8'h00, 8'h70, 8'h00};
mem1[39] = {8'h00, 8'h00, 8'h70, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00};
//5
mem1[40] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h80, 8'hC1, 8'h01};
mem1[41] = {8'h00, 8'hF8, 8'hE1, 8'h03, 8'hC0, 8'hFF, 8'h81, 8'h07};
mem1[42] = {8'hC0, 8'hCF, 8'h00, 8'h06, 8'hC0, 8'h60, 8'h00, 8'h0E};
mem1[43] = {8'hC0, 8'h60, 8'h00, 8'h0E, 8'hC0, 8'h60, 8'h00, 8'h0E};
mem1[44] = {8'hC0, 8'h60, 8'h00, 8'h0E, 8'hC0, 8'hE0, 8'h00, 8'h07};
mem1[45] = {8'hC0, 8'hC0, 8'h01, 8'h07, 8'hC0, 8'hC0, 8'hE7, 8'h03};
mem1[46] = {8'hC0, 8'h80, 8'hFF, 8'h01, 8'h00, 8'h00, 8'hFE, 8'h00};
mem1[47] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00};
//6
mem1[48] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h7C, 8'h00};
mem1[49] = {8'h00, 8'h00, 8'hFF, 8'h01, 8'h00, 8'hC0, 8'hFF, 8'h03};
mem1[50] = {8'h00, 8'hF0, 8'h83, 8'h07, 8'h00, 8'hF8, 8'h01, 8'h07};
mem1[51] = {8'h00, 8'hFE, 8'h00, 8'h06, 8'h00, 8'hCF, 8'h00, 8'h0E};
mem1[52] = {8'hC0, 8'hC7, 8'h00, 8'h0E, 8'hC0, 8'hC1, 8'h00, 8'h0E};
mem1[53] = {8'hC0, 8'hC0, 8'h00, 8'h06, 8'h00, 8'hC0, 8'h01, 8'h07};
mem1[54] = {8'h00, 8'h80, 8'hFF, 8'h03, 8'h00, 8'h00, 8'hFF, 8'h01};
mem1[55] = {8'h00, 8'h00, 8'hFE, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00};
//7
mem1[56] = {8'h00, 8'h00, 8'h00, 8'h00, 8'hC0, 8'h00, 8'h00, 8'h00};
mem1[57] = {8'hC0, 8'h00, 8'h00, 8'h00, 8'hC0, 8'h00, 8'h00, 8'h00};
mem1[58] = {8'hC0, 8'h00, 8'h00, 8'h04, 8'hC0, 8'h00, 8'h80, 8'h07};
mem1[59] = {8'hC0, 8'h00, 8'hF0, 8'h07, 8'hC0, 8'h00, 8'hFE, 8'h01};
mem1[60] = {8'hC0, 8'h80, 8'h3F, 8'h00, 8'hC0, 8'hE0, 8'h07, 8'h00};
mem1[61] = {8'hC0, 8'hF8, 8'h00, 8'h00, 8'hC0, 8'h3E, 8'h00, 8'h00};
mem1[62] = {8'hC0, 8'h0F, 8'h00, 8'h00, 8'hC0, 8'h03, 8'h00, 8'h00};
mem1[63] = {8'hC0, 8'h01, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00};
//8
mem1[64] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'hFC, 8'h01};
mem1[65] = {8'h00, 8'h7F, 8'hFE, 8'h03, 8'h80, 8'h7F, 8'hCF, 8'h07};
mem1[66] = {8'hC0, 8'hE1, 8'h07, 8'h07, 8'hC0, 8'hC0, 8'h03, 8'h06};
mem1[67] = {8'hC0, 8'h80, 8'h01, 8'h0E, 8'hC0, 8'h80, 8'h01, 8'h0E};
mem1[68] = {8'hC0, 8'h80, 8'h01, 8'h0E, 8'hC0, 8'hC0, 8'h03, 8'h06};
mem1[69] = {8'hC0, 8'hE1, 8'h03, 8'h07, 8'h80, 8'h7F, 8'h8F, 8'h07};
mem1[70] = {8'h00, 8'h7F, 8'hFE, 8'h03, 8'h00, 8'h1E, 8'hFC, 8'h01};
mem1[71] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00};
//9
mem1[72] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'hFE, 8'h01, 8'h00};
mem1[73] = {8'h00, 8'hFF, 8'h03, 8'h00, 8'h80, 8'h87, 8'h07, 8'h00};
mem1[74] = {8'hC0, 8'h01, 8'h07, 8'h08, 8'hC0, 8'h01, 8'h06, 8'h0E};
mem1[75] = {8'hC0, 8'h00, 8'h86, 8'h0F, 8'hC0, 8'h00, 8'hE6, 8'h03};
mem1[76] = {8'hC0, 8'h00, 8'hFE, 8'h01, 8'hC0, 8'h01, 8'h7F, 8'h00};
mem1[77] = {8'hC0, 8'h83, 8'h1F, 8'h00, 8'h80, 8'hFF, 8'h07, 8'h00};
mem1[78] = {8'h00, 8'hFF, 8'h03, 8'h00, 8'h00, 8'h7E, 8'h00, 8'h00};
mem1[79] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00};
//.
mem1[80] = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
mem1[81] = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
mem1[82] = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
mem1[83] = {8'h00,8'h00,8'h00,8'h07,8'h00,8'h00,8'h00,8'h07};
mem1[84] = {8'h00,8'h00,8'h00,8'h07,8'h00,8'h00,8'h00,8'h00};
mem1[85] = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
mem1[86] = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
mem1[87] = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
//sp
mem1[88] = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
mem1[89] = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
mem1[90] = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
mem1[91] = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
mem1[92] = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
mem1[93] = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
mem1[94] = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
mem1[95] = {8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
//V
mem1[96] = {8'hC0,8'h00,8'h00,8'h00,8'hC0,8'h00,8'h00,8'h00};
mem1[97] = {8'hC0,8'h3F,8'h00,8'h00,8'hC0,8'h3F,8'h00,8'h00};
mem1[98] = {8'hC0,8'hC0,8'h3F,8'h00,8'hC0,8'hC0,8'h3F,8'h00};
mem1[99] = {8'h00,8'h00,8'hC0,8'h0F,8'h00,8'h00,8'hC0,8'h0F};
mem1[100] = {8'h00,8'h00,8'hFC,8'h00,8'h00,8'h00,8'hFC,8'h00};
mem1[101] = {8'hC0,8'hF0,8'h03,8'h00,8'hC0,8'hF0,8'h03,8'h00};
mem1[102] = {8'hC0,8'h0F,8'h00,8'h00,8'hC0,8'h0F,8'h00,8'h00};
mem1[103] = {8'hC0,8'h00,8'h00,8'h00,8'hC0,8'h00,8'h00,8'h00};
end
3.3 bin_to_bcd 转码
量化运算 N = 256 * Vin / Vref,
那么逆向运算为Vin = N * Vref / 256,其中Vref = 3.3V,所以Vin = N * 0.0129
wire [15:0] bin_code = data * 16'd129;
将二进制数转换成BCD码的形式,采用左移加三的算法:
- 左移要转换的二进制码1位
- 左移之后,BCD码分别置于百位、十位、个位
- 如果移位后所在的BCD码列大于或等于5,则对该值加3
- 继续左移的过程直至全部移位完成
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
最后得到20位的数据输出,每4位表示一个BCD码,所以有5位有效数据,这里我们还需要将小数点左移4位,计算出来的数应该是X.XXXX伏特,1个整数位和4个小数位,本代码只显示前3位
第一位数字
char <= dac_data[19:16]<<3;
第二位数字
char <= dac_data[15:12]<<3;
第三位数字
char <= dac_data[11:8]<<3;
3.4顶层设计
module dac_top(
input clk,
input rst_n,
input ADC_Din,
output clkout,
output adc_clk,
output adc_cs,
output oled_csn,
output oled_rst,
output oled_dcn,
output oled_clk,
output oled_dat
);
wire [19:0] bcd_code;
wire adc_done;
wire [7:0] data;
clock clock(
.clk (clk ),
.rst_n (rst_n ),
.clkout (clkout )
);
adc_Driver adc_Driver(
.clkout (clkout ),
.rst_n (rst_n ),
.En (1'b1 ),
.ADC_Din (ADC_Din ),
.adc_clk (adc_clk ),
.adc_cs (adc_cs ),
.data (data ),
.adc_done (adc_done )
);
Control Control(
.clk (clk ),
.rst_n (rst_n ),
.adc_done (adc_done ),
.data (data ),
.bcd_code (bcd_code )
);
OLED12832 OLED12832(
.clkout (clkout ),
.rst_n (rst_n ),
.dac_data (bcd_code ),
.oled_csn (oled_csn ),
.oled_rst (oled_rst ),
.oled_dcn (oled_dcn ),
.oled_clk (oled_clk ),
.oled_dat (oled_dat )
);
endmodule
PART4 项目展示
PART5 遇到的问题
1.adc芯片驱动编写问题:
在仔细查阅实例代码和电子森林的示例代码和反复尝试,终于根据数据手册构建出了adc的串行通信代码
通过网上搜寻各种各样的资料可以有效的帮助我们找到解决方案,同时我也体会到和同学一起交流学习也能显著提高自己
2.未使用ip核
oled代码主要参考了寒假一起练项目四 - 电子森林 (eetree.cn)的代码,在此表示感谢