我买了一个PCF8591模块,用单片机是正常的。
我写了一个CPLD读PCF8591的ADC值的程序,可是读出来老是零。
代码如下:
module i2c(clk,rst,scl,sda,lcd_en ,
lcd_rw , //��Ϊִֻ��д������������ԶΪ0.
lcd_rs ,
lcd_data,led1,led2,led3,led4,adc_data);
input clk,rst;
output scl;
inout sda;
output led1,led2,led3,led4;
output adc_data;
output lcd_en ;
output lcd_rw ;
output lcd_rs ;
output [7:0] lcd_data;
reg scl;
reg adc_data;
reg ledn1,ledn2,ledn3,ledn4;
reg[23:0] cnt_scan;
reg sda_buf;
reg link;
reg phase0,phase1,phase2,phase3;
reg[7:0] clk_div;
reg[1:0] main_state;
reg[3:0] i2c_state;
reg[3:0] inner_state;
reg[19:0] cnt_delay;
reg start_delaycnt;
reg[7:0] readData_reg;
reg[7:0] addr;
//--------------------------------------------
//按键检测
reg[19:0] cnt_20ms; //20ms计数寄存器
always @ (posedge clk or negedge rst)
if(!rst) cnt_20ms <= 20'd0;
else cnt_20ms <= cnt_20ms+1'b1; //不断计数
parameter div_parameter=100;
parameter start=4'b0000,
first=4'b0001,
second=4'b0010,
third=4'b0011,
fourth=4'b0100,
fifth=4'b0101,
sixth=4'b0110,
seventh=4'b0111,
eighth=4'b1000,
ack=4'b1001,
stop=4'b1010;
parameter ini=4'b0000,
sendaddr=4'b0001,
//write_data=3'b010,
read_data=4'b0010,
read_ini=4'b0011,
read_s1=4'b0100,
read_s2=4'b0101,
read_s3=4'b0110,
read_s4=4'b0111,
read_s5=4'b1000,
read_s6=4'b1001,
read_s7=4'b1010,
read_s8=4'b1011,
read_s9=4'b1100,
read_s10=4'b1101,
read_s11=4'b1110,
read_s12=4'b1111;
wire lcd_en ;
wire lcd_rw;
reg [7:0] lcd_data;
reg lcd_rs ;
reg [5:0] c_state ;
reg [5:0] n_state ;
wire [127:0] row_1;
wire [127:0] row_2;
//reg[7:0] dis_data=0;
assign row_1 [127:120]=8'h30+adc_data/100;
assign row_1 [119:112]=8'h30+adc_data%100/10;
assign row_1 [111:104]=8'h30+adc_data%10;
assign row_1 [103:96]=8'h20;
assign row_1 [95:88]=8'h20;
assign row_1 [87:80]=8'h20;
assign row_1 [79:72]=8'h20;
assign row_1 [71:64]=8'h20;
assign row_1 [63:56]=8'h20;
assign row_1 [55:48]=8'h20;
assign row_1 [47:40]=8'h41;
assign row_1 [39:32]=8'h42;
assign row_1 [31:24]=8'h43;
assign row_1 [23:16]=8'h44;
assign row_1 [15:8]=8'h45;
assign row_1 [7:0]=8'h46;
//assign row_1 =" " ; //��һ����ʾ������
assign row_2 ="happy everyday !"; //�ڶ�����ʾ������
//----------------------------------------------------------------------
//initialize
//first step is waitng more than 20 ms. �����ֲ�Ҫ���ģ�Ŀ���ǵȴ�ϵͳ�ϵ��ȶ���
parameter TIME_20MS = 1000_000 ; //20000000/20=1000_000
parameter TIME_200MS = 1000_0000_0 ; //20000000/20=1000_000
//parameter TIME_15MS = 9'h100 ; //just for test
parameter TIME_500HZ= 100_000 ; //
//parameter TIME_500HZ= 4'hf; //just for test
//use gray code
parameter IDLE= 8'h00 ; //��Ϊ��״̬��һ����40��״̬�������������˸����룬һ��ֻ��1λ�����ı䡣00 01 03 02
parameter SET_FUNCTION= 8'h01 ;
parameter DISP_OFF= 8'h03 ;
parameter DISP_CLEAR= 8'h02 ;
parameter ENTRY_MODE= 8'h06 ;
parameter DISP_ON = 8'h07 ;
parameter ROW1_ADDR= 8'h05 ;
parameter ROW1_0= 8'h04 ;
parameter ROW1_1= 8'h0C ;
parameter ROW1_2= 8'h0D ;
parameter ROW1_3= 8'h0F ;
parameter ROW1_4= 8'h0E ;
parameter ROW1_5= 8'h0A ;
parameter ROW1_6= 8'h0B ;
parameter ROW1_7= 8'h09 ;
parameter ROW1_8= 8'h08 ;
parameter ROW1_9= 8'h18 ;
parameter ROW1_A= 8'h19 ;
parameter ROW1_B= 8'h1B ;
parameter ROW1_C= 8'h1A ;
parameter ROW1_D= 8'h1E ;
parameter ROW1_E= 8'h1F ;
parameter ROW1_F= 8'h1D ;
parameter ROW2_ADDR= 8'h1C ;
parameter ROW2_0= 8'h14 ;
parameter ROW2_1= 8'h15 ;
parameter ROW2_2= 8'h17 ;
parameter ROW2_3= 8'h16 ;
parameter ROW2_4= 8'h12 ;
parameter ROW2_5= 8'h13 ;
parameter ROW2_6= 8'h11 ;
parameter ROW2_7= 8'h10 ;
parameter ROW2_8= 8'h30 ;
parameter ROW2_9= 8'h31 ;
parameter ROW2_A= 8'h33 ;
parameter ROW2_B= 8'h32 ;
parameter ROW2_C= 8'h36 ;
parameter ROW2_D= 8'h37 ;
parameter ROW2_E= 8'h35 ;
parameter ROW2_F= 8'h34 ;
//20ms�ļ��������ʼ����һ��
reg [19:0] cnt_20ms1 ;
always @(posedge clk or negedge rst)begin
if(rst==1'b0)begin
cnt_20ms1<=0;
end
else if(cnt_20ms1 == TIME_20MS -1)begin
cnt_20ms1<=cnt_20ms1;
end
else
cnt_20ms1<=cnt_20ms1 + 1 ;
end
wire delay_done = (cnt_20ms1==TIME_20MS-1)? 1'b1 : 1'b0 ;
//----------------------------------------------------------------------
//500ns �����Ƿ�Ƶ����ΪLCD1602�Ĺ���Ƶ����500HZ,��FPGA��50Mhz,����Ҫ��Ƶ
reg [19:0] cnt_500hz;
always @(posedge clk or negedge rst)begin
if(rst==1'b0)begin
cnt_500hz <= 0;
end
else if(delay_done==1)begin
if(cnt_500hz== TIME_500HZ - 1)
cnt_500hz<=0;
else
cnt_500hz<=cnt_500hz + 1 ;
end
else
cnt_500hz<=0;
end
//20ms�ļ��������ʼ����һ��
reg [28:0] cnt_200ms ;
always @(posedge clk or negedge rst)begin
if(rst==1'b0)begin
cnt_200ms<=0;
end
else if(cnt_200ms == TIME_200MS -1)begin
cnt_200ms<=0;
end
else
cnt_200ms<=cnt_200ms + 1 ;
end
assign lcd_en = (cnt_500hz>(TIME_500HZ-1)/2)? 1'b0 : 1'b1; //�½���
assign write_flag = (cnt_500hz==TIME_500HZ - 1) ? 1'b1 : 1'b0 ;
//set_function ,display off ��display clear ,entry mode set
//----------------------------------------------------------------------״̬��
always @(posedge clk or negedge rst)begin
if(rst==1'b0)begin
c_state <= IDLE ;
end
else if(write_flag==1) begin
c_state<= n_state ;
end
else
c_state<=c_state ;
end
always @(*)begin
case (c_state)
IDLE: n_state = SET_FUNCTION ;
SET_FUNCTION: n_state = DISP_OFF ;
DISP_OFF: n_state = DISP_CLEAR ;
DISP_CLEAR: n_state = ENTRY_MODE ;
ENTRY_MODE: n_state = DISP_ON ;
DISP_ON : n_state = ROW1_ADDR ;
ROW1_ADDR: n_state = ROW1_0 ;
ROW1_0: n_state = ROW1_1 ;
ROW1_1: n_state = ROW1_2 ;
ROW1_2: n_state = ROW1_3 ;
ROW1_3: n_state = ROW1_4 ;
ROW1_4: n_state = ROW1_5 ;
ROW1_5: n_state = ROW1_6 ;
ROW1_6: n_state = ROW1_7 ;
ROW1_7: n_state = ROW1_8 ;
ROW1_8: n_state = ROW1_9 ;
ROW1_9: n_state = ROW1_A ;
ROW1_A: n_state = ROW1_B ;
ROW1_B: n_state = ROW1_C ;
ROW1_C: n_state = ROW1_D ;
ROW1_D: n_state = ROW1_E ;
ROW1_E: n_state = ROW1_F ;
ROW1_F: n_state = ROW2_ADDR ;
ROW2_ADDR: n_state = ROW2_0 ;
ROW2_0: n_state = ROW2_1 ;
ROW2_1: n_state = ROW2_2 ;
ROW2_2: n_state = ROW2_3 ;
ROW2_3: n_state = ROW2_4 ;
ROW2_4: n_state = ROW2_5 ;
ROW2_5: n_state = ROW2_6 ;
ROW2_6: n_state = ROW2_7 ;
ROW2_7: n_state = ROW2_8 ;
ROW2_8: n_state = ROW2_9 ;
ROW2_9: n_state = ROW2_A ;
ROW2_A: n_state = ROW2_B ;
ROW2_B: n_state = ROW2_C ;
ROW2_C: n_state = ROW2_D ;
ROW2_D: n_state = ROW2_E ;
ROW2_E: n_state = ROW2_F ;
ROW2_F: n_state = ROW1_ADDR ;
default: n_state = n_state ;
endcase
end
assign lcd_rw = 0;
always @(posedge clk or negedge rst)begin
if(rst==1'b0)begin
lcd_rs <= 0 ; //order or data 0: order 1:data
end
else if(write_flag == 1)begin
if((n_state==SET_FUNCTION)||(n_state==DISP_OFF)||
(n_state==DISP_CLEAR)||(n_state==ENTRY_MODE)||
(n_state==DISP_ON ) ||(n_state==ROW1_ADDR)||
(n_state==ROW2_ADDR))begin
lcd_rs<=0 ;
end
else begin
lcd_rs<= 1;
end
end
else begin
lcd_rs<=lcd_rs;
end
end
always @(posedge clk or negedge rst)begin
if(rst==1'b0)begin
lcd_data<=0 ;
end
else if(write_flag)begin
case(n_state)
IDLE: lcd_data <= 8'hxx;
SET_FUNCTION: lcd_data <= 8'h38; //2*16 5*8 8���
DISP_OFF: lcd_data <= 8'h08;
DISP_CLEAR: lcd_data <= 8'h01;
ENTRY_MODE: lcd_data <= 8'h06;
DISP_ON : lcd_data <= 8'h0c; //��ʾ���ܿ���û�й��꣬�Ҳ���˸��
ROW1_ADDR: lcd_data <= 8'h80; //00+80
ROW1_0: lcd_data <= row_1 [127:120];
ROW1_1: lcd_data <= row_1 [119:112];
ROW1_2: lcd_data <= row_1 [111:104];
ROW1_3: lcd_data <= row_1 [103: 96];
ROW1_4: lcd_data <= row_1 [ 95: 88];
ROW1_5: lcd_data <= row_1 [ 87: 80];
ROW1_6: lcd_data <= row_1 [ 79: 72];
ROW1_7: lcd_data <= row_1 [ 71: 64];
ROW1_8: lcd_data <= row_1 [ 63: 56];
ROW1_9: lcd_data <= row_1 [ 55: 48];
ROW1_A: lcd_data <= row_1 [ 47: 40];
ROW1_B: lcd_data <= row_1 [ 39: 32];
ROW1_C: lcd_data <= row_1 [ 31: 24];
ROW1_D: lcd_data <= row_1 [ 23: 16];
ROW1_E: lcd_data <= row_1 [ 15: 8];
ROW1_F: lcd_data <= row_1 [ 7: 0];
ROW2_ADDR: lcd_data <= 8'hc0; //40+80
ROW2_0: lcd_data <= row_2 [127:120];
ROW2_1: lcd_data <= row_2 [119:112];
ROW2_2: lcd_data <= row_2 [111:104];
ROW2_3: lcd_data <= row_2 [103: 96];
ROW2_4: lcd_data <= row_2 [ 95: 88];
ROW2_5: lcd_data <= row_2 [ 87: 80];
ROW2_6: lcd_data <= row_2 [ 79: 72];
ROW2_7: lcd_data <= row_2 [ 71: 64];
ROW2_8: lcd_data <= row_2 [ 63: 56];
ROW2_9: lcd_data <= row_2 [ 55: 48];
ROW2_A: lcd_data <= row_2 [ 47: 40];
ROW2_B: lcd_data <= row_2 [ 39: 32];
ROW2_C: lcd_data <= row_2 [ 31: 24];
ROW2_D: lcd_data <= row_2 [ 23: 16];
ROW2_E: lcd_data <= row_2 [ 15: 8];
ROW2_F: lcd_data <= row_2 [ 7: 0];
endcase
end
else
lcd_data<=lcd_data ;
end
assign sda=(link)? sda_buf:1'bz;
reg [19:0] tics;
always @(posedge clk or negedge rst)
begin
if(!rst)
tics<=0;
else if(tics==20'hfffff)
tics<=0;
else
tics<=tics+1;
end
always@(posedge clk or negedge rst)
begin
if(!rst)
cnt_delay<=0;
else begin
if(start_delaycnt) begin
if(cnt_delay!=20'd80)
cnt_delay<=cnt_delay+1;
else
cnt_delay<=0;
end
end
end
always@(posedge clk or negedge rst)
begin
if(!rst) begin
clk_div<=0;
phase0<=0;
phase1<=0;
phase2<=0;
phase3<=0;
end
else begin
if(clk_div!=div_parameter-1)
clk_div<=clk_div+1;
else
clk_div<=0;
if(phase0)
phase0<=0;
else if(clk_div==99)
phase0<=1;
if(phase1)
phase1<=0;
else if(clk_div==24)
phase1<=1;
if(phase2)
phase2<=0;
else if(clk_div==49)
phase2<=1;
if(phase3)
phase3<=0;
else if(clk_div==74)
phase3<=1;
end
end
///////////////////////////EEPROM/////////////
always@(posedge clk or negedge rst)
begin
if(!rst) begin
start_delaycnt<=0;
main_state<=2'b00;
i2c_state<=ini;
inner_state<=start;
scl<=1;
sda_buf<=1;
link<=0;
ledn1<=1;
ledn2<=1;
ledn3<=1;
ledn4<=1;
readData_reg<=0;
addr<=8'h40;
end
else begin
case(main_state)
2'b00: begin
scl<=1;
sda_buf<=1;
link<=0;
inner_state<=start;
i2c_state<=ini;
if(cnt_delay==0)
start_delaycnt<=1;
else if(cnt_delay==20'd80) begin
start_delaycnt<=0;
main_state<=2'b10;
end
end
2'b10: begin
if(phase0)
scl<=1;
else if(phase2)
scl<=0;
case(i2c_state)
ini: begin
case(inner_state)
start: begin
if(phase1) begin
link<=1;
sda_buf<=0;
end
if(phase3&&link) begin
inner_state<=first;
sda_buf<=1;
link<=1;
end
end
first:
if(phase3) begin
sda_buf<=0;
link<=1;
inner_state<=second;
end
second:
if(phase3) begin
sda_buf<=0;
link<=1;
inner_state<=third;
end
third:
if(phase3) begin
sda_buf<=1;
link<=1;
inner_state<=fourth;
end
fourth:
if(phase3) begin
sda_buf<=0;
link<=1;
inner_state<=fifth;
end
fifth:
if(phase3) begin
sda_buf<=0;
link<=1;
inner_state<=sixth;
end
sixth:
if(phase3) begin
sda_buf<=0;
link<=1;
inner_state<=seventh;
end
seventh:
if(phase3) begin
sda_buf<=0;
link<=1;
inner_state<=eighth;
end
eighth:
if(phase3) begin
link<=0;
inner_state<=ack;
end
ack: begin
if(phase0)
sda_buf<=sda;
if(phase1) begin
if(sda_buf==1)
//begin
main_state<=2'b00;
//main_state<=2'b11;
end
if(phase3) begin
link<=1;
sda_buf<=addr[7];
inner_state<=first;
i2c_state<=sendaddr;
end
end
endcase
end
sendaddr: begin
case(inner_state)
first:
if(phase3) begin
link<=1;
sda_buf<=addr[6];
inner_state<=second;
end
second:
if(phase3) begin
link<=1;
sda_buf<=addr[5];
inner_state<=third;
end
third:
if(phase3) begin
link<=1;
sda_buf<=addr[4];
inner_state<=fourth;
end
fourth:
if(phase3) begin
link<=1;
sda_buf<=addr[3];
inner_state<=fifth;
end
fifth:
if(phase3) begin
link<=1;
sda_buf<=addr[2];
inner_state<=sixth;
end
sixth:
if(phase3) begin
link<=1;
sda_buf<=addr[1];
inner_state<=seventh;
end
seventh:
if(phase3) begin
link<=1;
sda_buf<=addr[0];
inner_state<=eighth;
end
eighth:
if(phase3) begin
link<=0;
inner_state<=ack;
end
ack: begin
if(phase0)
sda_buf<=sda;
if(phase1) begin
if(sda_buf==1)
main_state<=2'b00;
//main_state<=2'b11;
end
if(phase3) begin
link<=1;
sda_buf<=1;
inner_state<=start;
i2c_state<=read_ini;
end
end
endcase
end
read_ini: begin
case(inner_state)
start: begin
if(phase1) begin
link<=1;
sda_buf<=0;
end
if(phase3&&link) begin
inner_state<=first;
sda_buf<=1;
link<=1;
end
end
first:
if(phase3) begin
sda_buf<=0;
link<=1;
inner_state<=second;
end
second:
if(phase3) begin
sda_buf<=0;
link<=1;
inner_state<=third;
end
third:
if(phase3) begin
sda_buf<=1;
link<=1;
inner_state<=fourth;
end
fourth:
if(phase3) begin
sda_buf<=0;
link<=1;
inner_state<=fifth;
end
fifth:
if(phase3) begin
sda_buf<=0;
link<=1;
inner_state<=sixth;
end
sixth:
if(phase3) begin
sda_buf<=0;
link<=1;
inner_state<=seventh;
end
seventh:
if(phase3) begin
sda_buf<=1;
link<=1;
inner_state<=eighth;
end
eighth:
if(phase3) begin
link<=0;
inner_state<=ack;
end
ack: begin
if(phase0)
sda_buf<=sda;
if(phase1) begin
if(sda_buf==1)
main_state<=2'b00;
//main_state<=2'b11;
end
if(phase3) begin
link<=0;
inner_state<=first;
i2c_state<=read_data;
end
end
endcase
end
read_data: begin
case(inner_state)
first: begin
if(phase0)
sda_buf<=sda;
if(phase1) begin
readData_reg[7:1]<=readData_reg[6:0];
readData_reg[0]<=sda;
end
if(phase3)
inner_state<=second;
end
second: begin
if(phase0)
sda_buf<=sda;
if(phase1) begin
readData_reg[7:1]<=readData_reg[6:0];
readData_reg[0]<=sda;
end
if(phase3)
inner_state<=third;
end
third: begin
if(phase0)
sda_buf<=sda;
if(phase1) begin
readData_reg[7:1]<=readData_reg[6:0];
readData_reg[0]<=sda;
end
if(phase3)
inner_state<=fourth;
end
fourth: begin
if(phase0)
sda_buf<=sda;
if(phase1) begin
readData_reg[7:1]<=readData_reg[6:0];
readData_reg[0]<=sda;
end
if(phase3)
inner_state<=fifth;
end
fifth: begin
if(phase0)
sda_buf<=sda;
if(phase1) begin
readData_reg[7:1]<=readData_reg[6:0];
readData_reg[0]<=sda;
end
if(phase3)
inner_state<=sixth;
end
sixth: begin
if(phase0)
sda_buf<=sda;
if(phase1) begin
readData_reg[7:1]<=readData_reg[6:0];
readData_reg[0]<=sda;
end
if(phase3)
inner_state<=seventh;
end
seventh: begin
if(phase0)
sda_buf<=sda;
if(phase1) begin
readData_reg[7:1]<=readData_reg[6:0];
readData_reg[0]<=sda;
end
if(phase3)
inner_state<=eighth;
end
eighth: begin
if(phase0)
sda_buf<=sda;
if(phase1) begin
readData_reg[7:1]<=readData_reg[6:0];
readData_reg[0]<=sda;
end
if(phase3)
inner_state<=ack;
end
ack: begin
if(phase3) begin
link<=1;
sda_buf<=0;
inner_state<=stop;
end
end
stop: begin
/*if(phase1)
sda_buf<=1;
ledn1<=0;
if(phase3) begin
link<=0;
inner_state<=first;
i2c_state<=read_s1;
ledn2<=0;
end*/
ledn3<=1;
if(phase1)
sda_buf<=1;
if(phase3)
i2c_state<=read_s1;
end
default:
;
endcase
end
read_s1:
i2c_state<=read_s2;
read_s2:
i2c_state<=read_s3;
read_s3:
i2c_state<=read_s4;
read_s4:
i2c_state<=read_s5;
read_s5:
i2c_state<=read_s6;
read_s6:
i2c_state<=read_s7;
read_s7:
i2c_state<=read_s8;
read_s8:
i2c_state<=read_s9;
read_s9:
i2c_state<=read_s10;
read_s10:
i2c_state<=read_s11;
read_s11:
i2c_state<=read_s12;
read_s12:
begin
if(tics[19])
begin
adc_data<=readData_reg;
main_state<=2'b00;
i2c_state<=ini;
inner_state<=start;
ledn3<=0;
end
else
i2c_state<=read_s12;
end
default:
;
endcase
end
endcase
end
end
assign led1=ledn1;
assign led2=ledn2;
assign led3=ledn3;
assign led4=ledn4;
endmodule
请高手指教,哪里有错?谢谢!我是参考例程AR24C04的程序改的。
引用: 火辣西米秀 发表于 2023-4-30 09:03 输入的模拟电压为零?还是AD转换电路不对,转换结果为零, ADC的参考电压是否选择错误
谢谢!输入的模拟电压不为零。AD模块是好的,用51没问题。
电路图: